feat: preserve mobile shares through sign-in (#313)
This commit is contained in:
1 parent
c0b42b71cf
commit
8ba4d48549
6 files changed
+226
-9
No files matched your search
+22
-2
@@ -2,15 +2,33 @@
|
||||
if (typeof module === 'object' && module.exports) module.exports = factory;
|
||||
else root.createLoginController = factory;
|
||||
}(typeof self !== 'undefined' ? self : this, function createLoginController(options) {
|
||||
function validShareContinuation(value) {
|
||||
if (typeof value !== 'string' || !value.startsWith('./?') || value.includes('#')) return './';
|
||||
const limits = { title: 200, text: 8000, url: 2048 };
|
||||
const params = new URLSearchParams(value.slice(3));
|
||||
const entries = Array.from(params.entries());
|
||||
if (!entries.length) return './';
|
||||
const invalid = entries.some(([name, content]) => (
|
||||
!Object.prototype.hasOwnProperty.call(limits, name)
|
||||
|| !content
|
||||
|| content.length > limits[name]
|
||||
));
|
||||
if (invalid) return './';
|
||||
return value;
|
||||
}
|
||||
|
||||
const form = options.form;
|
||||
const status = options.status;
|
||||
const button = options.button;
|
||||
const fetchImpl = options.fetchImpl;
|
||||
const location = options.location;
|
||||
const continuation = validShareContinuation(options.continuation);
|
||||
const setIntervalImpl = options.setIntervalImpl || setInterval;
|
||||
const clearIntervalImpl = options.clearIntervalImpl || clearInterval;
|
||||
let timer = null;
|
||||
|
||||
if (continuation !== './') status.textContent = 'Sign in to continue your shared capture.';
|
||||
|
||||
function showReason(reason) {
|
||||
if (reason !== 'session-expired') return;
|
||||
status.textContent = 'Your session expired. Private drafts remain on this device. Sign in to continue.';
|
||||
@@ -49,7 +67,7 @@
|
||||
}
|
||||
form.reset();
|
||||
if (response.ok) {
|
||||
location.replace('./');
|
||||
location.replace(continuation);
|
||||
return;
|
||||
}
|
||||
if (response.status === 429) {
|
||||
@@ -66,14 +84,16 @@ if (typeof document !== 'undefined') {
|
||||
const form = document.getElementById('sign-in');
|
||||
const status = document.getElementById('status');
|
||||
const button = document.getElementById('submit-sign-in');
|
||||
const loginParams = new URLSearchParams(window.location.search);
|
||||
const controller = createLoginController({
|
||||
form,
|
||||
status,
|
||||
button,
|
||||
fetchImpl: fetch.bind(window),
|
||||
location: window.location,
|
||||
continuation: loginParams.get('continue'),
|
||||
});
|
||||
controller.showReason(new URLSearchParams(window.location.search).get('reason'));
|
||||
controller.showReason(loginParams.get('reason'));
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
const accessToken = new FormData(form).get('access_token');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const BASE = new URL('./', self.location.href).pathname;
|
||||
importScripts(BASE + 'static/background-issue-sync.js');
|
||||
const CACHE = 'stackchain-dashboard-shell-v31';
|
||||
const CACHE = 'stackchain-dashboard-shell-v32';
|
||||
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
|
||||
const SHELL = [
|
||||
BASE,
|
||||
@@ -163,7 +163,9 @@ self.addEventListener('fetch', event => {
|
||||
event.respondWith(
|
||||
fetch(request).then(async response => {
|
||||
const cache = await caches.open(CACHE);
|
||||
if (response.ok) {
|
||||
const responseUrl = new URL(response.url || request.url);
|
||||
const isDashboardShell = responseUrl.origin === self.location.origin && responseUrl.pathname === BASE;
|
||||
if (response.ok && !response.redirected && isDashboardShell) {
|
||||
await cache.put(BASE, response.clone());
|
||||
} else if (OUTAGE_STATUSES.has(response.status)) {
|
||||
const cached = await cache.match(BASE);
|
||||
|
||||
Reference in new issue
Block a user