diff options
Diffstat (limited to 'view/js')
-rw-r--r-- | view/js/acl.js | 12 | ||||
-rw-r--r-- | view/js/autocomplete.js | 2 | ||||
-rw-r--r-- | view/js/main.js | 1335 | ||||
-rw-r--r-- | view/js/mod_articles.js | 2 | ||||
-rw-r--r-- | view/js/mod_cards.js | 2 | ||||
-rw-r--r-- | view/js/mod_cloud.js | 57 | ||||
-rw-r--r-- | view/js/mod_connections.js | 2 | ||||
-rw-r--r-- | view/js/mod_help.js | 61 | ||||
-rw-r--r-- | view/js/mod_hq.js | 3 | ||||
-rw-r--r-- | view/js/mod_import_progress.js | 6 | ||||
-rw-r--r-- | view/js/mod_photos.js | 57 |
11 files changed, 989 insertions, 550 deletions
diff --git a/view/js/acl.js b/view/js/acl.js index ee6cb062f..a96c39090 100644 --- a/view/js/acl.js +++ b/view/js/acl.js @@ -300,7 +300,7 @@ ACL.prototype.update_view = function(value) { that.update_select('public'); /* jot acl */ - $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-lock').addClass('fa-unlock'); + $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('bi-lock').addClass('bi-unlock'); $('#jot-perms-icon').removeClass('jot-lock-warn'); $('#dbtn-jotnets').show(); $('.profile-jot-net input').attr('disabled', false); @@ -314,7 +314,7 @@ ACL.prototype.update_view = function(value) { that.update_select(that.selected_id); /* jot acl */ - $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock'); + $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('bi-unlock').addClass('bi-lock'); $('#dbtn-jotnets').hide(); $('.profile-jot-net input').attr('disabled', 'disabled'); } @@ -326,7 +326,7 @@ ACL.prototype.update_view = function(value) { that.update_select('onlyme'); /* jot acl */ - $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock'); + $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('bi-unlock').addClass('bi-lock'); $('#dbtn-jotnets').hide(); $('.profile-jot-net input').attr('disabled', 'disabled'); } @@ -349,7 +349,7 @@ ACL.prototype.update_view = function(value) { } /* jot acl */ - $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock'); + $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('bi-unlock').addClass('bi-lock'); $('#dbtn-jotnets').hide(); $('.profile-jot-net input').attr('disabled', 'disabled'); } @@ -366,12 +366,12 @@ ACL.prototype.update_view = function(value) { /* jot acl */ if(that.allow_gid.length === 0 && that.allow_cid.length === 0 && that.deny_gid.length === 0 && that.deny_cid.length === 0 && value === 'custom') { - $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-lock').addClass('fa-unlock'); + $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('bi-lock').addClass('bi-unlock'); $('#dbtn-jotnets').show(); $('.profile-jot-net input').attr('disabled', false); } else { - $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock'); + $('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('bi-unlock').addClass('bi-lock'); $('#dbtn-jotnets').hide(); $('.profile-jot-net input').attr('disabled', 'disabled'); } diff --git a/view/js/autocomplete.js b/view/js/autocomplete.js index 7d6ddb1c4..ad8e04050 100644 --- a/view/js/autocomplete.js +++ b/view/js/autocomplete.js @@ -38,7 +38,7 @@ function contact_format(item) { var desc = ((item.label) ? item.nick + ' ' + item.label : item.nick); if(typeof desc === 'undefined') desc = ''; if(desc) desc = ' ('+desc+')'; - return "<div class='dropdown-item dropdown-notification lh-sm text-truncate' title='{4}'><img class='menu-img-2' src='{1}' loading='lazy'><strong>{2}</strong><br><small class='opacity-75'>{4}</small></div>".format(item.taggable, item.photo, item.name, desc, typeof(item.link) !== 'undefined' ? item.link : desc.replace('(','').replace(')','')); + return "<div class='dropdown-item dropdown-notification lh-sm text-truncate' title='{4}'><img class='menu-img-2' src='{1}' loading='lazy'><strong>{2}</strong><br><small class='text-body-secondary'>{4}</small></div>".format(item.taggable, item.photo, item.name, desc, typeof(item.link) !== 'undefined' ? item.link : desc.replace('(','').replace(')','')); } else return ""; diff --git a/view/js/main.js b/view/js/main.js index 7eca7408e..5bf7234aa 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -25,6 +25,11 @@ var savedTitle = ''; var followUpPageLoad = false; var window_needs_alert = true; var expanded_items = []; +var updateTimeout = []; +const singlethread_modules = ['display', 'hq']; +const redirect_modules = ['display', 'notify']; +let b64mids = []; + var page_cache = {}; @@ -58,42 +63,18 @@ $.ajaxSetup({cache: false}); var tf = new Function('n', 's', 'var k = s.split("/")['+aStr['plural_func']+']; return (k ? k : s);'); -jQuery.timeago.settings.strings = { - prefixAgo : aStr['t01'], - prefixFromNow : aStr['t02'], - suffixAgo : aStr['t03'], - suffixFromNow : aStr['t04'], - seconds : aStr['t05'], - minute : aStr['t06'], - minutes : function(value){return tf(value, aStr['t07']);}, - hour : aStr['t08'], - hours : function(value){return tf(value, aStr['t09']);}, - day : aStr['t10'], - days : function(value){return tf(value, aStr['t11']);}, - month : aStr['t12'], - months : function(value){return tf(value, aStr['t13']);}, - year : aStr['t14'], - years : function(value){return tf(value, aStr['t15']);}, - wordSeparator : aStr['t16'], - numbers : aStr['t17'], -}; - -jQuery.timeago.settings.allowFuture = true; - $(document).ready(function() { $(document).on('click focus', '.comment-edit-form', handle_comment_form); $(document).on('click', '.conversation-settings-link', getConversationSettings); $(document).on('click', '#settings_module_ajax_submit', postConversationSettings); - $(document).on('click', '#expand-aside', function() { - toggleAside(); - }); + $(document).on('click', '#expand-aside', toggleAside); $(document).on('click focus', '.comment-edit-form textarea', function(e) { if(! this.autocomplete_handled) { /* autocomplete @nicknames */ - $(this).editor_autocomplete(baseurl+"/acl?f=&n=1"); + $(this).editor_autocomplete(baseurl+"/acl?n=1"); /* autocomplete bbcode */ $(this).bbco_autocomplete('bbcode'); @@ -108,13 +89,153 @@ $(document).ready(function() { } }); + document.addEventListener('click', function(event) { + // Only handle clicks on .wall-item-reaction or its children + const target = event.target.closest('.wall-item-reaction'); + if (!target) return; + + let doRequest = true; + const isUserClick = event.isTrusted; + + // Destructure relevant data attributes + const { itemId: id, itemMid: mid, itemParent: parentId, itemUuid: uuid, itemVerb: verb } = target.dataset; + const isCommentBtn = target.classList.contains('wall-item-comment'); + + if (isCommentBtn) { + if (id === parentId) { + // Handle blog mode + target.classList.add('disabled'); + document.getElementById(`load-more-progress-wrapper-${id}`).classList.remove('d-none'); + document.getElementById(`load-more-${id}`).classList.remove('d-none') + request(id, mid, 'load', parentId, uuid, isUserClick); + return; + } + + // Get relevant DOM elements + const threadWrapper = document.getElementById(`thread-wrapper-${id}`); + const parentWrapper = document.getElementById(`thread-wrapper-${parentId}`); + const subThreadWrapper = document.getElementById(`wall-item-sub-thread-wrapper-${id}`); + const parentSubThreadWrapper = document.getElementById(`wall-item-sub-thread-wrapper-${parentId}`); + + // Query related sub-thread and highlight elements + const parentIndentedThreads = document.querySelectorAll(`#wall-item-sub-thread-wrapper-${parentId} .wall-item-sub-thread-wrapper.item-indent`); + + let ancestorIds = []; + + doRequest = !subThreadWrapper.children.length; + + // Set visual styles using UUID + subThreadWrapper.style.setProperty('--hz-item-indent', stringToHslColor(uuid)); + threadWrapper.style.setProperty('--hz-item-highlight', stringToHslColor(uuid)); + threadWrapper.style.setProperty('--hz-wall-item-expanded-before-content', '"' + aStr.dblclick_to_exit_zoom + '"'); + + // Clear previous highlights + parentSubThreadWrapper.querySelectorAll('.thread-wrapper.item-highlight').forEach(el => el.classList.remove('item-highlight')); + + if (isUserClick && parentIndentedThreads.length === 0 && !subThreadWrapper.children.length) { + // Handle first-time expansion and highlighting but not for toplevels (blog mode) + threadWrapper.classList.add('item-highlight'); + } else { + // Handle indentation and zooming + let ancestor = subThreadWrapper.parentElement; + ancestorIds.push(ancestor.id.slice(15)); // thread-wrapper-1234 + + while (ancestor) { + if (ancestor.classList.contains('item-indent') && ancestor.classList.contains('wall-item-sub-thread-wrapper')) { + ancestorIds.push(ancestor.parentElement.id.slice(15)); + } + ancestor = ancestor.parentElement; + } + + ancestorIds.reverse(); + + if (ancestorIds.length > 3) { + // Handle zooming in + let firstWrapper = document.getElementById('thread-wrapper-' + ancestorIds[0]); + let firstSubWrapper = document.getElementById('wall-item-sub-thread-wrapper-' + ancestorIds[0]); + + firstWrapper.querySelector('.wall-item-comment').classList.remove('indented'); + firstWrapper.classList.remove('wall-item-expanded', 'shadow'); + firstSubWrapper.classList.remove('item-indent'); + + let newFirstWrapper = document.getElementById('thread-wrapper-' + ancestorIds[1]) + let newFirstSubWrapper = document.getElementById('wall-item-sub-thread-wrapper-' + ancestorIds[1]) + + newFirstWrapper.classList.add('wall-item-expanded', 'shadow'); + parentWrapper.classList.add('wall-item-backdrop'); + + // Exit zoom on double-click + newFirstWrapper.addEventListener('dblclick', function() { + parentWrapper.querySelectorAll('.wall-item-comment.indented').forEach(el => el.classList.remove('indented')); + parentWrapper.querySelectorAll('.wall-item-comment.collapsed').forEach(el => el.classList.remove('collapsed')); + parentWrapper.classList.remove('wall-item-backdrop'); + parentWrapper.querySelectorAll('.wall-item-sub-thread-wrapper.item-indent').forEach(el => el.classList.remove('item-indent')); + parentWrapper.querySelectorAll('.wall-item-sub-thread-wrapper.d-none').forEach(el => el.classList.remove('d-none')); + parentWrapper.querySelectorAll('.thread-wrapper.wall-item-expanded').forEach(el => el.classList.remove('wall-item-expanded', 'shadow')); + }, { once: true }); + } + + // Toggle sub-thread visibility if indented + if (isUserClick && target.classList.contains('indented')) { + doRequest = false; + subThreadWrapper.classList.toggle('d-none'); + target.classList.toggle('collapsed'); + } + + // Indenting of already expanded but flattened items + if (isUserClick && subThreadWrapper.classList.contains('item-expanded') && !subThreadWrapper.classList.contains('item-indent')) { + doRequest = false; + + threadWrapper.querySelectorAll('.wall-item-sub-thread-wrapper.item-expanded').forEach(function (el, i) { + el.classList.add('item-indent'); + + el.querySelectorAll('.wall-item-comment.expanded').forEach(function (el, i) { + el.classList.add('collapsed', 'indented'); + }); + + // Collapse everything below the first level + if (i > 0) { + el.classList.add('d-none'); + } + }); + } + + // Indent the subthread + subThreadWrapper.classList.add('item-indent', 'item-expanded'); + + // Mark as indented after visibility toggle + target.classList.add('indented'); + } + + // Mark as expanded + target.classList.add('expanded'); + } + + if (doRequest) { + request(id, mid, verb, parentId, uuid, isUserClick); + } + }); + + document.addEventListener('click', function(event) { + const targetElement = event.target.closest('.dropdown-item-expand'); + if (!targetElement) return; + + event.preventDefault(); + + const id = targetElement.dataset.itemId; + const subWrapper = document.getElementById(`wall-item-sub-thread-wrapper-${id}`); + + subWrapper.innerHTML = ''; + autoExpand(id); + }); + // @hilmar |-> if ( typeof(window.tao) == 'undefined' ) { window.tao = {}; } if ( typeof(window.tao.zin) == 'undefined' ) { tao.zin = { syslc: '', syslcs: {}, htm: '', me: '', debug: '' }; - tao.zin.axim = '<div class="zinpax fa fa-sync fa-spin"> </div>'; + tao.zin.axim = '<i class="zinpax bi bi-arrow-repeat"></i>'; $('.navbar-app[href*="/lang"]').attr({"aria-expand": "true", "id": "zintog"}) .removeAttr('href').addClass('zinlcx zinlcxp dropdown dropdown-toggle').css('cursor','pointer'); $('.nav-link[href*="/lang"]').addClass('zinlcxmi zinlcx').removeAttr('href').css('cursor','pointer'); @@ -129,9 +250,9 @@ $(document).ready(function() { tao.zin.re = JSON.parse(re); tao.zin.syslc = tao.zin.re.lc; tao.zin.syslcs = tao.zin.re.lcs; - tao.zin.htm = '<ul class="zinlcs fa-ul">'; + tao.zin.htm = '<ul class="zinlcs">'; $.each( tao.zin.syslcs, function( k, v ) { - tao.zin.htm += '<li><a id="zinlc' + k + '" class="zinlc nav-link fakelink">' + k + ' ' + v + '</a></li>'; + tao.zin.htm += '<li><a id="zinlc' + k + '" class="zinlc fakelink">' + k + ' ' + v + '</a></li>'; }); tao.zin.htm += '</ul>'; $('.zinpax').remove(); @@ -172,17 +293,20 @@ $(document).ready(function() { let notify_id = this.dataset.notify_id; let path = $(this)[0].pathname.split('/')[1]; let stateObj = { b64mid: b64mid }; - let singlethread_modules = ['display', 'hq']; - let redirect_modules = ['display', 'notify']; - if(! b64mid && ! notify_id) + if (!b64mid && !notify_id) { return; + } - if(localUser && redirect_modules.indexOf(path) !== -1) { + if (document.querySelector('main').classList.contains('region_1-on')) { + toggleAside(); + } + + if (localUser && redirect_modules.indexOf(path) !== -1) { path = 'hq'; } - if(notify_id) { + if (notify_id) { $.ajax({ type: 'post', url: 'notify', @@ -198,21 +322,17 @@ $(document).ready(function() { window.location.href = path + '/' + b64mid; } else { - if (singlethread_modules.indexOf(module) !== -1) { history.pushState(stateObj, '', module + '/' + b64mid); - } if (b64mid) { - e.preventDefault(); - - if(! page_load) { + if (!page_load) { prepareLiveUpdate(b64mid, notify_id); $('.message').removeClass('active'); $('[data-b64mid="' + b64mid + '"].message').addClass('active'); - $('[data-b64mid="' + b64mid + '"].message .badge').remove(); + $('[data-b64mid="' + b64mid + '"].message .unseen_count').remove(); } } } @@ -231,44 +351,44 @@ $(document).ready(function() { updateInit(); - var e = document.getElementById('content-complete'); - if(e) + if (document.getElementById('content-complete')) { pageHasMoreContent = false; + } - $(document).on('hz:updateConvItems', function(event) { - if(!bParam_mid) + document.addEventListener('hz:updateConvItems', function(e) { + if (!bParam_mid) { cache_next_page(); + } }); - $(document).on('hz:handleNetworkNotificationsItems', function(e, obj) { + document.addEventListener('hz:handleNetworkNotificationsItems', function(e) { push_notification( - obj.name, - $('<p>' + obj.message + '</p>').text(), - obj.b64mid + e.detail.name, + $('<p>' + e.detail.message + '</p>').text(), + e.detail.b64mid ); }); }); function getConversationSettings() { - $.get('settings/conversation/?f=&aj=1',function(data) { + $.get('settings/conversation/?aj=1',function(data) { $('#conversation_settings_body').html(data); }); } function postConversationSettings() { - $.post( - 'settings/conversation', - $('#settings_module_ajax_form').serialize() + "&auto_update=" + next_page - ); - if(next_page === 1) { page_load = true; } - $('#conversation_settings').modal('hide'); - - if(timer) clearTimeout(timer); - timer = setTimeout(updateInit,100); + $.post( + 'settings/conversation', + $('#settings_module_ajax_form').serialize() + "&auto_update=" + next_page + ).done(function() { + $('#conversation_settings').modal('hide'); + toast('Conversation features updated', 'info'); + updateInit(); + }); return false; } @@ -351,6 +471,13 @@ function handle_comment_form(e) { var commentSaveTimer = null; var emptyCommentElm = form.find('.comment-edit-text').attr('id'); var convId = emptyCommentElm.replace('comment-edit-text-',''); + + // in case parent input is set use it as convId + const parentInputVal = form.find(':input[name=parent]').val(); + if (parentInputVal) { + convId = parentInputVal; + } + $('#' + emptyCommentElm).on('focusout',function(e){ if(commentSaveTimer) clearTimeout(commentSaveTimer); @@ -469,16 +596,18 @@ function inserteditortag(BBcode, id) { } function insertCommentAttach(comment,id) { - activeCommentID = id; activeCommentText = comment; - $('body').css('cursor', 'wait'); - $('#invisible-comment-upload').trigger('click'); - return false; +} +function insertCommentEmbed(comment,id) { + activeCommentID = id; + activeCommentText = comment; + initializeEmbedPhotoDialog(); + return false; } function insertCommentURL(comment, id) { @@ -486,7 +615,7 @@ function insertCommentURL(comment, id) { if(reply && reply.length) { reply = bin2hex(reply); $('body').css('cursor', 'wait'); - $.get('linkinfo?f=&binurl=' + reply, function(data) { + $.get('linkinfo?binurl=' + reply, function(data) { var tmpStr = $("#comment-edit-text-" + id).val(); if(tmpStr == comment) { tmpStr = ""; @@ -515,17 +644,22 @@ function viewsrc(id) { } function showHideComments(id) { - if( $('#collapsed-comments-' + id).is(':visible')) { - $('#collapsed-comments-' + id + ' .autotime').timeago('dispose'); - $('#collapsed-comments-' + id).hide(); - $('#hide-comments-' + id).html(aStr.showmore); - $('#hide-comments-total-' + id).show(); - } else { - $('#collapsed-comments-' + id + ' .autotime').timeago(); - $('#collapsed-comments-' + id).show(); - $('#hide-comments-' + id).html(aStr.showfewer); - $('#hide-comments-total-' + id).hide(); + let collapsedComments = document.getElementById('collapsed-comments-' + id); + let hideCommentsLabel = document.getElementById('hide-comments-label-' + id); + let hideCommentsTotal = document.getElementById('hide-comments-total-' + id); + let hideCommentsIcon = document.getElementById('hide-comments-icon-' + id); + let isCollapsed = collapsedComments.style.display === 'none'; + + collapsedComments.style.display = isCollapsed ? '' : 'none'; + hideCommentsLabel.textContent = isCollapsed ? hideCommentsLabel.dataset.expanded : hideCommentsLabel.dataset.collapsed; + + if (hideCommentsTotal) { + hideCommentsTotal.style.display = isCollapsed ? 'none' : ''; } + + let oldClass = isCollapsed ? 'bi-chevron-down' : 'bi-chevron-up'; + let newClass = isCollapsed ? 'bi-chevron-up' : 'bi-chevron-down'; + hideCommentsIcon.classList.replace(oldClass, newClass); } function openClose(theID, display) { @@ -566,7 +700,7 @@ function closeMenu(theID) { } function markRead(notifType) { - $.get('notifications?f=&markRead='+notifType); + $.get('notifications?markRead='+notifType); $('.' + notifType + '-button').fadeOut(function() { $("." + notifType + "-update").html('0'); $('#nav-' + notifType + '-menu').html(''); @@ -579,7 +713,7 @@ function markRead(notifType) { } function markItemRead(itemId) { - $.get('notifications?f=&markItemRead='+itemId); + $.get('notifications?markItemRead='+itemId); $('.unseen-wall-indicator-'+itemId).remove(); } @@ -648,201 +782,378 @@ function updatePageItems(mode, data) { collapseHeight(); } - -function updateConvItems(mode,data) { - let scroll_position = $(window).scrollTop(); +function updateConvItems(mode, data) { + let scroll_position = window.scrollY; let b64mids = []; - if(mode !== 'update') - $(document).trigger('hz:updateConvItems'); + // Parse the data string into a DOM object + let parser = new DOMParser(); + let doc = parser.parseFromString(data, 'text/html'); - if(mode === 'update' || mode === 'replace') { - prev = 'threads-begin'; + if (mode !== 'update') { + document.dispatchEvent(new Event('hz:updateConvItems')); } - if(mode === 'append') { - next = 'threads-end'; + + let prev, next; + if (mode === 'update' || mode === 'replace') { + prev = document.getElementById('threads-begin'); + } + if (mode === 'append') { + next = document.getElementById('threads-end'); } - $('.thread-wrapper', data).each(function() { - if(this.classList.contains('toplevel_item')) { - let ident = this.id; - let convId = ident.replace('thread-wrapper-',''); - let commentWrap = $('#'+ident+' .collapsed-comments').attr('id'); + doc.querySelectorAll('.thread-wrapper').forEach(function (elem) { + if (elem.classList.contains('toplevel_item')) { + let ident = elem.id; + let convId = ident.replace('thread-wrapper-', ''); + let commentWrap = elem.querySelector('.collapsed-comments')?.id; let itmId = 0; let isVisible = false; // figure out the comment state - if(typeof commentWrap !== 'undefined') - itmId = commentWrap.replace('collapsed-comments-',''); + if (commentWrap !== undefined) { + itmId = commentWrap.replace('collapsed-comments-', ''); + } - if($('#collapsed-comments-'+itmId).is(':visible')) + let collapsedComment = document.getElementById('collapsed-comments-' + itmId); + if (collapsedComment && collapsedComment.style.display !== 'none') { isVisible = true; + } // insert the content according to the mode and first_page // and whether or not the content exists already (overwrite it) - - if($('#' + ident).length == 0) { - if((mode === 'update' || mode === 'replace') && profile_page == 1) { - $('#' + prev).after($(this)); - prev = ident; + let existingElem = document.getElementById(ident); + if (!existingElem) { + if ((mode === 'update' || mode === 'replace') && profile_page == 1) { + if (prev) { + prev.after(elem); + prev = elem; + } } - if(mode === 'append') { - $('#' + next).before($(this)); + if (mode === 'append') { + if (next) { + next.before(elem); + } } - } - else { - $('#' + ident).replaceWith($(this)); + } else { + existingElem.replaceWith(elem); } - // set the comment state to the state we discovered earlier + // DOMParser will prevent scripts from execution for security reasons. + // We remove all scripts but possibly injected some from + // addons like for example gallery later. + // TODO: make the script run from the addon itself. + let scripts = elem.querySelectorAll('script'); + scripts.forEach(script => { + let scriptContent = script.textContent || script.innerText; + eval(scriptContent); // Execute the script + }); - if(isVisible) + // set the comment state to the state we discovered earlier + if (isVisible) { showHideComments(itmId); + } let commentBody = localStorage.getItem("comment_body-" + convId); - - if(commentBody) { - var commentElm = $('#comment-edit-text-' + convId); - if(auto_save_draft) { - if($(commentElm).val() === '') { - $('#comment-edit-form-' + convId).show(); - $(commentElm).addClass("expanded"); + if (commentBody) { + let commentElm = document.getElementById('comment-edit-text-' + convId); + if (auto_save_draft && commentElm) { + if (commentElm.value === '') { + let commentForm = document.getElementById('comment-edit-form-' + convId); + if (commentForm) { + commentForm.style.display = 'block'; + } + commentElm.classList.add("expanded"); openMenu("comment-tools-" + convId); - $(commentElm).val(commentBody); + commentElm.value = commentBody; } } else { localStorage.removeItem("comment_body-" + convId); } } - // trigger the autotime function on all newly created content - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); - $("> .shared_header .autotime",this).timeago(); - - if((mode === 'append' || mode === 'replace') && (loadingPage)) { + if ((mode === 'append' || mode === 'replace') && loadingPage) { loadingPage = false; } - // if single thread view and the item has a title, display it in the title bar - - if(mode === 'replace') { - if (window.location.search.indexOf("mid=") != -1 || window.location.pathname.indexOf("display") != -1) { - let title = $(".wall-item-title").text(); - title.replace(/^\s+/, ''); - title.replace(/\s+$/, ''); - if (title) { - savedTitle = title + " " + savedTitle; - document.title = title; + // if single thread view and the item has a title, display it in the title bar + if (mode === 'replace') { + if (window.location.search.includes("mid=") || window.location.pathname.includes("display")) { + let titleElem = document.querySelector(".wall-item-title"); + if (titleElem) { + let title = titleElem.textContent.trim(); + if (title) { + savedTitle = title + ' ' + savedTitle; + document.title = title; + } } } } } - $(this).data('b64mids').forEach((b64mid) => { - b64mids.push(b64mid); - }); + let data_json = JSON.parse(elem.dataset.b64mids); + + if (elem.parentNode.classList.contains('wall-item-sub-thread-wrapper') && elem.parentNode.children.length) { + // Set the highlight state + if (data_json.includes(bParam_mid) && !elem.parentNode.parentNode.classList.contains('toplevel_item')) { + elem.parentNode.parentNode.classList.add('item-highlight'); + document.documentElement.style.setProperty('--hz-item-highlight', stringToHslColor(JSON.parse(elem.parentNode.parentNode.dataset.b64mids)[0])); + } + + let elemSubThreadWrapper = elem.querySelector('.wall-item-sub-thread-wrapper'); + let elemCommentButton = elem.querySelector('.wall-item-comment'); + + // Set the button and sub-thread-wrapper state + if (elemCommentButton && elemSubThreadWrapper.children.length) { + elemCommentButton.classList.add('expanded'); + } + + elem.parentNode.classList.add('item-expanded'); + } + b64mids.push(...data_json); }); - $(document).trigger('hz:sse_setNotificationsStatus', [b64mids]); + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); - $(window).scrollTop(scroll_position); + window.scrollTo(0, scroll_position); - if(followUpPageLoad) { - $(document).trigger('hz:sse_bs_counts'); - } - else { - $(document).trigger('hz:sse_bs_init'); + if (followUpPageLoad) { + document.dispatchEvent(new Event('hz:sse_bs_counts')); + } else { + document.dispatchEvent(new Event('hz:sse_bs_init')); } - if(commentBusy) { + if (commentBusy) { commentBusy = false; - $('body').css('cursor', 'auto'); + document.body.style.cursor = 'auto'; } - // Setup to determine if the media player is playing. This affects - // some content loading decisions. + // Setup to determine if the media player is playing. This affects some content loading decisions. + ['playing', 'pause'].forEach(event => { + document.querySelectorAll('video, audio').forEach(media => { + media.removeEventListener(event, mediaHandler); + media.addEventListener(event, mediaHandler); + }); + }); - $('video').off('playing'); - $('video').off('pause'); - $('audio').off('playing'); - $('audio').off('pause'); + function mediaHandler(event) { + mediaPlaying = event.type === 'playing'; + } - $('video').on('playing', function() { - mediaPlaying = true; - }); - $('video').on('pause', function() { - mediaPlaying = false; - }); - $('audio').on('playing', function() { - mediaPlaying = true; - }); - $('audio').on('pause', function() { - mediaPlaying = false; + imagesLoaded(document.querySelectorAll('.wall-item-body img, .wall-photo-item img'), function () { + if (bParam_mid && mode === 'replace') { + scrollToItem(); + } + else { + collapseHeight(); + } }); - if(! preloadImages) { - $('.wall-item-body, .wall-photo-item').imagesLoaded() - .always( function( instance ) { - //console.log('all images loaded'); - collapseHeight(); + // reset rotators and cursors we may have set before reaching this place + let pageSpinner = document.getElementById("page-spinner"); + if (pageSpinner) { + pageSpinner.style.display = 'none'; + } + let profileJotTextLoading = document.getElementById("profile-jot-text-loading"); + if (profileJotTextLoading) { + profileJotTextLoading.style.display = 'none'; + } - if(bParam_mid && mode === 'replace') - scrollToItem(); + followUpPageLoad = true; - }) - .done( function( instance ) { - //console.log('all images successfully loaded'); - }) - .fail( function() { - //console.log('all images loaded, at least one is broken'); - }) - .progress( function( instance, image ) { - //var result = image.isLoaded ? 'loaded' : 'broken'; - //console.log( 'image is ' + result + ' for ' + image.img.src ); - }); + + updateRelativeTime('.autotime'); +} + +function imagesLoaded(elements, callback) { + let loadedCount = 0; + let totalImages = 0; + let timeoutId; + const timeout = 10000; + const processed = new Set(); // Use a Set for efficient lookup + + // Helper function to extract img elements from an HTML string + function extractImagesFromHtml(htmlString) { + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = htmlString; + return tempDiv.querySelectorAll('.wall-item-body img, .wall-photo-item img'); } - else { - collapseHeight(); - if(bParam_mid && mode === 'replace') - scrollToItem(); + function checkComplete(src) { + // Skip processing if image has already been processed + if (processed.has(src)) return; + + processed.add(src); + loadedCount++; + + // Update progress + const progress = Math.round((loadedCount * 100) / totalImages); + document.getElementById('image_counter').innerText = `${progress}%`; + + // If all images are loaded, trigger the callback + if (loadedCount === totalImages) { + document.getElementById('image_counter').innerText = ''; + clearTimeout(timeoutId); + callback(); + } } - // reset rotators and cursors we may have set before reaching this place + // Convert HTML string to img elements if necessary + if (typeof elements === 'string') { + elements = extractImagesFromHtml(elements); + } - $("#page-spinner").hide(); - $("#profile-jot-text-loading").hide(); + // Exit early if there are no images to load + if (!elements || elements.length === 0) { + callback(); + return; + } - followUpPageLoad = true; + // Filter valid image elements (only img with src attribute) + const images = Array.from(elements) + .filter((element) => element.tagName.toLowerCase() === 'img' && element.src) + .filter((element, index, self) => + index === self.findIndex(e => e.src === element.src) // Avoid duplicates + ); + + // If no images are found, call the callback immediately + if (images.length === 0) { + callback(); + return; + } + + totalImages = images.length; + + // Set timeout for the loading process + timeoutId = setTimeout(() => { + console.warn(`Image loading timed out after ${timeout}ms`); + callback(false); + }, timeout); + // Iterate through images to add load and error event listeners + images.forEach((img) => { + let new_img = new Image(); + new_img.src = img.src; + + if (new_img.complete && new_img.naturalHeight > 0) { + // Image is already loaded, handle immediately + // console.log(`Image cached: ${new_img.src}`); + checkComplete(new_img.src); + } else { + // Add event listeners for load and error events + new_img.addEventListener('load', () => { + // console.log(`Image loaded: ${new_img.src}`); + checkComplete(new_img.src) + }); + new_img.addEventListener('error', () => { + console.log(`Image failed to load: ${new_img.src}`); + checkComplete(new_img.src); + }); + } + + }); +} + +function updateRelativeTime(selector) { + // Get all elements with the given selector + const timeElements = document.querySelectorAll(selector); + if (timeElements.length === 0) return; + + // Default time style and map for supported options + const styleMap = ['narrow', 'short', 'long']; + const style = styleMap.find(s => selector.includes(s)) || 'long'; + + // Create an instance of RelativeTimeFormat + const rtf = new Intl.RelativeTimeFormat(lang, { + localeMatcher: 'best fit', // 'best fit' or 'lookup' + numeric: 'always', // 'always' or 'auto' + style: style // 'long', 'short', or 'narrow' + }); + + const now = Date.now(); // Get the current time only once + + // Helper function to calculate the time difference in appropriate units + function getRelativeTime(diffInSeconds) { + const isFuture = diffInSeconds > 0; + const absDiffInSeconds = Math.abs(diffInSeconds); + + if (absDiffInSeconds < 60) return { value: absDiffInSeconds, unit: 'second' }; + if (absDiffInSeconds < 3600) return { value: Math.floor(absDiffInSeconds / 60), unit: 'minute' }; + if (absDiffInSeconds < 86400) return { value: Math.floor(absDiffInSeconds / 3600), unit: 'hour' }; + if (absDiffInSeconds < 2592000) return { value: Math.floor(absDiffInSeconds / 86400), unit: 'day' }; + if (absDiffInSeconds < 31536000) return { value: Math.floor(absDiffInSeconds / 2592000), unit: 'month' }; + return { value: Math.floor(absDiffInSeconds / 31536000), unit: 'year' }; + } + + // Process each element + timeElements.forEach(element => { + const timestamp = new Date(element.title).getTime(); + if (isNaN(timestamp)) return; // Skip invalid timestamps + + const diffInSeconds = Math.floor((timestamp - now) / 1000); // Time difference in seconds + const { value, unit } = getRelativeTime(diffInSeconds); + + // Format the relative time and set it as the element's text + const formattedTime = rtf.format(diffInSeconds > 0 ? value : -value, unit); + element.textContent = formattedTime; + }); + + // Avoid duplicate timeout registrations for the same selector + if (!updateTimeout.includes(selector)) { + updateTimeout.push(selector); + setTimeout(() => updateRelativeTime(selector), 60000); // Re-run the update every 60 seconds + } } function scrollToItem() { // auto-scroll to a particular comment in a thread (designated by mid) when in single-thread mode - if(justifiedGalleryActive) - return; + if (justifiedGalleryActive) return; let submid = ((bParam_mid.length) ? bParam_mid : 'abcdefg'); - //var encoded = ((submid.substr(0,4) == 'b64.') ? true : false); - //var submid_encoded = ((encoded) ? submid : window.btoa(submid)); - $('.thread-wrapper').filter(function() { - if($(this).data('b64mids').indexOf(submid) > -1 && !$(this).hasClass('toplevel_item')) { - if($('.collapsed-comments').length) { - var scrolltoid = $('.collapsed-comments').attr('id').substring(19); - $('#collapsed-comments-' + scrolltoid + ' .autotime').timeago(); - $('#collapsed-comments-' + scrolltoid).show(); - $('#hide-comments-' + scrolltoid).html(aStr.showfewer); - $('#hide-comments-total-' + scrolltoid).hide(); + // Select all thread wrappers + let threadWrappers = document.querySelectorAll('.thread-wrapper'); + + threadWrappers.forEach(thread => { + // Get the 'data-b64mids' attribute and check if it contains submid + let b64mids = thread.dataset.b64mids; + + if (b64mids && b64mids.includes(submid)) { + // Handle collapsed comments if any + let collapsedComments = document.querySelectorAll('.collapsed-comments'); + if (collapsedComments.length) { + let scrollToId = collapsedComments[0].id.substring(19); + showHideComments(scrollToId); } - $('html, body').animate({ scrollTop: $(this).offset().top - $('nav').outerHeight(true) }, 'slow'); - $(this).addClass('item-highlight'); + + collapseHeight(); + + if (!thread.classList.contains('toplevel_item')) { + // Scroll to the target element + let navHeight = document.getElementById('navbar-top') ? document.getElementById('navbar-top').offsetHeight : 0; + window.scrollTo({ + top: getOffsetTopRelativeToBody(thread) - navHeight, + behavior: 'smooth' + }); + } + + let id = thread.id.replace('thread-wrapper-', ''); + let content = document.getElementById('wall-item-content-wrapper-' + id); + content.classList.add('item-highlight-fade'); } }); +} +function getOffsetTopRelativeToBody(element) { + let offsetTop = 0; + while (element) { + offsetTop += element.offsetTop; + element = element.offsetParent; + } + return offsetTop; } function collapseHeight() { @@ -869,8 +1180,8 @@ function collapseHeight() { startOpen: open, heightMargin: 50, collapsedHeight: divmore_height, - moreLink: '<a href="#" class="divgrow-showmore fakelink">' + aStr.divgrowmore + '</a>', - lessLink: '<a href="#" class="divgrow-showmore fakelink">' + aStr.divgrowless + '</a>', + moreLink: '<a href="#" class="divgrow-showmore fakelink"><i class="bi bi-chevron-down align-middle divgrow-showmore-icon"></i> <span class="divgrow-showmore-label align-middle">' + aStr.divgrowmore + '</span></a>', + lessLink: '<a href="#" class="divgrow-showmore fakelink"><i class="bi bi-chevron-up align-middle divgrow-showmore-icon"></i> <span class="divgrow-showmore-label align-middle">' + aStr.divgrowless + '</span></a>', beforeToggle: function(trigger, element, expanded) { if(expanded) { if((($(element).offset().top + divmore_height) - $(window).scrollTop()) < 65 ) { @@ -906,7 +1217,7 @@ function updateInit() { liveUpdate(); } else { - $(document).trigger('hz:sse_bs_init'); + document.dispatchEvent(new Event('hz:sse_bs_init')); } if($('#live-photos').length || $('#live-cards').length || $('#live-articles').length ) { @@ -1008,7 +1319,7 @@ function liveUpdate(notify_id) { in_progress = false; liveRecurse ++; if(liveRecurse < 10) { - liveUpdate(); + liveUpdate(notify_id); } else { console.log('Incomplete data. Too many attempts. Giving up.'); @@ -1030,45 +1341,16 @@ function liveUpdate(notify_id) { var dready = new Date(); console.log('DATA ready in: ' + (dready - dstart)/1000 + ' seconds.'); - if(update_mode === 'update' || preloadImages) { - console.log('LOADING images...'); - $('.wall-item-body, .wall-photo-item',data).imagesLoaded() - .always( function( instance ) { - //console.log('all images loaded'); - - var iready = new Date(); - console.log('IMAGES ready in: ' + (iready - dready)/1000 + ' seconds.'); - - page_load = false; - scroll_next = false; - updateConvItems(update_mode,data); - - in_progress = false; - $('#image_counter').html(''); - - // remove modal backdrop in case the update was triggered from a modal - $('.modal-backdrop').remove(); - }) - .done( function( instance ) { - //console.log('all images successfully loaded'); - }) - .fail( function() { - //console.log('all images loaded, at least one is broken'); - }) - .progress( function( instance, image ) { - $('#image_counter').html(Math.floor((instance.progressedCount*100)/instance.images.length) + '%'); - //var result = image.isLoaded ? 'loaded' : 'broken'; - //console.log( 'image is ' + result + ' for ' + image.img.src ); - }); + console.log('LOADING images...'); + imagesLoaded(data, function () { + var iready = new Date(); + console.log('IMAGES ready in: ' + (iready - dready)/1000 + ' seconds.'); - } - else { page_load = false; scroll_next = false; updateConvItems(update_mode,data); in_progress = false; - } - + }); }); } @@ -1102,9 +1384,8 @@ function cache_next_page() { console.log('cached: ' + update_url); - $('.wall-item-body, .wall-photo-item', data).imagesLoaded() - .always( function( instance ) { - console.log('page_cache images loaded:'); + imagesLoaded(data, function () { + console.log('page_cache: images loaded'); page_cache.data = data; page_cache.page = bParam_page; @@ -1112,19 +1393,7 @@ function cache_next_page() { bParam_page--; page_load = false; - }) - .done( function( instance ) { - console.log('success'); - }) - .fail( function() { - console.log('at least one is broken'); - }) - .progress( function( instance, image ) { - //console.log(instance.progressedCount + '/' + instance.images.length); - //var result = image.isLoaded ? 'loaded' : 'broken'; - //console.log( 'image is ' + result + ' for ' + image.img.src ); }); - }); } @@ -1144,7 +1413,7 @@ function pageUpdate() { bParam_page = 1; } - update_url = baseurl + '/' + decodeURIComponent(page_query) + '/?f=&aj=1&page=' + bParam_page + extra_args ; + update_url = baseurl + '/' + decodeURIComponent(page_query) + '?aj=1&page=' + bParam_page + extra_args ; $("#page-spinner").show(); update_mode = 'append'; @@ -1154,7 +1423,7 @@ function pageUpdate() { scroll_next = false; updatePageItems(update_mode,data); $("#page-spinner").hide(); - $(".autotime").timeago(); + updateRelativeTime('.autotime'); in_progress = false; }); } @@ -1175,21 +1444,299 @@ function justifyPhotosAjax(id) { $('#' + id).justifiedGallery('norewind').on('jg.complete', function(e){ justifiedGalleryActive = false; }); } +function request(id, mid, verb, parent, uuid, userClick) { + + if (verb === 'load') { + const dots = document.getElementById('load-more-dots-' + parent); + dots.classList.add('jumping-dots'); + + const parent_sub = document.getElementById('wall-item-sub-thread-wrapper-' + parent); + const offset = parent_sub.children.length; + + fetch('/request?offset=' + offset + '&verb=' + verb + '&mid=' + mid + '&parent=' + parent + '&module=' + module) + .then(response => response.json()) + .then(obj => { + let parser = new DOMParser(); + let doc = parser.parseFromString(obj.html, 'text/html'); + let b64mids = []; + + doc.querySelectorAll('.thread-wrapper').forEach(function (e) { + let data = JSON.parse(e.dataset.b64mids); + b64mids.push(...data); + }); + + imagesLoaded(doc.querySelectorAll('.wall-item-body img'), function () { + injectWithAnimation('wall-item-sub-thread-wrapper-' + parent, doc); + dots.classList.remove('jumping-dots'); + + const loadmore_progress = document.getElementById('load-more-progress-' + parent); + loadmore_progress.style.width = Math.round(100 * parent_sub.children.length / loadmore_progress.dataset.commentsTotal) + '%'; + + if (Number(parent_sub.children.length) === Number(loadmore_progress.dataset.commentsTotal)) { + const loadmore = document.getElementById('load-more-' + parent); + loadmore.remove(); + } + + updateRelativeTime('.autotime'); + collapseHeight(); + + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); + document.dispatchEvent(new Event('hz:sse_bs_counts')); + }); + + }) + .catch(error => { + console.error('Error fetching data:', error); + }); + + return; + } + + const loading = document.getElementById('like-rotator-' + id); + + if (userClick) { + loading.style.display = 'block'; + } + + if (verb === 'comment') { + if (userClick && singlethread_modules.indexOf(module) !== -1) { + let stateObj = { b64mid: uuid }; + history.pushState(stateObj, '', module + '/' + uuid); + } + + fetch('/request?verb=' + verb + '&mid=' + mid + '&parent=' + parent + '&module=' + module) + .then(response => response.json()) + .then(obj => { + let parser = new DOMParser(); + let doc = parser.parseFromString(obj.html, 'text/html'); + + doc.querySelectorAll('.thread-wrapper').forEach(function (e) { + let data = JSON.parse(e.dataset.b64mids); + b64mids.push(...data); + }); + + imagesLoaded(doc.querySelectorAll('.wall-item-body img'), function () { + injectWithAnimation('wall-item-sub-thread-wrapper-' + id, doc, true); + updateRelativeTime('.autotime'); + collapseHeight(); + + if (userClick) { + loading.style.display = 'none'; + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); + document.dispatchEvent(new Event('hz:sse_bs_counts')); + } + }); + + }) + .catch(error => { + console.error('Error fetching data:', error); + }); + } + else { + fetch('/request?verb=' + verb + '&mid=' + mid + '&parent=' + parent) + .then(response => response.json()) + .then(obj => { + const modal = new bootstrap.Modal('#reactions'); + const modal_content = document.getElementById('reactions_body'); + const modal_title = document.getElementById('reactions_title'); + const modal_action = document.getElementById('reactions_action'); + modal_action.style.display = 'none'; + modal_title.innerHTML = obj.title; + modal_content.innerHTML = ''; + if (obj.action) { + modal_action.innerHTML = '<a href="#" onclick="' + obj.action + '(' + id + ',\'' + verb + '\'); return false;">' + obj.action_label + '</a>'; + modal_action.style.display = 'block'; + } + console.log(obj) + obj.result.forEach(e => { + let mod = ''; + if (e.item_blocked === 4) { + mod = '<span onclick="moderate_approve(' + e.id + '); return false;" class="text-success pe-4 d-inline-block"><i class="bi bi-check-lg" ></i></span><span onclick="moderate_drop(' + e.id + '); return false;" class="text-danger pe-4 d-inline-block"><i class="bi bi-trash" ></i></span>'; + } + modal_content.innerHTML += '<a href="' + e.url + '" class="list-group-item list-group-item-action border-0">' + mod + '<img src="' + e.photo + '" class="menu-img-1" loading="lazy"> ' + e.name + '</a>'; + + }); + + modal.show(); + loading.style.display = 'none'; + }) + .catch(error => { + console.error('Error fetching data:', error); + }); + } + +} + +function injectWithAnimation(containerId, parsedDoc, overwrite = false) { + const container = document.getElementById(containerId); + if (!container) return; + if (overwrite) container.innerHTML = ''; + + const newElements = Array.from(parsedDoc.body.children); + + for (let i = newElements.length - 1; i >= 0; i--) { + const el = newElements[i].cloneNode(true); + el.classList.add('item-fade-in'); + container.insertBefore(el, container.firstChild); + + // Remove classes after transition ends + const onTransitionEnd = (event) => { + el.classList.remove('item-fade-in', 'show'); + el.removeEventListener('transitionend', onTransitionEnd); + }; + el.addEventListener('transitionend', onTransitionEnd); + + setTimeout(() => { + el.classList.add('show'); + }, (newElements.length - 1 - i) * 30); + } +} + +const autoExpand = (function () { + const clickedElements = new Set(); // Stores clicked button references + + // We wait 10 seconds for images. Set the timeout here slightly higher. + function waitForElement(selector, timeout = 11000) { + return new Promise((resolve, reject) => { + // Check if the element already exists + const element = document.querySelector(selector); + + if (element) { + resolve(element); + return; + } + + // Set up a timeout to reject the promise if the element doesn't appear in time + const timer = setTimeout(() => { + observer.disconnect(); + reject(new Error(`Element "${selector}" not found within ${timeout}ms`)); + }, timeout); + + // Create a MutationObserver to watch for DOM changes + const observer = new MutationObserver(() => { + const el = document.querySelector(selector); + if (el) { + clearTimeout(timer); + observer.disconnect(); + resolve(el); + } + }); + + // Start observing the document for changes + observer.observe(document.documentElement, { + childList: true, + subtree: true + }); + }); + } + + async function autoExpand(id) { + const loading = document.getElementById('like-rotator-' + id); + let iteration = 0; + const maxIterations = 3; + clickedElements.clear(); + + try { + // Step 1: Ensure initial button is clicked + const initBtnSelector = '#wall-item-comment-' + id; + const initBtn = await waitForElement(initBtnSelector); + + if (!clickedElements.has(initBtn)) { + initBtn.click(); + clickedElements.add(initBtn); + iteration++; + } + + // Step 2: Loop until no new buttons are found + let newButtonsFound; + + const commentSelector = `#wall-item-sub-thread-wrapper-${id} .thread-wrapper`; + const commentBtnSelector = `#wall-item-sub-thread-wrapper-${id} .wall-item-comment`; + + do { + newButtonsFound = false; + + // Wait for any comment to appear + await waitForElement(commentSelector); + + const expandButtons = document.querySelectorAll(commentBtnSelector); + + for (const btn of expandButtons) { + if (!clickedElements.has(btn)) { + btn.click(); + clickedElements.add(btn); + newButtonsFound = true; + // Optional: await waitForElement(...) to wait for new content + } + } + + // Wait between iterations to allow UI to update + if (newButtonsFound) { + iteration++; + await new Promise(res => setTimeout(res, 700)); + } + + } while (newButtonsFound && iteration < maxIterations); + + console.log('Replies loaded!'); + + loading.style.display = 'none'; + + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); + document.dispatchEvent(new Event('hz:sse_bs_counts')); + + } catch (error) { + loading.style.display = 'none'; + console.error("autoExpand failed:", error.message); + } + } + + return autoExpand; +})(); + + +function stringToHexColor(str) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + let color = "#"; + for (let i = 0; i < 3; i++) { + const value = (hash >> (i * 8)) & 0xFF; + color += value.toString(16).padStart(2, '0'); + } + return color; +} + +function stringToHslColor(str) { + let stringUniqueHash = [...str].reduce((acc, char) => { + return char.charCodeAt(0) + ((acc << 5) - acc); + }, 0); + return `hsl(${stringUniqueHash % 360}, 65%, 65%)`; +} + function dolike(ident, verb) { - $('#like-rotator-' + ident.toString()).show(); + $('#like-rotator-' + ident).show(); - if(typeof conv_mode == typeof undefined) + if (typeof conv_mode == typeof undefined) { conv_mode = ''; + } - if(typeof page_mode == typeof undefined) + if (typeof page_mode == typeof undefined) { page_mode = ''; + } + + let reload = 0; - var reload = ''; - if(module == 'photos') + if (module == 'photos') { reload = 1; + } - $.get('like/' + ident.toString() + '?verb=' + verb + '&conv_mode=' + conv_mode + '&page_mode=' + page_mode + '&reload=' + reload, function (data) { - if(data.success) { + + $.get('like/' + ident + '?verb=' + verb + '&conv_mode=' + conv_mode + '&page_mode=' + page_mode + '&reload=' + reload, function (data) { + if (data.success) { + + close_modal(); // mod photos if (data.reload) { @@ -1207,11 +1754,13 @@ function dolike(ident, verb) { else { $('#thread-wrapper-' + data.orig_id).replaceWith(data.html); } - $('#wall-item-ago-' + data.id + ' .autotime').timeago(); + + updateRelativeTime('.autotime'); collapseHeight(); liking = 0; } }); + liking = 1; } @@ -1221,17 +1770,73 @@ function doprofilelike(ident, verb) { function doreply(parent, ident, owner, hint) { - var form = $('#comment-edit-form-' + parent.toString()); - form.find('input[name=parent]').val(ident); - var i = form.find('button[type=submit]'); - var btn = i.html().replace(/<[^>]*>/g, '').trim(); - i.html('<i class="fa fa-reply" ></i> ' + btn); - var sel = 'wall-item-body-' + ident.toString(); - var quote = window.getSelection().toString().trim(); - form.find('textarea').val("@{" + owner + "}" + ((($(window.getSelection().anchorNode).closest("#" + sel).attr("id") != sel) || (quote.length === 0))? " " : "\n[quote]" + quote + "[/quote]\n")); - $('#comment-edit-text-' + parent.toString()).focus(); + const modal = new bootstrap.Modal('#reactions'); + const modal_content = document.getElementById('reactions_body'); + const modal_title = document.getElementById('reactions_title'); + const modal_action = document.getElementById('reactions_action'); + + modal_action.style.display = 'none'; + modal_title.innerHTML = hint; + + const preview = document.getElementById('comment-edit-preview-' + parent.toString()); + preview.innerHTML = ''; + + // Get the form element by ID + const form = document.getElementById('comment-edit-wrapper-' + parent.toString()); + if (!form) return; + + modal_content.innerHTML = ''; + modal_content.append(form); + + // Set the value of the input named 'parent' + const parentInput = form.querySelector('input[name=parent]'); + if (parentInput) { + parentInput.value = ident; + } + + // Find the submit button and update its HTML + const submitBtn = form.querySelector('button[type=submit]'); + if (submitBtn) { + const btnText = submitBtn.innerHTML.replace(/<[^>]*>/g, '').trim(); + submitBtn.innerHTML = '<i class="bi bi-arrow-90deg-left"></i> ' + btnText; + } + + // Prepare the quote logic + const sel = 'wall-item-body-' + ident.toString(); + const quote = window.getSelection().toString().trim(); + + // Check if the selection is inside the correct element + let isInSel = false; + const anchorNode = window.getSelection().anchorNode; + if (anchorNode) { + let node = anchorNode.nodeType === 3 ? anchorNode.parentNode : anchorNode; + while (node) { + if (node.id === sel) { + isInSel = true; + break; + } + node = node.parentNode; + } + } + + modal.show(); + + // Set the textarea value + const textarea = form.querySelector('textarea'); + if (textarea) { + let commentBody = localStorage.getItem('comment_body-' + ident); + if (commentBody) { + textarea.value = commentBody; + } + else { + textarea.value = "@{" + owner + "}" + ((!isInSel || quote.length === 0) ? " " : "\n[quote]" + quote + "[/quote]\n"); + } + + textarea.focus(); + } } + function doscroll(parent, hidden) { var id; var x = '#hide-comments-outer-' + hidden.toString(); @@ -1245,6 +1850,7 @@ function doscroll(parent, hidden) { var c = '#collapsed-comments-' + x; if($(c).length !== 0 && (! $(c).is(':visible'))) { showHideComments(x); + collapseHeight(); pos += $(c).height(); } } @@ -1257,7 +1863,7 @@ function doscroll(parent, hidden) { }); $('html, body').animate({scrollTop:(id.offset().top) - 50}, 'slow'); - $('<a href="javascript:doscrollback(' + pos + ');" id="back-to-reply" title="' + aStr['to_reply'] + '"><i class="fa fa-angle-double-down"></i></a>').insertAfter('#wall-item-ago-' + id.attr('id').replace(/\D/g,'')); + $('<a href="javascript:doscrollback(' + pos + ');" id="back-to-reply" title="' + aStr['to_reply'] + '"><i class="bi bi-chevron-double-down"></i></a>').insertAfter('#wall-item-ago-' + id.attr('id').replace(/\D/g,'')); } function doscrollback(pos) { @@ -1282,7 +1888,7 @@ function dopin(id) { $('.dropdown-item-pinnable').html($('.dropdown-item-pinnable').html().replace(aStr['unpin_item'],aStr['pin_item'])); $('.wall-item-pinned').remove() if(i.length == 0) { - $('<span class="wall-item-pinned" title="' + aStr['pinned'] + '" id="wall-item-pinned-' + id + '"><i class="fa fa-thumb-tack"> </i></span>').insertAfter('#wall-item-ago-' + id); + $('<span class="wall-item-pinned" title="' + aStr['pinned'] + '" id="wall-item-pinned-' + id + '"><i class="bi bi-pin"> </i></span>').insertAfter('#wall-item-ago-' + id); me.html(me.html().replace(aStr['pin_item'],aStr['unpin_item'])); }; }) @@ -1305,7 +1911,7 @@ function dropItem(url, object, b64mid) { $(object + ', #pinned-wrapper-' + id).remove(); $('body').css('cursor', 'auto'); - toast(aStr.itemdel, 'info') + toast(aStr.itemdel, 'info'); //$.jGrowl(aStr.itemdel, { sticky: false, theme: 'info', life: 3000 }); if (typeof b64mid !== typeof undefined) { @@ -1327,26 +1933,28 @@ function dropItem(url, object, b64mid) { } function dosubthread(ident) { - $('#like-rotator-' + ident.toString()).show(); - $.get('subthread/sub/' + ident.toString(), updateInit ); + $('#like-rotator-' + ident).show(); + $.get('subthread/sub/' + ident, updateInit ); liking = 1; } function dounsubthread(ident) { - $('#like-rotator-' + ident.toString()).show(); - $.get('subthread/unsub/' + ident.toString(), updateInit ); + $('#like-rotator-' + ident).show(); + $.get('subthread/unsub/' + ident, updateInit ); liking = 1; } -function moderate_approve(ident) { - $('#like-rotator-' + ident.toString()).show(); - $.get('moderate/' + ident.toString() + '/approve', updateInit ); +function moderate_approve(ident, verb) { + $('#like-rotator-' + ident).show(); + close_modal(); + $.get('moderate/' + ident + '/approve', updateInit ); liking = 1; } function moderate_drop(ident) { - $('#like-rotator-' + ident.toString()).show(); - $.get('moderate/' + ident.toString() + '/drop', $('#thread-wrapper-' + ident.toString()).fadeOut(function() { this.remove(); })); + $('#like-rotator-' + ident).show(); + close_modal(); + $.get('moderate/' + ident + '/drop', $('#thread-wrapper-' + ident).fadeOut(function() { this.remove(); })); liking = 1; } @@ -1357,18 +1965,18 @@ function dostar(ident) { if(data.result == 1) { $('#starred-' + ident).addClass('starred'); $('#starred-' + ident).removeClass('unstarred'); - $('#starred-' + ident).addClass('fa-star'); - $('#starred-' + ident).removeClass('fa-star-o'); + $('#starred-' + ident).addClass('bi-star-fill'); + $('#starred-' + ident).removeClass('bi-star'); $('#star-' + ident).addClass('hidden'); $('#unstar-' + ident).removeClass('hidden'); - var btn_tpl = '<div class="btn-group" id="star-button-' + ident + '"><button type="button" class="btn btn-outline-secondary border-0 btn-sm wall-item-star" onclick="dostar(' + ident + ');"><i class="fa fa-star"></i></button></div>' - $('#wall-item-tools-left-' + ident).prepend(btn_tpl); + var btn_tpl = '<div class="" id="star-button-' + ident + '"><button type="button" class="btn btn-sm btn-link link-secondary wall-item-star" onclick="dostar(' + ident + ');"><i class="bi bi-star generic-icons"></i></button></div>' + $('#wall-item-tools-right-' + ident).prepend(btn_tpl); } else { $('#starred-' + ident).addClass('unstarred'); $('#starred-' + ident).removeClass('starred'); - $('#starred-' + ident).addClass('fa-star-o'); - $('#starred-' + ident).removeClass('fa-star'); + $('#starred-' + ident).addClass('bi-star'); + $('#starred-' + ident).removeClass('bi-star-fill'); $('#star-' + ident).removeClass('hidden'); $('#unstar-' + ident).addClass('hidden'); $('#star-button-' + ident).remove(); @@ -1440,12 +2048,14 @@ function post_comment(id) { window.location.href = data.reload; } + close_modal(); localStorage.removeItem("comment_body-" + id); $("#comment-edit-preview-" + id).hide(); $("#comment-edit-text-" + id).val('').blur().attr('placeholder', aStr.comment); - $('#wall-item-comment-wrapper-' + id).before(data.html); - $('#wall-item-ago-' + data.id + ' .autotime').timeago(); + $('#wall-item-sub-thread-wrapper-' + data.thr_parent_id).append(data.html); + + updateRelativeTime('.autotime'); $('body').css('cursor', 'unset'); collapseHeight(); commentBusy = false; @@ -1475,7 +2085,7 @@ function preview_comment(id) { function(data) { if(data.preview) { $("#comment-edit-preview-" + id).html(data.preview); - $("#comment-edit-preview-" + id + " .autotime").timeago(); + updateRelativeTime('.autotime'); $("#comment-edit-preview-" + id + " a").click(function() { return false; }); } }, @@ -1505,7 +2115,7 @@ function preview_post() { function(data) { if(data.preview) { $("#jot-preview-content").html(data.preview); - $("#jot-preview-content .autotime").timeago(); + updateRelativeTime('.autotime'); $("#jot-preview-content" + " a").click(function() { return false; }); } }, @@ -1553,7 +2163,7 @@ function contactgroupChangeMember(gid, cid) { $('body').css('cursor', 'wait'); $.get('contactgroup/' + gid + '/' + cid, function(data) { $('body').css('cursor', 'auto'); - $('#group-' + gid).toggleClass('fa-check-square-o fa-square-o'); + $('#group-' + gid).toggleClass('bi-check-square bi-square'); }); } @@ -1622,140 +2232,11 @@ $(window).scroll(function () { } }); -function addhtmltext(data) { - data = h2b(data); - addeditortext(data); -} - function loadText(textRegion,data) { var currentText = $(textRegion).val(); $(textRegion).val(currentText + data); } -function addeditortext(data) { - if(plaintext == 'none') { - var currentText = $("#profile-jot-text").val(); - $("#profile-jot-text").val(currentText + data); - } -} - -function h2b(s) { - var y = s; - function rep(re, str) { - y = y.replace(re,str); - } - - rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"); - rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"); - rep(/<span style=\"color:(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"); - rep(/<font>(.*?)<\/font>/gi,"$1"); - rep(/<img.*?width=\"(.*?)\".*?height=\"(.*?)\".*?src=\"(.*?)\".*?\/>/gi,"[img=$1x$2]$3[/img]"); - rep(/<img.*?height=\"(.*?)\".*?width=\"(.*?)\".*?src=\"(.*?)\".*?\/>/gi,"[img=$2x$1]$3[/img]"); - rep(/<img.*?src=\"(.*?)\".*?height=\"(.*?)\".*?width=\"(.*?)\".*?\/>/gi,"[img=$3x$2]$1[/img]"); - rep(/<img.*?src=\"(.*?)\".*?width=\"(.*?)\".*?height=\"(.*?)\".*?\/>/gi,"[img=$2x$3]$1[/img]"); - rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"); - - rep(/<ul class=\"listbullet\" style=\"list-style-type\: circle\;\">(.*?)<\/ul>/gi,"[list]$1[/list]"); - rep(/<ul class=\"listnone\" style=\"list-style-type\: none\;\">(.*?)<\/ul>/gi,"[list=]$1[/list]"); - rep(/<ul class=\"listdecimal\" style=\"list-style-type\: decimal\;\">(.*?)<\/ul>/gi,"[list=1]$1[/list]"); - rep(/<ul class=\"listlowerroman\" style=\"list-style-type\: lower-roman\;\">(.*?)<\/ul>/gi,"[list=i]$1[/list]"); - rep(/<ul class=\"listupperroman\" style=\"list-style-type\: upper-roman\;\">(.*?)<\/ul>/gi,"[list=I]$1[/list]"); - rep(/<ul class=\"listloweralpha\" style=\"list-style-type\: lower-alpha\;\">(.*?)<\/ul>/gi,"[list=a]$1[/list]"); - rep(/<ul class=\"listupperalpha\" style=\"list-style-type\: upper-alpha\;\">(.*?)<\/ul>/gi,"[list=A]$1[/list]"); - rep(/<li>(.*?)<\/li>/gi,"[li]$1[/li]"); - - rep(/<code>(.*?)<\/code>/gi,"[code]$1[/code]"); - rep(/<\/(strong|b)>/gi,"[/b]"); - rep(/<(strong|b)>/gi,"[b]"); - rep(/<\/(em|i)>/gi,"[/i]"); - rep(/<(em|i)>/gi,"[i]"); - rep(/<\/u>/gi,"[/u]"); - - rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"); - rep(/<u>/gi,"[u]"); - rep(/<blockquote[^>]*>/gi,"[quote]"); - rep(/<\/blockquote>/gi,"[/quote]"); - rep(/<hr \/>/gi,"[hr]"); - rep(/<br (.*?)\/>/gi,"\n"); - rep(/<br\/>/gi,"\n"); - rep(/<br>/gi,"\n"); - rep(/<p>/gi,""); - rep(/<\/p>/gi,"\n"); - rep(/ /gi," "); - rep(/"/gi,"\""); - rep(/</gi,"<"); - rep(/>/gi,">"); - rep(/&/gi,"&"); - - return y; -} - -function b2h(s) { - var y = s; - function rep(re, str) { - y = y.replace(re,str); - } - - rep(/\&/gi,"&"); - rep(/\</gi,"<"); - rep(/\>/gi,">"); - rep(/\"/gi,"""); - - rep(/\n/gi,"<br />"); - rep(/\[b\]/gi,"<strong>"); - rep(/\[\/b\]/gi,"</strong>"); - rep(/\[i\]/gi,"<em>"); - rep(/\[\/i\]/gi,"</em>"); - rep(/\[u\]/gi,"<u>"); - rep(/\[\/u\]/gi,"</u>"); - rep(/\[hr\]/gi,"<hr />"); - rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>"); - rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>"); - rep(/\[img=(.*?)x(.*?)\](.*?)\[\/img\]/gi,"<img width=\"$1\" height=\"$2\" src=\"$3\" />"); - rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />"); - - rep(/\[zrl=([^\]]+)\](.*?)\[\/zrl\]/gi,"<a href=\"$1" + '?f=&zid=' + zid + "\">$2</a>"); - rep(/\[zrl\](.*?)\[\/zrl\]/gi,"<a href=\"$1" + '?f=&zid=' + zid + "\">$1</a>"); - rep(/\[zmg=(.*?)x(.*?)\](.*?)\[\/zmg\]/gi,"<img width=\"$1\" height=\"$2\" src=\"$3" + '?f=&zid=' + zid + "\" />"); - rep(/\[zmg\](.*?)\[\/zmg\]/gi,"<img src=\"$1" + '?f=&zid=' + zid + "\" />"); - - rep(/\[list\](.*?)\[\/list\]/gi, '<ul class="listbullet" style="list-style-type: circle;">$1</ul>'); - rep(/\[list=\](.*?)\[\/list\]/gi, '<ul class="listnone" style="list-style-type: none;">$1</ul>'); - rep(/\[list=1\](.*?)\[\/list\]/gi, '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>'); - rep(/\[list=i\](.*?)\[\/list\]/gi,'<ul class="listlowerroman" style="list-style-type: lower-roman;">$1</ul>'); - rep(/\[list=I\](.*?)\[\/list\]/gi, '<ul class="listupperroman" style="list-style-type: upper-roman;">$1</ul>'); - rep(/\[list=a\](.*?)\[\/list\]/gi, '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$1</ul>'); - rep(/\[list=A\](.*?)\[\/list\]/gi, '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$1</ul>'); - rep(/\[li\](.*?)\[\/li\]/gi, '<li>$1</li>'); - rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<span style=\"color: $1;\">$2</span>"); - rep(/\[size=(.*?)\](.*?)\[\/size\]/gi,"<span style=\"font-size: $1;\">$2</span>"); - rep(/\[code\](.*?)\[\/code\]/gi,"<code>$1</code>"); - rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<blockquote>$1</blockquote>"); - - rep(/\[video\](.*?)\[\/video\]/gi,"<a href=\"$1\">$1</a>"); - rep(/\[audio\](.*?)\[\/audio\]/gi,"<a href=\"$1\">$1</a>"); - - rep(/\[\&\;([#a-z0-9]+)\;\]/gi,'&$1;'); - - rep(/\<(.*?)(src|href)=\"[^hfm](.*?)\>/gi,'<$1$2="">'); - - return y; -} - -function zid(s) { - if((! s.length) || (s.indexOf('zid=') != (-1))) - return s; - - if(! zid.length) - return s; - - var has_params = ((s.indexOf('?') == (-1)) ? false : true); - var achar = ((has_params) ? '&' : '?'); - s = s + achar + 'f=&zid=' + zid; - - return s; -} - function makeid(length) { var result = ''; var characters = 'abcdef0123456789'; @@ -1801,7 +2282,7 @@ function push_notification(title, body, b64mid) { function toggleAside() { if ($('main.region_1-on').length) { - $('#expand-aside-icon').addClass('fa-arrow-circle-right').removeClass('fa-arrow-circle-left'); + $('#expand-aside-icon').addClass('bi-arrow-right-circle').removeClass('bi-arrow-left-circle'); $('html, body').css({ 'position': '', 'left': '' }); $('main').removeClass('region_1-on'); $('#region_1').addClass('d-none'); @@ -1809,7 +2290,7 @@ function toggleAside() { $('#overlay').remove(); } else { - $('#expand-aside-icon').removeClass('fa-arrow-circle-right').addClass('fa-arrow-circle-left'); + $('#expand-aside-icon').removeClass('bi-arrow-right-circle').addClass('bi-arrow-left-circle'); $('html, body').css({ 'position': 'sticky', 'left': '0px'}); $('main').addClass('region_1-on'); $('#region_1').removeClass('d-none'); @@ -1819,7 +2300,7 @@ function toggleAside() { } function toast(string, severity) { - let id = btoa(string); + let id = bin2hex(string); let container = document.getElementById('toast-container'); let toast = document.getElementById(id); @@ -1840,3 +2321,11 @@ function toast(string, severity) { toastInstance.show(); } + +function close_modal() { + let modal = bootstrap.Modal.getInstance(document.querySelector('.modal.show')); + + if (modal) { + modal.hide(); + } +} diff --git a/view/js/mod_articles.js b/view/js/mod_articles.js index 8b31c0f52..5ebe46aa0 100644 --- a/view/js/mod_articles.js +++ b/view/js/mod_articles.js @@ -1,5 +1,5 @@ $(document).ready( function() { - $(".autotime").timeago(); + updateRelativeTime('.autotime'); /* autocomplete @nicknames */ $(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl?f=&n=1"); diff --git a/view/js/mod_cards.js b/view/js/mod_cards.js index 8b31c0f52..5ebe46aa0 100644 --- a/view/js/mod_cards.js +++ b/view/js/mod_cards.js @@ -1,5 +1,5 @@ $(document).ready( function() { - $(".autotime").timeago(); + updateRelativeTime('.autotime'); /* autocomplete @nicknames */ $(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl?f=&n=1"); diff --git a/view/js/mod_cloud.js b/view/js/mod_cloud.js index fc9219bff..9669d86f5 100644 --- a/view/js/mod_cloud.js +++ b/view/js/mod_cloud.js @@ -519,42 +519,45 @@ function formatSizeUnits(bytes){ // this is basically a js port of include/text.php getIconFromType() function function getIconFromType(type) { - var map = { + let map = { //Common file - 'application/octet-stream': 'fa-file-o', + 'application/octet-stream': 'bi-file-earmark', //Text - 'text/plain': 'fa-file-text-o', - 'application/msword': 'fa-file-word-o', - 'application/pdf': 'fa-file-pdf-o', - 'application/vnd.oasis.opendocument.text': 'fa-file-word-o', - 'application/epub+zip': 'fa-book', + 'text/plain': 'bi-file-earmark-text', + 'text/markdown': 'bi-filetype-md', + 'text/bbcode': 'bi-file-earmark-text', + 'text/html': 'bi-filetype-html', + 'application/msword': 'bi-file-earmark-word', + 'application/pdf': 'bi-file-earmark-pdf', + 'application/vnd.oasis.opendocument.text': 'bifile--earmark-text', + 'application/epub+zip': 'bi-file-earmark-text', //Spreadsheet - 'application/vnd.oasis.opendocument.spreadsheet': 'fa-file-excel-o', - 'application/vnd.ms-excel': 'fa-file-excel-o', + 'application/vnd.oasis.opendocument.spreadsheet': 'bi-file-earmark-spreadsheet', + 'application/vnd.ms-excel': 'bi-file-earmark-spreadsheet', //Image - 'image/jpeg': 'fa-picture-o', - 'image/png': 'fa-picture-o', - 'image/gif': 'fa-picture-o', - 'image/svg+xml': 'fa-picture-o', + 'image/jpeg': 'bi-file-earmark-image', + 'image/png': 'bi-file-earmark-image', + 'image/gif': 'bi-file-earmark-image', + 'image/webp': 'bi-file-earmark-image', + 'image/svg+xml': 'bi-filetype-svg', //Archive - 'application/zip': 'fa-file-archive-o', - 'application/x-rar-compressed': 'fa-file-archive-o', + 'application/zip': 'bi-file-earmark-zip', + 'application/x-rar-compressed': 'bi-file-earmark-zip', //Audio - 'audio/mpeg': 'fa-file-audio-o', - 'audio/mp3': 'fa-file-audio-o', //webkit browsers need that - 'audio/wav': 'fa-file-audio-o', - 'application/ogg': 'fa-file-audio-o', - 'audio/ogg': 'fa-file-audio-o', - 'audio/webm': 'fa-file-audio-o', - 'audio/mp4': 'fa-file-audio-o', + 'audio/mpeg': 'bi-file-earmark-music', + 'audio/wav': 'bi-file-earmark-music', + 'application/ogg': 'bi-file-earmark-music', + 'audio/ogg': 'bi-file-earmark-music', + 'audio/webm': 'bi-file-earmark-music', + 'audio/mp4': 'bi-file-earmark-music', //Video - 'video/quicktime': 'fa-file-video-o', - 'video/webm': 'fa-file-video-o', - 'video/mp4': 'fa-file-video-o', - 'video/x-matroska': 'fa-file-video-o' + 'video/quicktime': 'bi-file-earmark-play', + 'video/webm': 'bi-file-earmark-play', + 'video/mp4': 'bi-file-earmark-play', + 'video/x-matroska': 'bi-file-earmark-play' }; - var iconFromType = 'fa-file-o'; + let iconFromType = 'bi-file-earmark'; if (type in map) { iconFromType = map[type]; diff --git a/view/js/mod_connections.js b/view/js/mod_connections.js index cb3ecc922..c8bd494d2 100644 --- a/view/js/mod_connections.js +++ b/view/js/mod_connections.js @@ -2,6 +2,6 @@ $(document).ready(function() { $("#contacts-search").name_autocomplete(baseurl + '/acl', 'a', true, function(data) { $("#contacts-search-xchan").val(data.xid); }); - $(".autotime").timeago(); + updateRelativeTime('.autotime'); }); diff --git a/view/js/mod_help.js b/view/js/mod_help.js index 9c3591498..8308f23ec 100644 --- a/view/js/mod_help.js +++ b/view/js/mod_help.js @@ -1,14 +1,3 @@ -function docoTocToggle() { - if ($('#doco-top-toc').is(':visible')) { - $('#doco-toc-toggle').removeClass('fa-cog').addClass('fa-caret-right'); - } else { - $('#doco-toc-toggle').removeClass('fa-caret-right').addClass('fa-caret-down'); - } - $('#doco-top-toc').toggle(); - - return false; -} - toc = {}; // Generate the table of contents in the side nav menu (see view/tpl/help.tpl) $(document).ready(function () { @@ -69,54 +58,4 @@ $(document).ready(function () { var newref = p.protocol + '//' + p.hostname + portstr + p.pathname + p.hash.split('?').shift(); location.replace(newref) } - - - // Determine language translations available from the language selector menu itself - var langChoices = []; - $('.lang-selector').find('.lang-choice').each(function (idx, a) { - langChoices.push($(a).html()); - }); - // Parse the URL and insert the language code for the loaded language, based - // on the variable "help_language" that is declared in the help.tpl page template - var path = window.location.pathname.split('/'); - var pathParts = []; - var pick_me = true; - for (var i = 0; i < path.length; i++) { - if(i === 2 && pick_me ) { - if(path[i].length > 0) { - pathParts.push(help_language); - pick_me = false; - if($.inArray(path[i], langChoices) < 0) { - i--; - } - } - } else { - if(path[i].length > 0) { - pathParts.push(path[i]); - } - } - - } - // Update the address bar to reflect the loaded language - window.history.replaceState({}, '', '/' + pathParts.join('/')); - - // Highlight the language in the language selector that is currently viewed - $('.lang-selector').find('.lang-choice:contains("' + help_language + '")').addClass('active'); - - // Construct the links to the available translations based and populate the selector menu - $('.lang-selector').find('.lang-choice').each(function (idx, a) { - var langLink = []; - - for (var i = 0; i < pathParts.length; i++) { - - if(i === 1) { - langLink.push($(a).html()); - } else { - langLink.push(pathParts[i]); - } - - } - $(a).attr('href', '/' + langLink.join('/')); - }); - }); diff --git a/view/js/mod_hq.js b/view/js/mod_hq.js index 1e4c02768..2c2aca37b 100644 --- a/view/js/mod_hq.js +++ b/view/js/mod_hq.js @@ -1,6 +1,5 @@ $(document).ready(function() { - - $('.autotime').timeago(); + updateRelativeTime('.autotime'); if (bParam_mid) { src = 'hq'; diff --git a/view/js/mod_import_progress.js b/view/js/mod_import_progress.js index 7aed56365..11b324862 100644 --- a/view/js/mod_import_progress.js +++ b/view/js/mod_import_progress.js @@ -30,6 +30,9 @@ $(document).ready(function() { $('#cprogress-bar').css('width', '0%'); } + $('#cprogress-completed span').html(data.ccompleted_str); + + // files if (typeof data.fprogress == 'number') { $('#fprogress-label').html(data.fprogress + '%'); @@ -50,5 +53,8 @@ $(document).ready(function() { $('#fprogress-label').html(data.fprogress); $('#fprogress-bar').css('width', '0%'); } + + $('#fprogress-completed span').html(data.fcompleted_str); + } }); diff --git a/view/js/mod_photos.js b/view/js/mod_photos.js index c487fc417..ca1d85f0c 100644 --- a/view/js/mod_photos.js +++ b/view/js/mod_photos.js @@ -131,42 +131,45 @@ function formatSizeUnits(bytes){ // this is basically a js port of include/text.php getIconFromType() function function getIconFromType(type) { - var map = { + let map = { //Common file - 'application/octet-stream': 'fa-file-o', + 'application/octet-stream': 'bi-file-earmark', //Text - 'text/plain': 'fa-file-text-o', - 'application/msword': 'fa-file-word-o', - 'application/pdf': 'fa-file-pdf-o', - 'application/vnd.oasis.opendocument.text': 'fa-file-word-o', - 'application/epub+zip': 'fa-book', + 'text/plain': 'bi-file-earmark-text', + 'text/markdown': 'bi-filetype-md', + 'text/bbcode': 'bi-file-earmark-text', + 'text/html': 'bi-filetype-html', + 'application/msword': 'bi-file-earmark-word', + 'application/pdf': 'bi-file-earmark-pdf', + 'application/vnd.oasis.opendocument.text': 'bifile--earmark-text', + 'application/epub+zip': 'bi-file-earmark-text', //Spreadsheet - 'application/vnd.oasis.opendocument.spreadsheet': 'fa-file-excel-o', - 'application/vnd.ms-excel': 'fa-file-excel-o', + 'application/vnd.oasis.opendocument.spreadsheet': 'bi-file-earmark-spreadsheet', + 'application/vnd.ms-excel': 'bi-file-earmark-spreadsheet', //Image - 'image/jpeg': 'fa-picture-o', - 'image/png': 'fa-picture-o', - 'image/gif': 'fa-picture-o', - 'image/svg+xml': 'fa-picture-o', + 'image/jpeg': 'bi-file-earmark-image', + 'image/png': 'bi-file-earmark-image', + 'image/gif': 'bi-file-earmark-image', + 'image/webp': 'bi-file-earmark-image', + 'image/svg+xml': 'bi-filetype-svg', //Archive - 'application/zip': 'fa-file-archive-o', - 'application/x-rar-compressed': 'fa-file-archive-o', + 'application/zip': 'bi-file-earmark-zip', + 'application/x-rar-compressed': 'bi-file-earmark-zip', //Audio - 'audio/mpeg': 'fa-file-audio-o', - 'audio/mp3': 'fa-file-audio-o', //webkit browsers need that - 'audio/wav': 'fa-file-audio-o', - 'application/ogg': 'fa-file-audio-o', - 'audio/ogg': 'fa-file-audio-o', - 'audio/webm': 'fa-file-audio-o', - 'audio/mp4': 'fa-file-audio-o', + 'audio/mpeg': 'bi-file-earmark-music', + 'audio/wav': 'bi-file-earmark-music', + 'application/ogg': 'bi-file-earmark-music', + 'audio/ogg': 'bi-file-earmark-music', + 'audio/webm': 'bi-file-earmark-music', + 'audio/mp4': 'bi-file-earmark-music', //Video - 'video/quicktime': 'fa-file-video-o', - 'video/webm': 'fa-file-video-o', - 'video/mp4': 'fa-file-video-o', - 'video/x-matroska': 'fa-file-video-o' + 'video/quicktime': 'bi-file-earmark-play', + 'video/webm': 'bi-file-earmark-play', + 'video/mp4': 'bi-file-earmark-play', + 'video/x-matroska': 'bi-file-earmark-play' }; - var iconFromType = 'fa-file-o'; + let iconFromType = 'bi-file-earmark'; if (type in map) { iconFromType = map[type]; |