3.4 KiB
static/js — JS Rules
Profile dropdown — loader model
Profiles are loaders, not persistent modes. Selecting one pushes settings into the sidebar; the sidebar is always the live state.
_setProfileClearBtn(visible)must be called alongside every assignment toS._activeProfileId.- Do not re-add a selectable
value=""option to#profileSelect— deliberately removed in v1.6.6.
Profile editor source panel race condition
_pmgmtSaveFullEdit detects whether Google/file checkboxes have rendered by querying the DOM directly:
const googleRendered = !!document.querySelector('#peSourcesPanel input[data-source-type="google"]');
const fileRendered = !!document.querySelector('#peSourcesPanel input[data-source-type="file"]');
Never revert to !!window._googleConnected / _fileSources.length > 0 — those async proxies can be true before the panel has rendered, silently clearing the user's source selection on save.
Progress bar phase parsing
_setProgressPhase(phase) in scan.js parses the phase string against _PHASE_SOURCE_MAP:
- Source found and
—(em-dash) present → split, resolve via_resolveDisplayName(), updateS._progressCurrentUser. - Source found but no dash → show pill +
S._progressCurrentUser(handles sub-phases like folder counts). - No source match → plain text fallback.
_PHASE_SOURCE_MAP ordering matters — Google Workspace must appear before Gmail in the map. The email regex uses /iu flags — do not drop the i.
Profile startup race conditions — profiles.js + users.js
loadProfiles() (fast, local file) resolves before loadUsers() (slow, Graph API). The user can select a profile before S._allUsers or the sources panel is populated.
user_ids = "all"must be deferred — ifS._allUsersis empty when_applyProfile()runs, setwindow._pendingProfileAllUsers = trueinstead of calling.forEach()on an empty array.loadUsers()checks this flag after populatingS._allUsersand selects everyone. Do not remove this — reverting will silently leave all accounts unchecked whenever a profile is chosen on a fast machine before the user list loads.- Source checkboxes may not exist yet —
_applyProfile()callsrenderSourcesPanel()first if#sourcesPanelcontains noinput[data-source-id]nodes. Same guard used inloadUsers(). Without it,querySelectorAllreturns nothing and the profile's source selection is discarded; the nextrenderSourcesPanel()call re-renders all sources as checked (their default).
Gotchas
scheduler.jsstrings must uset()— frequency labels (m365_sched_freq_daily/weekly/monthly), "Next" (m365_sched_next), "Running..." (m365_sched_running), "Disabled" (m365_sched_disabled), empty-job text (m365_sched_no_jobs), and empty-history text (m365_sched_no_runs) all have translation keys. Do not hard-code English strings inschedLoad()orschedRenderJobs().- Profile editor accounts — default to unchecked. Only explicitly saved
user_idsare checked. - Date presets — stored as
years * 365(integer days). Do not use* 365.25. copyTokenLinkis async — called fromonclickattributes as a fire-and-forget (the Promise is unhandled, which is fine). Itawaits_getShareBaseUrl()to get the machine's LAN IP before building the URL. Do not make it synchronous or revert towindow.location.origindirectly.