150 lines
7.1 KiB
C++
150 lines
7.1 KiB
C++
#include "ui_sync_conflicts.inl"
|
|
struct SyncView { HWND parent; App *app; };
|
|
void updateSyncControls(HWND w, App &app)
|
|
{
|
|
bool enabled = checked(w, 601);
|
|
bool savedEnabled = loadSyncConfig(app.data).enabled;
|
|
for (int id : {602, 603, 604, 605, 606, 607, 610, 611, 613})
|
|
EnableWindow(GetDlgItem(w, id), enabled);
|
|
EnableWindow(GetDlgItem(w, 612), enabled && savedEnabled);
|
|
EnableWindow(GetDlgItem(w, IDOK), enabled || savedEnabled);
|
|
value(w, IDOK, enabled ? L"&Save / Sign in / Sync" : L"&Save");
|
|
std::wstring status;
|
|
if (!enabled)
|
|
status = savedEnabled ? L"Click Save to disable synchronization." :
|
|
L"Synchronization is disabled. Enable it above to configure and sync.";
|
|
else if (!savedEnabled)
|
|
status = L"Configure the connection, then click Save / Sign in / Sync to enable synchronization.";
|
|
else
|
|
status = app.syncCommand();
|
|
if (value(w, 608) != status) value(w, 608, status);
|
|
}
|
|
SyncConfig syncFields(HWND w)
|
|
{
|
|
SyncConfig c;
|
|
c.enabled = checked(w, 601);
|
|
c.keepLocalLayouts = checked(w, 613);
|
|
c.server = value(w, 602);
|
|
while (!c.server.empty() && c.server.back() == L'/') c.server.pop_back();
|
|
c.username = lower(value(w, 603)); c.mount = value(w, 605);
|
|
c.path = value(w, 606); c.authMount = value(w, 607);
|
|
return c;
|
|
}
|
|
LRESULT CALLBACK syncProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
|
|
{
|
|
if (msg == WM_DPICHANGED) { resizeForDpi(w, wp, lp); return 0; }
|
|
auto *v = reinterpret_cast<SyncView *>(GetWindowLongPtrW(w, GWLP_USERDATA));
|
|
if (!v) return DefWindowProcW(w, msg, wp, lp);
|
|
try
|
|
{
|
|
if (msg == WM_TIMER)
|
|
{
|
|
updateSyncControls(w, *v->app);
|
|
return 0;
|
|
}
|
|
if (msg == WM_COMMAND)
|
|
{
|
|
int id = LOWORD(wp);
|
|
if (id == 601 && HIWORD(wp) == BN_CLICKED)
|
|
{
|
|
updateSyncControls(w, *v->app);
|
|
return 0;
|
|
}
|
|
if ((id == IDOK || id == 610 || id == 611 || id == 612) &&
|
|
!IsWindowEnabled(GetDlgItem(w, id))) return 0;
|
|
if (id == 612) { showSyncConflicts(w, *v->app); return 0; }
|
|
if (id == IDCANCEL) { DestroyWindow(w); return 0; }
|
|
if (id == 609)
|
|
{
|
|
auto c = loadSyncConfig(v->app->data);
|
|
c.enabled = false;
|
|
saveSyncConfig(v->app->data, c);
|
|
forgetSyncPassword(c);
|
|
check(w, 601, false);
|
|
value(w, 604, L"");
|
|
updateSyncControls(w, *v->app);
|
|
value(w, 608, L"Disabled. Saved password removed. An in-flight server request may still finish.");
|
|
KillTimer(w, 1);
|
|
return 0;
|
|
}
|
|
if (id == IDOK || id == 610 || id == 611)
|
|
{
|
|
if (!checked(w, 601))
|
|
{
|
|
if (id != IDOK) return 0;
|
|
auto c = loadSyncConfig(v->app->data);
|
|
c.enabled = false;
|
|
saveSyncConfig(v->app->data, c);
|
|
value(w, 604, L"");
|
|
updateSyncControls(w, *v->app);
|
|
return 0;
|
|
}
|
|
if (id != IDOK && MessageBoxW(w, id == 610 ?
|
|
L"Replace this PC's shared settings with the remote profile? A local backup will be saved. Unsaved edits in Settings are not included." :
|
|
L"Replace the remote profile with this PC's saved settings? OpenBao retains older versions according to its retention policy. Unsaved edits are not included.",
|
|
L"Resolve synchronization", MB_YESNO | MB_ICONWARNING) != IDYES) return 0;
|
|
auto c = syncFields(w);
|
|
if (c.enabled) validateSyncConfig(c);
|
|
auto password = value(w, 604);
|
|
try { if (!password.empty()) saveSyncPassword(c, password); }
|
|
catch (...) { SecureZeroMemory(password.data(), password.size() * sizeof(wchar_t)); throw; }
|
|
SecureZeroMemory(password.data(), password.size() * sizeof(wchar_t));
|
|
value(w, 604, L"");
|
|
saveSyncConfig(v->app->data, c);
|
|
value(w, 608, v->app->syncCommand(id == 610 ? 2 : id == 611 ? 3 : 1));
|
|
updateSyncControls(w, *v->app);
|
|
SetTimer(w, 1, 1000, nullptr);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
// Never display parser exceptions containing connection file contents.
|
|
value(w, 608, L"Unable to complete sync action. Check connection fields and saved configuration.");
|
|
if (dynamic_cast<const std::runtime_error *>(&e))
|
|
value(w, 608, wide(e.what()));
|
|
return 0;
|
|
}
|
|
if (msg == WM_CLOSE) { DestroyWindow(w); return 0; }
|
|
if (msg == WM_NCDESTROY)
|
|
{
|
|
KillTimer(w, 1);
|
|
EnableWindow(v->parent, TRUE); SetForegroundWindow(v->parent);
|
|
disposeFont(w); delete v; SetWindowLongPtrW(w, GWLP_USERDATA, 0);
|
|
}
|
|
return DefWindowProcW(w, msg, wp, lp);
|
|
}
|
|
void showSyncOptions(HWND parent, App &app)
|
|
{
|
|
auto c = loadSyncConfig(app.data);
|
|
HWND w = makeWindow(app, L"KSwitcher.Sync", L"Settings synchronization - OpenBao", syncProc, 660, 672);
|
|
SetWindowLongPtrW(w, GWLP_HWNDPARENT, (LONG_PTR)parent);
|
|
SetWindowLongPtrW(w, GWLP_USERDATA, (LONG_PTR)new SyncView{parent, &app});
|
|
checkbox(w, L"&Enable synchronization with your OpenBao (KV v2)", 601, 18, 18, 620);
|
|
check(w, 601, c.enabled);
|
|
label(w, L"Se&rver (HTTPS)", 18, 60, 160); edit(w, 602, 190, 56, 450); value(w, 602, c.server);
|
|
label(w, L"User&name", 18, 100, 160); edit(w, 603, 190, 96, 450); value(w, 603, c.username);
|
|
label(w, L"&Password", 18, 140, 160); edit(w, 604, 190, 136, 450, 25, ES_AUTOHSCROLL | ES_PASSWORD);
|
|
label(w, L"Leave password blank to use the saved Windows credential.", 190, 166, 450);
|
|
label(w, L"KV v2 &mount", 18, 210, 160); edit(w, 605, 190, 206, 450); value(w, 605, c.mount);
|
|
label(w, L"Profile pa&th", 18, 250, 160); edit(w, 606, 190, 246, 450); value(w, 606, c.path);
|
|
label(w, L"&Login mount", 18, 290, 160); edit(w, 607, 190, 286, 450); value(w, 607, c.authMount);
|
|
label(w, L"Sync uses saved settings. Close and reopen Settings after downloading changes.", 18, 330, 622);
|
|
edit(w, 608, 18, 362, 622, 76, ES_MULTILINE | ES_READONLY | WS_VSCROLL | ES_AUTOVSCROLL);
|
|
value(w, 608, app.syncCommand());
|
|
checkbox(w, L"&Keep this PC's layouts and layout shortcuts (sync other settings)", 613, 18, 446, 622);
|
|
check(w, 613, c.keepLocalLayouts);
|
|
button(w, L"&Save / Sign in / Sync", IDOK, 18, 484, 200);
|
|
button(w, L"&Download remote", 610, 230, 484, 195);
|
|
button(w, L"&Upload local", 611, 437, 484, 203);
|
|
button(w, L"Resolve &individual conflicts...", 612, 18, 530, 300);
|
|
label(w, L"Background check: every 10 minutes", 330, 534, 310);
|
|
button(w, L"Disconnect / &forget password", 609, 18, 582, 290);
|
|
button(w, L"&Close", IDCANCEL, 540, 582, 100);
|
|
updateSyncControls(w, app);
|
|
EnableWindow(parent, FALSE);
|
|
SetTimer(w, 1, 1000, nullptr);
|
|
showRequestedWindow(w); SetForegroundWindow(w);
|
|
}
|