Skip to content

Commit 9c1546f

Browse files
authored
Merge pull request #145 from XimingZheng/master
Add manual and automatic WebDAV cloud data synchronization
2 parents 51b6fa9 + 6e0d117 commit 9c1546f

12 files changed

Lines changed: 4032 additions & 1161 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ designs/*
77
output/*
88
packaged/*
99
.idea/*
10+
.omx
1011

1112
### Linux ###
1213
*~

.yarnrc.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
compressionLevel: mixed
2+
3+
enableGlobalCache: false
4+
15
nodeLinker: node-modules

custom-dialog.html

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,39 @@
1616

1717
<body>
1818
<script src="supporter.js"></script>
19+
<style>
20+
#main {
21+
padding: 10px 12px;
22+
}
23+
24+
#timer {
25+
width: 100% !important;
26+
max-width: 100%;
27+
}
28+
29+
#dialog-buttons {
30+
width: 100% !important;
31+
display: flex;
32+
justify-content: flex-end;
33+
align-items: center;
34+
flex-wrap: wrap;
35+
gap: 8px;
36+
}
37+
38+
#dialog-buttons .btn {
39+
white-space: nowrap;
40+
flex: 0 0 auto;
41+
}
42+
</style>
1943
<div class="d-flex mx-auto text-dark" id="main">
2044
<div id="timer" class="justify-content-left align-content-left text-left"
2145
style="transform: translateY(2px); width: 210px; -webkit-app-region: drag; -webkit-user-select: none;">
2246
<p class="small text-grey font-weight-bolder" style="margin-left: 0" id="dialog-title">wnr</p>
47+
<div id="dialog-spinner" class="d-none mb-2">
48+
<div class="spinner-border spinner-border-sm text-primary" role="status"></div>
49+
</div>
2350
<p id="dialog-msg" class="small" style="line-height: 1.5">Message</p>
51+
<p id="dialog-detail" class="small text-muted d-none" style="line-height: 1.5"></p>
2452
<div id="dialog-buttons" style="width:210px" class="text-right">
2553
<a type="button" id="dialog-cancel" class="btn btn-outline-secondary btn-sm text-right d-none"
2654
style="font-size: 12px"
@@ -43,22 +71,82 @@
4371
<script>
4472
let executeAfter = "";
4573
let msgNode = $("#dialog-msg");
74+
let detailNode = $("#dialog-detail");
75+
let currentDialogKind = "default";
76+
let currentExitSessionId = null;
4677

4778
function ok() {
79+
if (currentDialogKind === "exit-sync") {
80+
ipc.send("custom-dialog-action", { action: "primary", exitSessionId: currentExitSessionId });
81+
return;
82+
}
4883
ipc.send("custom-dialog", { mode: "off", executeAfter: executeAfter });
4984
}
5085

5186
function button3() {
87+
if (currentDialogKind === "exit-sync") {
88+
ipc.send("custom-dialog-action", { action: "tertiary", exitSessionId: currentExitSessionId });
89+
return;
90+
}
5291
ipc.send("custom-dialog", { mode: "button3_update", executeAfter: executeAfter });
5392
}
5493

5594
function cancel() {
95+
if (currentDialogKind === "exit-sync") {
96+
ipc.send("custom-dialog-action", { action: "secondary", exitSessionId: currentExitSessionId });
97+
return;
98+
}
5699
ipc.send("custom-dialog", { mode: "cancel" });
57100
}
58101

59102
ipc.on("dialog-init", function (event, message) {
103+
if (message.dialogKind === "exit-sync") {
104+
if (currentExitSessionId != null && message.exitSessionId < currentExitSessionId) {
105+
return;
106+
}
107+
currentDialogKind = "exit-sync";
108+
currentExitSessionId = message.exitSessionId;
109+
$("#dialog-title").text(message.title);
110+
$("#dialog-msg").text(message.msg);
111+
if (message.detail) detailNode.text(message.detail).removeClass("d-none");
112+
else detailNode.text("").addClass("d-none");
113+
$("#dialog-button-3").addClass("d-none");
114+
$("#timer").css("width", "100%");
115+
$("#dialog-buttons").css("width", "100%");
116+
117+
if (message.state === "syncing") {
118+
$("#dialog-spinner").removeClass("d-none");
119+
$("#dialog-ok").addClass("d-none");
120+
$("#dialog-cancel").addClass("d-none");
121+
$("#dialog-button-3").addClass("d-none");
122+
document.onkeydown = function () {};
123+
} else {
124+
$("#dialog-spinner").addClass("d-none");
125+
$("#dialog-ok").removeClass("d-none").text(message.primaryLabel || i18n.__('ok'));
126+
$("#dialog-cancel").removeClass("d-none").text(message.secondaryLabel || i18n.__('cancel'));
127+
if (message.tertiaryLabel) {
128+
$("#dialog-button-3").removeClass("d-none").text(message.tertiaryLabel);
129+
} else {
130+
$("#dialog-button-3").addClass("d-none");
131+
}
132+
document.onkeydown = function (event1) {
133+
let ev = document.all ? window.event : event1;
134+
if ((ev.keyCode || ev.which) === 13) {
135+
ok();
136+
}
137+
}
138+
}
139+
140+
ipc.send("custom-dialog-fit", Math.round((msgNode.height() + detailNode.height()) / parseFloat(msgNode.css('line-height'))));
141+
return;
142+
}
143+
144+
currentDialogKind = "default";
145+
currentExitSessionId = null;
60146
$("#dialog-title").text(message.title);
61147
$("#dialog-msg").text(message.msg);
148+
detailNode.text("").addClass("d-none");
149+
$("#dialog-spinner").addClass("d-none");
62150
executeAfter = message.executeAfter;
63151
ipc.send("custom-dialog-fit", Math.round(msgNode.height() / parseFloat(msgNode.css('line-height'))));
64152
document.onkeydown = function () {
@@ -94,4 +182,4 @@
94182
<script src="renderer.js"></script>
95183
</body>
96184

97-
</html>
185+
</html>

locales/en.json

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,67 @@
320320
"hotkey-for-miniMode": "Hotkey for mini mode: ",
321321
"hotkey-failed": "Failed. Try another? ",
322322
"data-management": "App data management",
323-
"data-management-tip": "Delete, backup or import your preferences and statistics data.",
323+
"data-management-tip": "Delete, backup, import, manually sync, or use WebDAV to sync your preferences and statistics data.",
324+
"webdav-sync": "WebDAV sync",
325+
"webdav-sync-msg": "WebDAV sync: ",
326+
"webdav-sync-tip": "Manually upload or download your core data through WebDAV. Credentials stay on this device.",
327+
"webdav-sync-url": "Server URL",
328+
"webdav-sync-username": "Username",
329+
"webdav-sync-password": "Password",
330+
"webdav-sync-password-saved": "Password saved",
331+
"webdav-sync-password-not-saved": "Password not saved",
332+
"webdav-sync-remote-path": "Remote folder path",
333+
"webdav-sync-remote-path-placeholder": "Relative to the WebDAV root, e.g. apps/wnr",
334+
"webdav-sync-enabled": "Enable cloud sync",
335+
"webdav-sync-enabled-tip": "When enabled, wnr may pull from WebDAV on startup, push local changes automatically, and guard exit with cloud sync checks.",
336+
"webdav-sync-test": "Test connection",
337+
"webdav-sync-upload": "Upload to WebDAV",
338+
"webdav-sync-download": "Download from WebDAV",
339+
"webdav-sync-testing": "Testing WebDAV connection...",
340+
"webdav-sync-uploading": "Uploading data to WebDAV...",
341+
"webdav-sync-downloading": "Downloading data from WebDAV...",
342+
"webdav-sync-auto-enabled": "Automatic sync is enabled: startup pulls from WebDAV, runtime local changes push back automatically.",
343+
"webdav-sync-auto-disabled": "Automatic sync is disabled until WebDAV is fully configured.",
344+
"webdav-sync-user-disabled": "Cloud sync is off. Startup sync, automatic push, and exit sync protection are disabled.",
345+
"webdav-sync-auto-awaiting-initial-sync": "Automatic sync will stay off until the first manual upload or download completes.",
346+
"webdav-sync-startup-status": "Startup sync: ",
347+
"webdav-sync-last-push-status": "Last auto-push: ",
348+
"webdav-sync-auto-idle": "Automatic sync is idle.",
349+
"webdav-sync-startup-failed": "Startup sync failed. Continuing with local data.",
350+
"webdav-sync-autopush-running": "Automatic sync is pushing local changes...",
351+
"webdav-sync-autopush-failed": "Automatic sync failed while pushing local changes.",
352+
"webdav-sync-show-details": "Show details",
353+
"webdav-sync-hide-details": "Hide details",
354+
"webdav-sync-missing-config": "Please complete the WebDAV URL, username, password, and remote folder path.",
355+
"webdav-sync-invalid-url": "The WebDAV URL is invalid.",
356+
"webdav-sync-https-required": "WebDAV URL must use HTTPS.",
357+
"webdav-sync-auth-failed": "WebDAV authentication failed.",
358+
"webdav-sync-path-missing": "The configured WebDAV folder does not exist.",
359+
"webdav-sync-path-error": "Failed to prepare the WebDAV folder.",
360+
"webdav-sync-connection-failed": "Failed to connect to the WebDAV server.",
361+
"webdav-sync-timeout": "WebDAV request timed out.",
362+
"webdav-sync-connection-ok": "WebDAV connection succeeded.",
363+
"webdav-sync-upload-ok": "Uploaded core data to WebDAV successfully.",
364+
"webdav-sync-download-ok": "Downloaded core data from WebDAV successfully.",
365+
"webdav-sync-upload-failed": "Failed to upload data to WebDAV.",
366+
"webdav-sync-download-failed": "Failed to download data from WebDAV.",
367+
"webdav-sync-invalid-remote": "The remote WebDAV data is invalid.",
368+
"webdav-sync-remote-missing": "The remote WebDAV file is missing:",
369+
"webdav-sync-confirm-upload": "Remote WebDAV files already exist. Continue and overwrite them?",
370+
"webdav-sync-confirm-download": "Downloading from WebDAV will overwrite your local settings, statistics, and recap. Continue?",
371+
"webdav-sync-exit-syncing-title": "Syncing cloud data before exit",
372+
"webdav-sync-exit-syncing-message": "Please wait while wnr syncs your latest local changes to WebDAV.",
373+
"webdav-sync-exit-failed-title": "Cloud sync failed before exit",
374+
"webdav-sync-exit-failed-message": "wnr could not sync your latest local changes to WebDAV before exiting.",
375+
"webdav-sync-exit-initial-choice-title": "Choose how to reconcile cloud data before exit",
376+
"webdav-sync-exit-initial-choice-message": "Cloud data already exists on WebDAV. Before exiting, choose whether wnr should upload your local data to overwrite the cloud copy or download the cloud copy to replace local data.",
377+
"webdav-sync-exit-timeout-title": "Sync timed out before exit",
378+
"webdav-sync-exit-timeout-message": "wnr is still trying to sync your latest local changes to WebDAV before exiting.",
379+
"webdav-sync-exit-upload-local": "Upload local data",
380+
"webdav-sync-exit-download-cloud": "Download cloud data",
381+
"webdav-sync-exit-wait": "Keep waiting",
382+
"webdav-sync-exit-force-quit": "Force quit",
383+
"webdav-sync-exit-retry": "Retry sync",
324384
"locker": "Lock mode (parent control)",
325385
"locker-mode": "Lock mode",
326386
"locker-tip": "In lock mode, you will not be able to edit preferences or exit wnr. Also, exiting from a counting timer will need the password. ",
@@ -439,4 +499,4 @@
439499
"increase-1-minute": "Increase 1 minute",
440500
"decrease-15-seconds": "Decrease 15 seconds",
441501
"increase-15-seconds": "Increase 15 seconds"
442-
}
502+
}

locales/zh-CN.json

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,67 @@
317317
"hotkey-for-miniMode": "打开 MINI 模式的快捷键",
318318
"hotkey-failed": "设置失败,换个按键组合试试看吧。",
319319
"data-management": "应用数据管理",
320-
"data-management-tip": "清除、备份和导入设置项和统计数据。",
320+
"data-management-tip": "清除、备份、导入、手动同步设置项和统计数据,或使用 WebDAV 同步这些数据。",
321+
"webdav-sync": "WebDAV 同步",
322+
"webdav-sync-msg": "WebDAV 同步:",
323+
"webdav-sync-tip": "通过 WebDAV 手动上传或下载核心数据。连接凭据仅保存在当前设备。",
324+
"webdav-sync-url": "服务器地址",
325+
"webdav-sync-username": "用户名",
326+
"webdav-sync-password": "密码",
327+
"webdav-sync-password-saved": "密码已保存",
328+
"webdav-sync-password-not-saved": "密码未保存",
329+
"webdav-sync-remote-path": "远程文件夹路径",
330+
"webdav-sync-remote-path-placeholder": "相对于 WebDAV 根目录,例如 apps/wnr",
331+
"webdav-sync-enabled": "启用云端数据同步",
332+
"webdav-sync-enabled-tip": "开启后,wnr 会在启动时尝试从 WebDAV 拉取数据、在运行时自动回推本地变更,并在退出前执行云端同步保护。",
333+
"webdav-sync-test": "测试连接",
334+
"webdav-sync-upload": "上传到 WebDAV",
335+
"webdav-sync-download": "从 WebDAV 下载",
336+
"webdav-sync-testing": "正在测试 WebDAV 连接...",
337+
"webdav-sync-uploading": "正在上传数据到 WebDAV...",
338+
"webdav-sync-downloading": "正在从 WebDAV 下载数据...",
339+
"webdav-sync-auto-enabled": "自动同步已启用:启动时从 WebDAV 拉取,运行时本地变更会自动回推。",
340+
"webdav-sync-auto-disabled": "WebDAV 未完整配置前,自动同步不会启用。",
341+
"webdav-sync-user-disabled": "云端数据同步已关闭。启动同步、自动回推和退出前同步保护均不会执行。",
342+
"webdav-sync-auto-awaiting-initial-sync": "首次手动上传或下载完成前,自动同步会保持关闭。",
343+
"webdav-sync-startup-status": "启动同步:",
344+
"webdav-sync-last-push-status": "最近一次自动回推:",
345+
"webdav-sync-auto-idle": "自动同步处于空闲状态。",
346+
"webdav-sync-startup-failed": "启动同步失败,已继续使用本地数据。",
347+
"webdav-sync-autopush-running": "自动同步正在回推本地变更...",
348+
"webdav-sync-autopush-failed": "自动同步回推本地变更失败。",
349+
"webdav-sync-show-details": "显示详细信息",
350+
"webdav-sync-hide-details": "隐藏详细信息",
351+
"webdav-sync-missing-config": "请完整填写 WebDAV 地址、用户名、密码和远程文件夹路径。",
352+
"webdav-sync-invalid-url": "WebDAV 地址无效。",
353+
"webdav-sync-https-required": "WebDAV 地址必须使用 HTTPS。",
354+
"webdav-sync-auth-failed": "WebDAV 认证失败。",
355+
"webdav-sync-path-missing": "配置的 WebDAV 文件夹不存在。",
356+
"webdav-sync-path-error": "准备 WebDAV 文件夹失败。",
357+
"webdav-sync-connection-failed": "连接 WebDAV 服务器失败。",
358+
"webdav-sync-timeout": "WebDAV 请求超时。",
359+
"webdav-sync-connection-ok": "WebDAV 连接成功。",
360+
"webdav-sync-upload-ok": "核心数据已成功上传到 WebDAV。",
361+
"webdav-sync-download-ok": "核心数据已成功从 WebDAV 下载。",
362+
"webdav-sync-upload-failed": "上传数据到 WebDAV 失败。",
363+
"webdav-sync-download-failed": "从 WebDAV 下载数据失败。",
364+
"webdav-sync-invalid-remote": "远端 WebDAV 数据无效。",
365+
"webdav-sync-remote-missing": "远端 WebDAV 文件缺失:",
366+
"webdav-sync-confirm-upload": "远端 WebDAV 文件已存在,是否继续覆盖?",
367+
"webdav-sync-confirm-download": "从 WebDAV 下载会覆盖本地设置、统计和回顾数据,是否继续?",
368+
"webdav-sync-exit-syncing-title": "正在同步云数据后退出",
369+
"webdav-sync-exit-syncing-message": "请稍候,wnr 正在把你最新的本地变更同步到 WebDAV。",
370+
"webdav-sync-exit-failed-title": "退出前云同步失败",
371+
"webdav-sync-exit-failed-message": "wnr 在退出前未能把你最新的本地变更同步到 WebDAV。",
372+
"webdav-sync-exit-initial-choice-title": "退出前请先处理云端数据",
373+
"webdav-sync-exit-initial-choice-message": "检测到 WebDAV 上已经存在云端数据。退出前,请选择将本地数据上传并覆盖云端,或下载云端数据并替换本地数据。",
374+
"webdav-sync-exit-timeout-title": "退出前同步超时",
375+
"webdav-sync-exit-timeout-message": "wnr 正在尝试把你最新的本地变更同步到 WebDAV 后再退出。",
376+
"webdav-sync-exit-upload-local": "上传本地数据",
377+
"webdav-sync-exit-download-cloud": "下载云端数据",
378+
"webdav-sync-exit-wait": "继续等待",
379+
"webdav-sync-exit-force-quit": "强制退出",
380+
"webdav-sync-exit-retry": "重试同步",
321381
"locker": "锁定模式(家长控制)",
322382
"locker-mode": "锁定模式",
323383
"locker-tip": "打开锁定模式后,将无法修改设置,无法随意退出程序。如果自控力较弱,不妨让别人输入密码。",
@@ -434,4 +494,4 @@
434494
"custom": "自定义",
435495
"custom-notify-sound": "自定义提示音",
436496
"input-url": "输入路径"
437-
}
497+
}

0 commit comments

Comments
 (0)