Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Chat: hide message home/end buttons by default in portrait mode and add a menu toggle for them, and swapped the button positions (seems more natural). Minor tweak to the div.content resize algo to make use of CSS calc(). |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
deb9963ac6daca869b43a48ad266e251 |
| User & Date: | stephan 2020-12-27 17:42:37.859 |
Context
|
2020-12-27
| ||
| 17:44 | Doc typo fix reported in the forum. ... (check-in: 988c599810 user: stephan tags: trunk) | |
| 17:42 | Chat: hide message home/end buttons by default in portrait mode and add a menu toggle for them, and swapped the button positions (seems more natural). Minor tweak to the div.content resize algo to make use of CSS calc(). ... (check-in: deb9963ac6 user: stephan tags: trunk) | |
| 09:56 | Some flicker reduction when batch loading chat messages. Minor chat layout tweaks. ... (check-in: 5e046b64c7 user: stephan tags: trunk) | |
Changes
Changes to src/chat.c.
| ︙ | ︙ | |||
118 119 120 121 122 123 124 | @ <form accept-encoding="utf-8" id="chat-form" autocomplete="off"> @ <div id='chat-input-line'> @ <input type="text" name="msg" id="chat-input-single" \ @ placeholder="Type message here." autocomplete="off"> @ <textarea rows="8" id="chat-input-multi" \ @ placeholder="Type message here" class="hidden"></textarea> @ <input type="submit" value="Send" id="chat-message-submit"> | | | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | @ <form accept-encoding="utf-8" id="chat-form" autocomplete="off"> @ <div id='chat-input-line'> @ <input type="text" name="msg" id="chat-input-single" \ @ placeholder="Type message here." autocomplete="off"> @ <textarea rows="8" id="chat-input-multi" \ @ placeholder="Type message here" class="hidden"></textarea> @ <input type="submit" value="Send" id="chat-message-submit"> @ <button id="chat-scroll-top">↑</button> @ <button id="chat-scroll-bottom">↓</button> @ <span id="chat-settings-button" class="settings-icon" \ @ aria-label="Settings..." aria-haspopup="true" ></span> @ </div> @ <div id='chat-input-file-area'> @ <div class='file-selection-wrapper'> @ <div class='help-buttonlet'> @ Select a file to upload, drag/drop a file into this spot, |
| ︙ | ︙ |
Changes to src/chat.js.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 |
}
const bcl = document.body.classList;
const resized = function(){
const wh = window.innerHeight,
com = bcl.contains('chat-only-mode');
var ht;
if(com){
| | | | > > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
}
const bcl = document.body.classList;
const resized = function(){
const wh = window.innerHeight,
com = bcl.contains('chat-only-mode');
var ht;
if(com){
ht = wh;
}else{
f.extra = 0;
[f.eHead, f.eMenu, f.eFoot].forEach(f.measure);
ht = wh - f.extra;
}
f.contentArea.style.height =
f.contentArea.style.maxHeight = [
"calc(", (ht>=100 ? ht : 100), "px",
" - 1em"/*fudge value*/,")"
].join('');
if(false){
console.debug("resized.",wh, f.extra, ht,
window.getComputedStyle(f.contentArea).maxHeight,
f.contentArea);
}
};
var doit;
|
| ︙ | ︙ | |||
87 88 89 90 91 92 93 |
messagesWrapper: E1('#chat-messages-wrapper'),
inputForm: E1('#chat-form'),
btnSubmit: E1('#chat-message-submit'),
inputSingle: E1('#chat-input-single'),
inputMulti: E1('#chat-input-multi'),
inputCurrent: undefined/*one of inputSingle or inputMulti*/,
inputFile: E1('#chat-input-file'),
| | > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
messagesWrapper: E1('#chat-messages-wrapper'),
inputForm: E1('#chat-form'),
btnSubmit: E1('#chat-message-submit'),
inputSingle: E1('#chat-input-single'),
inputMulti: E1('#chat-input-multi'),
inputCurrent: undefined/*one of inputSingle or inputMulti*/,
inputFile: E1('#chat-input-file'),
contentDiv: E1('div.content'),
btnMsgHome: E1('#chat-scroll-top'),
btnMsgEnd: E1('#chat-scroll-bottom')
},
me: F.user.name,
mxMsg: F.config.chat.initSize ? -F.config.chat.initSize : -50,
mnMsg: undefined/*lowest message ID we've seen so far (for history loading)*/,
pageIsActive: 'visible'===document.visibilityState,
changesSincePageHidden: 0,
notificationBubbleColor: 'white',
|
| ︙ | ︙ | |||
293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
}else if(Chat.e.newestMessage){
Chat.e.newestMessage.scrollIntoView(false);
}
},
toggleChatOnlyMode: function(){
return this.chatOnlyMode(!this.isChatOnlyMode());
},
settings:{
get: (k,dflt)=>F.storage.get(k,dflt),
getBool: (k,dflt)=>F.storage.getBool(k,dflt),
set: (k,v)=>F.storage.set(k,v),
defaults:{
"images-inline": !!F.config.chat.imagesInline,
"monospace-messages": false
| > > > > > > > > | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
}else if(Chat.e.newestMessage){
Chat.e.newestMessage.scrollIntoView(false);
}
},
toggleChatOnlyMode: function(){
return this.chatOnlyMode(!this.isChatOnlyMode());
},
/* Turn the message area top/bottom buttons on (yes===true), off
(yes==false), or toggle them (no arguments). Returns this. */
toggleNavButtons: function(yes){
const e = [this.e.btnMsgHome, this.e.btnMsgEnd], c = 'hidden';
if(0===arguments.length) D.toggleClass(e, c);
else if(!arguments[0]) D.addClass(e, c);
else D.removeClass(e, c);
},
settings:{
get: (k,dflt)=>F.storage.get(k,dflt),
getBool: (k,dflt)=>F.storage.getBool(k,dflt),
set: (k,v)=>F.storage.set(k,v),
defaults:{
"images-inline": !!F.config.chat.imagesInline,
"monospace-messages": false
|
| ︙ | ︙ | |||
315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
if(window.innerWidth<window.innerHeight){
/* Alignment of 'my' messages: right alignment is conventional
for mobile chat apps but can be difficult to read in wide
windows (desktop/tablet landscape mode), so we default to a
layout based on the apparently "orientation" of the window:
tall vs wide. Can be toggled via settings popup. */
document.body.classList.add('my-messages-right');
}
if(cs.settings.getBool('monospace-messages',false)){
document.body.classList.add('monospace-messages');
}
cs.e.inputCurrent = cs.e.inputSingle;
cs.pageTitleOrig = cs.e.pageTitle.innerText;
| > | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
if(window.innerWidth<window.innerHeight){
/* Alignment of 'my' messages: right alignment is conventional
for mobile chat apps but can be difficult to read in wide
windows (desktop/tablet landscape mode), so we default to a
layout based on the apparently "orientation" of the window:
tall vs wide. Can be toggled via settings popup. */
document.body.classList.add('my-messages-right');
cs.toggleNavButtons(false);
}
if(cs.settings.getBool('monospace-messages',false)){
document.body.classList.add('monospace-messages');
}
cs.e.inputCurrent = cs.e.inputSingle;
cs.pageTitleOrig = cs.e.pageTitle.innerText;
|
| ︙ | ︙ | |||
783 784 785 786 787 788 789 790 791 792 793 794 795 796 |
},{
label: "Left-align my posts",
boolValue: ()=>!document.body.classList.contains('my-messages-right'),
callback: function f(){
document.body.classList.toggle('my-messages-right');
}
},{
label: "Images inline",
boolValue: ()=>Chat.settings.getBool('images-inline'),
callback: function(){
const v = Chat.settings.getBool('images-inline',true);
Chat.settings.set('images-inline', !v);
F.toast.message("Image mode set to "+(v ? "hyperlink" : "inline")+".");
}
| > > > > | 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 |
},{
label: "Left-align my posts",
boolValue: ()=>!document.body.classList.contains('my-messages-right'),
callback: function f(){
document.body.classList.toggle('my-messages-right');
}
},{
label: "Message home/end buttons",
boolValue: ()=>!Chat.e.btnMsgHome.classList.contains('hidden'),
callback: ()=>Chat.toggleNavButtons()
},{
label: "Images inline",
boolValue: ()=>Chat.settings.getBool('images-inline'),
callback: function(){
const v = Chat.settings.getBool('images-inline',true);
Chat.settings.set('images-inline', !v);
F.toast.message("Image mode set to "+(v ? "hyperlink" : "inline")+".");
}
|
| ︙ | ︙ |
Changes to src/default.css.
| ︙ | ︙ | |||
1613 1614 1615 1616 1617 1618 1619 |
}
body.chat .chat-settings-popup > span {
vertical-align: middle;
}
body.chat .chat-settings-popup > span.menu-entry{
white-space: nowrap;
cursor: pointer;
| | > > | 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 |
}
body.chat .chat-settings-popup > span {
vertical-align: middle;
}
body.chat .chat-settings-popup > span.menu-entry{
white-space: nowrap;
cursor: pointer;
border: 1px solid;
border-radius: 0.25em;
padding: 0.25em 0.5em;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
body.chat .chat-settings-popup > span.menu-entry:hover {
}
body.chat .chat-settings-popup > span.menu-entry > .help-buttonlet {
vertical-align: middle;
}
body.chat .chat-settings-popup > span.menu-entry > span.button {
margin: 0.25em 0.2em;
padding: 0.5em;
|
| ︙ | ︙ | |||
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 |
margin: 0 0.25em;
}
body.chat #chat-input-line > button {
max-width: 4em;
}
body.chat #chat-input-line > #chat-settings-button{
margin: 0 0 0 0.25em;
}
body.chat #chat-input-line > input[type=text],
body.chat #chat-input-line > textarea {
flex: 5 1 auto;
}
/* Widget holding the file selection control and preview */
body.chat #chat-input-file-area {
| > | 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 |
margin: 0 0.25em;
}
body.chat #chat-input-line > button {
max-width: 4em;
}
body.chat #chat-input-line > #chat-settings-button{
margin: 0 0 0 0.25em;
max-width: 2em;
}
body.chat #chat-input-line > input[type=text],
body.chat #chat-input-line > textarea {
flex: 5 1 auto;
}
/* Widget holding the file selection control and preview */
body.chat #chat-input-file-area {
|
| ︙ | ︙ |
Changes to src/fossil.dom.js.
| ︙ | ︙ | |||
628 629 630 631 632 633 634 |
return e;
};
/**
"Blinks" the given element a single time for the given number of
milliseconds, defaulting (if the 2nd argument is falsy or not a
number) to flashOnce.defaultTimeMs. If a 3rd argument is passed
| | | | 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
return e;
};
/**
"Blinks" the given element a single time for the given number of
milliseconds, defaulting (if the 2nd argument is falsy or not a
number) to flashOnce.defaultTimeMs. If a 3rd argument is passed
in, it must be a function, and it gets called at the end of the
asynchronous flashing processes.
This will only activate once per element during that timeframe -
further calls will become no-ops until the blink is
completed. This routine adds a dataset member to the element for
the duration of the blink, to allow it to block multiple blinks.
If passed 2 arguments and the 2nd is a function, it behaves as if
|
| ︙ | ︙ |