Add: webdav sync (#1363)
This commit is contained in:
parent
3ea7e45624
commit
f6e6a138db
|
@ -1200,6 +1200,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"optionsSyncUsername": {
|
||||
"message": "Username"
|
||||
},
|
||||
"optionsSyncPassword": {
|
||||
"message": "Password"
|
||||
},
|
||||
"optionsSyncUrl": {
|
||||
"message": "URL"
|
||||
},
|
||||
"optionsSyncStatusRelogin": {
|
||||
"message": "Session expired, please login again."
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* global API msg */// msg.js
|
||||
/* global chromeLocal */// storage-util.js
|
||||
/* global chromeLocal chromeSync */// storage-util.js
|
||||
/* global compareRevision */// common.js
|
||||
/* global iconMan */
|
||||
/* global prefs */
|
||||
|
@ -18,6 +18,7 @@ const syncMan = (() => {
|
|||
disconnecting: 'disconnecting',
|
||||
});
|
||||
const STORAGE_KEY = 'sync/state/';
|
||||
const NO_LOGIN = ['webdav'];
|
||||
const status = /** @namespace SyncManager.Status */ {
|
||||
STATES,
|
||||
state: STATES.disconnected,
|
||||
|
@ -85,19 +86,29 @@ const syncMan = (() => {
|
|||
return ctrl.put(...args);
|
||||
},
|
||||
|
||||
async setDriveOptions(driveName, options) {
|
||||
const key = `secure/sync/driveOptions/${driveName}`;
|
||||
await chromeSync.setValue(key, options);
|
||||
},
|
||||
|
||||
async getDriveOptions(driveName) {
|
||||
const key = `secure/sync/driveOptions/${driveName}`;
|
||||
return await chromeSync.getValue(key) || {};
|
||||
},
|
||||
|
||||
async start(name, fromPref = false) {
|
||||
if (ready.then) await ready;
|
||||
if (!ctrl) await initController();
|
||||
|
||||
if (currentDrive) return;
|
||||
currentDrive = getDrive(name);
|
||||
currentDrive = await getDrive(name);
|
||||
ctrl.use(currentDrive);
|
||||
|
||||
status.state = STATES.connecting;
|
||||
status.currentDriveName = currentDrive.name;
|
||||
emitStatusChange();
|
||||
|
||||
if (fromPref) {
|
||||
if (fromPref || NO_LOGIN.includes(currentDrive.name)) {
|
||||
status.login = true;
|
||||
} else {
|
||||
try {
|
||||
|
@ -240,11 +251,11 @@ const syncMan = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
function getDrive(name) {
|
||||
if (name === 'dropbox' || name === 'google' || name === 'onedrive') {
|
||||
return dbToCloud.drive[name]({
|
||||
getAccessToken: () => tokenMan.getToken(name),
|
||||
});
|
||||
async function getDrive(name) {
|
||||
if (name === 'dropbox' || name === 'google' || name === 'onedrive' || name === 'webdav') {
|
||||
const options = await syncMan.getDriveOptions(name);
|
||||
options.getAccessToken = () => tokenMan.getToken(name);
|
||||
return dbToCloud.drive[name](options);
|
||||
}
|
||||
throw new Error(`unknown cloud name: ${name}`);
|
||||
}
|
||||
|
|
17
options.html
17
options.html
|
@ -199,10 +199,27 @@
|
|||
<option value="dropbox">Dropbox</option>
|
||||
<option value="google">Google Drive</option>
|
||||
<option value="onedrive">OneDrive</option>
|
||||
<option value="webdav">WebDAV</option>
|
||||
</select>
|
||||
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="drive-options">
|
||||
<div class="webdav-options" data-drive="webdav">
|
||||
<label class="url">
|
||||
<span i18n-text="optionsSyncUrl"></span>
|
||||
<input type="text" data-option="url">
|
||||
</label>
|
||||
<label class="username">
|
||||
<span i18n-text="optionsSyncUsername"></span>
|
||||
<input type="text" data-option="username">
|
||||
</label>
|
||||
<label class="password">
|
||||
<span i18n-text="optionsSyncPassword"></span>
|
||||
<input type="password" data-option="password">
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="actions">
|
||||
<button type="button" class="connect" i18n-text="optionsSyncConnect"></button>
|
||||
<button type="button" class="disconnect" i18n-text="optionsSyncDisconnect"></button>
|
||||
|
|
|
@ -163,7 +163,7 @@ label > :first-child {
|
|||
}
|
||||
|
||||
label:not([disabled]),
|
||||
label:not([disabled]) :not([type="number"]) {
|
||||
label:not([disabled]) :not([type="number"]):not([type="text"]):not([type="password"]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,25 @@ input[type="radio"].radio:checked::after {
|
|||
.sync-status::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sync-options .drive-options {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
.drive-options > :not([hidden]) {
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
||||
.drive-options > * > label {
|
||||
display: table-row;
|
||||
}
|
||||
.drive-options > * > label > * {
|
||||
display: table-cell;
|
||||
}
|
||||
.drive-options > * input {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sync-options .actions button {
|
||||
margin-top: .5em;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ document.onclick = e => {
|
|||
const elSyncNow = $('.sync-options .sync-now');
|
||||
const elStatus = $('.sync-options .sync-status');
|
||||
const elLogin = $('.sync-options .sync-login');
|
||||
const elDriveOptions = $('.sync-options .drive-options');
|
||||
/** @type {Sync.Status} */
|
||||
let status = {};
|
||||
msg.onExtension(e => {
|
||||
|
@ -108,7 +109,10 @@ document.onclick = e => {
|
|||
|
||||
elCloud.on('change', updateButtons);
|
||||
for (const [btn, fn] of [
|
||||
[elStart, () => API.sync.start(elCloud.value)],
|
||||
[elStart, async () => {
|
||||
await API.sync.setDriveOptions(elCloud.value, getDriveOptions());
|
||||
await API.sync.start(elCloud.value);
|
||||
}],
|
||||
[elStop, API.sync.stop],
|
||||
[elSyncNow, API.sync.syncNow],
|
||||
[elLogin, async () => {
|
||||
|
@ -123,12 +127,26 @@ document.onclick = e => {
|
|||
});
|
||||
}
|
||||
|
||||
function getDriveOptions() {
|
||||
const result = {};
|
||||
for (const el of $$(`[data-drive=${elCloud.value}] [data-option]`)) {
|
||||
result[el.dataset.option] = el.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function setDriveOptions(options) {
|
||||
for (const el of $$(`[data-drive=${elCloud.value}] [data-option]`)) {
|
||||
el.value = options[el.dataset.option] || '';
|
||||
}
|
||||
}
|
||||
|
||||
function setStatus(newStatus) {
|
||||
status = newStatus;
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
function updateButtons() {
|
||||
async function updateButtons() {
|
||||
const {state, STATES} = status;
|
||||
const isConnected = state === STATES.connected;
|
||||
const isDisconnected = state === STATES.disconnected;
|
||||
|
@ -137,6 +155,7 @@ document.onclick = e => {
|
|||
}
|
||||
for (const [el, enable] of [
|
||||
[elCloud, isDisconnected],
|
||||
[elDriveOptions, isDisconnected],
|
||||
[elStart, isDisconnected && elCloud.value !== 'none'],
|
||||
[elStop, isConnected && !status.syncing],
|
||||
[elSyncNow, isConnected && !status.syncing && status.login],
|
||||
|
@ -145,6 +164,10 @@ document.onclick = e => {
|
|||
}
|
||||
elStatus.textContent = getStatusText();
|
||||
elLogin.hidden = !isConnected || status.login;
|
||||
for (const el of elDriveOptions.children) {
|
||||
el.hidden = el.dataset.drive !== elCloud.value;
|
||||
}
|
||||
setDriveOptions(await API.sync.getDriveOptions(elCloud.value));
|
||||
}
|
||||
|
||||
function getStatusText() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user