Lagrange [work/v1.11]

Site-specific settings

=> e455699fca461e7e73d920a9ebfe557c20a67f98

diff --git a/po/en.po b/po/en.po
index 6db26259..22c10e44 100644
--- a/po/en.po
+++ b/po/en.po
@@ -760,6 +760,27 @@ msgstr "Trust"
 msgid "dlg.cert.fingerprint"
 msgstr "Copy Fingerprint"
 
+msgid "pageinfo.settings"
+msgstr "Settings"
+
+msgid "heading.sitespec"
+msgstr "Site-Specific Settings"
+
+msgid "sitespec.ansi"
+msgstr "ANSI escape warnings:"
+
+msgid "sitespec.palette"
+msgstr "Theme palette seed:"
+
+msgid "sitespec.accept"
+msgstr "Save Settings"
+
+msgid "keys.pageinfo"
+msgstr "Show page information"
+
+msgid "keys.sitespec"
+msgstr "Show site-specific settings"
+
 #, c-format
 msgid "dlg.input.prompt"
 msgstr "Please enter input for %s:"
diff --git a/res/lang/cs.bin b/res/lang/cs.bin
index f3f2a060..0cf36a2b 100644
Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ
diff --git a/res/lang/de.bin b/res/lang/de.bin
index 0f918bfb..ea6e1841 100644
Binary files a/res/lang/de.bin and b/res/lang/de.bin differ
diff --git a/res/lang/en.bin b/res/lang/en.bin
index 727258d1..372cef24 100644
Binary files a/res/lang/en.bin and b/res/lang/en.bin differ
diff --git a/res/lang/eo.bin b/res/lang/eo.bin
index f68ac15d..8a9519b6 100644
Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ
diff --git a/res/lang/es.bin b/res/lang/es.bin
index 1d09138c..3435a8d8 100644
Binary files a/res/lang/es.bin and b/res/lang/es.bin differ
diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin
index d3efe8fe..5c527322 100644
Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ
diff --git a/res/lang/fi.bin b/res/lang/fi.bin
index 24e2a905..cdbda504 100644
Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ
diff --git a/res/lang/fr.bin b/res/lang/fr.bin
index c644fab8..3ab07f12 100644
Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ
diff --git a/res/lang/gl.bin b/res/lang/gl.bin
index e93d1eb7..5f5d467b 100644
Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ
diff --git a/res/lang/hu.bin b/res/lang/hu.bin
index 5bfe37eb..17486efa 100644
Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ
diff --git a/res/lang/ia.bin b/res/lang/ia.bin
index 4b0b9bc3..8cae5947 100644
Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ
diff --git a/res/lang/ie.bin b/res/lang/ie.bin
index b69fd2a4..bd647d76 100644
Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ
diff --git a/res/lang/isv.bin b/res/lang/isv.bin
index 0cbd0f67..81d30963 100644
Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ
diff --git a/res/lang/nl.bin b/res/lang/nl.bin
index 82d13774..e860c109 100644
Binary files a/res/lang/nl.bin and b/res/lang/nl.bin differ
diff --git a/res/lang/pl.bin b/res/lang/pl.bin
index 9d13a9e2..b759b1b7 100644
Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ
diff --git a/res/lang/ru.bin b/res/lang/ru.bin
index 6a09521d..8463fbfe 100644
Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ
diff --git a/res/lang/sk.bin b/res/lang/sk.bin
index 9532ca17..a0197c5b 100644
Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ
diff --git a/res/lang/sr.bin b/res/lang/sr.bin
index 58828fea..dc10b8a0 100644
Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ
diff --git a/res/lang/tok.bin b/res/lang/tok.bin
index 0c4f6123..977454a8 100644
Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ
diff --git a/res/lang/tr.bin b/res/lang/tr.bin
index f62d0968..c131d0ea 100644
Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ
diff --git a/res/lang/uk.bin b/res/lang/uk.bin
index bbc10575..8377c0ba 100644
Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ
diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin
index 3a34d15d..acaaaa77 100644
Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ
diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin
index f0ac2727..cf674d55 100644
Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ
diff --git a/src/sitespec.c b/src/sitespec.c
index 31094981..21edc0a2 100644
--- a/src/sitespec.c
+++ b/src/sitespec.c
@@ -268,6 +268,12 @@ void setValueString_SiteSpec(const iString *site, enum iSiteSpecKey key, const i
                 set_String(¶ms->titanIdentity, value);
             }
             break;
+        case paletteSeed_SiteSpecKey:
+            if (!equal_String(¶ms->paletteSeed, value)) {
+                needSave = iTrue;
+                set_String(¶ms->paletteSeed, value);
+            }
+            break;            
         default:
             break;
     }
@@ -339,6 +345,8 @@ const iString *valueString_SiteSpec(const iString *site, enum iSiteSpecKey key)
     switch (key) {
         case titanIdentity_SiteSpecKey:
             return ¶ms->titanIdentity;
+        case paletteSeed_SiteSpecKey:
+            return ¶ms->paletteSeed;
         default:
             return collectNew_String();
     }    
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 7d9ac154..1f3e0e37 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -4033,6 +4033,12 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
         addAction_Widget(dlg, SDLK_SPACE, 0, "message.ok");
         return iTrue;
     }
+    else if (equal_Command(cmd, "document.sitespec") && d == document_App()) {
+        if (!findWidget_App("sitespec.palette")) {
+            makeSiteSpecificSettings_Widget(d->mod.url);
+        }
+        return iTrue;
+    }
     else if (equal_Command(cmd, "server.unexpire") && document_App() == d) {
         const iRangecc host = urlHost_String(d->mod.url);
         const uint16_t port = urlPort_String(d->mod.url);
diff --git a/src/ui/keys.c b/src/ui/keys.c
index 26a286bc..88efa98b 100644
--- a/src/ui/keys.c
+++ b/src/ui/keys.c
@@ -243,6 +243,8 @@ static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] =
     { 110,{ "${menu.save.downloads}",       SDLK_s, KMOD_PRIMARY,           "document.save"                     }, 0 },
     { 120,{ "${keys.upload}",               SDLK_u, KMOD_PRIMARY,           "document.upload"                   }, 0 },
     { 121,{ "${keys.upload.edit}",          SDLK_e, KMOD_PRIMARY,           "document.upload copy:1"            }, 0 },
+    { 125,{ "${keys.pageinfo}",             SDLK_i, KMOD_PRIMARY,           "document.info"                     }, 0 },
+    { 126,{ "${keys.sitespec}",             ',', KMOD_PRIMARY | KMOD_SHIFT, "document.sitespec"                 }, 0 },
     { 130,{ "${keys.input.precedingline}",  SDLK_v, KMOD_PRIMARY | KMOD_SHIFT, "input.precedingline"            }, 0 },
     /* The following cannot currently be changed (built-in duplicates). */
 #if defined (iPlatformApple)
diff --git a/src/ui/util.c b/src/ui/util.c
index 54715121..5cd8a582 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 #include "keys.h"
 #include "labelwidget.h"
 #include "root.h"
+#include "sitespec.h"
 #include "text.h"
 #include "touch.h"
 #include "widget.h"
@@ -3126,7 +3127,7 @@ iWidget *makeBookmarkCreation_Widget(const iString *url, const iString *title, i
 
 static iBool handleFeedSettingCommands_(iWidget *dlg, const char *cmd) {
     if (equal_Command(cmd, "cancel")) {
-        setupSheetTransition_Mobile(dlg, iFalse);
+        setupSheetTransition_Mobile(dlg, 0);
         destroy_Widget(dlg);
         return iTrue;
     }
@@ -3233,32 +3234,108 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) {
     return dlg;
 }
 
+/*----------------------------------------------------------------------------------------------*/
+
+static void siteSpecificThemeChanged_(const iWidget *dlg) {
+    iDocumentWidget *doc = document_App();
+    setThemeSeed_GmDocument((iGmDocument *) document_DocumentWidget(doc),
+                            urlPaletteSeed_String(url_DocumentWidget(doc)),
+                            urlThemeSeed_String(url_DocumentWidget(doc)));
+    postCommand_App("theme.changed");    
+}
+
+static const iString *siteSpecificRoot_(const iWidget *dlg) {
+    return collect_String(suffix_Command(cstr_String(id_Widget(dlg)), "site"));
+}
+
+static void updateSiteSpecificTheme_(iInputWidget *palSeed, void *context) {
+    iWidget *dlg = context;
+    const iString *siteRoot = siteSpecificRoot_(dlg);
+    setValueString_SiteSpec(siteRoot, paletteSeed_SiteSpecKey, text_InputWidget(palSeed));
+    siteSpecificThemeChanged_(dlg);
+    /* Allow seeing the new theme. */
+    setFlags_Widget(dlg, noFadeBackground_WidgetFlag, iTrue);
+}
+
+static void closeSiteSpecific_(iWidget *dlg) {
+    setupSheetTransition_Mobile(dlg, 0);
+    delete_String(userData_Object(dlg)); /* saved original palette seed */
+    destroy_Widget(dlg);
+}
+
+static iBool siteSpecificSettingsHandler_(iWidget *dlg, const char *cmd) {
+    if (equal_Command(cmd, "cancel")) {
+        iInputWidget *palSeed = findChild_Widget(dlg, "sitespec.palette");
+        setText_InputWidget(palSeed, userData_Object(dlg));
+        updateSiteSpecificTheme_(palSeed, dlg);
+        closeSiteSpecific_(dlg);
+        return iTrue;
+    }
+    if (startsWith_CStr(cmd, "input.ended id:sitespec.palette")) {
+        setFlags_Widget(dlg, noFadeBackground_WidgetFlag, iFalse);
+        refresh_Widget(dlg);
+        siteSpecificThemeChanged_(dlg);
+        return iTrue;
+    }
+    if (equal_Command(cmd, "sitespec.accept")) {
+        const iInputWidget *palSeed   = findChild_Widget(dlg, "sitespec.palette");
+        const iBool         warnAnsi  = isSelected_Widget(findChild_Widget(dlg, "sitespec.ansi"));
+        const iString      *siteRoot  = siteSpecificRoot_(dlg);
+        int                 dismissed = value_SiteSpec(siteRoot, dismissWarnings_SiteSpecKey);
+        iChangeFlags(dismissed, ansiEscapes_GmDocumentWarning, !warnAnsi);
+        setValue_SiteSpec(siteRoot, dismissWarnings_SiteSpecKey, dismissed);
+        setValueString_SiteSpec(siteRoot, paletteSeed_SiteSpecKey, text_InputWidget(palSeed));
+        siteSpecificThemeChanged_(dlg);
+        /* Note: The active DocumentWidget may actually be different than when opening the dialog. */
+        closeSiteSpecific_(dlg);
+        return iTrue;
+    }
+    return iFalse;
+}
+
 iWidget *makeSiteSpecificSettings_Widget(const iString *url) {
     iWidget *dlg;
     const iMenuItem actions[] = {
-        { "${cancel}" }, { "${sitespec.accept}", SDLK_RETURN, KMOD_PRIMARY, "sitespec.accept" }
+        { "${cancel}" },
+        { "${sitespec.accept}", SDLK_RETURN, KMOD_PRIMARY, "sitespec.accept" }
     };
     if (isUsingPanelLayout_Mobile()) {
         iAssert(iFalse);
     }
     else {
         iWidget *headings, *values;
-        dlg = makeSheet_Widget("sitespec");
+        dlg = makeSheet_Widget(format_CStr("sitespec site:%s", cstr_Rangecc(urlRoot_String(url))));
         addDialogTitle_(dlg, "${heading.sitespec}", "heading.sitespec");
         addChild_Widget(dlg, iClob(makeTwoColumns_Widget(&headings, &values)));
+        iInputWidget *palSeed = new_InputWidget(0);
+        setHint_InputWidget(palSeed, cstr_Block(urlThemeSeed_String(url)));
+        addPrefsInputWithHeading_(headings, values, "sitespec.palette", iClob(palSeed));
         addDialogToggle_(headings, values, "${sitespec.ansi}", "sitespec.ansi");
-        iInputWidget *palInput = new_InputWidget(0);
-        addPrefsInputWithHeading_(headings, values, "sitespec.palette", iClob(palInput));
-        as_Widget(palInput)->rect.size.x = 80 * gap_UI;
-        addChild_Widget(dlg, iClob(makeDialogButtons_Widget(actions, iElemCount(actions))));
+        addChild_Widget(dlg, iClob(makeDialogButtons_Widget(actions, iElemCount(actions))));        
+        addChild_Widget(get_Root()->widget, iClob(dlg));
+        as_Widget(palSeed)->rect.size.x = 60 * gap_UI;
+        arrange_Widget(dlg);
     }
     /* Initialize. */ {
-        const iRangecc root = urlRoot_String(url);
-        
+        const iString *site = collectNewRange_String(urlRoot_String(url));
+        setToggle_Widget(findChild_Widget(dlg, "sitespec.ansi"),
+                         ~value_SiteSpec(site, dismissWarnings_SiteSpecKey) & ansiEscapes_GmDocumentWarning);
+        setText_InputWidget(findChild_Widget(dlg, "sitespec.palette"),
+                            valueString_SiteSpec(site, paletteSeed_SiteSpecKey));
+        /* Keep a copy of the original palette seed for restoring on cancel. */
+        setUserData_Object(dlg, copy_String(valueString_SiteSpec(site, paletteSeed_SiteSpecKey)));
+        if (!isUsingPanelLayout_Mobile()) {
+            setValidator_InputWidget(findChild_Widget(dlg, "sitespec.palette"),
+                                     updateSiteSpecificTheme_, dlg);
+        }        
     }
+    setCommandHandler_Widget(dlg, siteSpecificSettingsHandler_);
+    setupSheetTransition_Mobile(dlg, incoming_TransitionFlag);
     return dlg;
 }
 
+/*----------------------------------------------------------------------------------------------*/
+
 iWidget *makeIdentityCreation_Widget(void) {
     const iMenuItem actions[] = { { "${dlg.newident.more}", 0, 0, "ident.showmore" },
                                   { "---" },
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.11/cdiff/e455699fca461e7e73d920a9ebfe557c20a67f98
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
30.969333 milliseconds
Gemini-to-HTML Time
0.40798 milliseconds

This content has been proxied by September (ba2dc).