PageSourceSearch

https://www.federacionanarquista.net/wp-content/themes/AnarchistAr…/ngnm-reader-sources-list.js?ver=1790283450

js federacionanarquista.net collected 2026-09-24 21:02:43 UTC 4,776 bytes, 121 lines download raw bytes

1/**
2 * Hides/favourite/notify controls on sources_list.php (heavily disk-cached page,
3 * so personalization is hydrated client-side against ngnm_reader_api.php,
4 * same pattern as ngnm-reader-home.js).
5 */
6(function () {
7    'use strict';
8
9    var cfg = window.NgnmReaderSourcesList || {};
10    var apiBase = cfg.apiBase || '';
11    var portalUrl = cfg.portalUrl || '';
12    var dashboardUrl = cfg.dashboardUrl || '';
13    if (!apiBase) {
14        return;
15    }
16
17    var disabled = {};
18    var favoriteAuthors = {};
19    var notifyAuthors = {};
20    var loggedIn = false;
21    var pushEnabled = false;
22    var requestProof = '';
23
24    function setPressed(btn, on, iconOnColor) {
25        btn.setAttribute('aria-pressed', on ? 'true' : 'false');
26        var icon = btn.querySelector('i');
27        if (icon) {
28            icon.style.color = on ? iconOnColor : 'rgb(151,151,151)';
29        }
30    }
31
32    function refreshRow(row) {
33        var aid = row.getAttribute('data-author-id');
34        if (!aid) return;
35        var hideBtn = row.querySelector('.ngnm-src-hide');
36        var favBtn = row.querySelector('.ngnm-src-fav');
37        var notifyBtn = row.querySelector('.ngnm-src-notify');
38        if (hideBtn) setPressed(hideBtn, !!disabled[aid], '#f87171');
39        if (favBtn) setPressed(favBtn, !!favoriteAuthors[aid], '#facc15');
40        if (notifyBtn) setPressed(notifyBtn, !!notifyAuthors[aid], '#ff8a80');
41    }
42
43    function post(action, authorId) {
44        return fetch(apiBase + '?action=' + action, {
45            method: 'POST',
46            credentials: 'same-origin',
47            headers: { 'Content-Type': 'application/json', 'X-NGNM-Reader-Proof': requestProof },
48            body: JSON.stringify({ author_id: parseInt(authorId, 10) })
49        }).then(function (r) { return r.json(); });
50    }
51
52    function onClick(e) {
53        var btn = e.target.closest ? e.target.closest('.ngnm-src-btn') : null;
54        if (!btn) return;
55        e.preventDefault();
56        var row = btn.closest('[data-ngnm-reader-source-row]');
57        if (!row) return;
58        var aid = row.getAttribute('data-author-id');
59        if (!aid) return;
60
61        if (!loggedIn) {
62            if (portalUrl) {
63                window.location.href = portalUrl + '?mode=register';
64            }
65            return;
66        }
67
68        var action = btn.getAttribute('data-action');
69        if (action === 'hide') {
70            post('hide_author', aid).then(function (data) {
71                if (!data || !data.ok) return;
72                disabled = {};
73                (data.disabled_author_ids || []).forEach(function (id) { disabled[String(id)] = true; });
74                refreshRow(row);
75            });
76        } else if (action === 'favorite') {
77            post('favorite_author_toggle', aid).then(function (data) {
78                if (!data || !data.ok) return;
79                favoriteAuthors = {};
80                (data.favorite_author_ids || []).forEach(function (id) { favoriteAuthors[String(id)] = true; });
81                refreshRow(row);
82            });
83        } else if (action === 'notify') {
84            post('notify_author_toggle', aid).then(function (data) {
85                if (!data || !data.ok) return;
86                notifyAuthors = {};
87                (data.notify_author_ids || []).forEach(function (id) { notifyAuthors[String(id)] = true; });
88                refreshRow(row);
89                if (data.notify && !pushEnabled && row.getAttribute('data-notify-browser') === '1' && dashboardUrl) {
90                    window.location.href = dashboardUrl + '#ngnm-reader-push';
91                }
92            });
93        }
94    }
95
96    function boot() {
97        document.addEventListener('click', onClick);
98        fetch(apiBase + '?action=me', { credentials: 'same-origin' })
99            .then(function (r) { return r.json(); })
100            .then(function (data) {
101                if (!data) return;
102                loggedIn = !!data.logged_in;
103                pushEnabled = !!data.push_enabled;
104                requestProof = data.request_proof || '';
105                (data.disabled_author_ids || []).forEach(function (id) { disabled[String(id)] = true; });
106                (data.favorite_author_ids || []).forEach(function (id) { favoriteAuthors[String(id)] = true; });
107                (data.notify_author_ids || []).forEach(function (id) { notifyAuthors[String(id)] = true; });
108                var rows = document.querySelectorAll('[data-ngnm-reader-source-row]');
109                for (var i = 0; i < rows.length; i++) {
110                    refreshRow(rows[i]);
111                }
112            })
113            .catch(function () {});
114    }
115
116    if (document.readyState === 'loading') {
117        document.addEventListener('DOMContentLoaded', boot);
118    } else {
119        boot();
120    }
121})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.