Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Forcibly disable drop support in the new editor widget, as the browser will otherwise allow the user to drop images to it, which is confusing and does not work with our ability to upload images. Found a way to implement placeholder text in the contenteditable field. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | chat-input-rework |
| Files: | files | file ages | folders |
| SHA3-256: |
86d6be3fe212ad50b0d51124712ac8a6 |
| User & Date: | stephan 2021-09-30 19:32:25.977 |
Context
|
2021-09-30
| ||
| 19:56 | Re-enabled ctrl-enter-sends when enter-sends mode is active (was disabled during testing). Update the tooltip on the send button to reflect the current send mode. ... (check-in: 7d6c07496e user: stephan tags: chat-input-rework) | |
| 19:32 | Forcibly disable drop support in the new editor widget, as the browser will otherwise allow the user to drop images to it, which is confusing and does not work with our ability to upload images. Found a way to implement placeholder text in the contenteditable field. ... (check-in: 86d6be3fe2 user: stephan tags: chat-input-rework) | |
| 17:24 | Minor restructuring and docs in the enter/ctrl-enter handling. Trying to get ctrl-enter to add newlines when in enter-sends mode, but it's not working for reasons beyond my ken. ... (check-in: ab9fef759e user: stephan tags: chat-input-rework) | |
Changes
Changes to src/chat.c.
| ︙ | ︙ | |||
140 141 142 143 144 145 146 |
**
** Other /chat-OP pages are used by XHR requests from this page to
** send new chat message, delete older messages, or poll for changes.
*/
void chat_webpage(void){
char *zAlert;
char *zProjectName;
| < < > | | | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
**
** Other /chat-OP pages are used by XHR requests from this page to
** send new chat message, delete older messages, or poll for changes.
*/
void chat_webpage(void){
char *zAlert;
char *zProjectName;
char * zInputPlaceholder0; /* Common text input placeholder value */
login_check_credentials();
if( !g.perm.Chat ){
login_needed(g.anon.Chat);
return;
}
zAlert = mprintf("%s/builtin/%s", g.zBaseURL,
db_get("chat-alert-sound","alerts/plunk.wav"));
zProjectName = db_get("project-name","Unnamed project");
zInputPlaceholder0 =
mprintf("Type markdown-formatted message for %h.", zProjectName);
style_set_current_feature("chat");
style_header("Chat");
@ <div id='chat-input-area'>
@ <div id='chat-input-line' class='single-line'>
@ <div contenteditable id="chat-input-field" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class=""></div>
@ <div id='chat-edit-buttons'>
@ <button id="chat-preview-button" \
@ title="Preview message (Shift-Enter)">👁</button>
@ <button id="chat-settings-button" \
@ title="Configure chat">⚙</button>
@ <button id="chat-message-submit" \
@ title="Send message (Ctrl-Enter)">📤</button>
|
| ︙ | ︙ |
Changes to src/fossil.page.chat.js.
| ︙ | ︙ | |||
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 |
drop: function(ev){
D.removeClass(dropHighlight, 'dragover');
},
dragenter: function(ev){
ev.preventDefault();
ev.dataTransfer.dropEffect = "copy";
D.addClass(dropHighlight, 'dragover');
},
dragleave: function(ev){
D.removeClass(dropHighlight, 'dragover');
},
dragend: function(ev){
D.removeClass(dropHighlight, 'dragover');
}
};
Object.keys(dropEvents).forEach(
| > > > > > > > > > > | > > | 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 |
drop: function(ev){
D.removeClass(dropHighlight, 'dragover');
},
dragenter: function(ev){
ev.preventDefault();
ev.dataTransfer.dropEffect = "copy";
D.addClass(dropHighlight, 'dragover');
return false;
},
dragleave: function(ev){
D.removeClass(dropHighlight, 'dragover');
},
dragend: function(ev){
D.removeClass(dropHighlight, 'dragover');
}
};
const cancelEvent = function(ev){
/* contenteditable tries to do its own thing with dropped data,
which is not compatible with how we use it, so... */
//if(ev.dataTransfer) ev.dataTransfer.dropEffect = 'none';
ev.preventDefault();
ev.stopPropagation();
return false;
};
Object.keys(dropEvents).forEach(
(k)=>{
Chat.e.inputFile.addEventListener(k, dropEvents[k], true);
Chat.inputElement().addEventListener(k, cancelEvent, false);
}
);
return bxs;
})()/*drag/drop*/;
const tzOffsetToString = function(off){
const hours = Math.round(off/60), min = Math.round(off % 30);
return ''+(hours + (min ? '.5' : ''));
|
| ︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 |
};
const inputWidgetKeydown = function f(ev){
if(!f.$toggleCtrl){
f.$toggleCtrl = function(currentMode){
currentMode = !currentMode;
Chat.settings.set('edit-ctrl-send', currentMode);
| < < < > < < < < < < < < < > > > > > > > > > > > > > > > | | 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 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 |
};
const inputWidgetKeydown = function f(ev){
if(!f.$toggleCtrl){
f.$toggleCtrl = function(currentMode){
currentMode = !currentMode;
Chat.settings.set('edit-ctrl-send', currentMode);
};
f.$toggleCompact = function(currentMode){
currentMode = !currentMode;
Chat.settings.set('edit-compact-mode', currentMode);
};
}
if(13 !== ev.keyCode) return;
const text = Chat.inputValue().trim();
const ctrlMode = Chat.settings.getBool('edit-ctrl-send', false);
//console.debug("Enter key event:", ctrlMode, ev.ctrlKey, ev.shiftKey, ev);
if(ev.shiftKey){
const compactMode = Chat.settings.getBool('edit-compact-mode', false);
ev.preventDefault();
ev.stopPropagation();
/* 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{
Chat.e.btnPreview.click();
}
return false;
}
if(ev.ctrlKey && !text){
/* Ctrl-enter on an empty field 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 conteneditable 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;
}
if((!ctrlMode && !ev.ctrlKey) || (ev.ctrlKey && ctrlMode)){
/* Ship it! */
ev.preventDefault();
ev.stopPropagation();
Chat.submitMessage();
return false;
}
};
|
| ︙ | ︙ | |||
1337 1338 1339 1340 1341 1342 1343 |
"blank lines. "+
"When off, both Enter and Ctrl-Enter send. "+
"When the input field has focus, is empty, and preview "+
"mode is NOT active then Ctrl-Enter toggles this setting.",
boolValue: 'edit-ctrl-send'
},{
label: "Compact mode",
| | | 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 |
"blank lines. "+
"When off, both Enter and Ctrl-Enter send. "+
"When the input field has focus, is empty, and preview "+
"mode is NOT active then Ctrl-Enter toggles this setting.",
boolValue: 'edit-ctrl-send'
},{
label: "Compact mode",
hint: "Toggle between a space-saving or more spacious writing area. "+
"When the input field has focus, is empty, and preview mode "+
"is NOT active then Shift-Enter toggles this setting.",
boolValue: 'edit-compact-mode'
},{
label: "Left-align my posts",
hint: "Default alignment of your own messages is selected "
+"based window width/height relationship.",
|
| ︙ | ︙ | |||
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 |
Chat.settings.addListener('chat-only-mode',function(s){
Chat.chatOnlyMode(s.value);
});
Chat.settings.addListener('edit-compact-mode',function(s){
Chat.e.inputLine.classList[
s.value ? 'add' : 'remove'
]('compact');
});
const valueKludges = {
/* Convert certain string-format values to other types... */
"false": false,
"true": true
};
Object.keys(Chat.settings.defaults).forEach(function(k){
| > > > > > > | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 |
Chat.settings.addListener('chat-only-mode',function(s){
Chat.chatOnlyMode(s.value);
});
Chat.settings.addListener('edit-compact-mode',function(s){
Chat.e.inputLine.classList[
s.value ? 'add' : 'remove'
]('compact');
});
Chat.settings.addListener('edit-ctrl-send',function(s){
const label = (s.value ? "Ctrl-" : "")+"Enter submits messages.";
const eInput = Chat.inputElement();
eInput.dataset.placeholder = eInput.dataset.placeholder0 + " " +label;
F.toast.message(label);
});
const valueKludges = {
/* Convert certain string-format values to other types... */
"false": false,
"true": true
};
Object.keys(Chat.settings.defaults).forEach(function(k){
|
| ︙ | ︙ |
Changes to src/style.chat.css.
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
padding: 0.25em 0.5em;
margin-top: 0;
min-width: 9em /*avoid unsightly "underlap" with the neighboring
.message-widget-tab element*/;
white-space: normal;
}
body.chat.monospace-messages .message-widget-content,
| | | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
padding: 0.25em 0.5em;
margin-top: 0;
min-width: 9em /*avoid unsightly "underlap" with the neighboring
.message-widget-tab element*/;
white-space: normal;
}
body.chat.monospace-messages .message-widget-content,
/*body.chat.monospace-messages textarea,*/
/*body.chat.monospace-messages input[type=text],*/
body.chat.monospace-messages #chat-input-field{
font-family: monospace;
}
body.chat .message-widget-content > * {
margin: 0;
padding: 0;
}
|
| ︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
body.chat:not(.chat-only-mode) #chat-input-area{
/* Safari user reports that 2em is necessary to keep the file selection
widget from overlapping the page footer, whereas a margin of 0 is fine
for FF/Chrome (and 2em is a *huge* waste of space for those). */
margin-bottom: 0;
}
#chat-input-field {
padding: 0.2em;
flex: 50 1 85%;
background-color: rgba(156,156,156,0.3);
overflow: auto;
max-height: 8rem /*arbitrary!*/;
}
#chat-input-field:not(:focus){
border-width: 1px;
border-style: solid;
border-radius: 0.25em;
}
#chat-input-field:focus{
| > > > > > > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
body.chat:not(.chat-only-mode) #chat-input-area{
/* Safari user reports that 2em is necessary to keep the file selection
widget from overlapping the page footer, whereas a margin of 0 is fine
for FF/Chrome (and 2em is a *huge* waste of space for those). */
margin-bottom: 0;
}
#chat-input-field {
display: inline-block/*supposed workaround for Chrome weirdness*/;
padding: 0.2em;
flex: 50 1 85%;
background-color: rgba(156,156,156,0.3);
overflow: auto;
max-height: 8rem /*arbitrary!*/;
/*white-space: pre-wrap;*/
}
#chat-input-field:empty::before {
content: attr(data-placeholder);
opacity: 0.6;
}
#chat-input-field:not(:focus){
border-width: 1px;
border-style: solid;
border-radius: 0.25em;
}
#chat-input-field:focus{
|
| ︙ | ︙ |