Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch shift-enter-preview Excluding Merge-Ins
This is equivalent to a diff from 70cae0a9 to 895ecf9e
2023-12-22
| ||
14:32 | Add option to disable the shift-enter preview hotkey in /wikiedit, /fileedit, and /chat as a workaround for software keyboards which report the shift key being pressed when auto-capitalizing text, per discussion in forum post dbd5b68366147ce8. (check-in: 4bb5515c user: stephan tags: trunk) | |
14:27 | Remove the write-perms check from the /ajax/preview-text route so that folks without checkin permissions can use /chat. Problem reported in forum post ed4a762b3a557898. Some code-adjacent end-of-line whitespace cleanups. (check-in: 0c6e669a user: stephan tags: trunk) | |
2023-12-16
| ||
01:39 | Add the shift-enter toggle config option to /chat, sharing the same persistent config key as /wikiedit and /fileedit. (Closed-Leaf check-in: 895ecf9e user: stephan tags: shift-enter-preview) | |
01:10 | In /wikiedit and /fileedit, add a checkbox to disable shift-enter for toggling preview, as per discussion in forum post dbd5b68366147ce8. (check-in: 8c1c4fa9 user: stephan tags: shift-enter-preview) | |
2023-12-14
| ||
17:24 | Update the built-in SQLite to the latest trunk version that is destined to become 3.45.0 someday. This is beta-testing for SQLite. (check-in: 70cae0a9 user: drh tags: trunk) | |
16:29 | Improve "whatis" output when in "filename" mode and parse supported whatis options when using "fossil all whatis". (check-in: e1e9da26 user: mgagnon tags: trunk) | |
Changes to src/fileedit.c.
︙ | ︙ | |||
1696 1697 1698 1699 1700 1701 1702 | "data-tab-parent='fileedit-tabs' " "data-tab-label='File Selection' " "class='hidden'" ">"); CX("<div id='fileedit-file-selector'></div>"); CX("</div>"/*#fileedit-tab-fileselect*/); } | | > | > | 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 | "data-tab-parent='fileedit-tabs' " "data-tab-label='File Selection' " "class='hidden'" ">"); CX("<div id='fileedit-file-selector'></div>"); CX("</div>"/*#fileedit-tab-fileselect*/); } /******* Content tab *******/ { CX("<div id='fileedit-tab-content' " "data-tab-parent='fileedit-tabs' " "data-tab-label='File Content' " "class='hidden'" ">"); CX("<div class='fileedit-options flex-container " "flex-row child-gap-small'>"); CX("<div class='input-with-label'>" "<button class='fileedit-content-reload confirmer' " ">Discard & Reload</button>" "<div class='help-buttonlet'>" "Reload the file from the server, discarding " "any local edits. To help avoid accidental loss of " "edits, it requires confirmation (a second click) within " "a few seconds or it will not reload." "</div>" "</div>"); style_select_list_int("select-font-size", "editor_font_size", "Editor font size", NULL/*tooltip*/, 100, "100%", 100, "125%", 125, "150%", 150, "175%", 175, "200%", 200, NULL); wikiedit_emit_toggle_preview(); CX("</div>"); CX("<div class='flex-container flex-column stretch'>"); CX("<textarea name='content' id='fileedit-content-editor' " "class='fileedit' rows='25'>"); CX("</textarea>"); CX("</div>"/*textarea wrapper*/); CX("</div>"/*#tab-file-content*/); |
︙ | ︙ |
Changes to src/fossil.page.chat.js.
1 2 | /** This file contains the client-side implementation of fossil's /chat | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** This file contains the client-side implementation of fossil's /chat application. */ window.fossil.onPageLoad(function(){ const F = window.fossil, D = F.dom; const E1 = function(selector){ const e = document.querySelector(selector); if(!e) throw new Error("missing required DOM element: "+selector); return e; }; /** Returns true if e is entirely within the bounds of the window's viewport. */ const isEntirelyInViewport = function(e) { const rect = e.getBoundingClientRect(); return ( rect.top >= 0 && |
︙ | ︙ | |||
394 395 396 397 398 399 400 401 402 403 404 405 406 407 | ctrl-enter both send them. */ "edit-ctrl-send": false, /* When on, the edit field starts as a single line and expands as the user types, and the relevant buttons are laid out in a compact form. When off, the edit field and buttons are larger. */ "edit-compact-mode": true, /* When on, sets the font-family on messages and the edit field to monospace. */ "monospace-messages": false, /* When on, non-chat UI elements (page header/footer) are hidden */ "chat-only-mode": false, /* When set to a URI, it is assumed to be an audio file, | > > > > > | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | ctrl-enter both send them. */ "edit-ctrl-send": false, /* When on, the edit field starts as a single line and expands as the user types, and the relevant buttons are laid out in a compact form. When off, the edit field and buttons are larger. */ "edit-compact-mode": true, /* See notes for this setting in fossil.page.wikiedit.js. Both /wikiedit and /fileedit share this persistent config option under the same storage key. */ "edit-shift-enter-preview": F.storage.getBool('edit-shift-enter-preview', true), /* When on, sets the font-family on messages and the edit field to monospace. */ "monospace-messages": false, /* When on, non-chat UI elements (page header/footer) are hidden */ "chat-only-mode": false, /* When set to a URI, it is assumed to be an audio file, |
︙ | ︙ | |||
1497 1498 1499 1500 1501 1502 1503 | /* Shift-enter will run preview mode UNLESS preview mode is active AND the input field is empty, in which case it will switch back to message view. */ if(Chat.e.currentView===Chat.e.viewPreview && !text){ Chat.setCurrentView(Chat.e.viewMessages); }else if(!text){ f.$toggleCompact(compactMode); | | | | | 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 | /* Shift-enter will run preview mode UNLESS preview mode is active AND the input field is empty, in which case it will switch back to message view. */ if(Chat.e.currentView===Chat.e.viewPreview && !text){ Chat.setCurrentView(Chat.e.viewMessages); }else if(!text){ f.$toggleCompact(compactMode); }else if(Chat.settings.getBool('edit-shift-enter-preview', true)){ Chat.e.btnPreview.click(); } return false; } if(ev.ctrlKey && !text && !BlobXferState.blob){ /* Ctrl-enter on empty input field(s) toggles Enter/Ctrl-enter mode */ ev.preventDefault(); ev.stopPropagation(); f.$toggleCtrl(ctrlMode); return false; } if(!ctrlMode && ev.ctrlKey && text){ //console.debug("!ctrlMode && ev.ctrlKey && text."); /* Ctrl-enter in Enter-sends mode SHOULD, with this logic add a newline, but that is not happening, for unknown reasons (possibly related to this element being a contenteditable DIV instead of a textarea). Forcibly appending a newline do the input area does not work, also for unknown reasons, and would only be suitable when we're at the end of the input. Strangely, this approach DOES work for shift-enter, but we need shift-enter as a hotkey for preview mode. */ //return; // return here "should" cause newline to be added, but that doesn't work } if((!ctrlMode && !ev.ctrlKey) || (ev.ctrlKey/* && ctrlMode*/)){ /* Ship it! */ ev.preventDefault(); ev.stopPropagation(); Chat.submitMessage(); return false; } }; Chat.e.inputFields.forEach( (e)=>e.addEventListener('keydown', inputWidgetKeydown, false) ); Chat.e.btnSubmit.addEventListener('click',(e)=>{ e.preventDefault(); Chat.submitMessage(); return false; |
︙ | ︙ | |||
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 | boolValue: 'edit-widget-x', hint: [ "When enabled, chat input uses a so-called 'contenteditable' ", "field. Though generally more comfortable and modern than ", "plain-text input fields, browser-specific quirks and bugs ", "may lead to frustration. Ideal for mobile devices." ].join('') }] },{ label: "Appearance Options...", children:[{ label: "Left-align my posts", hint: "Default alignment of your own messages is selected " + "based window width/height ratio.", | > > > > > > > | 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 | boolValue: 'edit-widget-x', hint: [ "When enabled, chat input uses a so-called 'contenteditable' ", "field. Though generally more comfortable and modern than ", "plain-text input fields, browser-specific quirks and bugs ", "may lead to frustration. Ideal for mobile devices." ].join('') },{ label: "Shift-enter to preview", hint: ["Use shift-enter to preview being-edited messages. ", "This is normally desirable but some software-mode ", "keyboards misinteract with this, in which cases it can be ", "disabled."], boolValue: 'edit-shift-enter-preview' }] },{ label: "Appearance Options...", children:[{ label: "Left-align my posts", hint: "Default alignment of your own messages is selected " + "based window width/height ratio.", |
︙ | ︙ |
Changes to src/fossil.page.fileedit.js.
︙ | ︙ | |||
68 69 70 71 72 73 74 | ); */ const E = (s)=>document.querySelector(s), D = F.dom, P = F.page; P.config = { | | > > > > > > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | ); */ const E = (s)=>document.querySelector(s), D = F.dom, P = F.page; P.config = { defaultMaxStashSize: 7, /** See notes for this setting in fossil.page.wikiedit.js. Both /wikiedit and /fileedit share this persistent config option under the same storage key. */ shiftEnterPreview: F.storage.getBool('edit-shift-enter-preview', true) }; /** $stash is an internal-use-only object for managing "stashed" local edits, to help avoid that users accidentally lose content by switching tabs or following links or some such. The basic theory of operation is... |
︙ | ︙ | |||
722 723 724 725 726 727 728 | } } ); //////////////////////////////////////////////////////////// // Trigger preview on Ctrl-Enter. This only works on the built-in // editor widget, not a client-provided one. P.e.taEditor.addEventListener('keydown',function(ev){ | | | 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | } } ); //////////////////////////////////////////////////////////// // Trigger preview on Ctrl-Enter. This only works on the built-in // editor widget, not a client-provided one. P.e.taEditor.addEventListener('keydown',function(ev){ if(P.config.shiftEnterPreview && ev.shiftKey && 13===ev.keyCode){ ev.preventDefault(); ev.stopPropagation(); P.e.taEditor.blur(/*force change event, if needed*/); P.tabs.switchToTab(P.e.tabs.preview); if(!P.e.cbAutoPreview.checked){/* If NOT in auto-preview mode, trigger an update. */ P.preview(); } |
︙ | ︙ | |||
843 844 845 846 847 848 849 850 851 852 853 854 855 856 | } ); P.fileSelectWidget.init(); P.stashWidget.init( P.e.tabs.content.lastElementChild ); }/*F.onPageLoad()*/); /** Getter (if called with no args) or setter (if passed an arg) for the current file content. The setter form sets the content, dispatches a | > > > > > > > | 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | } ); P.fileSelectWidget.init(); P.stashWidget.init( P.e.tabs.content.lastElementChild ); const cbEditPreview = E('#edit-shift-enter-preview'); cbEditPreview.addEventListener('change', function(e){ F.storage.set('edit-shift-enter-preview', P.config.shiftEnterPreview = e.target.checked); }, false); cbEditPreview.checked = P.config.shiftEnterPreview; }/*F.onPageLoad()*/); /** Getter (if called with no args) or setter (if passed an arg) for the current file content. The setter form sets the content, dispatches a |
︙ | ︙ |
Changes to src/fossil.page.wikiedit.js.
︙ | ︙ | |||
73 74 75 76 77 78 79 | useConfirmerButtons:{ /* If true during fossil.page setup, certain buttons will use a "confirmer" step, else they will not. The confirmer topic has been the source of much contention in the forum. */ save: false, reload: true, discardStash: true | > > > > > > > | > > > > > > | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | useConfirmerButtons:{ /* If true during fossil.page setup, certain buttons will use a "confirmer" step, else they will not. The confirmer topic has been the source of much contention in the forum. */ save: false, reload: true, discardStash: true }, /** If true, a keyboard combo of shift-enter (from the editor) toggles between preview and edit modes. This is normally desired but at least one software keyboard is known to misinteract with this, treating an Enter after automatically-capitalized letters as a shift-enter: https://fossil-scm.org/forum/forumpost/dbd5b68366147ce8 Maintenance note: /fileedit also uses this same key for the same purpose. */ shiftEnterPreview: F.storage.getBool('edit-shift-enter-preview', true) }; /** $stash is an internal-use-only object for managing "stashed" local edits, to help avoid that users accidentally lose content by switching tabs or following links or some such. The basic theory of operation is... |
︙ | ︙ | |||
452 453 454 455 456 457 458 | opt.dataset.isDeleted = true; } self._refreshStashMarks(opt); }); D.enable(sel); if(P.winfo) sel.value = P.winfo.name; }, | | | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | opt.dataset.isDeleted = true; } self._refreshStashMarks(opt); }); D.enable(sel); if(P.winfo) sel.value = P.winfo.name; }, /** Loads the page list and populates the selection list. */ loadList: function callee(){ if(!callee.onload){ const self = this; callee.onload = function(list){ self.cache.pageList = list; self._rebuildList(); |
︙ | ︙ | |||
649 650 651 652 653 654 655 | }, false); D.append( parentElem, D.append(D.addClass(D.div(), 'fieldset-wrapper'), fsFilter, fsNewPage, fsLegend) ); | | | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | }, false); D.append( parentElem, D.append(D.addClass(D.div(), 'fieldset-wrapper'), fsFilter, fsNewPage, fsLegend) ); D.append(parentElem, btn); btn.addEventListener('click', ()=>this.loadList(), false); this.loadList(); const onSelect = (e)=>P.loadPage(e.target.value); sel.addEventListener('change', onSelect, false); sel.addEventListener('dblclick', onSelect, false); F.page.addEventListener('wiki-stash-updated', ()=>{ |
︙ | ︙ | |||
672 673 674 675 676 677 678 679 | if(page.isEmpty) opt.dataset.isDeleted = true; else delete opt.dataset.isDeleted; self._refreshStashMarks(opt); }else if('sandbox'!==page.type){ F.error("BUG: internal mis-handling of page object: missing OPTION for page "+page.name); } }); delete this.init; | > > > > > > > | | 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | if(page.isEmpty) opt.dataset.isDeleted = true; else delete opt.dataset.isDeleted; self._refreshStashMarks(opt); }else if('sandbox'!==page.type){ F.error("BUG: internal mis-handling of page object: missing OPTION for page "+page.name); } }); const cbEditPreview = E('#edit-shift-enter-preview'); cbEditPreview.addEventListener('change', function(e){ F.storage.set('edit-shift-enter-preview', P.config.shiftEnterPreview = e.target.checked); }, false); cbEditPreview.checked = P.config.shiftEnterPreview; delete this.init; }/*init()*/ }; /** Widget for listing and selecting $stash entries. */ P.stashWidget = { e:{/*DOM element(s)*/}, |
︙ | ︙ | |||
912 913 914 915 916 917 918 | } } ); //////////////////////////////////////////////////////////// // Trigger preview on Ctrl-Enter. This only works on the built-in // editor widget, not a client-provided one. P.e.taEditor.addEventListener('keydown',function(ev){ | | | 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 | } } ); //////////////////////////////////////////////////////////// // Trigger preview on Ctrl-Enter. This only works on the built-in // editor widget, not a client-provided one. P.e.taEditor.addEventListener('keydown',function(ev){ if(P.config.shiftEnterPreview && ev.shiftKey && 13===ev.keyCode){ ev.preventDefault(); ev.stopPropagation(); P.e.taEditor.blur(/*force change event, if needed*/); P.tabs.switchToTab(P.e.tabs.preview); if(!P.e.cbAutoPreview.checked){/* If NOT in auto-preview mode, trigger an update. */ P.preview(); } |
︙ | ︙ |
Changes to src/style.fileedit.css.
︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | overflow: auto; } body.fileedit #fileedit-tab-preview-wrapper > pre { margin: 0; } body.fileedit #fileedit-tab-fileselect > h1 { margin: 0; } body.fileedit .fileedit-options.commit-message > div { display: flex; flex-direction: column; align-items: stretch; font-family: monospace; } | > > > | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | overflow: auto; } body.fileedit #fileedit-tab-preview-wrapper > pre { margin: 0; } body.fileedit #fileedit-tab-fileselect > h1 { margin: 0; } body.fileedit .fileedit-options > div > * { margin: 0.25em; } body.fileedit .fileedit-options.commit-message > div { display: flex; flex-direction: column; align-items: stretch; font-family: monospace; } |
︙ | ︙ | |||
103 104 105 106 107 108 109 | margin: 0.5em; } body.fileedit .tab-container > .tabs > .tab-panel > .fileedit-options > input { vertical-align: middle; margin: 0.5em; } body.fileedit .tab-container > .tabs > .tab-panel > .fileedit-options > .input-with-label { | < | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | margin: 0.5em; } body.fileedit .tab-container > .tabs > .tab-panel > .fileedit-options > input { vertical-align: middle; margin: 0.5em; } body.fileedit .tab-container > .tabs > .tab-panel > .fileedit-options > .input-with-label { margin: 0 0.5em 0.25em 0.5em; } body.fileedit .fileedit-options > div > * { margin: 0.25em; } body.fileedit .fileedit-options.flex-container.flex-row { align-items: first baseline; } |
︙ | ︙ |
Changes to src/style.wikiedit.css.
︙ | ︙ | |||
41 42 43 44 45 46 47 | margin: 0.5em; } body.wikiedit .tab-container > .tabs > .tab-panel > .wikiedit-options > input { vertical-align: middle; margin: 0.5em; } body.wikiedit .tab-container > .tabs > .tab-panel > .wikiedit-options > .input-with-label { | < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | margin: 0.5em; } body.wikiedit .tab-container > .tabs > .tab-panel > .wikiedit-options > input { vertical-align: middle; margin: 0.5em; } body.wikiedit .tab-container > .tabs > .tab-panel > .wikiedit-options > .input-with-label { margin: 0 0.5em 0.25em 0.5em; } body.wikiedit label { display: inline; /* some skins set label display to block! */ } body.wikiedit .wikiedit-options > div > * { margin: 0.25em; |
︙ | ︙ |
Changes to src/wiki.c.
︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 | "CSRF violation (make sure sending of HTTP " "Referer headers is enabled for XHR " "connections)."); return; } pRoute->xCallback(); } /* ** WEBPAGE: wikiedit ** URL: /wikedit?name=PAGENAME ** ** The main front-end for the Ajax-based wiki editor app. Passing ** in the name of an unknown page will trigger the creation | > > > > > > > > > > > > > > > > | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 | "CSRF violation (make sure sending of HTTP " "Referer headers is enabled for XHR " "connections)."); return; } pRoute->xCallback(); } /* ** Emits a preview-toggle option widget for /wikiedit and /fileedit. */ void wikiedit_emit_toggle_preview(void){ CX("<div class='input-with-label'>" "<input type='checkbox' id='edit-shift-enter-preview' " "></input><label for='edit-shift-enter-preview'>" "Shift-enter previews</label>" "<div class='help-buttonlet'>" "When enabled, shift-enter switches between preview and edit modes. " "Some software-based keyboards misinteract with this, so it can be " "disabled when needed." "</div>" "</div>"); } /* ** WEBPAGE: wikiedit ** URL: /wikedit?name=PAGENAME ** ** The main front-end for the Ajax-based wiki editor app. Passing ** in the name of an unknown page will trigger the creation |
︙ | ︙ | |||
1309 1310 1311 1312 1313 1314 1315 | "Status messages will go here.</div>\n" /* will be moved into the tab container via JS */); CX("<div id='wikiedit-edit-status''>" "<span class='name'></span>" "<span class='links'></span>" "</div>"); | | | 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 | "Status messages will go here.</div>\n" /* will be moved into the tab container via JS */); CX("<div id='wikiedit-edit-status''>" "<span class='name'></span>" "<span class='links'></span>" "</div>"); /* Main tab container... */ CX("<div id='wikiedit-tabs' class='tab-container'>Loading...</div>"); /* The .hidden class on the following tab elements is to help lessen the FOUC effect of the tabs before JS re-assembles them. */ /******* Page list *******/ { |
︙ | ︙ | |||
1369 1370 1371 1372 1373 1374 1375 | "<div class='help-buttonlet'>" "Reload the file from the server, discarding " "any local edits. To help avoid accidental loss of " "edits, it requires confirmation (a second click) within " "a few seconds or it will not reload." "</div>" "</div>"); | | | 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 | "<div class='help-buttonlet'>" "Reload the file from the server, discarding " "any local edits. To help avoid accidental loss of " "edits, it requires confirmation (a second click) within " "a few seconds or it will not reload." "</div>" "</div>"); wikiedit_emit_toggle_preview(); CX("</div>"); CX("<div class='flex-container flex-column stretch'>"); CX("<textarea name='content' id='wikiedit-content-editor' " "class='wikiedit' rows='25'>"); CX("</textarea>"); CX("</div>"/*textarea wrapper*/); CX("</div>"/*#tab-file-content*/); |
︙ | ︙ |