From 52e23096ff3ed8d989cb100715082329704b003d Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 14 Dec 2021 16:17:53 -0500 Subject: [PATCH] Major change to the javascript forum view. We now wait for all messages to be loaded before rendering them all in one shot. Rendering works, opening the reply box works, saving a message works, but we still have to figure out how to render a message in the location where it was entered. Or maybe that's not a good idea? Also the scroll_to semantics are broken but we are in a better position to redo this in a simpler way. --- webcit-ng/forum_view.c | 11 -- webcit-ng/static/js/main.js | 52 -------- webcit-ng/static/js/util.js | 49 ++++++++ webcit-ng/static/js/view_forum.js | 192 ++++++++++++++++-------------- 4 files changed, 154 insertions(+), 150 deletions(-) diff --git a/webcit-ng/forum_view.c b/webcit-ng/forum_view.c index f3a9b5853..c6aedbd1a 100644 --- a/webcit-ng/forum_view.c +++ b/webcit-ng/forum_view.c @@ -1,4 +1,3 @@ -// // Forum view (threaded/flat) // // Copyright (c) 1996-2021 by the citadel.org team @@ -15,16 +14,6 @@ #include "webcit.h" -struct mthread { - long msgnum; - time_t datetime; - int threadhash; - int refhashes[10]; - char from[64]; - int parent; -}; - - // Commands we need to send to Citadel Server before we begin rendering forum view. // These are common to flat and threaded views. void setup_for_forum_view(struct ctdlsession *c) { diff --git a/webcit-ng/static/js/main.js b/webcit-ng/static/js/main.js index 10e953a60..05d7fc40b 100644 --- a/webcit-ng/static/js/main.js +++ b/webcit-ng/static/js/main.js @@ -31,58 +31,6 @@ function _(x) { } -// Generate a random string of the specified length -// Useful for generating one-time-use div names -// -function randomString(length) { - var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split(''); - var str = ''; - - if (!length) { - length = Math.floor(Math.random() * chars.length); - } - for (var i = 0; i < length; i++) { - str += chars[Math.floor(Math.random() * chars.length)]; - } - return str; -} - - -// string escape for html display -// -function escapeHTML(text) { - 'use strict'; - return text.replace(/[\"&<>]/g, function (a) { - return { - '"': '"', - '&': '&', - '<': '<', - '>': '>' - }[a]; - }); -} - - -// string escape for html display -// -function escapeHTMLURI(text) { - 'use strict'; - return text.replace(/./g, function (a) { - return '%' + a.charCodeAt(0).toString(16); - }); -} - - -// string escape for JavaScript string -// -function escapeJS(text) { - 'use strict'; - return text.replace(/[\"\']/g, function (a) { - return '\\' + a ; - }); -} - - // This is called at the very beginning of the main page load. // ctdl_startup = async() => { diff --git a/webcit-ng/static/js/util.js b/webcit-ng/static/js/util.js index ec5c1d062..eba84e238 100644 --- a/webcit-ng/static/js/util.js +++ b/webcit-ng/static/js/util.js @@ -42,3 +42,52 @@ function quoted_printable_encode(str) { // Strip last softline break return str.substr(0, str.length - 3) } + + +// Generate a random string of the specified length +// Useful for generating one-time-use div names +function randomString(length) { + var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split(''); + var str = ''; + + if (!length) { + length = Math.floor(Math.random() * chars.length); + } + for (var i = 0; i < length; i++) { + str += chars[Math.floor(Math.random() * chars.length)]; + } + return str; +} + + +// string escape for html display +function escapeHTML(text) { + 'use strict'; + return text.replace(/[\"&<>]/g, function (a) { + return { + '"': '"', + '&': '&', + '<': '<', + '>': '>' + }[a]; + }); +} + + +// string escape for html display +function escapeHTMLURI(text) { + 'use strict'; + return text.replace(/./g, function (a) { + return '%' + a.charCodeAt(0).toString(16); + }); +} + + +// string escape for JavaScript string +// +function escapeJS(text) { + 'use strict'; + return text.replace(/[\"\']/g, function (a) { + return '\\' + a ; + }); +} diff --git a/webcit-ng/static/js/view_forum.js b/webcit-ng/static/js/view_forum.js index b804702bc..3950000b3 100644 --- a/webcit-ng/static/js/view_forum.js +++ b/webcit-ng/static/js/view_forum.js @@ -59,10 +59,15 @@ function forum_readmessages(target_div, gt_msg, lt_msg) { } // Render an empty div for each message. We will fill them in later. - for (var i in msgs) { - document.getElementById(target_div).innerHTML += "
" ; - document.getElementById("ctdl_msg_"+msgs[i]).style.display = "none"; - } + //for (var i in msgs) { + //document.getElementById(target_div).innerHTML += "
" ; + //} + + // The messages will go here. + let msgs_div_name = "ctdl_msgs_" + randomString(5); + document.getElementById(target_div).innerHTML += "
" ; + + if (lt_msg == 9999999999) { new_new_div_name = randomString(5); if (msgs.length <= 0) { @@ -94,7 +99,7 @@ function forum_readmessages(target_div, gt_msg, lt_msg) { } // Render the individual messages in the divs - forum_render_messages(msgs, "ctdl_msg_", scroll_to) + forum_render_messages(msgs, msgs_div_name, scroll_to) } else { // if xhr fails, this will make the link reappear so the user can try again @@ -105,85 +110,97 @@ function forum_readmessages(target_div, gt_msg, lt_msg) { } -// Render a range of messages, with the div prefix specified -function forum_render_messages(msgs, prefix, scroll_to) { - for (i=0; i response.json()); } + + // Here is the async function that waits for all the messages to be loaded, and then renders them. + fetch_msg_list = async() => { + document.body.style.cursor = "wait"; + await Promise.all(msg_promises); + document.body.style.cursor = "default"; + + // At this point all of the Promises are resolved and we can render. + // Note: "let" keeps "i" in scope even through the .then scope + for (let i=0; i { + document.getElementById(msgs_div_name).innerHTML += + forum_render_one(message_numbers[i], one_message); + }); + //if (msgnum == scroll_to) { + //document.getElementById(prefix+msgnum).scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"}); + //} + } + } + + fetch_msg_list(); } // We have to put each XHR for forum_render_messages() into its own stack frame, otherwise it jumbles them together. I don't know why. -function forum_render_one(prefix, msgnum, scroll_to) { +function forum_render_one(msgnum, msg) { - console.log("Rendering message " + msgnum + " in div " + prefix+msgnum); - document.getElementById(prefix+msgnum).innerHTML = "render the stuff here"; + mdiv = randomString(10); // div name for this message - document.body.style.cursor = "wait"; - fetch_message = async() => { - response = await fetch("/ctdl/r/" + escapeHTMLURI(current_room) + "/" + msgs[i] + "/json"); - msg = await response.json(); - if (response.ok) { - outmsg = - "
" // begin message wrapper - + "
" // begin avatar - + "" - + "
" // end avatar - + "
" // begin content - + "
" // begin header - + "" // begin header info on left side - + "" // FIXME link to user profile - + msg.from - + "" // end username - + "" - + msg.time - + "" // end msgdate - + "" // end header info on left side - + "" // begin buttons on right side - - + "" // Reply - + "" - + " " - + _("Reply") - + "" - - + "" // ReplyQuoted - + "" - + " " - + _("ReplyQuoted") - + "" - - + "" // Delete , show only with permission FIXME - + " " - + _("Delete") - + "" - - + ""; // end buttons on right side - if (msg.subj) { - outmsg += - "
" + msg.subj + ""; - } - outmsg += - "

" // end header - + "
" // begin body - + msg.text - + "
" // end body - + "
" // end content - + "
" // end wrapper - ; - document.getElementById(prefix+msgnum).innerHTML = outmsg; - } - else { - document.getElementById(prefix+msgnum).innerHTML = "ERROR"; - } - document.getElementById(prefix+msgnum).style.display = "inline"; - if (msgnum == scroll_to) { - document.getElementById(prefix+msgnum).scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"}); - document.body.style.cursor = "default"; - } + outmsg = + "
" // begin message div + + "
" // begin message wrapper + + "
" // begin avatar + + "" + + "
" // end avatar + + "
" // begin content + + "
" // begin header + + "" // begin header info on left side + + "" // FIXME link to user profile + + msg.from + + "" // end username + + "" + + msg.time + + "" // end msgdate + + "" // end header info on left side + + "" // begin buttons on right side + + + "" // Reply + + "" + + " " + + _("Reply") + + "" + + + "" // ReplyQuoted + + "" + + " " + + _("ReplyQuoted") + + "" + + + "" // Delete , show only with permission FIXME + + " " + + _("Delete") + + "" + + + ""; // end buttons on right side + if (msg.subj) { + outmsg += + "
" + msg.subj + ""; } - fetch_message(); + outmsg += + "

" // end header + + "
" // begin body + + msg.text + + "
" // end body + + "
" // end content + + "
" // end wrapper + + "
" // end message div + ; + + return(outmsg); } @@ -208,11 +225,12 @@ function compose_references(references, msgid) { // Open a reply box directly below a specific message -function open_reply_box(prefix, msgnum, is_quoted, references, msgid) { +function open_reply_box(parent_div, is_quoted, references, msgid) { let new_div = document.createElement("div"); - let new_div_name = prefix + "reply_to_" + msgnum; + let new_div_name = randomString(10); new_div.id = new_div_name; - document.getElementById(prefix+msgnum).append(new_div); + + document.getElementById(parent_div).append(new_div); replybox = "
" // begin message wrapper @@ -253,13 +271,13 @@ function open_reply_box(prefix, msgnum, is_quoted, references, msgid) { + "" + ""; // end buttons on right side - if (msg.subj) { - replybox += - "
" + "FIXME subject" + ""; - } - else { // hidden filed for empty subject + //if (msg.subj) { + //replybox += + //"
" + "FIXME subject" + ""; + //} + //else { // hidden filed for empty subject replybox += ""; - } + //} replybox += "

" // end header @@ -276,7 +294,7 @@ function open_reply_box(prefix, msgnum, is_quoted, references, msgid) { + "" // end footer info on left side + "" // begin buttons on right side - + "" + + "" + " " // save button + _("Post message") + "" @@ -337,7 +355,7 @@ function forum_cancel_post(div_name) { // Save the posted message to the server -function forum_save_message(prefix, editor_div_name) { +function forum_save_message(editor_div_name) { document.body.style.cursor = "wait"; wefw = (document.getElementById("ctdl-replyreferences").innerHTML).replaceAll("|","!"); // references (if present) -- 2.39.2