Fossil SCM
Split ctrl-enter/enter input modes and combat/spacious layout to two independent settings.
Commit
a83defad3a950b159631c275262624d5f6c94298658dbe55323776a0f673f07e
Parent
bcfb758dc38b434…
2 files changed
+61
-25
+7
-7
+61
-25
| --- src/fossil.page.chat.js | ||
| +++ src/fossil.page.chat.js | ||
| @@ -375,11 +375,12 @@ | ||
| 375 | 375 | if(ev.detail.key===setting) f(ev.detail); |
| 376 | 376 | }, false); |
| 377 | 377 | }, |
| 378 | 378 | defaults:{ |
| 379 | 379 | "images-inline": !!F.config.chat.imagesInline, |
| 380 | - "edit-multiline": false, | |
| 380 | + "edit-ctrl-send": false, | |
| 381 | + "edit-compact-mode": true, | |
| 381 | 382 | "monospace-messages": false, |
| 382 | 383 | "chat-only-mode": false, |
| 383 | 384 | "audible-alert": true, |
| 384 | 385 | "active-user-list": false, |
| 385 | 386 | "active-user-list-timestamps": false |
| @@ -1044,20 +1045,21 @@ | ||
| 1044 | 1045 | }; |
| 1045 | 1046 | /** Updates the paste/drop zone with details of the pasted/dropped |
| 1046 | 1047 | data. The argument must be a Blob or Blob-like object (File) or |
| 1047 | 1048 | it can be falsy to reset/clear that state.*/ |
| 1048 | 1049 | const updateDropZoneContent = function(blob){ |
| 1050 | + console.debug("updateDropZoneContent()",blob); | |
| 1049 | 1051 | const dd = bxs.dropDetails; |
| 1050 | 1052 | bxs.blob = blob; |
| 1051 | 1053 | D.clearElement(dd); |
| 1052 | 1054 | if(!blob){ |
| 1053 | 1055 | Chat.e.inputFile.value = ''; |
| 1054 | 1056 | return; |
| 1055 | 1057 | } |
| 1056 | 1058 | D.append(dd, "Name: ", blob.name, |
| 1057 | 1059 | D.br(), "Size: ",blob.size); |
| 1058 | - if(blob.type && blob.type.startsWith("image/")){ | |
| 1060 | + if(blob.type && (blob.type.startsWith("image/") || blob.type==='BITMAP')){ | |
| 1059 | 1061 | const img = D.img(); |
| 1060 | 1062 | D.append(dd, D.br(), img); |
| 1061 | 1063 | const reader = new FileReader(); |
| 1062 | 1064 | reader.onload = (e)=>img.setAttribute('src', e.target.result); |
| 1063 | 1065 | reader.readAsDataURL(blob); |
| @@ -1070,19 +1072,39 @@ | ||
| 1070 | 1072 | updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined) |
| 1071 | 1073 | }); |
| 1072 | 1074 | /* Handle image paste from clipboard. TODO: figure out how we can |
| 1073 | 1075 | paste non-image binary data as if it had been selected via the |
| 1074 | 1076 | file selection element. */ |
| 1075 | - document.addEventListener('paste', function(event){ | |
| 1077 | + const pasteListener = function(event){ | |
| 1076 | 1078 | const items = event.clipboardData.items, |
| 1077 | 1079 | item = items[0]; |
| 1078 | - if(!item || !item.type) return; | |
| 1079 | - else if('file'===item.kind){ | |
| 1080 | + //console.debug("paste event",event.target,item,event); | |
| 1081 | + //console.debug("paste event item",item); | |
| 1082 | + if(item && item.type && ('file'===item.kind || 'BITMAP'===item.type)){ | |
| 1080 | 1083 | updateDropZoneContent(false/*clear prev state*/); |
| 1081 | 1084 | updateDropZoneContent(item.getAsFile()); |
| 1085 | + event.stopPropagation(); | |
| 1086 | + event.preventDefault(true); | |
| 1087 | + return false; | |
| 1082 | 1088 | } |
| 1083 | - }, false); | |
| 1089 | + /* else continue propagating */ | |
| 1090 | + }; | |
| 1091 | + document.addEventListener('paste', pasteListener, true); | |
| 1092 | + if(0){ | |
| 1093 | + const onPastePlainText = function(ev){ | |
| 1094 | + var pastedText = undefined; | |
| 1095 | + if (window.clipboardData && window.clipboardData.getData) { // IE | |
| 1096 | + pastedText = window.clipboardData.getData('Text'); | |
| 1097 | + }else if (ev.clipboardData && ev.clipboardData.getData) { | |
| 1098 | + pastedText = ev.clipboardData.getData('text/plain'); | |
| 1099 | + } | |
| 1100 | + ev.target.textContent += pastedText; | |
| 1101 | + ev.preventDefault(); | |
| 1102 | + return false; | |
| 1103 | + }; | |
| 1104 | + Chat.e.inputField.addEventListener('paste', onPastePlainText, false); | |
| 1105 | + } | |
| 1084 | 1106 | /* Add help button for drag/drop/paste zone */ |
| 1085 | 1107 | Chat.e.inputFile.parentNode.insertBefore( |
| 1086 | 1108 | F.helpButtonlets.create( |
| 1087 | 1109 | Chat.e.fileSelectWrapper.querySelector('.help-buttonlet') |
| 1088 | 1110 | ), Chat.e.inputFile |
| @@ -1170,36 +1192,45 @@ | ||
| 1170 | 1192 | BlobXferState.clear(); |
| 1171 | 1193 | Chat.inputValue("").inputFocus(); |
| 1172 | 1194 | }; |
| 1173 | 1195 | |
| 1174 | 1196 | const inputWidgetKeydown = function f(ev){ |
| 1175 | - if(!f.$toggle){ | |
| 1176 | - f.$toggle = function(currentMode){ | |
| 1197 | + if(!f.$toggleCtrl){ | |
| 1198 | + f.$toggleCtrl = function(currentMode){ | |
| 1199 | + currentMode = !currentMode; | |
| 1200 | + Chat.settings.set('edit-ctrl-send', currentMode); | |
| 1201 | + }; | |
| 1202 | + f.$toggleCompact = function(currentMode){ | |
| 1177 | 1203 | currentMode = !currentMode; |
| 1178 | - Chat.settings.set('edit-multiline', currentMode); | |
| 1204 | + Chat.settings.set('edit-compact-mode', currentMode); | |
| 1179 | 1205 | }; |
| 1180 | 1206 | } |
| 1181 | 1207 | if(13 === ev.keyCode){ |
| 1182 | - const multi = Chat.settings.getBool('edit-multiline', false); | |
| 1208 | + const ctrlMode = Chat.settings.getBool('edit-ctrl-send', false); | |
| 1183 | 1209 | if(ev.shiftKey){ |
| 1210 | + const compactMode = Chat.settings.getBool('edit-compact-mode', false); | |
| 1184 | 1211 | ev.preventDefault(); |
| 1185 | 1212 | ev.stopPropagation(); |
| 1186 | 1213 | /* Shift-enter will run preview mode UNLESS preview mode is |
| 1187 | 1214 | active AND the input field is empty, in which case it will |
| 1188 | 1215 | switch back to message view. */ |
| 1189 | 1216 | const text = Chat.inputValue().trim(); |
| 1190 | - if(Chat.e.currentView===Chat.e.viewPreview && !text) Chat.setCurrentView(Chat.e.viewMessages); | |
| 1191 | - else if(!text) f.$toggle(multi); | |
| 1217 | + if(Chat.e.currentView===Chat.e.viewPreview && !text){ | |
| 1218 | + Chat.setCurrentView(Chat.e.viewMessages); | |
| 1219 | + } | |
| 1220 | + else if(!text){ | |
| 1221 | + f.$toggleCompact(compactMode); | |
| 1222 | + } | |
| 1192 | 1223 | else Chat.e.btnPreview.click(); |
| 1193 | 1224 | return false; |
| 1194 | - }else if(!multi || (ev.ctrlKey && multi)){ | |
| 1225 | + }else if(!ctrlMode || (ev.ctrlKey && ctrlMode)){ | |
| 1195 | 1226 | /* ^^^ note that it is intended that both ctrl-enter and enter |
| 1196 | - work for single-line input mode. */ | |
| 1227 | + work for compact input mode. */ | |
| 1197 | 1228 | ev.preventDefault(); |
| 1198 | 1229 | ev.stopPropagation(); |
| 1199 | 1230 | const text = Chat.inputValue().trim(); |
| 1200 | - if(!text) f.$toggle(multi); | |
| 1231 | + if(!text) f.$toggleCtrl(ctrlMode); | |
| 1201 | 1232 | else Chat.submitMessage(); |
| 1202 | 1233 | return false; |
| 1203 | 1234 | } |
| 1204 | 1235 | } |
| 1205 | 1236 | }; |
| @@ -1277,17 +1308,22 @@ | ||
| 1277 | 1308 | sync with external changes to that setting. Various Chat UI |
| 1278 | 1309 | elements stay in sync with the config UI via those settings |
| 1279 | 1310 | events. |
| 1280 | 1311 | */ |
| 1281 | 1312 | const settingsOps = [{ |
| 1282 | - label: "Multi-line input", | |
| 1283 | - hint: [ | |
| 1284 | - "When the input field is empty, Ctrl-Enter or Shift-Enter will toggle this.", | |
| 1285 | - "In multi-line mode, Ctrl-Enter sends messages. In single-line mode, " | |
| 1286 | - +"Enter or Ctrl-Enter sends messages." | |
| 1287 | - ].join('\n'), | |
| 1288 | - boolValue: 'edit-multiline' | |
| 1313 | + label: "Ctrl-enter to Send", | |
| 1314 | + hint: "When on, only Ctrl-Enter will send messages. "+ | |
| 1315 | + "When off, both Enter and Ctrl-Enter send. "+ | |
| 1316 | + "When the input field has focus, is empty, and preview "+ | |
| 1317 | + "mode is NOT active then Ctrl-Enter toggles this setting.", | |
| 1318 | + boolValue: 'edit-ctrl-send' | |
| 1319 | + },{ | |
| 1320 | + label: "Compact mode", | |
| 1321 | + hint: "Toggle between a space-saving and more spacious writing area. "+ | |
| 1322 | + "When the input field has focus, is empty, and preview mode "+ | |
| 1323 | + "is NOT active then Shift-Enter toggles this setting.", | |
| 1324 | + boolValue: 'edit-compact-mode' | |
| 1289 | 1325 | },{ |
| 1290 | 1326 | label: "Left-align my posts", |
| 1291 | 1327 | hint: "Default alignment of your own messages is selected " |
| 1292 | 1328 | +"based window width/height relationship.", |
| 1293 | 1329 | boolValue: ()=>!document.body.classList.contains('my-messages-right'), |
| @@ -1426,14 +1462,14 @@ | ||
| 1426 | 1462 | Chat.showActiveUserTimestamps(s.value); |
| 1427 | 1463 | }); |
| 1428 | 1464 | Chat.settings.addListener('chat-only-mode',function(s){ |
| 1429 | 1465 | Chat.chatOnlyMode(s.value); |
| 1430 | 1466 | }); |
| 1431 | - Chat.settings.addListener('edit-multiline',function(s){ | |
| 1467 | + Chat.settings.addListener('edit-compact-mode',function(s){ | |
| 1432 | 1468 | Chat.e.inputLine.classList[ |
| 1433 | - s.value ? 'remove' : 'add' | |
| 1434 | - ]('single-line'); | |
| 1469 | + s.value ? 'add' : 'remove' | |
| 1470 | + ]('compact'); | |
| 1435 | 1471 | }); |
| 1436 | 1472 | const valueKludges = { |
| 1437 | 1473 | /* Convert certain string-format values to other types... */ |
| 1438 | 1474 | "false": false, |
| 1439 | 1475 | "true": true |
| 1440 | 1476 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -375,11 +375,12 @@ | |
| 375 | if(ev.detail.key===setting) f(ev.detail); |
| 376 | }, false); |
| 377 | }, |
| 378 | defaults:{ |
| 379 | "images-inline": !!F.config.chat.imagesInline, |
| 380 | "edit-multiline": false, |
| 381 | "monospace-messages": false, |
| 382 | "chat-only-mode": false, |
| 383 | "audible-alert": true, |
| 384 | "active-user-list": false, |
| 385 | "active-user-list-timestamps": false |
| @@ -1044,20 +1045,21 @@ | |
| 1044 | }; |
| 1045 | /** Updates the paste/drop zone with details of the pasted/dropped |
| 1046 | data. The argument must be a Blob or Blob-like object (File) or |
| 1047 | it can be falsy to reset/clear that state.*/ |
| 1048 | const updateDropZoneContent = function(blob){ |
| 1049 | const dd = bxs.dropDetails; |
| 1050 | bxs.blob = blob; |
| 1051 | D.clearElement(dd); |
| 1052 | if(!blob){ |
| 1053 | Chat.e.inputFile.value = ''; |
| 1054 | return; |
| 1055 | } |
| 1056 | D.append(dd, "Name: ", blob.name, |
| 1057 | D.br(), "Size: ",blob.size); |
| 1058 | if(blob.type && blob.type.startsWith("image/")){ |
| 1059 | const img = D.img(); |
| 1060 | D.append(dd, D.br(), img); |
| 1061 | const reader = new FileReader(); |
| 1062 | reader.onload = (e)=>img.setAttribute('src', e.target.result); |
| 1063 | reader.readAsDataURL(blob); |
| @@ -1070,19 +1072,39 @@ | |
| 1070 | updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined) |
| 1071 | }); |
| 1072 | /* Handle image paste from clipboard. TODO: figure out how we can |
| 1073 | paste non-image binary data as if it had been selected via the |
| 1074 | file selection element. */ |
| 1075 | document.addEventListener('paste', function(event){ |
| 1076 | const items = event.clipboardData.items, |
| 1077 | item = items[0]; |
| 1078 | if(!item || !item.type) return; |
| 1079 | else if('file'===item.kind){ |
| 1080 | updateDropZoneContent(false/*clear prev state*/); |
| 1081 | updateDropZoneContent(item.getAsFile()); |
| 1082 | } |
| 1083 | }, false); |
| 1084 | /* Add help button for drag/drop/paste zone */ |
| 1085 | Chat.e.inputFile.parentNode.insertBefore( |
| 1086 | F.helpButtonlets.create( |
| 1087 | Chat.e.fileSelectWrapper.querySelector('.help-buttonlet') |
| 1088 | ), Chat.e.inputFile |
| @@ -1170,36 +1192,45 @@ | |
| 1170 | BlobXferState.clear(); |
| 1171 | Chat.inputValue("").inputFocus(); |
| 1172 | }; |
| 1173 | |
| 1174 | const inputWidgetKeydown = function f(ev){ |
| 1175 | if(!f.$toggle){ |
| 1176 | f.$toggle = function(currentMode){ |
| 1177 | currentMode = !currentMode; |
| 1178 | Chat.settings.set('edit-multiline', currentMode); |
| 1179 | }; |
| 1180 | } |
| 1181 | if(13 === ev.keyCode){ |
| 1182 | const multi = Chat.settings.getBool('edit-multiline', false); |
| 1183 | if(ev.shiftKey){ |
| 1184 | ev.preventDefault(); |
| 1185 | ev.stopPropagation(); |
| 1186 | /* Shift-enter will run preview mode UNLESS preview mode is |
| 1187 | active AND the input field is empty, in which case it will |
| 1188 | switch back to message view. */ |
| 1189 | const text = Chat.inputValue().trim(); |
| 1190 | if(Chat.e.currentView===Chat.e.viewPreview && !text) Chat.setCurrentView(Chat.e.viewMessages); |
| 1191 | else if(!text) f.$toggle(multi); |
| 1192 | else Chat.e.btnPreview.click(); |
| 1193 | return false; |
| 1194 | }else if(!multi || (ev.ctrlKey && multi)){ |
| 1195 | /* ^^^ note that it is intended that both ctrl-enter and enter |
| 1196 | work for single-line input mode. */ |
| 1197 | ev.preventDefault(); |
| 1198 | ev.stopPropagation(); |
| 1199 | const text = Chat.inputValue().trim(); |
| 1200 | if(!text) f.$toggle(multi); |
| 1201 | else Chat.submitMessage(); |
| 1202 | return false; |
| 1203 | } |
| 1204 | } |
| 1205 | }; |
| @@ -1277,17 +1308,22 @@ | |
| 1277 | sync with external changes to that setting. Various Chat UI |
| 1278 | elements stay in sync with the config UI via those settings |
| 1279 | events. |
| 1280 | */ |
| 1281 | const settingsOps = [{ |
| 1282 | label: "Multi-line input", |
| 1283 | hint: [ |
| 1284 | "When the input field is empty, Ctrl-Enter or Shift-Enter will toggle this.", |
| 1285 | "In multi-line mode, Ctrl-Enter sends messages. In single-line mode, " |
| 1286 | +"Enter or Ctrl-Enter sends messages." |
| 1287 | ].join('\n'), |
| 1288 | boolValue: 'edit-multiline' |
| 1289 | },{ |
| 1290 | label: "Left-align my posts", |
| 1291 | hint: "Default alignment of your own messages is selected " |
| 1292 | +"based window width/height relationship.", |
| 1293 | boolValue: ()=>!document.body.classList.contains('my-messages-right'), |
| @@ -1426,14 +1462,14 @@ | |
| 1426 | Chat.showActiveUserTimestamps(s.value); |
| 1427 | }); |
| 1428 | Chat.settings.addListener('chat-only-mode',function(s){ |
| 1429 | Chat.chatOnlyMode(s.value); |
| 1430 | }); |
| 1431 | Chat.settings.addListener('edit-multiline',function(s){ |
| 1432 | Chat.e.inputLine.classList[ |
| 1433 | s.value ? 'remove' : 'add' |
| 1434 | ]('single-line'); |
| 1435 | }); |
| 1436 | const valueKludges = { |
| 1437 | /* Convert certain string-format values to other types... */ |
| 1438 | "false": false, |
| 1439 | "true": true |
| 1440 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -375,11 +375,12 @@ | |
| 375 | if(ev.detail.key===setting) f(ev.detail); |
| 376 | }, false); |
| 377 | }, |
| 378 | defaults:{ |
| 379 | "images-inline": !!F.config.chat.imagesInline, |
| 380 | "edit-ctrl-send": false, |
| 381 | "edit-compact-mode": true, |
| 382 | "monospace-messages": false, |
| 383 | "chat-only-mode": false, |
| 384 | "audible-alert": true, |
| 385 | "active-user-list": false, |
| 386 | "active-user-list-timestamps": false |
| @@ -1044,20 +1045,21 @@ | |
| 1045 | }; |
| 1046 | /** Updates the paste/drop zone with details of the pasted/dropped |
| 1047 | data. The argument must be a Blob or Blob-like object (File) or |
| 1048 | it can be falsy to reset/clear that state.*/ |
| 1049 | const updateDropZoneContent = function(blob){ |
| 1050 | console.debug("updateDropZoneContent()",blob); |
| 1051 | const dd = bxs.dropDetails; |
| 1052 | bxs.blob = blob; |
| 1053 | D.clearElement(dd); |
| 1054 | if(!blob){ |
| 1055 | Chat.e.inputFile.value = ''; |
| 1056 | return; |
| 1057 | } |
| 1058 | D.append(dd, "Name: ", blob.name, |
| 1059 | D.br(), "Size: ",blob.size); |
| 1060 | if(blob.type && (blob.type.startsWith("image/") || blob.type==='BITMAP')){ |
| 1061 | const img = D.img(); |
| 1062 | D.append(dd, D.br(), img); |
| 1063 | const reader = new FileReader(); |
| 1064 | reader.onload = (e)=>img.setAttribute('src', e.target.result); |
| 1065 | reader.readAsDataURL(blob); |
| @@ -1070,19 +1072,39 @@ | |
| 1072 | updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined) |
| 1073 | }); |
| 1074 | /* Handle image paste from clipboard. TODO: figure out how we can |
| 1075 | paste non-image binary data as if it had been selected via the |
| 1076 | file selection element. */ |
| 1077 | const pasteListener = function(event){ |
| 1078 | const items = event.clipboardData.items, |
| 1079 | item = items[0]; |
| 1080 | //console.debug("paste event",event.target,item,event); |
| 1081 | //console.debug("paste event item",item); |
| 1082 | if(item && item.type && ('file'===item.kind || 'BITMAP'===item.type)){ |
| 1083 | updateDropZoneContent(false/*clear prev state*/); |
| 1084 | updateDropZoneContent(item.getAsFile()); |
| 1085 | event.stopPropagation(); |
| 1086 | event.preventDefault(true); |
| 1087 | return false; |
| 1088 | } |
| 1089 | /* else continue propagating */ |
| 1090 | }; |
| 1091 | document.addEventListener('paste', pasteListener, true); |
| 1092 | if(0){ |
| 1093 | const onPastePlainText = function(ev){ |
| 1094 | var pastedText = undefined; |
| 1095 | if (window.clipboardData && window.clipboardData.getData) { // IE |
| 1096 | pastedText = window.clipboardData.getData('Text'); |
| 1097 | }else if (ev.clipboardData && ev.clipboardData.getData) { |
| 1098 | pastedText = ev.clipboardData.getData('text/plain'); |
| 1099 | } |
| 1100 | ev.target.textContent += pastedText; |
| 1101 | ev.preventDefault(); |
| 1102 | return false; |
| 1103 | }; |
| 1104 | Chat.e.inputField.addEventListener('paste', onPastePlainText, false); |
| 1105 | } |
| 1106 | /* Add help button for drag/drop/paste zone */ |
| 1107 | Chat.e.inputFile.parentNode.insertBefore( |
| 1108 | F.helpButtonlets.create( |
| 1109 | Chat.e.fileSelectWrapper.querySelector('.help-buttonlet') |
| 1110 | ), Chat.e.inputFile |
| @@ -1170,36 +1192,45 @@ | |
| 1192 | BlobXferState.clear(); |
| 1193 | Chat.inputValue("").inputFocus(); |
| 1194 | }; |
| 1195 | |
| 1196 | const inputWidgetKeydown = function f(ev){ |
| 1197 | if(!f.$toggleCtrl){ |
| 1198 | f.$toggleCtrl = function(currentMode){ |
| 1199 | currentMode = !currentMode; |
| 1200 | Chat.settings.set('edit-ctrl-send', currentMode); |
| 1201 | }; |
| 1202 | f.$toggleCompact = function(currentMode){ |
| 1203 | currentMode = !currentMode; |
| 1204 | Chat.settings.set('edit-compact-mode', currentMode); |
| 1205 | }; |
| 1206 | } |
| 1207 | if(13 === ev.keyCode){ |
| 1208 | const ctrlMode = Chat.settings.getBool('edit-ctrl-send', false); |
| 1209 | if(ev.shiftKey){ |
| 1210 | const compactMode = Chat.settings.getBool('edit-compact-mode', false); |
| 1211 | ev.preventDefault(); |
| 1212 | ev.stopPropagation(); |
| 1213 | /* Shift-enter will run preview mode UNLESS preview mode is |
| 1214 | active AND the input field is empty, in which case it will |
| 1215 | switch back to message view. */ |
| 1216 | const text = Chat.inputValue().trim(); |
| 1217 | if(Chat.e.currentView===Chat.e.viewPreview && !text){ |
| 1218 | Chat.setCurrentView(Chat.e.viewMessages); |
| 1219 | } |
| 1220 | else if(!text){ |
| 1221 | f.$toggleCompact(compactMode); |
| 1222 | } |
| 1223 | else Chat.e.btnPreview.click(); |
| 1224 | return false; |
| 1225 | }else if(!ctrlMode || (ev.ctrlKey && ctrlMode)){ |
| 1226 | /* ^^^ note that it is intended that both ctrl-enter and enter |
| 1227 | work for compact input mode. */ |
| 1228 | ev.preventDefault(); |
| 1229 | ev.stopPropagation(); |
| 1230 | const text = Chat.inputValue().trim(); |
| 1231 | if(!text) f.$toggleCtrl(ctrlMode); |
| 1232 | else Chat.submitMessage(); |
| 1233 | return false; |
| 1234 | } |
| 1235 | } |
| 1236 | }; |
| @@ -1277,17 +1308,22 @@ | |
| 1308 | sync with external changes to that setting. Various Chat UI |
| 1309 | elements stay in sync with the config UI via those settings |
| 1310 | events. |
| 1311 | */ |
| 1312 | const settingsOps = [{ |
| 1313 | label: "Ctrl-enter to Send", |
| 1314 | hint: "When on, only Ctrl-Enter will send messages. "+ |
| 1315 | "When off, both Enter and Ctrl-Enter send. "+ |
| 1316 | "When the input field has focus, is empty, and preview "+ |
| 1317 | "mode is NOT active then Ctrl-Enter toggles this setting.", |
| 1318 | boolValue: 'edit-ctrl-send' |
| 1319 | },{ |
| 1320 | label: "Compact mode", |
| 1321 | hint: "Toggle between a space-saving and more spacious writing area. "+ |
| 1322 | "When the input field has focus, is empty, and preview mode "+ |
| 1323 | "is NOT active then Shift-Enter toggles this setting.", |
| 1324 | boolValue: 'edit-compact-mode' |
| 1325 | },{ |
| 1326 | label: "Left-align my posts", |
| 1327 | hint: "Default alignment of your own messages is selected " |
| 1328 | +"based window width/height relationship.", |
| 1329 | boolValue: ()=>!document.body.classList.contains('my-messages-right'), |
| @@ -1426,14 +1462,14 @@ | |
| 1462 | Chat.showActiveUserTimestamps(s.value); |
| 1463 | }); |
| 1464 | Chat.settings.addListener('chat-only-mode',function(s){ |
| 1465 | Chat.chatOnlyMode(s.value); |
| 1466 | }); |
| 1467 | Chat.settings.addListener('edit-compact-mode',function(s){ |
| 1468 | Chat.e.inputLine.classList[ |
| 1469 | s.value ? 'add' : 'remove' |
| 1470 | ]('compact'); |
| 1471 | }); |
| 1472 | const valueKludges = { |
| 1473 | /* Convert certain string-format values to other types... */ |
| 1474 | "false": false, |
| 1475 | "true": true |
| 1476 |
+7
-7
| --- src/style.chat.css | ||
| +++ src/style.chat.css | ||
| @@ -206,14 +206,14 @@ | ||
| 206 | 206 | display: flex; |
| 207 | 207 | flex-direction: row; |
| 208 | 208 | align-items: stretch; |
| 209 | 209 | flex-wrap: nowrap; |
| 210 | 210 | } |
| 211 | -/*body.chat #chat-input-line:not(.single-line) { | |
| 211 | +/*body.chat #chat-input-line:not(.compact) { | |
| 212 | 212 | flex-wrap: nowrap; |
| 213 | 213 | }*/ |
| 214 | -body.chat #chat-input-line.single-line #chat-input-field { | |
| 214 | +body.chat #chat-input-line.compact #chat-input-field { | |
| 215 | 215 | max-height: 2rem /*arbitrary*/; |
| 216 | 216 | } |
| 217 | 217 | |
| 218 | 218 | body.chat #chat-edit-buttons { |
| 219 | 219 | flex: 1 1 auto; |
| @@ -221,31 +221,31 @@ | ||
| 221 | 221 | flex-direction: column; |
| 222 | 222 | justify-content: space-between; |
| 223 | 223 | min-width: 4em; |
| 224 | 224 | min-height: 1.5em; |
| 225 | 225 | } |
| 226 | -body.chat #chat-input-line.single-line #chat-edit-buttons { | |
| 226 | +body.chat #chat-input-line.compact #chat-edit-buttons { | |
| 227 | 227 | flex-direction: row; |
| 228 | 228 | margin-top: 0.25em; |
| 229 | 229 | } |
| 230 | 230 | body.chat #chat-edit-buttons > * { |
| 231 | 231 | flex: 1 1 auto; |
| 232 | 232 | padding: initial/*some skins mess this up for buttons*/; |
| 233 | 233 | } |
| 234 | -body.chat #chat-input-line:not(.single-line) #chat-edit-buttons > * { | |
| 234 | +body.chat #chat-input-line:not(.compact) #chat-edit-buttons > * { | |
| 235 | 235 | max-width: 4em; |
| 236 | 236 | margin: 0.25em; |
| 237 | 237 | min-height: 2em; |
| 238 | 238 | } |
| 239 | -body.chat #chat-input-line:not(.single-line) #chat-input-field { | |
| 239 | +body.chat #chat-input-line:not(.compact) #chat-input-field { | |
| 240 | 240 | /*border-left-style: double; |
| 241 | 241 | border-left-width: 3px; |
| 242 | 242 | border-right-style: double; |
| 243 | 243 | border-right-width: 3px;*/ |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | -body.chat #chat-input-line.single-line #chat-edit-buttons > * { | |
| 246 | +body.chat #chat-input-line.compact #chat-edit-buttons > * { | |
| 247 | 247 | margin: 0 0.25em; |
| 248 | 248 | min-width: 2em; |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | 251 | body.chat #chat-input-line > button { |
| @@ -259,11 +259,11 @@ | ||
| 259 | 259 | body.chat #chat-input-line > textarea { |
| 260 | 260 | flex: 20 1 auto; |
| 261 | 261 | max-width: revert; |
| 262 | 262 | min-width: 20em; |
| 263 | 263 | } |
| 264 | -body.chat #chat-input-line.single-line > input[type=text] { | |
| 264 | +body.chat #chat-input-line.compact > input[type=text] { | |
| 265 | 265 | margin: 0 0 0.25em 0/* gap for if/when buttons wrap*/; |
| 266 | 266 | } |
| 267 | 267 | /* Widget holding the file selection control and preview */ |
| 268 | 268 | body.chat #chat-input-file-area { |
| 269 | 269 | display: flex; |
| 270 | 270 |
| --- src/style.chat.css | |
| +++ src/style.chat.css | |
| @@ -206,14 +206,14 @@ | |
| 206 | display: flex; |
| 207 | flex-direction: row; |
| 208 | align-items: stretch; |
| 209 | flex-wrap: nowrap; |
| 210 | } |
| 211 | /*body.chat #chat-input-line:not(.single-line) { |
| 212 | flex-wrap: nowrap; |
| 213 | }*/ |
| 214 | body.chat #chat-input-line.single-line #chat-input-field { |
| 215 | max-height: 2rem /*arbitrary*/; |
| 216 | } |
| 217 | |
| 218 | body.chat #chat-edit-buttons { |
| 219 | flex: 1 1 auto; |
| @@ -221,31 +221,31 @@ | |
| 221 | flex-direction: column; |
| 222 | justify-content: space-between; |
| 223 | min-width: 4em; |
| 224 | min-height: 1.5em; |
| 225 | } |
| 226 | body.chat #chat-input-line.single-line #chat-edit-buttons { |
| 227 | flex-direction: row; |
| 228 | margin-top: 0.25em; |
| 229 | } |
| 230 | body.chat #chat-edit-buttons > * { |
| 231 | flex: 1 1 auto; |
| 232 | padding: initial/*some skins mess this up for buttons*/; |
| 233 | } |
| 234 | body.chat #chat-input-line:not(.single-line) #chat-edit-buttons > * { |
| 235 | max-width: 4em; |
| 236 | margin: 0.25em; |
| 237 | min-height: 2em; |
| 238 | } |
| 239 | body.chat #chat-input-line:not(.single-line) #chat-input-field { |
| 240 | /*border-left-style: double; |
| 241 | border-left-width: 3px; |
| 242 | border-right-style: double; |
| 243 | border-right-width: 3px;*/ |
| 244 | } |
| 245 | |
| 246 | body.chat #chat-input-line.single-line #chat-edit-buttons > * { |
| 247 | margin: 0 0.25em; |
| 248 | min-width: 2em; |
| 249 | } |
| 250 | |
| 251 | body.chat #chat-input-line > button { |
| @@ -259,11 +259,11 @@ | |
| 259 | body.chat #chat-input-line > textarea { |
| 260 | flex: 20 1 auto; |
| 261 | max-width: revert; |
| 262 | min-width: 20em; |
| 263 | } |
| 264 | body.chat #chat-input-line.single-line > input[type=text] { |
| 265 | margin: 0 0 0.25em 0/* gap for if/when buttons wrap*/; |
| 266 | } |
| 267 | /* Widget holding the file selection control and preview */ |
| 268 | body.chat #chat-input-file-area { |
| 269 | display: flex; |
| 270 |
| --- src/style.chat.css | |
| +++ src/style.chat.css | |
| @@ -206,14 +206,14 @@ | |
| 206 | display: flex; |
| 207 | flex-direction: row; |
| 208 | align-items: stretch; |
| 209 | flex-wrap: nowrap; |
| 210 | } |
| 211 | /*body.chat #chat-input-line:not(.compact) { |
| 212 | flex-wrap: nowrap; |
| 213 | }*/ |
| 214 | body.chat #chat-input-line.compact #chat-input-field { |
| 215 | max-height: 2rem /*arbitrary*/; |
| 216 | } |
| 217 | |
| 218 | body.chat #chat-edit-buttons { |
| 219 | flex: 1 1 auto; |
| @@ -221,31 +221,31 @@ | |
| 221 | flex-direction: column; |
| 222 | justify-content: space-between; |
| 223 | min-width: 4em; |
| 224 | min-height: 1.5em; |
| 225 | } |
| 226 | body.chat #chat-input-line.compact #chat-edit-buttons { |
| 227 | flex-direction: row; |
| 228 | margin-top: 0.25em; |
| 229 | } |
| 230 | body.chat #chat-edit-buttons > * { |
| 231 | flex: 1 1 auto; |
| 232 | padding: initial/*some skins mess this up for buttons*/; |
| 233 | } |
| 234 | body.chat #chat-input-line:not(.compact) #chat-edit-buttons > * { |
| 235 | max-width: 4em; |
| 236 | margin: 0.25em; |
| 237 | min-height: 2em; |
| 238 | } |
| 239 | body.chat #chat-input-line:not(.compact) #chat-input-field { |
| 240 | /*border-left-style: double; |
| 241 | border-left-width: 3px; |
| 242 | border-right-style: double; |
| 243 | border-right-width: 3px;*/ |
| 244 | } |
| 245 | |
| 246 | body.chat #chat-input-line.compact #chat-edit-buttons > * { |
| 247 | margin: 0 0.25em; |
| 248 | min-width: 2em; |
| 249 | } |
| 250 | |
| 251 | body.chat #chat-input-line > button { |
| @@ -259,11 +259,11 @@ | |
| 259 | body.chat #chat-input-line > textarea { |
| 260 | flex: 20 1 auto; |
| 261 | max-width: revert; |
| 262 | min-width: 20em; |
| 263 | } |
| 264 | body.chat #chat-input-line.compact > input[type=text] { |
| 265 | margin: 0 0 0.25em 0/* gap for if/when buttons wrap*/; |
| 266 | } |
| 267 | /* Widget holding the file selection control and preview */ |
| 268 | body.chat #chat-input-file-area { |
| 269 | display: flex; |
| 270 |