Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix --resync issue #94

Merged
merged 1 commit into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ async def delete_lock_files(self):
"Executing: RcloneSyncManager.delete_lock_files()")
return await self.manager_sync.delete_lock_files()

async def needs_resync(self):
decky_plugin.logger.debug(
"Executing: RcloneSyncManager.needs_resync()")
return await self.manager_sync.needs_resync()

# Processes

async def signal(self, pid: int, s: str):
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "decky-cloud-save",
"version": "1.4.0",
"version": "1.4.1-pre1",
"description": "Manage cloud saves for games that do not support it in [current year].",
"scripts": {
"build": "shx rm -rf dist && rollup -c",
Expand Down
8 changes: 4 additions & 4 deletions py_modules/logger_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ def get_last_sync_log() -> str:
log: str = ""
with open(decky_plugin.DECKY_PLUGIN_LOG) as f:
for line in reversed(list(f)):
if(record==False):
if "Sync finished" in line:
if(record == False):
if "=== FINISHING SYNC ===" in line:
record = True
else:
if "Running command: /home/deck/homebrew/plugins/decky-cloud-save/bin/rcloneLauncher" in line.strip():
if "=== STARTING SYNC ===" in line:
break
else:
log = line + '\n' + log
Expand All @@ -53,7 +53,7 @@ def get_plugin_log() -> str:
"""
log: str = ""
with open(decky_plugin.DECKY_PLUGIN_LOG) as f:
for line in reversed(list(open(decky_plugin.DECKY_PLUGIN_LOG))):
for line in reversed(list(f)):
log = line + '\n' + log
if "Logger initialized at level" in line.strip():
break
Expand Down
31 changes: 11 additions & 20 deletions py_modules/rclone_sync_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import plugin_config
import os
import os.path
from glob import glob


class RcloneSyncManager:
Expand All @@ -14,11 +15,9 @@ async def delete_lock_files(self):
"""
Deletes rclone lock files
"""
args = [decky_plugin.HOME + "/.cache/rclone/bisync/*.lck"]
cmd = ["rm", *args]
decky_plugin.logger.info(
"Running command: %s", subprocess.list2cmdline(cmd))
await create_subprocess_exec(*cmd)
decky_plugin.logger.info("Deleting lock files.")
for hgx in glob(decky_plugin.HOME + "/.cache/rclone/bisync/*.lck"):
os.remove(hgx)

async def sync_now(self, winner: str, resync: bool):
"""
Expand Down Expand Up @@ -54,9 +53,11 @@ async def sync_now(self, winner: str, resync: bool):
decky_plugin.DECKY_PLUGIN_LOG, "--log-format", "none", "-v"])

cmd = [plugin_config.rclone_bin, *args]

decky_plugin.logger.info("=== STARTING SYNC ===")

decky_plugin.logger.info(
"Running command: %s", subprocess.list2cmdline(cmd))

self.current_sync = await create_subprocess_exec(*cmd)

async def probe(self):
Expand All @@ -68,18 +69,8 @@ async def probe(self):
"""
if not self.current_sync:
return 0

if self.current_sync.returncode is not None:
decky_plugin.logger.info("=== FINISHING SYNC ===")

return self.current_sync.returncode

async def needs_resync(self):
"""
Checks if resync if needed.

Returns:
bool: is needed
"""
dirPath = decky_plugin.HOME + "/.cache/rclone/bisync"
if not os.path.isdir(dirPath):
return True
else:
return len([name for name in os.listdir(dirPath)]) == 0
return self.current_sync.returncode
6 changes: 2 additions & 4 deletions src/helpers/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,16 @@ export class ApiClient {

let body;
let time = 2000;
let action = () => { };
let action = () => { Navigation.Navigate("/dcs-sync-logs"); };

const syncLogs = await Backend.getLastSyncLog();
Storage.setSessionStorageItem("syncLogs", syncLogs);

if (pass) {
body = Translator.translate("sync.completed", { "time": timeDiff });
action = () => { Navigation.Navigate("/dcs-sync-logs"); };
} else {
body = Translator.translate("sync.failed");
time = 5000;
action = () => { Navigation.Navigate("/dcs-error-sync-logs"); };
time = 15000;
}

if (showToast || (!pass)) {
Expand Down
4 changes: 0 additions & 4 deletions src/helpers/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,4 @@ export class Backend {
public static async log(lvl: string, ...args: any): Promise<void> {
return Backend.backend_call<{ level: string, msg: string }, void>("log", { level: lvl, msg: `[UI]: ${JSON.stringify(args)}` });
}

public static async needsResync(): Promise<boolean> {
return Backend.backend_call<{}, boolean>("needs_resync", {});
}
}
9 changes: 3 additions & 6 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { Backend } from "./helpers/backend";
import { FaSave } from "react-icons/fa";
import ConfigurePathsPage from "./pages/ConfigurePathsPage";
import ConfigureBackendPage from "./pages/ConfigureBackendPage";
import RenderSyncErrorLogPage from "./pages/RenderSyncErrorLogPage";
import RenderSyncLogPage from "./pages/RenderSyncLogPage";
import RenderPluginLogPage from "./pages/RenderPluginLogPage";

Expand All @@ -26,7 +25,6 @@ export default definePlugin((serverApi: ServerAPI) => {

serverApi.routerHook.addRoute("/dcs-configure-paths", () => <ConfigurePathsPage serverApi={serverApi} />, { exact: true });
serverApi.routerHook.addRoute("/dcs-configure-backend", () => <ConfigureBackendPage serverApi={serverApi} />, { exact: true });
serverApi.routerHook.addRoute("/dcs-error-sync-logs", () => <RenderSyncErrorLogPage />, { exact: true });
serverApi.routerHook.addRoute("/dcs-sync-logs", () => <RenderSyncLogPage />, { exact: true });
serverApi.routerHook.addRoute("/dcs-plugin-logs", () => <RenderPluginLogPage />, { exact: true });

Expand All @@ -39,7 +37,7 @@ export default definePlugin((serverApi: ServerAPI) => {
ApplicationState.setAppState("playing", String(e.bRunning));

if (shouldSync(gameInfo)) {
syncGame(e.bRunning);
syncGame(e);
}
} else {
Logger.info("No futher actions");
Expand All @@ -55,17 +53,16 @@ export default definePlugin((serverApi: ServerAPI) => {
Storage.clearAllSessionStorage();
serverApi.routerHook.removeRoute("/dcs-configure-paths");
serverApi.routerHook.removeRoute("/dcs-configure-backend");
serverApi.routerHook.removeRoute("/dcs-error-sync-logs");
serverApi.routerHook.removeRoute("/dcs-sync-logs");
serverApi.routerHook.removeRoute("/dcs-plugin-logs");
},
};
});

function syncGame(started: boolean) {
function syncGame(e: LifetimeNotification) {
const currentState = ApplicationState.getAppState().currentState;
let toast = currentState.toast_auto_sync === "true";
if (started) {
if (e.bRunning) {
// Only sync at start when bisync is enabled. No need to when its not.
if (currentState.bisync_enabled === "true") {
if (toast) {
Expand Down
20 changes: 2 additions & 18 deletions src/pages/RenderDCSMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,6 @@ export const Content: VFC<{}> = () => {
ApiClient.getCloudBackend().then((e) => setHasProvider(!!e));
}, []);

const [needsResync, setNeedsSync] = useState(false);
setInterval(async () => {
if (
ApplicationState.getAppState().currentState.playing === "false" &&
ApplicationState.getAppState().currentState.bisync_enabled === "true" &&
ApplicationState.getAppState().currentState.syncing === "false"
) {
setNeedsSync(await Backend.needsResync());
}
}, 1000);

return (
<>
<Head />
Expand All @@ -40,16 +29,11 @@ export const Content: VFC<{}> = () => {
layout="below"
disabled={appState.syncing === "true" || !hasProvider}
onClick={() => {
if (needsResync) {
ApiClient.resyncNow("path1");
} else {
ApiClient.syncNow(true);
}
ApiClient.syncNow(true);
}}
>
<DeckyStoreButton icon={<FaSave className={appState.syncing === "true" ? "dcs-rotate" : ""} />}>
{needsResync && Translator.translate("resync.now")}
{!needsResync && Translator.translate("sync.now")}
{Translator.translate("sync.now")}
</DeckyStoreButton>
</ButtonItem>
{hasProvider === false && <small>{Translator.translate("provider.not.configured")}.</small>}
Expand Down
55 changes: 0 additions & 55 deletions src/pages/RenderSyncErrorLogPage.tsx

This file was deleted.

51 changes: 49 additions & 2 deletions src/pages/RenderSyncLogPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,63 @@ import { Navigation } from "decky-frontend-lib";
import Container from "../components/Container";
import { Translator } from "../helpers/translator";
import { Storage } from "../helpers/storage";

import { useMemo, useState } from "react";
import { Toast } from "../helpers/toast";
import { ApiClient } from "../helpers/apiClient";

export default function RenderSyncLogPage() {
Navigation.CloseSideMenus();

const [logs, _] = useState<string>(() => Storage.getSessionStorageItem("syncLogs")?.replace(/\n{2,}/g, "\n") ?? "");

return (
<Container title={Translator.translate("sync.logs")}>
<div style={{ maxHeight: "300px" }}>
<pre style={{ overflowY: 'scroll', whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: "smaller", maxHeight: "300px" }}>{Storage.getSessionStorageItem("syncLogs")?.replace(/\n{2,}/g, '\n')}</pre>
<pre style={{ overflowY: "scroll", whiteSpace: "pre-wrap", wordBreak: "break-word", fontSize: "smaller", maxHeight: "300px" }}>{logs}</pre>
</div>
<SyncLogErrorButtons logs={logs} />
</Container>
);
}

function SyncLogErrorButtons({ logs }: { logs: string }) {
const deleteLockNeeded = useMemo(() => logs.indexOf("rclone deletefile") > 0, [logs]);
const resyncNeeded = useMemo(() => logs.indexOf("Must run --resync") > 0, [logs]);

return (
<div>
<button
hidden={!resyncNeeded}
style={{ marginLeft: "10px" }}
onClick={() => {
Navigation.CloseSideMenus();
Navigation.NavigateBack();
let winner = "path1";
if (Storage.getSessionStorageItem("rcloneLogs")?.indexOf("--conflict-resolve path2") !== -1) {
winner = "path2";
}
Toast.toast(Translator.translate("resynchronizing.savedata"));
ApiClient.resyncNow(winner);
}}
>
{Translator.translate("resync.now")}
</button>
<button
hidden={!deleteLockNeeded}
style={{ marginLeft: "10px" }}
onClick={() => {
Navigation.CloseSideMenus();
Navigation.NavigateBack();
let winner = "path1";
if (Storage.getSessionStorageItem("rcloneLogs")?.indexOf("--conflict-resolve path2") !== -1) {
winner = "path2";
}
Toast.toast(Translator.translate("deleting.locks.sync"));
ApiClient.deleteLocksAndResync(winner);
}}
>
{Translator.translate("delete.locks")}
</button>
</div>
);
}