Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Reimplemented chat message operations popup as an inlined DOM element to enable a confirmation option on the global delete button, per request from drh (and it's also more platform-portable). |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
fb9026e2648cec21d6ad4081e304dd63 |
| User & Date: | stephan 2021-09-21 16:10:28.206 |
Context
|
2021-09-21
| ||
| 16:28 | Removed some extraneous console debug output. ... (check-in: 8663dde1df user: stephan tags: trunk) | |
| 16:10 | Reimplemented chat message operations popup as an inlined DOM element to enable a confirmation option on the global delete button, per request from drh (and it's also more platform-portable). ... (check-in: fb9026e264 user: stephan tags: trunk) | |
| 15:02 | Updated changelog for chat preview. Hyperlinks in preview mode now have target=_blank. Removed extraneous FORM element around chat input area, as it caused only grief with regards to Enter key handling (always activating the first button in the list, which is now the preview button). ... (check-in: 60ed1ff951 user: stephan tags: trunk) | |
Changes
Changes to src/chat.c.
| ︙ | ︙ | |||
194 195 196 197 198 199 200 | @ <button>Close Settings</button> @ </div> @ <div id='chat-messages-wrapper'> /* New chat messages get inserted immediately after this element */ @ <span id='message-inject-point'></span> @ </div> fossil_free(zProjectName); | | | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
@ <button>Close Settings</button>
@ </div>
@ <div id='chat-messages-wrapper'>
/* New chat messages get inserted immediately after this element */
@ <span id='message-inject-point'></span>
@ </div>
fossil_free(zProjectName);
builtin_fossil_js_bundle_or("popupwidget", "storage", "fetch",
"pikchr", "confirmer", NULL);
/* Always in-line the javascript for the chat page */
@ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
/* We need an onload handler to ensure that window.fossil is
initialized before the chat init code runs. */
@ window.addEventListener('load', function(){
@ document.body.classList.add('chat')
@ /*^^^for skins which add their own BODY tag */;
|
| ︙ | ︙ |
Changes to src/chat.js.
| ︙ | ︙ | |||
628 629 630 631 632 633 634 |
/**
Constructor. If passed an argument, it is passed to
this.setMessage() after initialization.
*/
const cf = function(){
this.e = {
body: D.addClass(D.div(), 'message-widget'),
| | | 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
/**
Constructor. If passed an argument, it is passed to
this.setMessage() after initialization.
*/
const cf = function(){
this.e = {
body: D.addClass(D.div(), 'message-widget'),
tab: D.addClass(D.div(), 'message-widget-tab'),
content: D.addClass(D.div(), 'message-widget-content')
};
D.append(this.e.body, this.e.tab, this.e.content);
this.e.tab.setAttribute('role', 'button');
if(arguments.length){
this.setMessage(arguments[0]);
}
|
| ︙ | ︙ | |||
690 691 692 693 694 695 696 |
}
const d = new Date(m.mtime);
D.clearElement(this.e.tab);
var contentTarget = this.e.content;
var eXFrom /* element holding xfrom name */;
if(m.xfrom){
eXFrom = D.append(D.addClass(D.span(), 'xfrom'), m.xfrom);
| | | | | | 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
}
const d = new Date(m.mtime);
D.clearElement(this.e.tab);
var contentTarget = this.e.content;
var eXFrom /* element holding xfrom name */;
if(m.xfrom){
eXFrom = D.append(D.addClass(D.span(), 'xfrom'), m.xfrom);
const wrapper = D.append(
D.span(), eXFrom,
D.text(" #",(m.msgid||'???'),' @ ',theTime(d)))
D.append(this.e.tab, wrapper);
}else{/*notification*/
D.addClass(this.e.body, 'notification');
if(m.isError){
D.addClass([contentTarget, this.e.tab], 'error');
}
D.append(
this.e.tab,
|
| ︙ | ︙ | |||
749 750 751 752 753 754 755 |
contentTarget.innerHTML = m.xmsg;
contentTarget.querySelectorAll('a').forEach(addAnchorTargetBlank);
if(F.pikchr){
F.pikchr.addSrcView(contentTarget.querySelectorAll('svg.pikchr'));
}
}
}
| | | | | | | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 |
contentTarget.innerHTML = m.xmsg;
contentTarget.querySelectorAll('a').forEach(addAnchorTargetBlank);
if(F.pikchr){
F.pikchr.addSrcView(contentTarget.querySelectorAll('svg.pikchr'));
}
}
}
this.e.tab.firstElementChild.addEventListener('click', this._handleLegendClicked, false);
/*if(eXFrom){
eXFrom.addEventListener('click', ()=>this.e.tab.click(), false);
}*/
return this;
},
/* Event handler for clicking .message-user elements to show their
timestamps. */
_handleLegendClicked: function f(ev){
if(!f.popup){
/* Timestamp popup widget */
f.popup = {
e: D.addClass(D.div(), 'chat-message-popup'),
refresh:function(){
const eMsg = this.$eMsg/*.message-widget element*/;
if(!eMsg) return;
D.clearElement(this.e);
const d = new Date(eMsg.dataset.timestamp);
if(d.getMinutes().toString()!=="NaN"){
// Date works, render informative timestamps
const xfrom = eMsg.dataset.xfrom || 'server';
D.append(this.e,
|
| ︙ | ︙ | |||
800 801 802 803 804 805 806 |
btnDeleteLocal.addEventListener('click', function(){
self.hide();
Chat.deleteMessageElem(eMsg);
});
if(Chat.userMayDelete(eMsg)){
const btnDeleteGlobal = D.button("Delete globally");
D.append(toolbar, btnDeleteGlobal);
| | > > > > | | > | > > > | < < | > | > > > | | > > > > | | < > | < < < | < < < | | | 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 |
btnDeleteLocal.addEventListener('click', function(){
self.hide();
Chat.deleteMessageElem(eMsg);
});
if(Chat.userMayDelete(eMsg)){
const btnDeleteGlobal = D.button("Delete globally");
D.append(toolbar, btnDeleteGlobal);
F.confirmer(btnDeleteGlobal,{
pinSize: true,
ticks: F.config.confirmerButtonTicks,
confirmText: "Confirm delete?",
onconfirm:function(){
self.hide();
Chat.deleteMessage(eMsg);
}
});
}
const toolbar2 = D.addClass(D.div(), 'toolbar');
D.append(this.e, toolbar2);
const btnToggleText = D.button("Toggle text mode");
btnToggleText.addEventListener('click', function(){
self.hide();
Chat.toggleTextMode(eMsg);
},false);
D.append(toolbar2, btnToggleText);
if(eMsg.dataset.xfrom){
/* Add a link to the /timeline filtered on this user. */
const timelineLink = D.attr(
D.a(F.repoUrl('timeline',{
u: eMsg.dataset.xfrom,
y: 'a'
}), "User's Timeline"),
'target', '_blank'
);
D.append(toolbar2, timelineLink);
}
const tab = eMsg.querySelector('.message-widget-tab');
D.append(tab, this.e);
D.removeClass(this.e, 'hidden');
}/*refresh()*/,
hide: function(){
D.addClass(D.clearElement(this.e), 'hidden');
delete this.$eMsg;
},
show: function(tgtMsg){
if(tgtMsg === this.$eMsg){
this.hide();
return;
}
this.$eMsg = tgtMsg;
this.refresh();
}
}/*f.popup*/;
}/*end static init*/
console.debug("event =",ev);
console.debug("event.target =",ev.target);
let theMsg = ev.target;
while( theMsg && !theMsg.classList.contains('message-widget')){
theMsg = theMsg.parentNode;
}
if(theMsg) f.popup.show(theMsg);
}/*_handleLegendClicked()*/
};
return cf;
})()/*MessageWidget*/;
const BlobXferState = (function(){/*drag/drop bits...*/
/* State for paste and drag/drop */
|
| ︙ | ︙ |
Changes to src/style.chat.css.
| ︙ | ︙ | |||
68 69 70 71 72 73 74 |
font-style: italic;
font-weight: bold;
}
/* The popup element for displaying message timestamps
and deletion controls. */
body.chat .chat-message-popup {
font-family: monospace;
| | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
font-style: italic;
font-weight: bold;
}
/* The popup element for displaying message timestamps
and deletion controls. */
body.chat .chat-message-popup {
font-family: monospace;
font-size: 0.9em;
text-align: left;
display: flex;
flex-direction: column;
align-items: stretch;
padding: 0.25em;
margin-top: 0.25em;
}
/* Full message timestamps. */
body.chat .chat-message-popup > span { white-space: nowrap; }
/* Container for the message deletion buttons. */
body.chat .chat-message-popup > .toolbar {
padding: 0;
margin: 0;
|
| ︙ | ︙ |