Add: login button to generate the access token interactively

This commit is contained in:
eight 2019-10-21 02:34:08 +08:00
parent fca75ce207
commit 6c4f73a49a
4 changed files with 40 additions and 11 deletions

View File

@ -68,7 +68,8 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
syncStart: sync.start, syncStart: sync.start,
syncStop: sync.stop, syncStop: sync.stop,
syncNow: sync.syncNow, syncNow: sync.syncNow,
getSyncStatus: sync.getStatus getSyncStatus: sync.getStatus,
syncLogin: sync.login
}); });
// eslint-disable-next-line no-var // eslint-disable-next-line no-var

View File

@ -12,7 +12,8 @@ const sync = (() => {
syncing: false, syncing: false,
progress: null, progress: null,
currentDriveName: null, currentDriveName: null,
errorMessage: null errorMessage: null,
login: false
}; };
let currentDrive; let currentDrive;
const ctrl = dbToCloud.dbToCloud({ const ctrl = dbToCloud.dbToCloud({
@ -73,7 +74,8 @@ const sync = (() => {
return ctrl.delete(...args); return ctrl.delete(...args);
}, },
syncNow, syncNow,
getStatus: () => status getStatus: () => status,
login
}); });
function ensurePrepared(obj) { function ensurePrepared(obj) {
@ -141,10 +143,17 @@ const sync = (() => {
function handle401Error(err) { function handle401Error(err) {
if (err.code === 401) { if (err.code === 401) {
return tokenManager.revokeToken(currentDrive.name) return tokenManager.revokeToken(currentDrive.name)
.catch(console.error)
.then(() => { .then(() => {
status.login = false;
emitStatusChange();
throw err; throw err;
}); });
} }
if (/User interaction required|Requires user interaction/i.test(err.message)) {
status.login = false;
emitStatusChange();
}
throw err; throw err;
} }
@ -152,6 +161,21 @@ const sync = (() => {
msg.broadcastExtension({method: 'syncStatusUpdate', status}); msg.broadcastExtension({method: 'syncStatusUpdate', status});
} }
function login(name = prefs.get('sync.enabled')) {
return tokenManager.getToken(name, true)
.catch(err => {
if (/Authorization page could not be loaded/i.test(err.message)) {
// FIXME: Chrome always fails at the first login so we try again
return tokenManager.getToken(name);
}
throw err;
})
.then(() => {
status.login = true;
emitStatusChange();
});
}
function start(name, fromPref = false) { function start(name, fromPref = false) {
if (currentDrive) { if (currentDrive) {
return Promise.resolve(); return Promise.resolve();
@ -160,16 +184,10 @@ const sync = (() => {
ctrl.use(currentDrive); ctrl.use(currentDrive);
status.state = 'connecting'; status.state = 'connecting';
status.currentDriveName = currentDrive.name; status.currentDriveName = currentDrive.name;
status.login = true;
emitStatusChange(); emitStatusChange();
return withFinally( return withFinally(
tokenManager.getToken(name, !fromPref) (fromPref ? Promise.resolve() : login(name))
.catch(err => {
if (/Authorization page could not be loaded/i.test(err.message)) {
// FIXME: Chrome always fails at the first login so we try again
return tokenManager.getToken(name);
}
throw err;
})
.catch(handle401Error) .catch(handle401Error)
.then(() => syncNow()), .then(() => syncNow()),
err => { err => {
@ -211,6 +229,7 @@ const sync = (() => {
prefs.set('sync.enabled', 'none'); prefs.set('sync.enabled', 'none');
status.state = 'disconnected'; status.state = 'disconnected';
status.currentDriveName = null; status.currentDriveName = null;
status.login = false;
emitStatusChange(); emitStatusChange();
} }
); );

View File

@ -154,6 +154,7 @@
<button type="button" class="connect">Connect</button> <button type="button" class="connect">Connect</button>
<button type="button" class="disconnect">Disconnect</button> <button type="button" class="disconnect">Disconnect</button>
<button type="button" class="sync-now">Sync now</button> <button type="button" class="sync-now">Sync now</button>
<button type="button" class="sync-login">Login</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -81,6 +81,7 @@ document.onclick = e => {
const disconnectButton = document.querySelector('.sync-options .disconnect'); const disconnectButton = document.querySelector('.sync-options .disconnect');
const syncButton = document.querySelector('.sync-options .sync-now'); const syncButton = document.querySelector('.sync-options .sync-now');
const statusText = document.querySelector('.sync-options .sync-status'); const statusText = document.querySelector('.sync-options .sync-status');
const loginButton = document.querySelector('.sync-options .sync-login');
let status = {}; let status = {};
@ -112,6 +113,7 @@ document.onclick = e => {
disconnectButton.disabled = status.state !== 'connected' || status.syncing; disconnectButton.disabled = status.state !== 'connected' || status.syncing;
syncButton.disabled = status.state !== 'connected' || status.syncing; syncButton.disabled = status.state !== 'connected' || status.syncing;
statusText.textContent = getStatusText(); statusText.textContent = getStatusText();
loginButton.style.display = status.state === 'connected' && !status.login ? '' : 'none';
} }
function getStatusText() { function getStatusText() {
@ -149,6 +151,12 @@ document.onclick = e => {
API.syncNow().catch(console.error); API.syncNow().catch(console.error);
} }
}); });
loginButton.addEventListener('click', e => {
if (validClick(e)) {
API.syncLogin().catch(console.error);
}
});
})(); })();
function checkUpdates() { function checkUpdates() {