PageSourceSearch

https://pupwife.com/scripts/dependencies/accountIndicator.js

js pupwife.com collected 2026-09-30 15:05:42 UTC 8,564 bytes, 233 lines download raw bytes

1// ====================================
2// ACCOUNT PILL — homepage only (index)
3// ====================================
4
5(function () {
6    'use strict';
7
8    function isHomePage() {
9        const path = (window.location.pathname || '').replace(/\/$/, '') || '/';
10        return path === '' || path === '/' || path === '/index' || path === '/index.html';
11    }
12
13    function shouldShowAccountIndicator() {
14        if (window.SpaChromePolicy &&
15            typeof window.SpaChromePolicy.getCurrentPolicy === 'function' &&
16            window.SpaChromePolicy.getCurrentPolicy()) {
17            return window.SpaChromePolicy.isEnabled('accountIndicator');
18        }
19        return isHomePage();
20    }
21
22    function ensureAccountIndicatorCss() {
23        if (document.querySelector('link[data-account-indicator-css]')) return;
24        const link = document.createElement('link');
25        link.rel = 'stylesheet';
26        link.href = '/css/account-indicator.css';
27        link.setAttribute('data-account-indicator-css', '1');
28        document.head.appendChild(link);
29    }
30
31    function ensureFontAwesome() {
32        if (typeof window.ensureSiteFontAwesome === 'function') {
33            return window.ensureSiteFontAwesome();
34        }
35        return new Promise(function (resolve) {
36            if (document.querySelector('script[src*="ensureSiteFontAwesome.js"]')) {
37                var pending = document.querySelector('script[src*="ensureSiteFontAwesome.js"]');
38                function done() {
39                    if (typeof window.ensureSiteFontAwesome === 'function') {
40                        window.ensureSiteFontAwesome().then(resolve);
41                    } else {
42                        resolve();
43                    }
44                }
45                if (pending.getAttribute('data-fa-loader-ready') === '1') {
46                    done();
47                } else {
48                    pending.addEventListener('load', done, { once: true });
49                    pending.addEventListener('error', done, { once: true });
50                }
51                return;
52            }
53            var script = document.createElement('script');
54            script.src = '/scripts/effects/ensureSiteFontAwesome.js';
55            script.async = false;
56            script.setAttribute('data-fa-loader', '1');
57            script.onload = script.onerror = function () {
58                script.setAttribute('data-fa-loader-ready', '1');
59                if (typeof window.ensureSiteFontAwesome === 'function') {
60                    window.ensureSiteFontAwesome().then(resolve);
61                } else {
62                    resolve();
63                }
64            };
65            document.head.appendChild(script);
66        });
67    }
68
69    function readStoredUsername() {
70        if (window.__sharedUsername && typeof window.__sharedUsername.get === 'function') {
71            return window.__sharedUsername.get();
72        }
73        try {
74            return localStorage.getItem('puppy_shared_username');
75        } catch (e) {
76            return null;
77        }
78    }
79
80    function isLoggedInAccount() {
81        const username = readStoredUsername();
82        const hasPassword = localStorage.getItem('puppy_username_password') !== null;
83        const isGuestMode = localStorage.getItem('puppy_guest_mode') === 'true';
84        return !!(username && hasPassword && !isGuestMode);
85    }
86
87    function openAccountFlow() {
88        if (isCitrusOsPage()) {
89            if (window.CitrusAccountWindow && typeof window.CitrusAccountWindow.open === 'function') {
90                window.CitrusAccountWindow.open();
91                return;
92            }
93        }
94        if (isLoggedInAccount()) {
95            window.location.href = 'account.html';
96            return;
97        }
98        if (window.__sharedUsername && typeof window.__sharedUsername.promptAgain === 'function') {
99            window.__sharedUsername.promptAgain();
100        } else {
101            window.location.href = 'account.html';
102        }
103    }
104
105    function isCitrusOsPage() {
106        return !!(document.body && document.body.classList.contains('page-citrusos'));
107    }
108
109    function ensureCitrusAccountCss() {
110        if (document.querySelector('link[data-citrus-account-css]')) return;
111        var link = document.createElement('link');
112        link.rel = 'stylesheet';
113        link.href = '/css/citrusAccount.css';
114        link.setAttribute('data-citrus-account-css', '1');
115        document.head.appendChild(link);
116    }
117
118    function mountAccountIndicator(indicator) {
119        if (!indicator) return;
120
121        if (isCitrusOsPage()) {
122            ensureCitrusAccountCss();
123            indicator.classList.remove('citrus-tray-btn');
124            indicator.classList.add('citrusos-taskbar-account');
125            var taskbar = document.getElementById('citrusos-taskbar');
126            var startBtn = document.getElementById('citrusos-start-btn');
127            if (taskbar && startBtn && startBtn.parentNode === taskbar) {
128                if (indicator.parentNode !== taskbar) {
129                    taskbar.insertBefore(indicator, startBtn);
130                }
131                return;
132            }
133            if (indicator.parentNode !== document.body) {
134                document.body.appendChild(indicator);
135            }
136            return;
137        }
138
139        indicator.classList.remove('citrusos-taskbar-account', 'citrus-tray-btn');
140        if (indicator.parentNode !== document.body) {
141            document.body.appendChild(indicator);
142        }
143    }
144
145    function createAccountIndicator() {
146        if (!shouldShowAccountIndicator()) return null;
147
148        ensureAccountIndicatorCss();
149
150        const indicator = document.createElement('button');
151        indicator.type = 'button';
152        indicator.id = 'account-indicator';
153        indicator.className = 'account-indicator';
154        indicator.setAttribute('aria-label', 'Account');
155        indicator.title = 'Account';
156
157        indicator.innerHTML =
158            '<span class="account-indicator-inner">' +
159            '<span class="account-indicator-icon" aria-hidden="true"><i class="fa-solid fa-user"></i></span>' +
160            '<span class="account-indicator-copy">' +
161            '<span class="account-indicator-meta"></span>' +
162            '<span id="account-indicator-username" class="account-indicator-username"></span>' +
163            '</span></span>';
164
165        indicator.addEventListener('click', openAccountFlow);
166        mountAccountIndicator(indicator);
167        return indicator;
168    }
169
170    function updateAccountIndicator() {
171        if (!shouldShowAccountIndicator()) {
172            const existing = document.getElementById('account-indicator');
173            if (existing) existing.style.display = 'none';
174            return;
175        }
176
177        let indicator = document.getElementById('account-indicator');
178        if (!indicator) {
179            indicator = createAccountIndicator();
180        }
181        if (!indicator) return;
182
183        mountAccountIndicator(indicator);
184
185        const usernameDisplay = document.getElementById('account-indicator-username');
186        if (!usernameDisplay) return;
187
188        indicator.style.display = 'flex';
189
190        const loggedIn = isLoggedInAccount();
191        indicator.classList.toggle('account-indicator--logged-in', loggedIn);
192
193        if (loggedIn) {
194            const username = readStoredUsername();
195            usernameDisplay.textContent = username;
196            indicator.title = 'View account (' + username + ')';
197            indicator.setAttribute('aria-label', 'View account for ' + username);
198        } else {
199            usernameDisplay.textContent = 'Sign in';
200            indicator.title = 'Sign in or create a free account';
201            indicator.setAttribute('aria-label', 'Sign in or create account');
202        }
203    }
204
205    function init() {
206        ensureFontAwesome().then(updateAccountIndicator);
207    }
208
209    if (document.readyState === 'loading') {
210        document.addEventListener('DOMContentLoaded', function () {
211            setTimeout(init, 400);
212        });
213    } else {
214        setTimeout(init, 400);
215    }
216
217    window.addEventListener('usernameSet', function () {
218        setTimeout(function () {
219            ensureFontAwesome().then(updateAccountIndicator);
220        }, 200);
221    });
222
223    window.addEventListener('pupwife:spa-chrome', function () {
224        updateAccountIndicator();
225    });
226
227    window.AccountIndicator = {
228        update: updateAccountIndicator,
229        open: openAccountFlow,
230        isLoggedIn: isLoggedInAccount,
231        shouldShow: shouldShowAccountIndicator
232    };
233})();

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.