From 0b8f9982fc08ee8fe711b96538e30622f655fa9d Mon Sep 17 00:00:00 2001 From: Weixuan Fu Date: Mon, 4 Mar 2024 20:05:05 +0800 Subject: [PATCH 1/6] fix two way sync to window --- __init__.py | 55 +---------- service/db_service.py | 65 +++++++++++++ service/file_sync_service.py | 13 ++- service/scan_my_workflows_folder.py | 4 +- service/twoway_sync_folder_service.py | 9 ++ ui/src/App.tsx | 13 ++- .../WorkspaceSettingsModal.tsx | 15 --- ui/src/apis/TwowaySyncApi.ts | 96 +++++-------------- ui/src/apis/TwowaySyncFolderApi.ts | 37 ++----- ui/src/db-tables/FoldersTable.ts | 5 +- ui/src/settings/SelectMyWorkflowsDir.tsx | 3 +- ui/src/utils.tsx | 2 + ui/src/utils/OsPathUtils.ts | 49 ++++++---- ui/src/utils/twowaySyncUtils.ts | 14 +-- 14 files changed, 170 insertions(+), 210 deletions(-) create mode 100644 service/db_service.py diff --git a/__init__.py b/__init__.py index 4497c2f..a357ef0 100644 --- a/__init__.py +++ b/__init__.py @@ -14,9 +14,9 @@ from .service.model_manager.model_installer import download_url_with_wget from .service.model_manager.model_list import get_model_list from .service.media_service import * from .service.file_sync_service import * +from .service.db_service import get_my_workflows_dir WEB_DIRECTORY = "entry" -DEFAULT_USER = "guest" NODE_CLASS_MAPPINGS = {} __all__ = ['NODE_CLASS_MAPPINGS'] version = "V1.0.0" @@ -36,43 +36,6 @@ if os.path.exists(dist_path): server.PromptServer.instance.app.add_subapp("/workspace_web/", workspace_app) -@server.PromptServer.instance.routes.post("/workspace/save_db") -async def save_db(request): - # Extract parameters from the request - data = await request.json() - table = data['table'] - json_data = data['json'] - - file_name = f'{db_dir_path}/{table}.json' - # Offload file writing to a separate thread - def write_json_string_to_db(file_name, json_data): - if not os.path.exists(db_dir_path): - os.makedirs(db_dir_path) - # Write the JSON data to the specified file - with open(file_name, 'w') as file: - file.write(json.dumps(json_data, indent=4)) - await asyncio.to_thread(write_json_string_to_db, file_name, json_data) - return web.Response(text=f"JSON saved to {file_name}") - -def read_table(table): - if not table: - return None - file_name = f'{db_dir_path}/{table}.json' - if not os.path.exists(file_name): - return None - - with open(file_name, 'r') as file: - data = json.load(file) - return data - - -@server.PromptServer.instance.routes.get("/workspace/get_db") -async def get_workspace(request): - # Extract the table parameter from the query string - table = request.query.get('table') - data = await asyncio.to_thread(read_table, table) - return web.json_response(data) - BACKUP_DIR = os.path.join(workspace_path, "backup") MAX_BACKUP_FILES = 20 @@ -132,22 +95,6 @@ async def get_default_my_workflows_dir(request): except Exception as e: return web.Response(text=json.dumps({"error": str(e)}), status=500) -def get_my_workflows_dir(): - data = read_table('userSettings') - if (data): - records = json.loads(data) - - if DEFAULT_USER in records and 'myWorkflowsDir' in records[DEFAULT_USER]: - curDir = records[DEFAULT_USER]['myWorkflowsDir'] - elif 'myWorkflowsDir' in records: - curDir = records['myWorkflowsDir'] - - if curDir: - return curDir - - return os.path.join(comfy_path, 'my_workflows') - - @server.PromptServer.instance.routes.post("/workspace/update_file") async def update_file(request): data = await request.json() diff --git a/service/db_service.py b/service/db_service.py new file mode 100644 index 0000000..229ab8c --- /dev/null +++ b/service/db_service.py @@ -0,0 +1,65 @@ + +import server +import os +import folder_paths +import json +import asyncio +from aiohttp import web +from .model_manager.model_preview import get_thumbnail_for_image_file + +workspace_path = os.path.join(os.path.dirname(os.path.dirname(__file__))) +comfy_path = os.path.dirname(folder_paths.__file__) +db_dir_path = os.path.join(workspace_path, "db") +DEFAULT_USER = "guest" + +@server.PromptServer.instance.routes.post("/workspace/save_db") +async def save_db(request): + # Extract parameters from the request + data = await request.json() + table = data['table'] + json_data = data['json'] + + file_name = f'{db_dir_path}/{table}.json' + # Offload file writing to a separate thread + def write_json_string_to_db(file_name, json_data): + if not os.path.exists(db_dir_path): + os.makedirs(db_dir_path) + # Write the JSON data to the specified file + with open(file_name, 'w') as file: + file.write(json.dumps(json_data, indent=4)) + await asyncio.to_thread(write_json_string_to_db, file_name, json_data) + return web.Response(text=f"JSON saved to {file_name}") + +def read_table(table): + if not table: + return None + file_name = f'{db_dir_path}/{table}.json' + if not os.path.exists(file_name): + return None + + with open(file_name, 'r') as file: + data = json.load(file) + return data + + +@server.PromptServer.instance.routes.get("/workspace/get_db") +async def get_workspace(request): + # Extract the table parameter from the query string + table = request.query.get('table') + data = await asyncio.to_thread(read_table, table) + return web.json_response(data) + +def get_my_workflows_dir(): + data = read_table('userSettings') + if (data): + records = json.loads(data) + + if DEFAULT_USER in records and 'myWorkflowsDir' in records[DEFAULT_USER]: + curDir = records[DEFAULT_USER]['myWorkflowsDir'] + elif 'myWorkflowsDir' in records: + curDir = records['myWorkflowsDir'] + + if curDir: + return curDir + + return os.path.join(comfy_path, 'my_workflows') diff --git a/service/file_sync_service.py b/service/file_sync_service.py index cbc4b81..eed8375 100644 --- a/service/file_sync_service.py +++ b/service/file_sync_service.py @@ -1,6 +1,5 @@ import asyncio from datetime import datetime - import platform import tempfile import server @@ -77,10 +76,9 @@ async def move_file(request): def move_file_sync(reqJson): current_path = reqJson.get('path') new_path = reqJson.get('newParentPath') + current_path = os.path.join(get_my_workflows_dir(), current_path) + new_path = os.path.join(get_my_workflows_dir(), new_path) try: - target_path = Path(new_path) / Path(current_path).name - # if target_path.suffix != ".json": - # raise ValueError("Target file must be a .json file") shutil.move(current_path, new_path) return {"success": True} except Exception as e: @@ -100,9 +98,10 @@ def create_workflow_file(reqJson): if not parentFolderPath or not name or workflow_json is None: return {} # Missing necessary data - abs_path = Path(parentFolderPath) + abs_path = Path(get_my_workflows_dir() / parentFolderPath) # Create the directory if it does not exist abs_path.mkdir(parents=True, exist_ok=True) + print(f"🌐Creating workflow file at {abs_path}") # Ensuring the file name is unique base_name, extension = os.path.splitext(name) @@ -115,7 +114,7 @@ def create_workflow_file(reqJson): counter += 1 new_file_path = abs_path / new_file_name - + print(f"🌐Creating workflow file at name {new_file_path}") # Writing JSON data to the file with open(new_file_path, 'w', encoding='utf-8') as file: file.write(workflow_json) @@ -126,7 +125,7 @@ def create_workflow_file(reqJson): return {} # In case of any error def read_workflow_file(path, id): - abs_path = Path(path) + abs_path = os.path.join(get_my_workflows_dir(), path) create_time, update_time = getFileCreateTime(abs_path) with open(abs_path, 'r', encoding='utf-8') as f: json_data = json.load(f) diff --git a/service/scan_my_workflows_folder.py b/service/scan_my_workflows_folder.py index 041ccce..fc8dbe0 100644 --- a/service/scan_my_workflows_folder.py +++ b/service/scan_my_workflows_folder.py @@ -7,11 +7,13 @@ import glob from threading import Lock import server import uuid +from .twoway_sync_folder_service import get_my_workflows_abs_path @server.PromptServer.instance.routes.post('/workspace/file/scan_my_workflows_folder') async def scan_my_workflows_files(request): reqJson = await request.json() path = reqJson['path'] + path = get_my_workflows_abs_path(path) recursive = reqJson.get('recursive', False) metaInfoOnly = reqJson.get('metaInfoOnly', False) @@ -68,8 +70,6 @@ def file_handle(name, fileList, file_path, metaInfoOnly): fileList.append(fileInfo) -# Note: Implement getFileCreateTime function as per your existing logic - def getFileCreateTime(path): # Cross-platform compatibility for creation time file_stats = os.stat(path) diff --git a/service/twoway_sync_folder_service.py b/service/twoway_sync_folder_service.py index 81ad680..d1f3f68 100644 --- a/service/twoway_sync_folder_service.py +++ b/service/twoway_sync_folder_service.py @@ -4,6 +4,7 @@ from aiohttp import web import os from pathlib import Path import server +from .db_service import get_my_workflows_dir @server.PromptServer.instance.routes.post('/workspace/folder/create') async def create_folder(request): @@ -13,6 +14,7 @@ async def create_folder(request): def create_folder_sync(reqJson): folder_path = reqJson.get('path') + folder_path = os.join(get_my_workflows_dir(), folder_path) try: Path(folder_path).mkdir(parents=True, exist_ok=True) return {"success": True} @@ -27,6 +29,7 @@ async def delete_folder(request): def delete_folder_sync(reqJson): folder_path = reqJson.get('path') + folder_path = os.join(get_my_workflows_dir(), folder_path) try: shutil.rmtree(folder_path) return {"success": True} @@ -41,6 +44,7 @@ async def rename_folder(request): def rename_folder_sync(reqJson): current_path = reqJson.get('absPath') + current_path = os.join(get_my_workflows_dir(), current_path) new_name = reqJson.get('newName') try: new_path = Path(current_path).parent / new_name @@ -57,9 +61,14 @@ async def move_folder(request): def move_folder_sync(reqJson): current_path = reqJson.get('folder') + current_path = os.join(get_my_workflows_dir(), current_path) new_path = reqJson.get('newParentPath') try: shutil.move(current_path, new_path) return {"success": True} except Exception as e: return {"success": False, "error": str(e)} + +def get_my_workflows_abs_path(rel_path: str): + myworkflows = get_my_workflows_dir() + return os.path.join(myworkflows, rel_path) diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 7cdbfc4..dbf6aaa 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -27,9 +27,11 @@ import { getWorkflowIdInUrlHash, generateUrlHashWithFlowId, openWorkflowInNewTab, + validateOrSaveAllJsonFileMyWorkflows, + rewriteAllLocalFiles, } from "./utils"; import { Topbar } from "./topbar/Topbar"; -import { PanelPosition, Workflow, WorkflowVersion } from "./types/dbTypes"; +import { Workflow, WorkflowVersion } from "./types/dbTypes"; import { useDialog } from "./components/AlertDialogProvider"; import React from "react"; const RecentFilesDrawer = React.lazy( @@ -176,6 +178,15 @@ export default function App() { if (latestWfID) { loadWorkflowIDImpl(latestWfID); } + /** + * For two-way sync, one-time rewrite all /my_workflows files to the database + */ + if (localStorage.getItem("REWRITTEN_ALL_LOCAL_DISK_FILE") === "true") { + await validateOrSaveAllJsonFileMyWorkflows(); + } else { + await rewriteAllLocalFiles(); + localStorage.setItem("REWRITTEN_ALL_LOCAL_DISK_FILE", "true"); + } }; const subsribeToWsToStopWarning = () => { diff --git a/ui/src/RecentFilesDrawer/WorkspaceSettingsModal.tsx b/ui/src/RecentFilesDrawer/WorkspaceSettingsModal.tsx index d8223fe..ed7d078 100644 --- a/ui/src/RecentFilesDrawer/WorkspaceSettingsModal.tsx +++ b/ui/src/RecentFilesDrawer/WorkspaceSettingsModal.tsx @@ -6,24 +6,9 @@ import { ModalHeader, ModalBody, ModalCloseButton, - Text, StackDivider, VStack, - Box, - Tag, - IconButton, - Button, - Flex, - Input, - Stack, - useToast, - SimpleGrid, - Tooltip, } from "@chakra-ui/react"; -import { IconEdit } from "@tabler/icons-react"; -import { useRef, useState, useEffect } from "react"; -import { getSystemDir } from "../Api"; -import { userSettingsTable } from "../db-tables/WorkspaceDB"; import { ShortcutSettings } from "../settings/ShortcutSettings"; import FolderOnTopSettings from "../settings/FolderOnTopSettings"; import TwoWaySyncSettings from "../settings/TwoWaySyncSettings"; diff --git a/ui/src/apis/TwowaySyncApi.ts b/ui/src/apis/TwowaySyncApi.ts index a606c09..c1c4f43 100644 --- a/ui/src/apis/TwowaySyncApi.ts +++ b/ui/src/apis/TwowaySyncApi.ts @@ -1,29 +1,17 @@ import { COMFYSPACE_TRACKING_FIELD_NAME } from "../const"; -import { userSettingsTable } from "../db-tables/WorkspaceDB"; import { indexdb } from "../db-tables/indexdb"; import { Workflow } from "../types/dbTypes"; -import { genAbsPathByRelPath, sanitizeAbsPath } from "../utils/OsPathUtils"; +import { + getWorkflowRelPath, + joinRelPath, + sanitizeRelPath, +} from "../utils/OsPathUtils"; export namespace TwowaySyncAPI { - async function genWorkflowAbsPath({ - parentFolderID, - name, - }: Workflow): Promise { - const myWorkflowsDir = - await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath( - `${myWorkflowsDir}/${parentFolderID ?? ""}/${name}.json`, - ); - return absPath; - } export async function moveWorkflow( workflow: Workflow, newParentFolderRelPath: string, ) { - const absPath = await genWorkflowAbsPath(workflow); - const newParentFolderAbs = await genAbsPathByRelPath( - newParentFolderRelPath, - ); try { const response = await fetch("/workspace/file/move", { method: "POST", @@ -31,8 +19,8 @@ export namespace TwowaySyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - path: absPath, - newParentPath: newParentFolderAbs, + path: getWorkflowRelPath(workflow), + newParentPath: newParentFolderRelPath, }), }); const result = await response.json(); @@ -50,7 +38,6 @@ export namespace TwowaySyncAPI { fileName: string, parentFolderID: string | null, ): Promise { - const absPath = await genAbsPathByRelPath(`${parentFolderID}/${fileName}`); try { const response = await fetch("/workspace/file/gen_unique_name", { method: "POST", @@ -58,7 +45,7 @@ export namespace TwowaySyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - path: absPath, + path: joinRelPath(parentFolderID ?? "", fileName), }), }); const result = await response.json(); @@ -77,11 +64,6 @@ export namespace TwowaySyncAPI { { parentFolderID, name }: Pick, newName: string, ) { - const myWorkflowsDir = - await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath( - `${myWorkflowsDir}/${parentFolderID ?? ""}/${name}.json`, - ); try { const response = await fetch("/workspace/file/rename", { method: "POST", @@ -89,7 +71,7 @@ export namespace TwowaySyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - path: absPath, + path: joinRelPath(parentFolderID ?? "", name + ".json"), newName: newName, }), }); @@ -112,29 +94,8 @@ export namespace TwowaySyncAPI { }>; }; } - export async function scanMyWorkflowsDupId() { - const myWorkflowsDir = - await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath(myWorkflowsDir!); - try { - const response = await fetch("/workspace/file/scan_dup_id", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - path: absPath, - }), - }); - const result = (await response.json()) as DuplicatesResponse; - return true; - } catch (error) { - console.error("Error deleting file:", error); - } - } export async function saveWorkflow(workflow: Workflow) { - const absPath = await genWorkflowAbsPath(workflow); const json = workflow.json; const flow = JSON.parse(json); flow.extra[COMFYSPACE_TRACKING_FIELD_NAME] = { @@ -147,7 +108,7 @@ export namespace TwowaySyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - path: absPath, + path: getWorkflowRelPath(workflow), json: JSON.stringify(flow), }), }); @@ -163,7 +124,6 @@ export namespace TwowaySyncAPI { return result; } export async function deleteWorkflow(workflow: Workflow) { - const absPath = await genWorkflowAbsPath(workflow); try { const response = await fetch("/workspace/delete_file", { method: "POST", @@ -171,7 +131,7 @@ export namespace TwowaySyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - file_path: absPath, + file_path: getWorkflowRelPath(workflow), deleteEmptyFolder: false, }), }); @@ -188,11 +148,6 @@ export namespace TwowaySyncAPI { json, id, }: Workflow) { - const myWorkflowsDir = - await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath( - `${myWorkflowsDir}/${parentFolderID ?? ""}`, - ); let jsonObj: any = JSON.parse(json); jsonObj = { @@ -204,10 +159,11 @@ export namespace TwowaySyncAPI { }, }; const input: { parentFolderPath: string; name: string; json: string } = { - parentFolderPath: absPath, + parentFolderPath: sanitizeRelPath(parentFolderID ?? ""), name: name, json: JSON.stringify(jsonObj), }; + console.log("createWorkflow", input); try { const response = await fetch("/workspace/create_workflow_file", { method: "POST", @@ -220,13 +176,15 @@ export namespace TwowaySyncAPI { result.name && (await indexdb.workflows?.update(id, { - filePath: `${absPath}/${name}.json`, name: result.name, })); return result; } catch (error) { - console.error(`Error creating file <${id}> at "${absPath}"`, error); - alert(`Error creating file <${id}> at "${absPath}"`); + console.error( + `Error creating file <${id}> at "${parentFolderID}"`, + error, + ); + alert(`Error creating file <${id}> at "${parentFolderID}"`); return {}; } } @@ -242,11 +200,7 @@ export namespace TwowaySyncAPI { json?: Object; error?: string; }> { - const myWorkflowsDir = - await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath( - `${myWorkflowsDir}/${parentFolderID ?? ""}/${name}.json`, - ); + const relPath = joinRelPath(parentFolderID ?? "", name + ".json"); try { const response = await fetch("/workspace/get_workflow_file", { method: "POST", @@ -255,24 +209,24 @@ export namespace TwowaySyncAPI { }, body: JSON.stringify({ - path: absPath, + path: relPath, id: id, }), }); const result = await response.json(); if (result.error) { console.error( - `Error getting file <${id}> at "${absPath}"`, + `Error getting file <${id}> at "${relPath}"`, result.error, ); alert({ - message: `Error getting file <${id}> at "${absPath}"`, + message: `Error getting file <${id}> at "${relPath}"`, level: "error", }); } return result; } catch (error) { - console.error(`Erro finding file <${id}> at "${absPath}"`, error); + console.error(`Erro finding file <${id}> at "${relPath}"`, error); return {}; } } @@ -287,8 +241,10 @@ export type ScanLocalFile = { updateTime: number; }; export type ScanLocalFolder = { + id: string; type: "folder"; name: string; + parentFolderID: string; }; export async function scanLocalFiles( path: string, @@ -302,7 +258,7 @@ export async function scanLocalFiles( "Content-Type": "application/json", }, body: JSON.stringify({ - path: sanitizeAbsPath(path), + path: sanitizeRelPath(path), recursive, metaInfoOnly, }), diff --git a/ui/src/apis/TwowaySyncFolderApi.ts b/ui/src/apis/TwowaySyncFolderApi.ts index 4c96b3b..2299b97 100644 --- a/ui/src/apis/TwowaySyncFolderApi.ts +++ b/ui/src/apis/TwowaySyncFolderApi.ts @@ -1,10 +1,5 @@ -import { userSettingsTable } from "../db-tables/WorkspaceDB"; import { Folder } from "../types/dbTypes"; -import { - genAbsPathByRelPath, - sanitizeAbsPath, - sanitizeRelPath, -} from "../utils/OsPathUtils"; +import { sanitizeRelPath } from "../utils/OsPathUtils"; export namespace TwowayFolderSyncAPI { export async function genFolderRelPath({ @@ -16,26 +11,15 @@ export namespace TwowayFolderSyncAPI { }): Promise { return sanitizeRelPath(`${parentFolderID ?? ""}/${name}`); } - export async function genFolderAbsPath({ - parentFolderID, - name, - }: Pick): Promise { - const myWorkflowsDir = - await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath( - `${myWorkflowsDir}/${parentFolderID ?? ""}/${name}`, - ); - return absPath; - } + export async function createFolder(folder: Folder) { - const abs = await genFolderAbsPath(folder); await fetch("/workspace/folder/create", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - path: abs, + path: sanitizeRelPath(folder.id), }), }); } @@ -43,16 +27,14 @@ export namespace TwowayFolderSyncAPI { folderToBeMoved: string, newParentPath: string, ) { - const absPath = await genAbsPathByRelPath(folderToBeMoved); - const absNewParentPath = await genAbsPathByRelPath(newParentPath); const resp = await fetch("/workspace/folder/move", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - folder: absPath, - newParentPath: absNewParentPath, + folder: folderToBeMoved, + newParentPath: newParentPath, }), }); const result = await resp.json(); @@ -62,7 +44,6 @@ export namespace TwowayFolderSyncAPI { return; } export async function deleteFolder(relPath: string) { - const absPath = await genAbsPathByRelPath(relPath); try { const response = await fetch("/workspace/folder/delete", { method: "POST", @@ -70,7 +51,7 @@ export namespace TwowayFolderSyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - path: absPath, + path: relPath, }), }); const result = await response.text(); @@ -83,7 +64,6 @@ export namespace TwowayFolderSyncAPI { export async function genFilesCountInFolder( folderRelPath: string, ): Promise { - const absPath = await genAbsPathByRelPath(folderRelPath); try { const response = await fetch("/workspace/file/count_files", { method: "POST", @@ -91,7 +71,7 @@ export namespace TwowayFolderSyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - path: absPath, + path: folderRelPath, }), }); const result = await response.json(); @@ -109,7 +89,6 @@ export namespace TwowayFolderSyncAPI { folderRelPath: string, newName: string, ): Promise { - const oldAbsPath = await genAbsPathByRelPath(folderRelPath); try { const response = await fetch("/workspace/folder/rename", { method: "POST", @@ -117,7 +96,7 @@ export namespace TwowayFolderSyncAPI { "Content-Type": "application/json", }, body: JSON.stringify({ - absPath: oldAbsPath, + absPath: folderRelPath, newName: newName, }), }); diff --git a/ui/src/db-tables/FoldersTable.ts b/ui/src/db-tables/FoldersTable.ts index d6151f9..8eb15eb 100644 --- a/ui/src/db-tables/FoldersTable.ts +++ b/ui/src/db-tables/FoldersTable.ts @@ -6,7 +6,6 @@ import { TableBase } from "./TableBase"; import { indexdb } from "./indexdb"; import { TwowayFolderSyncAPI } from "../apis/TwowaySyncFolderApi"; import { TwowaySyncAPI, scanLocalFiles } from "../apis/TwowaySyncApi"; -import { genAbsPathByRelPath } from "../utils/OsPathUtils"; export class FoldersTable extends TableBase { static readonly TABLE_NAME = "folders"; @@ -98,9 +97,7 @@ export class FoldersTable extends TableBase { ) { const twoWaySyncEnabled = await userSettingsTable?.getSetting("twoWaySync"); if (twoWaySyncEnabled) { - const absPath = await genAbsPathByRelPath(id); - // delete from indexdb - await scanLocalFiles(absPath, true, true).then((files) => { + await scanLocalFiles(id, true, true).then((files) => { files.forEach((file) => { if (file.type === "workflow") { console.log("delete workflow", file); diff --git a/ui/src/settings/SelectMyWorkflowsDir.tsx b/ui/src/settings/SelectMyWorkflowsDir.tsx index 542a672..a6a39bd 100644 --- a/ui/src/settings/SelectMyWorkflowsDir.tsx +++ b/ui/src/settings/SelectMyWorkflowsDir.tsx @@ -22,6 +22,7 @@ import { IconEdit } from "@tabler/icons-react"; import { useRef, useState, useEffect } from "react"; import { getSystemDir } from "../Api"; import { userSettingsTable } from "../db-tables/WorkspaceDB"; +import { validateOrSaveAllJsonFileMyWorkflows } from "../utils"; export default function SelectMyWorkflowsDir() { const [isManualEntry, setIsManualEntry] = useState(false); @@ -106,7 +107,7 @@ export default function SelectMyWorkflowsDir() { manualEntry && setNoPermission(false); onCloseEditDirectory(); // to update /my_workflows files in disk to new location - await userSettingsTable?.getSetting("twoWaySync"); + validateOrSaveAllJsonFileMyWorkflows(); }; const onReset = async () => { diff --git a/ui/src/utils.tsx b/ui/src/utils.tsx index fbda2e6..12b3229 100644 --- a/ui/src/utils.tsx +++ b/ui/src/utils.tsx @@ -151,6 +151,8 @@ export function sortFlows( export async function validateOrSaveAllJsonFileMyWorkflows( deleteEmptyFolder = false, ) { + const twoWaySync = await userSettingsTable?.getSetting("twoWaySync"); + if (twoWaySync) return; // disable this function in two way sync mode const flowList = (await workflowsTable?.listAll()) ?? []; for (const workflow of flowList) { const fullPath = await generateFilePathAbsolute(workflow); diff --git a/ui/src/utils/OsPathUtils.ts b/ui/src/utils/OsPathUtils.ts index ddc3b9c..5d949ec 100644 --- a/ui/src/utils/OsPathUtils.ts +++ b/ui/src/utils/OsPathUtils.ts @@ -1,24 +1,37 @@ -import { userSettingsTable } from "../db-tables/WorkspaceDB"; +import type { Workflow } from "../types/dbTypes"; -export function osPathJoin(...args: string[]) { - const joined = args.filter((segment) => segment !== "").join("/"); - if (joined.endsWith("/")) { - return joined.slice(0, -1); - } - return sanitizeRelPath(joined); -} - -export function sanitizeAbsPath(path: string) { - const segments = path.split("/").filter((segment) => segment !== ""); - return "/" + segments.join("/"); +export function joinRelPath(...segments: string[]) { + const rel = segments.filter((segment) => segment !== "").join("/"); + return sanitizeRelPath(rel); } +// export function sanitizeRelPath(path: string) { +// const segments = path.split("/").filter((segment) => segment !== ""); +// if (segments.length === 0) { +// return ""; +// } +// return segments.join("/"); +// } export function sanitizeRelPath(path: string) { - const segments = path.split("/").filter((segment) => segment !== ""); - return segments.join("/"); + const segments = path + .split("/") + .filter((segment) => segment !== "") + .join("/"); + // Replace backslashes with forward slashes to handle Windows paths + let sanitizedPath = segments.replace(/\\/g, "/"); + + // If the path contains a Windows drive letter, remove it + sanitizedPath = sanitizedPath.replace(/^[a-zA-Z]:/, ""); + + // Remove leading slashes to ensure the path is treated as relative + sanitizedPath = sanitizedPath.replace(/^\/+/, ""); + + return sanitizedPath; } -export async function genAbsPathByRelPath(relPath: string): Promise { - const myWorkflowsDir = await userSettingsTable?.getSetting("myWorkflowsDir"); - const absPath = sanitizeAbsPath(`${myWorkflowsDir}/${relPath}`); - return absPath; +export function getWorkflowRelPath(workflow: Workflow) { + return joinRelPath(workflow.parentFolderID ?? "", workflow.name + ".json"); +} + +export function getFolderRelPath(folder: { id: string }) { + return folder.id; } diff --git a/ui/src/utils/twowaySyncUtils.ts b/ui/src/utils/twowaySyncUtils.ts index f432d03..5a03d2e 100644 --- a/ui/src/utils/twowaySyncUtils.ts +++ b/ui/src/utils/twowaySyncUtils.ts @@ -8,7 +8,7 @@ import { isFolder, userSettingsTable } from "../db-tables/WorkspaceDB"; import { indexdb } from "../db-tables/indexdb"; import { Folder, Workflow } from "../types/dbTypes"; import { sortFileItem } from "../utils"; -import { sanitizeAbsPath } from "./OsPathUtils"; +import { sanitizeRelPath } from "./OsPathUtils"; export async function scanMyWorkflowsDir( parentFolderID: string | null, @@ -19,21 +19,18 @@ export async function scanMyWorkflowsDir( alert("No Workspace saving directory found, please go to Settings."); return []; } - const parentRelPath = parentFolderID ?? ""; + const parentRelPath = sanitizeRelPath(parentFolderID ?? ""); + console.log("scanMyWorkflowsDir", parentRelPath); // folderID is the relative path of the folder in two way sync mode - const scanDir = `${myWorkflowsDir}/${parentRelPath}`; - const fileList = await scanLocalFiles(scanDir); + const fileList = await scanLocalFiles(parentRelPath); const allFilesPromises = fileList.map(async (file) => { const fileName = file.name; - const absPath = sanitizeAbsPath([scanDir, fileName].join("/")); - // const absPath = osPathJoin(scanDir, fileName); const relPath = [parentRelPath, fileName].join("/"); - if (scanFileIsFolder(file)) { // is folder const folder: Folder = { - id: relPath, + id: sanitizeRelPath(relPath), name: file.name, parentFolderID: parentRelPath, type: "folder", @@ -51,7 +48,6 @@ export async function scanMyWorkflowsDir( const newWorkflow: Workflow = { ...existingWorkflow, id: file.id, - filePath: absPath, lastSavedJson: file.json ?? "{}", json: file.json ?? "{}", name: fileName.replace(/\.json$/, ""), From 2612e4df9f43f58222d2d4756ecb50f5329add11 Mon Sep 17 00:00:00 2001 From: Weixuan Fu Date: Mon, 4 Mar 2024 20:18:56 +0800 Subject: [PATCH 2/6] fix save file, create file --- service/file_sync_service.py | 10 ++++------ ui/src/db-tables/WorkflowsTable.ts | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/service/file_sync_service.py b/service/file_sync_service.py index eed8375..c5e21c1 100644 --- a/service/file_sync_service.py +++ b/service/file_sync_service.py @@ -21,7 +21,7 @@ async def save_file(request): def save_file_sync(reqJson): current_path = reqJson.get('path') new_json_data_str = reqJson.get('json') - + current_path = os.path.join(get_my_workflows_dir(), current_path) try: new_json_data = json.loads(new_json_data_str) except json.JSONDecodeError: @@ -95,13 +95,12 @@ def create_workflow_file(reqJson): name = reqJson.get('name') workflow_json = reqJson.get('json') - if not parentFolderPath or not name or workflow_json is None: + if not name or workflow_json is None: + print('🔴Create workflow missing necessary data') return {} # Missing necessary data - - abs_path = Path(get_my_workflows_dir() / parentFolderPath) + abs_path = Path(get_my_workflows_dir()) / parentFolderPath # Create the directory if it does not exist abs_path.mkdir(parents=True, exist_ok=True) - print(f"🌐Creating workflow file at {abs_path}") # Ensuring the file name is unique base_name, extension = os.path.splitext(name) @@ -114,7 +113,6 @@ def create_workflow_file(reqJson): counter += 1 new_file_path = abs_path / new_file_name - print(f"🌐Creating workflow file at name {new_file_path}") # Writing JSON data to the file with open(new_file_path, 'w', encoding='utf-8') as file: file.write(workflow_json) diff --git a/ui/src/db-tables/WorkflowsTable.ts b/ui/src/db-tables/WorkflowsTable.ts index 89c7c90..71dcafa 100644 --- a/ui/src/db-tables/WorkflowsTable.ts +++ b/ui/src/db-tables/WorkflowsTable.ts @@ -87,6 +87,7 @@ export class WorkflowsTable extends TableBase { (name ?? "Untitled Flow") + ".json", parentFolderID ?? "", ); + console.log("generateUniqueName", fileName); return fileName?.replace(/\.json$/, "") ?? "Untitled Flow"; } /** From 556780de24dc32a1564b15646f1a02bd2cb618cd Mon Sep 17 00:00:00 2001 From: Weixuan Fu - windows Date: Mon, 4 Mar 2024 20:56:49 +0800 Subject: [PATCH 3/6] fix title not working, fix open workflow not working when my_workflows url is broken --- service/db_service.py | 4 +--- ui/src/App.tsx | 4 ++-- ui/src/RecentFilesDrawer/RecentFilesDrawer.tsx | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/service/db_service.py b/service/db_service.py index 229ab8c..75db9d4 100644 --- a/service/db_service.py +++ b/service/db_service.py @@ -58,8 +58,6 @@ def get_my_workflows_dir(): curDir = records[DEFAULT_USER]['myWorkflowsDir'] elif 'myWorkflowsDir' in records: curDir = records['myWorkflowsDir'] - - if curDir: + if os.path.exists(curDir): return curDir - return os.path.join(comfy_path, 'my_workflows') diff --git a/ui/src/App.tsx b/ui/src/App.tsx index dbf6aaa..5a7e493 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -152,10 +152,10 @@ export default function App() { if (getWorkflowIdInUrlHash()) { const newUrlHash = generateUrlHashWithFlowId(id); window.location.hash = newUrlHash; - document.title = name + " - ComfyUI"; + document.title = workflow!.name + " - ComfyUI"; } else { localStorage.setItem("curFlowID", id); - document.title = "ComfyUI - " + name; + document.title = "ComfyUI - " + workflow!.name; } }; diff --git a/ui/src/RecentFilesDrawer/RecentFilesDrawer.tsx b/ui/src/RecentFilesDrawer/RecentFilesDrawer.tsx index 74786ca..d8b1ab9 100644 --- a/ui/src/RecentFilesDrawer/RecentFilesDrawer.tsx +++ b/ui/src/RecentFilesDrawer/RecentFilesDrawer.tsx @@ -223,7 +223,7 @@ export default function RecentFilesDrawer({ onClose, onClickNewFlow }: Props) { - ☕️Workspace + 🦄Workspace {/* Login From 62a965f8b7a7bd1b78f4b835d94b7b81c30e64ab Mon Sep 17 00:00:00 2001 From: Weixuan Fu - windows Date: Mon, 4 Mar 2024 22:28:12 +0800 Subject: [PATCH 4/6] fix get myworkflows endpoint, settings myworkflows dir fetch from server instead of from indexdb --- __init__.py | 9 +++++---- ui/src/Api.ts | 10 ++++++++++ ui/src/db-tables/UserSettingsTable.ts | 13 +++++-------- ui/src/settings/SelectMyWorkflowsDir.tsx | 9 ++++----- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/__init__.py b/__init__.py index a357ef0..da52c6b 100644 --- a/__init__.py +++ b/__init__.py @@ -84,14 +84,15 @@ async def get_system_dir(request): return web.Response(text=json.dumps({"dir_path": dir_path, "dir_contents": dir_contents}), content_type='application/json') except Exception as e: + print('🔴🔴Error',e) return web.Response(text=json.dumps({"error": str(e)}), status=500) -@server.PromptServer.instance.routes.get("/workspace/get_default_my_workflows_dir") -async def get_default_my_workflows_dir(request): +@server.PromptServer.instance.routes.get("/workspace/get_my_workflows_dir") +async def fetch_my_workflows_dir(request): try: - dir = os.path.join(comfy_path, 'my_workflows') - return web.Response(text=json.dumps({"path": dir}), content_type='application/json') + dir = get_my_workflows_dir() + return web.Response(text=json.dumps({"path": dir, "os": sys.platform}), content_type='application/json') except Exception as e: return web.Response(text=json.dumps({"error": str(e)}), status=500) diff --git a/ui/src/Api.ts b/ui/src/Api.ts index 14e9021..c397282 100644 --- a/ui/src/Api.ts +++ b/ui/src/Api.ts @@ -122,6 +122,16 @@ export async function openWorkflowsFolder() { } } +export async function fetchMyWorkflowsDir(){ + const resp = await fetch("/workspace/get_my_workflows_dir"); + const res = (await resp.json()) as { path?: string; error?: string; os:string }; + if (res.error) { + alert(`Failed to fetch my workflows path: ${res.error}`) + + } + return(res.path) +} + export async function getAllModelsList() { try { const response = await fetch("/model_manager/get_model_list", { diff --git a/ui/src/db-tables/UserSettingsTable.ts b/ui/src/db-tables/UserSettingsTable.ts index 6a3250b..9820895 100644 --- a/ui/src/db-tables/UserSettingsTable.ts +++ b/ui/src/db-tables/UserSettingsTable.ts @@ -1,6 +1,7 @@ import { UserSettings } from "../types/dbTypes"; import { TableBase } from "./TableBase"; import { MODEL_TYPE_TO_FOLDER_MAPPING } from "../model-manager/install-models/util/modelTypes"; +import { fetchMyWorkflowsDir } from "../Api"; export class UserSettingsTable extends TableBase { public defaultSettings: UserSettings; @@ -90,14 +91,10 @@ export class UserSettingsTable extends TableBase { static async load(): Promise { const instance = new UserSettingsTable(); - const resp = await fetch("/workspace/get_default_my_workflows_dir"); - const res = (await resp.json()) as { path?: string; error?: string }; - if (res.error) { - console.error("Failed to get myWorkflowsDir"); - } else if (res.path) { - instance.defaultSettings.myWorkflowsDir = res.path; - } - + const myWorkflowsDir=await fetchMyWorkflowsDir(); + + instance.defaultSettings.myWorkflowsDir = myWorkflowsDir! + await instance.getSetting("autoSave").then((res) => { instance._autoSave = res ?? true; }); diff --git a/ui/src/settings/SelectMyWorkflowsDir.tsx b/ui/src/settings/SelectMyWorkflowsDir.tsx index a6a39bd..14e54d1 100644 --- a/ui/src/settings/SelectMyWorkflowsDir.tsx +++ b/ui/src/settings/SelectMyWorkflowsDir.tsx @@ -20,7 +20,7 @@ import { } from "@chakra-ui/react"; import { IconEdit } from "@tabler/icons-react"; import { useRef, useState, useEffect } from "react"; -import { getSystemDir } from "../Api"; +import { fetchMyWorkflowsDir, getSystemDir } from "../Api"; import { userSettingsTable } from "../db-tables/WorkspaceDB"; import { validateOrSaveAllJsonFileMyWorkflows } from "../utils"; @@ -36,9 +36,8 @@ export default function SelectMyWorkflowsDir() { const toast = useToast(); useEffect(() => { - userSettingsTable?.getSetting("myWorkflowsDir").then((res) => { - setCurrentDirectory(res); - }); + fetchMyWorkflowsDir().then((dir)=> + setCurrentDirectory(dir??"")) userSettingsTable?.getSetting("twoWaySync").then((res) => { setTwoWaySync(res ?? false); }); @@ -70,7 +69,7 @@ export default function SelectMyWorkflowsDir() { setSubdirectoryList(dirList); setIsEditDirectory(true); setDirPathList( - (currentDirectory && currentDirectory.split("/").filter((p) => !!p)) || + (currentDirectory && currentDirectory.split(/[\\|\/]/).filter((p) => !!p)) || [], ); } From da628cd56532cb21490c9788c1c2f3b698111be1 Mon Sep 17 00:00:00 2001 From: Weixuan Fu Date: Mon, 4 Mar 2024 23:16:27 +0800 Subject: [PATCH 5/6] fixed folder rename move create --- service/file_sync_service.py | 17 +++-------------- service/twoway_sync_folder_service.py | 10 +++++----- ui/src/apis/TwowaySyncApi.ts | 2 +- ui/src/db-tables/UserSettingsTable.ts | 8 ++++---- ui/src/db-tables/WorkflowsTable.ts | 1 - ui/src/settings/SelectMyWorkflowsDir.tsx | 6 +++--- ui/src/utils/OsPathUtils.ts | 12 +----------- 7 files changed, 17 insertions(+), 39 deletions(-) diff --git a/service/file_sync_service.py b/service/file_sync_service.py index c5e21c1..a52e3b9 100644 --- a/service/file_sync_service.py +++ b/service/file_sync_service.py @@ -56,12 +56,10 @@ async def rename_file(request): return web.json_response(data, content_type='application/json') def rename_file_sync(reqJson): - current_path = reqJson.get('path') + current_path = Path(get_my_workflows_dir()) / reqJson['path'] new_name = reqJson.get('newName') try: - new_path = Path(current_path).parent / new_name - # if new_path.suffix != ".json": - # raise ValueError("New file name must have a .json extension") + new_path = current_path.parent / new_name Path(current_path).rename(new_path) return {"success": True} except Exception as e: @@ -197,15 +195,6 @@ def file_handle(name, file, fileList, file_path): } fileList.append(fileInfo) -def atomic_json_update(filepath, data): - # Generate a temporary file - dir_name, file_name = os.path.split(filepath) - with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', dir=dir_name, delete=False) as tmp_file: - json.dump(data, tmp_file, indent=4) - temp_name = tmp_file.name - # Replace the old file with the new file atomically - os.replace(temp_name, filepath) - @server.PromptServer.instance.routes.post('/workspace/file/gen_unique_name') async def generate_unique_file_name(request): reqJson = await request.json() @@ -217,7 +206,7 @@ def generate_unique_file_name_sync(reqJson): if not file_path: return {"success": False, "error": "File path is required"} - path = Path(file_path) + path = Path(get_my_workflows_dir()) / file_path if not path.parent.is_dir(): return {"success": False, "error": "Directory of the provided path does not exist"} diff --git a/service/twoway_sync_folder_service.py b/service/twoway_sync_folder_service.py index d1f3f68..bbbb86f 100644 --- a/service/twoway_sync_folder_service.py +++ b/service/twoway_sync_folder_service.py @@ -14,7 +14,7 @@ async def create_folder(request): def create_folder_sync(reqJson): folder_path = reqJson.get('path') - folder_path = os.join(get_my_workflows_dir(), folder_path) + folder_path = os.path.join(get_my_workflows_dir(), folder_path) try: Path(folder_path).mkdir(parents=True, exist_ok=True) return {"success": True} @@ -29,7 +29,7 @@ async def delete_folder(request): def delete_folder_sync(reqJson): folder_path = reqJson.get('path') - folder_path = os.join(get_my_workflows_dir(), folder_path) + folder_path = os.path.join(get_my_workflows_dir(), folder_path) try: shutil.rmtree(folder_path) return {"success": True} @@ -44,7 +44,7 @@ async def rename_folder(request): def rename_folder_sync(reqJson): current_path = reqJson.get('absPath') - current_path = os.join(get_my_workflows_dir(), current_path) + current_path = os.path.join(get_my_workflows_dir(), current_path) new_name = reqJson.get('newName') try: new_path = Path(current_path).parent / new_name @@ -61,8 +61,8 @@ async def move_folder(request): def move_folder_sync(reqJson): current_path = reqJson.get('folder') - current_path = os.join(get_my_workflows_dir(), current_path) - new_path = reqJson.get('newParentPath') + current_path = os.path.join(get_my_workflows_dir(), current_path) + new_path = os.path.join(get_my_workflows_dir(), reqJson.get('newParentPath',"")) try: shutil.move(current_path, new_path) return {"success": True} diff --git a/ui/src/apis/TwowaySyncApi.ts b/ui/src/apis/TwowaySyncApi.ts index c1c4f43..dc6c829 100644 --- a/ui/src/apis/TwowaySyncApi.ts +++ b/ui/src/apis/TwowaySyncApi.ts @@ -77,7 +77,7 @@ export namespace TwowaySyncAPI { }); const result = await response.json(); if (result.error) { - alert("Error moving file: " + result.error); + alert("Error rename file: " + result.error); return false; } return true; diff --git a/ui/src/db-tables/UserSettingsTable.ts b/ui/src/db-tables/UserSettingsTable.ts index 9820895..885f0b7 100644 --- a/ui/src/db-tables/UserSettingsTable.ts +++ b/ui/src/db-tables/UserSettingsTable.ts @@ -91,10 +91,10 @@ export class UserSettingsTable extends TableBase { static async load(): Promise { const instance = new UserSettingsTable(); - const myWorkflowsDir=await fetchMyWorkflowsDir(); - - instance.defaultSettings.myWorkflowsDir = myWorkflowsDir! - + const myWorkflowsDir = await fetchMyWorkflowsDir(); + + instance.defaultSettings.myWorkflowsDir = myWorkflowsDir!; + await instance.getSetting("autoSave").then((res) => { instance._autoSave = res ?? true; }); diff --git a/ui/src/db-tables/WorkflowsTable.ts b/ui/src/db-tables/WorkflowsTable.ts index 71dcafa..89c7c90 100644 --- a/ui/src/db-tables/WorkflowsTable.ts +++ b/ui/src/db-tables/WorkflowsTable.ts @@ -87,7 +87,6 @@ export class WorkflowsTable extends TableBase { (name ?? "Untitled Flow") + ".json", parentFolderID ?? "", ); - console.log("generateUniqueName", fileName); return fileName?.replace(/\.json$/, "") ?? "Untitled Flow"; } /** diff --git a/ui/src/settings/SelectMyWorkflowsDir.tsx b/ui/src/settings/SelectMyWorkflowsDir.tsx index 14e54d1..8c4b7b4 100644 --- a/ui/src/settings/SelectMyWorkflowsDir.tsx +++ b/ui/src/settings/SelectMyWorkflowsDir.tsx @@ -36,8 +36,7 @@ export default function SelectMyWorkflowsDir() { const toast = useToast(); useEffect(() => { - fetchMyWorkflowsDir().then((dir)=> - setCurrentDirectory(dir??"")) + fetchMyWorkflowsDir().then((dir) => setCurrentDirectory(dir ?? "")); userSettingsTable?.getSetting("twoWaySync").then((res) => { setTwoWaySync(res ?? false); }); @@ -69,7 +68,8 @@ export default function SelectMyWorkflowsDir() { setSubdirectoryList(dirList); setIsEditDirectory(true); setDirPathList( - (currentDirectory && currentDirectory.split(/[\\|\/]/).filter((p) => !!p)) || + (currentDirectory && + currentDirectory.split(/[\\|\/]/).filter((p) => !!p)) || [], ); } diff --git a/ui/src/utils/OsPathUtils.ts b/ui/src/utils/OsPathUtils.ts index 5d949ec..72cfee1 100644 --- a/ui/src/utils/OsPathUtils.ts +++ b/ui/src/utils/OsPathUtils.ts @@ -4,13 +4,7 @@ export function joinRelPath(...segments: string[]) { const rel = segments.filter((segment) => segment !== "").join("/"); return sanitizeRelPath(rel); } -// export function sanitizeRelPath(path: string) { -// const segments = path.split("/").filter((segment) => segment !== ""); -// if (segments.length === 0) { -// return ""; -// } -// return segments.join("/"); -// } + export function sanitizeRelPath(path: string) { const segments = path .split("/") @@ -18,10 +12,6 @@ export function sanitizeRelPath(path: string) { .join("/"); // Replace backslashes with forward slashes to handle Windows paths let sanitizedPath = segments.replace(/\\/g, "/"); - - // If the path contains a Windows drive letter, remove it - sanitizedPath = sanitizedPath.replace(/^[a-zA-Z]:/, ""); - // Remove leading slashes to ensure the path is treated as relative sanitizedPath = sanitizedPath.replace(/^\/+/, ""); From 1b11dca467cf6d72e8f8ff55e64377fcaef50e02 Mon Sep 17 00:00:00 2001 From: Weixuan Fu Date: Mon, 4 Mar 2024 23:25:10 +0800 Subject: [PATCH 6/6] cleanup code --- ui/src/utils/twowaySyncUtils.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ui/src/utils/twowaySyncUtils.ts b/ui/src/utils/twowaySyncUtils.ts index 5a03d2e..21e3155 100644 --- a/ui/src/utils/twowaySyncUtils.ts +++ b/ui/src/utils/twowaySyncUtils.ts @@ -14,13 +14,7 @@ export async function scanMyWorkflowsDir( parentFolderID: string | null, sortBy?: ESortTypes, ): Promise<(Workflow | Folder)[]> { - const myWorkflowsDir = await userSettingsTable?.getSetting("myWorkflowsDir"); - if (myWorkflowsDir == null || myWorkflowsDir === "") { - alert("No Workspace saving directory found, please go to Settings."); - return []; - } const parentRelPath = sanitizeRelPath(parentFolderID ?? ""); - console.log("scanMyWorkflowsDir", parentRelPath); // folderID is the relative path of the folder in two way sync mode const fileList = await scanLocalFiles(parentRelPath);