feat: pause Today during mobile Security Center (Closes #1086)
This commit is contained in:
1 parent
aba4b55ca0
commit
473f592615
11 files changed
+174
-14
No files matched your search
@@ -1853,6 +1853,7 @@
|
||||
},
|
||||
onCapture:() => openCreateIssueSheet(),
|
||||
});
|
||||
window.stackchainTodayTimerView = timerView;
|
||||
mobileInsights.start();
|
||||
todaySessionSync = attachTodaySessionHandoff({
|
||||
fetchJson:fetchReviewJson, storage:localStorage, timer, qs,
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
<div><h2>Security Center</h2><p class="small muted">Investigate activity, remove untrusted access, and verify the result.</p></div>
|
||||
<button id="close-active-devices" type="button" aria-label="Close active devices">Close</button>
|
||||
</div>
|
||||
<aside class="today-detour-interruption" id="security-center-today-detour" data-today-detour role="status" aria-live="polite" hidden>
|
||||
<strong data-today-detour-label>Today paused</strong>
|
||||
<button id="return-from-security-center" data-return-from-detour type="button">Return to Today</button>
|
||||
</aside>
|
||||
<nav class="security-section-nav" aria-label="Security Center sections">
|
||||
<button id="security-section-activity" type="button">Activity</button>
|
||||
<button id="security-section-devices" type="button">Devices</button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function (root, factory) {
|
||||
if (typeof module !== 'undefined' && module.exports) module.exports = factory;
|
||||
else root.attachSecurityCenter = boundary => factory({ root, boundary });
|
||||
})(typeof window !== 'undefined' ? window : this, function attachSecurityCenter({ root, boundary }) {
|
||||
else root.attachSecurityCenter = (boundary, options = {}) => factory({ root, boundary, ...options });
|
||||
})(typeof window !== 'undefined' ? window : this, function attachSecurityCenter({ root, boundary, onOpen = () => {}, onClose = () => {} }) {
|
||||
const devicesButton = root.document.getElementById('active-devices');
|
||||
const devicesSheet = root.document.getElementById('active-devices-sheet');
|
||||
const devicesList = root.document.getElementById('active-devices-list');
|
||||
@@ -52,6 +52,7 @@
|
||||
if (!devicesSheet.hidden) {
|
||||
devicesSheet.hidden = true;
|
||||
devicesButton?.focus();
|
||||
onClose();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -222,6 +223,7 @@
|
||||
|
||||
const open = () => {
|
||||
if (!devicesSheet) return;
|
||||
onOpen();
|
||||
devicesSheet.hidden = false;
|
||||
root.document.getElementById('close-active-devices')?.focus();
|
||||
navigate('activity', { history: root.history?.state?.stackchainSecuritySection !== 'activity' });
|
||||
|
||||
+16
-1
@@ -45,6 +45,12 @@
|
||||
const devicesSheet = root.document.getElementById('active-devices-sheet');
|
||||
const devicesStatus = root.document.getElementById('active-devices-status');
|
||||
const closeDevices = root.document.getElementById('close-active-devices');
|
||||
const returnFromSecurity = root.document.getElementById('return-from-security-center');
|
||||
const beginSecurityDetour = () => {
|
||||
if (root.matchMedia?.('(max-width: 600px)')?.matches) {
|
||||
root.stackchainTodayTimerView?.beginDetour?.('security-center');
|
||||
}
|
||||
};
|
||||
const securityFeatures = root.createFeatureLoader({
|
||||
document: root.document,
|
||||
urls: {
|
||||
@@ -57,6 +63,7 @@
|
||||
const openSecurityCenter = async () => {
|
||||
if (loadingSecurityCenter) return;
|
||||
loadingSecurityCenter = true;
|
||||
beginSecurityDetour();
|
||||
devicesSheet.hidden = false;
|
||||
closeDevices?.focus();
|
||||
try {
|
||||
@@ -66,7 +73,10 @@
|
||||
retryLabel: 'Tap Active devices to retry.',
|
||||
}, () => {
|
||||
devicesButton.removeEventListener('click', openSecurityCenter);
|
||||
root.attachSecurityCenter(boundary).open();
|
||||
root.attachSecurityCenter(boundary, {
|
||||
onOpen: beginSecurityDetour,
|
||||
onClose: () => root.stackchainTodayTimerView?.finishDetour?.('security-center'),
|
||||
}).open();
|
||||
});
|
||||
} finally {
|
||||
loadingSecurityCenter = false;
|
||||
@@ -78,6 +88,11 @@
|
||||
if (closeDevices && devicesSheet) closeDevices.addEventListener('click', () => {
|
||||
devicesSheet.hidden = true;
|
||||
devicesButton?.focus();
|
||||
root.stackchainTodayTimerView?.finishDetour?.('security-center');
|
||||
});
|
||||
if (returnFromSecurity && devicesSheet) returnFromSecurity.addEventListener('click', () => {
|
||||
if (root.history?.state?.stackchainSecuritySection) root.history.back();
|
||||
else devicesSheet.hidden = true;
|
||||
});
|
||||
boundary.refreshOfflineLease().then(valid => {
|
||||
if (valid) boundary.resumeQueuedWork();
|
||||
|
||||
@@ -57,7 +57,7 @@ function createTodayTimer({ storage, getLogin, now = () => Date.now(), onChange
|
||||
const validDetour = state => {
|
||||
const pending = state.detour_interruption;
|
||||
return pending && typeof pending.identity === 'string' && pending.identity &&
|
||||
typeof pending.resume === 'boolean' && ['find', 'queues', 'insights', 'device-setup'].includes(pending.reason) ?
|
||||
typeof pending.resume === 'boolean' && ['find', 'queues', 'insights', 'device-setup', 'security-center'].includes(pending.reason) ?
|
||||
{ identity:pending.identity, resume:pending.resume, reason:pending.reason } : null;
|
||||
};
|
||||
const validBreak = state => {
|
||||
@@ -289,7 +289,7 @@ function createTodayTimer({ storage, getLogin, now = () => Date.now(), onChange
|
||||
return write(state) ? { identity:pending.identity, resumed } : null;
|
||||
},
|
||||
beginDetour(reason) {
|
||||
if (!['find', 'queues', 'insights', 'device-setup'].includes(reason)) return null;
|
||||
if (!['find', 'queues', 'insights', 'device-setup', 'security-center'].includes(reason)) return null;
|
||||
const state = read();
|
||||
const existing = validDetour(state);
|
||||
if (existing) return existing;
|
||||
@@ -304,9 +304,10 @@ function createTodayTimer({ storage, getLogin, now = () => Date.now(), onChange
|
||||
detourInterruption() {
|
||||
return validDetour(read());
|
||||
},
|
||||
returnFromDetour() {
|
||||
returnFromDetour(reason = '') {
|
||||
const state = read();
|
||||
const pending = validDetour(state);
|
||||
if (reason && pending?.reason !== reason) return null;
|
||||
const entry = pending && state.entries[pending.identity];
|
||||
if (!pending || !entry || state.active_identity !== pending.identity) return null;
|
||||
const resumed = pending.resume && !entry.running;
|
||||
@@ -521,7 +522,7 @@ function createTodayTimerView({ timer, isActive, queryAll, formatEstimate, getRu
|
||||
reopen(identity) { onReopen?.(identity); },
|
||||
search(action, ...args) { return searchView[action]?.(...args); },
|
||||
beginDetour(reason) { return detourView.open(reason); },
|
||||
finishDetour() { return detourView.finish(); },
|
||||
finishDetour(reason) { return detourView.finish(reason); },
|
||||
finish() { timer.stop(); progress = null; runway = null; render(); },
|
||||
update(nextProgress, nextRunway) { progress = nextProgress; runway = nextRunway; render(); },
|
||||
reset() { progress = null; runway = null; render(); },
|
||||
@@ -701,9 +702,9 @@ function createTodayDetourInterruption({ timer, queryAll, getItemLabel, onChange
|
||||
return pending;
|
||||
},
|
||||
restore() { return render(); },
|
||||
finish() {
|
||||
const result = timer.returnFromDetour?.();
|
||||
render(null);
|
||||
finish(reason) {
|
||||
const result = timer.returnFromDetour?.(reason);
|
||||
if (result || !reason) render(null);
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user