[Mainsite/Reader] Chapters from blocked groups remain hidden after logging out of the site

Dex-chan lover
Joined
May 14, 2018
Messages
787
Description:
I have the group J-Novel Club blocked, so their chapters don't appear. When I logged out of the site, their chapters still didn't appear, even though they do appear when visiting the same title page in a private browsing session.

Steps to Reproduce:
  1. While logged in, navigate to a title that has chapters from a blocked group.
  2. Note what chapters appear
  3. Log out of the site
  4. Note what chapters appear

Environment Details:
  • Browser: Firefox Ver. 139.0.4 (64-bit)
  • Operating System: Windows 10 Home ver. 10.0.19045 Build 19045
  • Device: Desktop PC
(Add any other detail if needed)

Additional Information:
This issue shows up for the chapter list on the title page, but also occurs for the Change Group button (with the group in question absent from the Change Group menu on the chapter even after logging out).

Here are screenshots:

Logged out:

54600640540_73d0836084_n.jpg


54600542933_7a390a3437_b.jpg


Private Browsing Session (it won't let me un-bold this text):
54600643430_d43a1b10eb_k.jpg


Additional Context:

  • I originally thought this was a bug where the Change Group button was present on a chapter with only one translation available in that language, because I saw that behavior and logged out of the site to see if it was just a matter of one of the versions being from a blocked group. It was that, but I didn't realize because logging out still didn't display the blocked J-Novel Club version of the chapter. I didn't think of trying a private/incognito browsing session until I started writing this report. Here's the chapter in question: https://mangadex.org/chapter/7a068e7f-38e3-42fd-bd10-62e8797aed45/1
  • I first encountered this issue on Chrome, but it was while using WatchParty's virtual browser feature, so I don't know anything about the system info (and I forgot to check what version of Chrome it was)
 
୧⍢⃝୨
Staff
Super Moderator
Joined
Jan 7, 2023
Messages
282
Hey, apologies for the very very late response (I raised this issue to the devs some weeks ago).

Due to the way the settings work at the moment, there isn't an easy way to fix this.

This is because most settings are currently stored in your browser's localstorage. This means that the site would need to clear this storage when you log out for hidden groups to reappear while you are logged out.
However, this would also delete any other settings you have, most notably your Reader settings, which aren't saved to your account, as well as many others.
 
Joined
Nov 24, 2024
Messages
691
However, this would also delete any other settings you have, most notably your Reader settings, which aren't saved to your account, as well as many others.
I must dare speak out of My place , How‑ever ; that is ſimply not correct , one mꜽ update storage Local without removing any Other data.
This is because most settings are currently stored in your browser's localstorage.
It is , when I run This script — I Humbly apologize for the crude nature of It — and log out normally It clears groupBlacklist Quite well as I’ve observed ſo far including Mine Observer script , which shows : groupBlacklist getting populated by at ke at https://mangadex.org/_nuxt/entry.DcBIC3Jf.js:2:39327.
The code that tries solely to delete Local storage :
Code:
(function() { 'use strict'; function clearUserData() { try { const mdData = localStorage.getItem('md'); if (mdData) { const parsedData = JSON.parse(mdData); if (parsedData.userPreferences && parsedData.userPreferences.groupBlacklist) { parsedData.userPreferences.groupBlacklist = []; } if (parsedData.groupBlacklist) { parsedData.groupBlacklist = []; } localStorage.setItem('md', JSON.stringify(parsedData)); } } catch (error) { // Silent error handling } } function isSignOutButton(element) { const signOutText = element.querySelector('span[data-v-39ad6aa0]'); if (signOutText && signOutText.textContent.trim() === 'Sign Out') { return true; } const hasClasses = element.classList.contains('list__item') && element.classList.contains('cursor-pointer'); const hasLogoutIcon = element.querySelector('svg path[d*="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4m7 14 5-5-5-5m5 5H9"]'); return hasClasses && hasLogoutIcon; } document.addEventListener('click', function(event) { const clickedElement = event.target.closest('button'); if (clickedElement && isSignOutButton(clickedElement)) { clearUserData(); } }); let lastUrl = location.href; new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; } }).observe(document, {subtree: true, childList: true}); })();
The code is obfuscated intentionally so apart from knowing that at https://mangadex.org/_nuxt/entry.DcBIC3Jf.js:2:39327 exists a function — whose contents are given hereinunder — named ke tries to sꜹe data to Local storage & upon failure — or Other defined criteria I ‘ꜹe No knowledge of , for I hꜹe delved not that Deep into the ſource code yet — clears Every‑thing and sꜹes again by syncing the data. Data comes from — sorry for the In‑correct terms before I lꜽ Them down — a Plug‑in for Vue.jsPinia , who gets It from ſome‑where Un‑known to Me as of now , therefore ; I won’t get into details — and the code checks It from there using const Kr , whose contents are presented under the 1ˢᵗ Code‑block.
Code:
function ke(e, t) {
    try {
        localStorage.setItem(e, JSON.stringify(t))
    } catch {
        const o = {};
        for (let r = 0, i; i = localStorage.key(r), i; r++)
            o[i] = localStorage.getItem(i);
        localStorage.clear(),
        o[e] = JSON.stringify(t);
        for (const r of Object.keys(o))
            localStorage.setItem(r, o[r])
    }
}
Code:
const Kr = R(e => {
    let t = he(!0)
      , a = t.metadata.modified ?? 0;
    const o = new Map
      , r = new Map
      , {$pinia: i} = e;
    i.use( ({store: s, options: n}) => {
        if (!n.persist)
            return;
        o.set(s.$id, s),
        r.set(s, !1),
        be(s, t[s.$id] ?? {});
        const l = new ze(`mangadex-state-${s.$id}`);
        s.$subscribe( (d, u) => {
            var p;
            if (r.get(s))
                return;
            const g = Date.now();
            l.postMessage({
                modified: g,
                state: JSON.stringify(u)
            }).catch(_ => console.error(_));
            let h = he(!1);
            if (h === void 0 && (h = he(!0)),
            (((p = h.metadata) == null ? void 0 : p.modified) ?? 0) > a) {
                a = h.metadata.modified;
                for (const [_,m] of o)
                    r.set(m, !0),
                    be(m, t[_] ?? {}),
                    r.set(m, !1);
                return
            }
            h.metadata.modified = g,
            h[s.$id] = u,
            ke("md", h),
            a = g
        }
        , {
            detached: !0
        }),
        l.onmessage = d => {
            a > d.modified || (r.set(s, !0),
            a = d.modified,
            be(s, JSON.parse(d.state)),
            r.set(s, !1))
        }
    }
    )
}
);
Due to the way the settings work at the moment, there isn't an easy way to fix this.
You can delete a datum alone & alone in Local storage , I must sꜽ It again but — do , please , not see this as rudeneſs — this is Plain Wrong‑information.
☞In eßence
We can conclude that : if ‘twas — the action of storing User preferences — only happening in Local storage Mine actions would be permanent instead of getting Over‑ridden by the server’s† data , Whence‑fore ; MangaDex Actively keeps User data in It’s Back‑end† and All evidence ſo far points in the Opposite light of what Thine Esteemed self has said.
Code to implement for users to fix This iſsuͤ as It stands currently :
Code:
(function() { 'use strict'; function clearGroupBlacklist() { try { const mdData = localStorage.getItem('md'); if (mdData) { const parsedData = JSON.parse(mdData); let modified = false; if (parsedData.userPreferences && parsedData.userPreferences.groupBlacklist && parsedData.userPreferences.groupBlacklist.length > 0) { parsedData.userPreferences.groupBlacklist = []; modified = true; } if (modified) { localStorage.setItem('md', JSON.stringify(parsedData)); } } const vueApp = document.querySelector('#__nuxt').__vue_app__; if (vueApp && vueApp.config && vueApp.config.globalProperties && vueApp.config.globalProperties.$pinia) { const pinia = vueApp.config.globalProperties.$pinia; const userPreferencesStore = pinia._s.get('userPreferences'); if (userPreferencesStore && userPreferencesStore.groupBlacklist && userPreferencesStore.groupBlacklist.length > 0) { userPreferencesStore.groupBlacklist = []; } } } catch (error) { } } function isSignOutButton(element) { const signOutText = element.querySelector('span[data-v-39ad6aa0]'); if (signOutText && signOutText.textContent.trim() === 'Sign Out') { return true; } const hasClasses = element.classList.contains('list__item') && element.classList.contains('cursor-pointer'); const hasLogoutIcon = element.querySelector('svg path[d*="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4m7 14 5-5-5-5m5 5H9"]'); return hasClasses && hasLogoutIcon; } document.addEventListener('click', function handler(event) { const clickedElement = event.target.closest('button'); if (clickedElement && isSignOutButton(clickedElement)) { event.preventDefault(); event.stopPropagation(); clearGroupBlacklist(); document.removeEventListener('click', handler, true); clickedElement.click(); document.addEventListener('click', handler, true); } }, true); })();
I apologize for Any mistakes I hꜹe herein written in advance.

†I call Any‑thing that is not Immediately acceßible in Local storage „ ſerver sided „ , ergo ; I beg of forgiveneſs to Mine ignorance in This matter from those who know better than Me.
 
Last edited:

Users who are viewing this thread

Top