Fossil SCM
chat setting: toggle whether 'my' messages are on the right or left, with the default depending on whether the window is wider than it is tall.
Commit
f1e91a200a7582b3481de1d41abd5c9643d7ee47a234da03b98332eaddff63dc
Parent
467dbc8fd7881af…
2 files changed
+63
-28
+9
-2
+63
-28
| --- src/chat.js | ||
| +++ src/chat.js | ||
| @@ -25,10 +25,15 @@ | ||
| 25 | 25 | changesSincePageHidden: 0, |
| 26 | 26 | notificationBubbleColor: 'white', |
| 27 | 27 | totalMessageCount: 0, // total # of inbound messages |
| 28 | 28 | //! Number of messages to load for the history buttons |
| 29 | 29 | loadMessageCount: Math.abs(F.config.chatInitSize || 20), |
| 30 | + /* Alignment of 'my' messages: must be 'left' or 'right'. Note | |
| 31 | + that 'right' is conventional for mobile chat apps but can be | |
| 32 | + difficult to read in wide windows (desktop/tablet landscape | |
| 33 | + mode). Can be toggled via settings popup. */ | |
| 34 | + msgMyAlign: (window.innerWidth<window.innerHeight) ? 'right' : 'left', | |
| 30 | 35 | ajaxInflight: 0, |
| 31 | 36 | /** Enables (if yes is truthy) or disables all elements in |
| 32 | 37 | * this.disableDuringAjax. */ |
| 33 | 38 | enableAjaxComponents: function(yes){ |
| 34 | 39 | D[yes ? 'enable' : 'disable'](this.disableDuringAjax); |
| @@ -365,35 +370,61 @@ | ||
| 365 | 370 | const rect = settingsButton.getBoundingClientRect(); |
| 366 | 371 | return rect.top + rect.height + 2; |
| 367 | 372 | } |
| 368 | 373 | }); |
| 369 | 374 | settingsPopup.installClickToHide(); |
| 370 | - const btnToggleBody = D.button("Toggle page body"); | |
| 371 | - D.append(settingsPopup.e, btnToggleBody); | |
| 372 | - const toggleBody = function f(){ | |
| 373 | - if(f.isHidden){ | |
| 374 | - D.removeClass(f.elemsToToggle, 'hidden'); | |
| 375 | - D.removeClass(document.body, 'chat-only-mode'); | |
| 376 | - }else{ | |
| 377 | - D.addClass(f.elemsToToggle, 'hidden'); | |
| 378 | - D.addClass(document.body, 'chat-only-mode'); | |
| 379 | - } | |
| 380 | - f.isHidden = !f.isHidden; | |
| 381 | - }; | |
| 382 | - toggleBody.elemsToToggle = []; | |
| 383 | - toggleBody.isHidden = false; | |
| 384 | - document.body.childNodes.forEach(function(e){ | |
| 385 | - if(!e.classList) return/*TEXT nodes and such*/; | |
| 386 | - else if(!e.classList.contains('content')){ | |
| 387 | - toggleBody.elemsToToggle.push(e); | |
| 388 | - } | |
| 389 | - settingsPopup.hide(); | |
| 390 | - }); | |
| 391 | - btnToggleBody.addEventListener('click', toggleBody); | |
| 392 | - settingsButton.addEventListener('click',function(){ | |
| 393 | - settingsPopup.show(settingsButton); | |
| 394 | - }); | |
| 375 | + | |
| 376 | + /* Settings menu entries... */ | |
| 377 | + const settingsOps = [{ | |
| 378 | + label: "Toggle page body", | |
| 379 | + callback: function f(){ | |
| 380 | + if(undefined === f.isHidden){ | |
| 381 | + f.isHidden = false; | |
| 382 | + f.elemsToToggle = []; | |
| 383 | + document.body.childNodes.forEach(function(e){ | |
| 384 | + if(!e.classList) return/*TEXT nodes and such*/; | |
| 385 | + else if(!e.classList.contains('content')){ | |
| 386 | + f.elemsToToggle.push(e); | |
| 387 | + } | |
| 388 | + }); | |
| 389 | + } | |
| 390 | + if(f.isHidden){ | |
| 391 | + D.removeClass(f.elemsToToggle, 'hidden'); | |
| 392 | + D.removeClass(document.body, 'chat-only-mode'); | |
| 393 | + }else{ | |
| 394 | + D.addClass(f.elemsToToggle, 'hidden'); | |
| 395 | + D.addClass(document.body, 'chat-only-mode'); | |
| 396 | + } | |
| 397 | + f.isHidden = !f.isHidden; | |
| 398 | + } | |
| 399 | + },{ | |
| 400 | + label: "Toggle left/right layout", | |
| 401 | + callback: function f(){ | |
| 402 | + if('right'===Chat.msgMyAlign) Chat.msgMyAlign = 'left'; | |
| 403 | + else Chat.msgMyAlign = 'right'; | |
| 404 | + const msgs = Chat.e.messagesWrapper.querySelectorAll('.message-row'); | |
| 405 | + msgs.forEach(function(row){ | |
| 406 | + if(row.dataset.xfrom!==Chat.me) return; | |
| 407 | + row.querySelector('legend').setAttribute('align', Chat.msgMyAlign); | |
| 408 | + if('right'===Chat.msgMyAlign) row.style.justifyContent = "flex-end"; | |
| 409 | + else row.style.justifyContent = "flex-start"; | |
| 410 | + }); | |
| 411 | + } | |
| 412 | + }]; | |
| 413 | + | |
| 414 | + settingsOps.forEach(function(op){ | |
| 415 | + const btn = D.append(D.span(), op.label); | |
| 416 | + D.append(settingsPopup.e, btn); | |
| 417 | + op.callback.button = btn; | |
| 418 | + if('function'===op.init) op.init(); | |
| 419 | + btn.addEventListener('click', function(ev){ | |
| 420 | + settingsPopup.hide(); | |
| 421 | + op.callback.call(this,ev); | |
| 422 | + }); | |
| 423 | + }); | |
| 424 | + settingsButton.addEventListener('click',()=>settingsPopup.show(settingsButton), false); | |
| 425 | + | |
| 395 | 426 | /* Find an ideal X position for the popup, directly under the settings |
| 396 | 427 | button, based on the size of the popup... */ |
| 397 | 428 | settingsPopup.show(document.body); |
| 398 | 429 | popupSize = settingsPopup.e.getBoundingClientRect(); |
| 399 | 430 | settingsPopup.hide(); |
| @@ -427,13 +458,17 @@ | ||
| 427 | 458 | row.dataset.msgid = m.msgid; |
| 428 | 459 | row.dataset.xfrom = m.xfrom; |
| 429 | 460 | row.dataset.timestamp = m.mtime; |
| 430 | 461 | Chat.injectMessageElem(row,atEnd); |
| 431 | 462 | eWho.addEventListener('click', handleLegendClicked, false); |
| 432 | - if( m.xfrom==Chat.me && window.outerWidth<1000 ){ | |
| 433 | - eWho.setAttribute('align', 'right'); | |
| 434 | - row.style.justifyContent = "flex-end"; | |
| 463 | + if( m.xfrom==Chat.me ){ | |
| 464 | + eWho.setAttribute('align', Chat.msgMyAlign); | |
| 465 | + if('right'===Chat.msgMyAlign){ | |
| 466 | + row.style.justifyContent = "flex-end"; | |
| 467 | + }else{ | |
| 468 | + row.style.justifyContent = "flex-start"; | |
| 469 | + } | |
| 435 | 470 | }else{ |
| 436 | 471 | eWho.setAttribute('align', 'left'); |
| 437 | 472 | } |
| 438 | 473 | eWho.style.backgroundColor = m.uclr; |
| 439 | 474 | eWho.classList.add('message-user'); |
| 440 | 475 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -25,10 +25,15 @@ | |
| 25 | changesSincePageHidden: 0, |
| 26 | notificationBubbleColor: 'white', |
| 27 | totalMessageCount: 0, // total # of inbound messages |
| 28 | //! Number of messages to load for the history buttons |
| 29 | loadMessageCount: Math.abs(F.config.chatInitSize || 20), |
| 30 | ajaxInflight: 0, |
| 31 | /** Enables (if yes is truthy) or disables all elements in |
| 32 | * this.disableDuringAjax. */ |
| 33 | enableAjaxComponents: function(yes){ |
| 34 | D[yes ? 'enable' : 'disable'](this.disableDuringAjax); |
| @@ -365,35 +370,61 @@ | |
| 365 | const rect = settingsButton.getBoundingClientRect(); |
| 366 | return rect.top + rect.height + 2; |
| 367 | } |
| 368 | }); |
| 369 | settingsPopup.installClickToHide(); |
| 370 | const btnToggleBody = D.button("Toggle page body"); |
| 371 | D.append(settingsPopup.e, btnToggleBody); |
| 372 | const toggleBody = function f(){ |
| 373 | if(f.isHidden){ |
| 374 | D.removeClass(f.elemsToToggle, 'hidden'); |
| 375 | D.removeClass(document.body, 'chat-only-mode'); |
| 376 | }else{ |
| 377 | D.addClass(f.elemsToToggle, 'hidden'); |
| 378 | D.addClass(document.body, 'chat-only-mode'); |
| 379 | } |
| 380 | f.isHidden = !f.isHidden; |
| 381 | }; |
| 382 | toggleBody.elemsToToggle = []; |
| 383 | toggleBody.isHidden = false; |
| 384 | document.body.childNodes.forEach(function(e){ |
| 385 | if(!e.classList) return/*TEXT nodes and such*/; |
| 386 | else if(!e.classList.contains('content')){ |
| 387 | toggleBody.elemsToToggle.push(e); |
| 388 | } |
| 389 | settingsPopup.hide(); |
| 390 | }); |
| 391 | btnToggleBody.addEventListener('click', toggleBody); |
| 392 | settingsButton.addEventListener('click',function(){ |
| 393 | settingsPopup.show(settingsButton); |
| 394 | }); |
| 395 | /* Find an ideal X position for the popup, directly under the settings |
| 396 | button, based on the size of the popup... */ |
| 397 | settingsPopup.show(document.body); |
| 398 | popupSize = settingsPopup.e.getBoundingClientRect(); |
| 399 | settingsPopup.hide(); |
| @@ -427,13 +458,17 @@ | |
| 427 | row.dataset.msgid = m.msgid; |
| 428 | row.dataset.xfrom = m.xfrom; |
| 429 | row.dataset.timestamp = m.mtime; |
| 430 | Chat.injectMessageElem(row,atEnd); |
| 431 | eWho.addEventListener('click', handleLegendClicked, false); |
| 432 | if( m.xfrom==Chat.me && window.outerWidth<1000 ){ |
| 433 | eWho.setAttribute('align', 'right'); |
| 434 | row.style.justifyContent = "flex-end"; |
| 435 | }else{ |
| 436 | eWho.setAttribute('align', 'left'); |
| 437 | } |
| 438 | eWho.style.backgroundColor = m.uclr; |
| 439 | eWho.classList.add('message-user'); |
| 440 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -25,10 +25,15 @@ | |
| 25 | changesSincePageHidden: 0, |
| 26 | notificationBubbleColor: 'white', |
| 27 | totalMessageCount: 0, // total # of inbound messages |
| 28 | //! Number of messages to load for the history buttons |
| 29 | loadMessageCount: Math.abs(F.config.chatInitSize || 20), |
| 30 | /* Alignment of 'my' messages: must be 'left' or 'right'. Note |
| 31 | that 'right' is conventional for mobile chat apps but can be |
| 32 | difficult to read in wide windows (desktop/tablet landscape |
| 33 | mode). Can be toggled via settings popup. */ |
| 34 | msgMyAlign: (window.innerWidth<window.innerHeight) ? 'right' : 'left', |
| 35 | ajaxInflight: 0, |
| 36 | /** Enables (if yes is truthy) or disables all elements in |
| 37 | * this.disableDuringAjax. */ |
| 38 | enableAjaxComponents: function(yes){ |
| 39 | D[yes ? 'enable' : 'disable'](this.disableDuringAjax); |
| @@ -365,35 +370,61 @@ | |
| 370 | const rect = settingsButton.getBoundingClientRect(); |
| 371 | return rect.top + rect.height + 2; |
| 372 | } |
| 373 | }); |
| 374 | settingsPopup.installClickToHide(); |
| 375 | |
| 376 | /* Settings menu entries... */ |
| 377 | const settingsOps = [{ |
| 378 | label: "Toggle page body", |
| 379 | callback: function f(){ |
| 380 | if(undefined === f.isHidden){ |
| 381 | f.isHidden = false; |
| 382 | f.elemsToToggle = []; |
| 383 | document.body.childNodes.forEach(function(e){ |
| 384 | if(!e.classList) return/*TEXT nodes and such*/; |
| 385 | else if(!e.classList.contains('content')){ |
| 386 | f.elemsToToggle.push(e); |
| 387 | } |
| 388 | }); |
| 389 | } |
| 390 | if(f.isHidden){ |
| 391 | D.removeClass(f.elemsToToggle, 'hidden'); |
| 392 | D.removeClass(document.body, 'chat-only-mode'); |
| 393 | }else{ |
| 394 | D.addClass(f.elemsToToggle, 'hidden'); |
| 395 | D.addClass(document.body, 'chat-only-mode'); |
| 396 | } |
| 397 | f.isHidden = !f.isHidden; |
| 398 | } |
| 399 | },{ |
| 400 | label: "Toggle left/right layout", |
| 401 | callback: function f(){ |
| 402 | if('right'===Chat.msgMyAlign) Chat.msgMyAlign = 'left'; |
| 403 | else Chat.msgMyAlign = 'right'; |
| 404 | const msgs = Chat.e.messagesWrapper.querySelectorAll('.message-row'); |
| 405 | msgs.forEach(function(row){ |
| 406 | if(row.dataset.xfrom!==Chat.me) return; |
| 407 | row.querySelector('legend').setAttribute('align', Chat.msgMyAlign); |
| 408 | if('right'===Chat.msgMyAlign) row.style.justifyContent = "flex-end"; |
| 409 | else row.style.justifyContent = "flex-start"; |
| 410 | }); |
| 411 | } |
| 412 | }]; |
| 413 | |
| 414 | settingsOps.forEach(function(op){ |
| 415 | const btn = D.append(D.span(), op.label); |
| 416 | D.append(settingsPopup.e, btn); |
| 417 | op.callback.button = btn; |
| 418 | if('function'===op.init) op.init(); |
| 419 | btn.addEventListener('click', function(ev){ |
| 420 | settingsPopup.hide(); |
| 421 | op.callback.call(this,ev); |
| 422 | }); |
| 423 | }); |
| 424 | settingsButton.addEventListener('click',()=>settingsPopup.show(settingsButton), false); |
| 425 | |
| 426 | /* Find an ideal X position for the popup, directly under the settings |
| 427 | button, based on the size of the popup... */ |
| 428 | settingsPopup.show(document.body); |
| 429 | popupSize = settingsPopup.e.getBoundingClientRect(); |
| 430 | settingsPopup.hide(); |
| @@ -427,13 +458,17 @@ | |
| 458 | row.dataset.msgid = m.msgid; |
| 459 | row.dataset.xfrom = m.xfrom; |
| 460 | row.dataset.timestamp = m.mtime; |
| 461 | Chat.injectMessageElem(row,atEnd); |
| 462 | eWho.addEventListener('click', handleLegendClicked, false); |
| 463 | if( m.xfrom==Chat.me ){ |
| 464 | eWho.setAttribute('align', Chat.msgMyAlign); |
| 465 | if('right'===Chat.msgMyAlign){ |
| 466 | row.style.justifyContent = "flex-end"; |
| 467 | }else{ |
| 468 | row.style.justifyContent = "flex-start"; |
| 469 | } |
| 470 | }else{ |
| 471 | eWho.setAttribute('align', 'left'); |
| 472 | } |
| 473 | eWho.style.backgroundColor = m.uclr; |
| 474 | eWho.classList.add('message-user'); |
| 475 |
+9
-2
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -1569,15 +1569,22 @@ | ||
| 1569 | 1569 | body.chat #chat-settings-button { |
| 1570 | 1570 | } |
| 1571 | 1571 | body.chat .chat-settings-popup { |
| 1572 | 1572 | font-size: 0.8em; |
| 1573 | 1573 | text-align: left; |
| 1574 | - opacity: 0.8; | |
| 1575 | 1574 | display: flex; |
| 1576 | 1575 | flex-direction: column; |
| 1577 | 1576 | align-items: stretch; |
| 1578 | 1577 | padding: 0.25em; |
| 1578 | +} | |
| 1579 | +body.chat .chat-settings-popup > span { | |
| 1580 | + margin: 0.25em 0.2em; | |
| 1581 | + padding: 0.5em; | |
| 1582 | + white-space: nowrap; | |
| 1583 | + cursor: pointer; | |
| 1584 | + border: 1px outset; | |
| 1585 | + border-radius: 0.25em; | |
| 1579 | 1586 | } |
| 1580 | 1587 | body.chat #chat-messages-wrapper { |
| 1581 | 1588 | display: flex; |
| 1582 | 1589 | flex-direction: column; |
| 1583 | 1590 | } |
| @@ -1617,11 +1624,11 @@ | ||
| 1617 | 1624 | align-items: center; |
| 1618 | 1625 | } |
| 1619 | 1626 | body.chat #chat-input-line > input[type=submit] { |
| 1620 | 1627 | flex: 1 5 auto; |
| 1621 | 1628 | max-width: 6em; |
| 1622 | - margin-right: 1em; | |
| 1629 | + margin: 0 1em; | |
| 1623 | 1630 | } |
| 1624 | 1631 | body.chat #chat-input-line > input[type=text] { |
| 1625 | 1632 | flex: 5 1 auto; |
| 1626 | 1633 | } |
| 1627 | 1634 | body.chat #chat-input-file-area { |
| 1628 | 1635 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1569,15 +1569,22 @@ | |
| 1569 | body.chat #chat-settings-button { |
| 1570 | } |
| 1571 | body.chat .chat-settings-popup { |
| 1572 | font-size: 0.8em; |
| 1573 | text-align: left; |
| 1574 | opacity: 0.8; |
| 1575 | display: flex; |
| 1576 | flex-direction: column; |
| 1577 | align-items: stretch; |
| 1578 | padding: 0.25em; |
| 1579 | } |
| 1580 | body.chat #chat-messages-wrapper { |
| 1581 | display: flex; |
| 1582 | flex-direction: column; |
| 1583 | } |
| @@ -1617,11 +1624,11 @@ | |
| 1617 | align-items: center; |
| 1618 | } |
| 1619 | body.chat #chat-input-line > input[type=submit] { |
| 1620 | flex: 1 5 auto; |
| 1621 | max-width: 6em; |
| 1622 | margin-right: 1em; |
| 1623 | } |
| 1624 | body.chat #chat-input-line > input[type=text] { |
| 1625 | flex: 5 1 auto; |
| 1626 | } |
| 1627 | body.chat #chat-input-file-area { |
| 1628 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1569,15 +1569,22 @@ | |
| 1569 | body.chat #chat-settings-button { |
| 1570 | } |
| 1571 | body.chat .chat-settings-popup { |
| 1572 | font-size: 0.8em; |
| 1573 | text-align: left; |
| 1574 | display: flex; |
| 1575 | flex-direction: column; |
| 1576 | align-items: stretch; |
| 1577 | padding: 0.25em; |
| 1578 | } |
| 1579 | body.chat .chat-settings-popup > span { |
| 1580 | margin: 0.25em 0.2em; |
| 1581 | padding: 0.5em; |
| 1582 | white-space: nowrap; |
| 1583 | cursor: pointer; |
| 1584 | border: 1px outset; |
| 1585 | border-radius: 0.25em; |
| 1586 | } |
| 1587 | body.chat #chat-messages-wrapper { |
| 1588 | display: flex; |
| 1589 | flex-direction: column; |
| 1590 | } |
| @@ -1617,11 +1624,11 @@ | |
| 1624 | align-items: center; |
| 1625 | } |
| 1626 | body.chat #chat-input-line > input[type=submit] { |
| 1627 | flex: 1 5 auto; |
| 1628 | max-width: 6em; |
| 1629 | margin: 0 1em; |
| 1630 | } |
| 1631 | body.chat #chat-input-line > input[type=text] { |
| 1632 | flex: 5 1 auto; |
| 1633 | } |
| 1634 | body.chat #chat-input-file-area { |
| 1635 |