diff --git a/localization/locales/en/translation.json b/localization/locales/en/translation.json index 03b856e3..3c15fb04 100644 --- a/localization/locales/en/translation.json +++ b/localization/locales/en/translation.json @@ -2,6 +2,7 @@ "Hello": "Hello", "WorkspaceSelector": { "Add": "Add", + "OpenWorkspaceTagTiddler": "Open {{tagName}}", "EditWorkspace": "Edit Workspace", "RemoveWorkspace": "Remove Workspace", "AreYouSure": "Are you sure you want to remove this workspace? \nRemoving the workspace will delete the workspace in this application, but will not delete the folders from the hard drive. \nBut, if you choose to delete the Wiki folder as well, all contents will be deleted.", @@ -295,7 +296,7 @@ "DoubleWikiInstanceError": "E-4 DoubleWikiInstanceError", "DoubleWikiInstanceErrorDescription": "E-4 You started the same Wiki twice. This may be caused by a bug in the program.", "InsertMenuAfterSubMenuIndexError": "E-5 InsertMenuAfterSubMenuIndexError", - "InsertMenuAfterSubMenuIndexErrorDescription": "E-5 You try to insert menu with afterSubMenu \"{afterSubMenu}\" in menu \"{menuID}\", but we can not found it in menu \"{menu}\", please specific a menuitem with correct id attribute", + "InsertMenuAfterSubMenuIndexErrorDescription": "E-5 You try to insert menu with afterSubMenu \"{{afterSubMenu}}\" in menu \"{{menuID}}\", but we can not found it in menu \"{{menu}}\", please specific a menuitem with correct id attribute", "InitWikiGitSyncedWikiNoGitUserInfoError": "E-6 InitWikiGitSyncedWikiNoGitUserInfoErrorDescription", "InitWikiGitSyncedWikiNoGitUserInfoErrorDescription": "E-6 Initializing the note repository synchronized to the cloud requires you to select a cloud git repository address and provide the certification credentials for the corresponding cloud service. However, this information is not currently available.", "MainWindowMissing": "E-7 This program can't access main window data, can't run normally.", diff --git a/localization/locales/zh_CN/translation.json b/localization/locales/zh_CN/translation.json index ccb97e41..bd3d294a 100644 --- a/localization/locales/zh_CN/translation.json +++ b/localization/locales/zh_CN/translation.json @@ -3,6 +3,7 @@ "LinOnetwo": "林一二", "WorkspaceSelector": { "Add": "添加", + "OpenWorkspaceTagTiddler": "打开 {{tagName}}", "EditWorkspace": "编辑工作区", "EditCurrentWorkspace": "编辑当前工作区", "ReloadCurrentWorkspace": "刷新当前工作区", @@ -326,7 +327,7 @@ "DoubleWikiInstanceError": "E-4 重复启动维基错误", "DoubleWikiInstanceErrorDescription": "E-4 你启动了同一个Wiki两次,这可能是程序bug导致的。", "InsertMenuAfterSubMenuIndexError": "E-5 插入目录模板到现有目录后错误", - "InsertMenuAfterSubMenuIndexErrorDescription": "E-5 你尝试插入目录,且 afterSubMenu \"{afterSubMenu}\" 在目录 menuID \"{menuID}\" 内,但我们无法在目录 \"{menu}\" 里找到它,请用正确的 menuID 指定一个目录。", + "InsertMenuAfterSubMenuIndexErrorDescription": "E-5 你尝试插入目录,且 afterSubMenu \"{{afterSubMenu}}\" 在目录 menuID \"{{menuID}}\" 内,但我们无法在目录 \"{{menu}}\" 里找到它,请用正确的 menuID 指定一个目录。", "InitWikiGitSyncedWikiNoGitUserInfoError": "E-6 笔记仓库初始化失败因为没有提供Git信息错误", "InitWikiGitSyncedWikiNoGitUserInfoErrorDescription": "E-6 初始化同步到云端的笔记仓库需要你选择一个云端的 git 仓库地址,还有提供相应云服务的认证凭证,然而目前没有获得这些信息。", "MainWindowMissing": "E-7 程序无法获取主窗口信息,无法正常运行。", diff --git a/src/pages/AddWorkspace/useForm.ts b/src/pages/AddWorkspace/useForm.ts index f8f29111..39b5988c 100644 --- a/src/pages/AddWorkspace/useForm.ts +++ b/src/pages/AddWorkspace/useForm.ts @@ -141,6 +141,7 @@ export function workspaceConfigFromForm(form: IWikiWorkspaceForm, isCreateMainWo gitUrl: isCreateSyncedWorkspace ? form.gitRepoUrl : null, isSubWiki: !isCreateMainWorkspace, mainWikiToLink: !isCreateMainWorkspace ? form.mainWikiToLink.wikiFolderLocation : null, + mainWikiID: !isCreateMainWorkspace ? form.mainWikiToLink.id : null, name: form.wikiFolderName, storageService: form.storageProvider, tagName: !isCreateMainWorkspace ? form.tagName : null, diff --git a/src/pages/Main/SortableWorkspaceSelector.tsx b/src/pages/Main/SortableWorkspaceSelector.tsx index e19807cb..89b898c2 100644 --- a/src/pages/Main/SortableWorkspaceSelector.tsx +++ b/src/pages/Main/SortableWorkspaceSelector.tsx @@ -5,9 +5,9 @@ import { CSS } from '@dnd-kit/utilities'; import { WindowNames } from '@services/windows/WindowProperties'; import WorkspaceSelector from './WorkspaceSelector'; import { IWorkspace } from '@services/workspaces/interface'; +import { getWorkspaceMenuTemplate, openWorkspaceTagTiddler } from '@services/workspaces/getWorkspaceMenuTemplate'; import defaultIcon from '@/images/default-icon.png'; -import { WikiChannel } from '@/constants/channels'; export interface ISortableItemProps { index: number; @@ -29,68 +29,12 @@ export function SortableWorkspaceSelector({ index, workspace, showSidebarShortcu style={style} {...attributes} {...listeners} - onClick={async () => { - if (isSubWiki) { - if (typeof tagName === 'string') { - await window.service.wiki.requestOpenTiddlerInWiki(tagName); - } - } else { - const activeWorkspace = await window.service.workspace.getActiveWorkspace(); - if (activeWorkspace?.id === id) { - await window.service.wiki.requestWikiSendActionMessage('tm-home'); - } else { - await window.service.workspaceView.setActiveWorkspaceView(id); - } - } - }} + onClick={async () => await openWorkspaceTagTiddler(workspace, window.service)} onContextMenu={(event) => { event.preventDefault(); event.stopPropagation(); - const template = [ - { - label: t('WorkspaceSelector.EditWorkspace'), - click: async () => { - await window.service.window.open(WindowNames.editWorkspace, { workspaceID: id }); - }, - }, - { - label: t('WorkspaceSelector.RemoveWorkspace'), - click: async () => await window.service.wikiGitWorkspace.removeWorkspace(id), - }, - { - label: t('WorkspaceSelector.OpenWorkspaceFolder'), - click: async () => await window.service.native.open(wikiFolderLocation, true), - }, - { - label: t('ContextMenu.Reload'), - click: async () => await window.service.view.reloadViewsWebContents(id), - }, - { - label: t('ContextMenu.RestartService'), - click: async () => { - const workspaceToRestart = await window.service.workspace.get(id); - if (workspaceToRestart !== undefined) { - await window.service.wiki.restartWiki(workspaceToRestart); - await window.service.view.reloadViewsWebContents(id); - await window.service.wiki.wikiOperation(WikiChannel.generalNotification, [t('ContextMenu.RestartServiceComplete')]); - } - }, - }, - ]; - - if (!active && !isSubWiki) { - template.splice(1, 0, { - label: hibernated ? t('WorkspaceSelector.WakeUpWorkspace') : t('WorkspaceSelector.HibernateWorkspace'), - click: async () => { - if (hibernated) { - return await window.service.workspaceView.wakeUpWorkspaceView(id); - } - return await window.service.workspaceView.hibernateWorkspaceView(id); - }, - }); - } - - void window.remote.buildContextMenuAndPopup(template, { x: event.clientX, y: event.clientY, editFlags: { canCopy: false } }); + const workspaceContextMenuTemplate = getWorkspaceMenuTemplate(workspace, t, window.service); + void window.remote.buildContextMenuAndPopup(workspaceContextMenuTemplate, { x: event.clientX, y: event.clientY, editFlags: { canCopy: false } }); }}> { + const workspaceContextMenuTemplate = getWorkspaceMenuTemplate(workspace, i18next.t.bind(i18next), services); + return { + label: workspace.name, + submenu: workspaceContextMenuTemplate, + }; + }), + }), + ); + } menu.append( new MenuItem({ label: i18next.t('ContextMenu.Back'), diff --git a/src/services/workspaces/getWorkspaceMenuTemplate.ts b/src/services/workspaces/getWorkspaceMenuTemplate.ts new file mode 100644 index 00000000..e2ce5419 --- /dev/null +++ b/src/services/workspaces/getWorkspaceMenuTemplate.ts @@ -0,0 +1,97 @@ +import type { TFunction } from 'i18next'; +import type { MenuItemConstructorOptions } from 'electron'; +import { WikiChannel } from '@/constants/channels'; +import { WindowNames } from '@services/windows/WindowProperties'; +import type { IWindowService } from '@services/windows/interface'; +import type { IWorkspaceViewService } from '@services/workspacesView/interface'; +import type { IWorkspace, IWorkspaceService } from './interface'; +import type { INativeService } from '@services/native/interface'; +import type { IViewService } from '@services/view/interface'; +import type { IWikiService } from '@services/wiki/interface'; +import type { IWikiGitWorkspaceService } from '@services/wikiGitWorkspace/interface'; + +interface IWorkspaceMenuRequiredServices { + native: Pick; + view: Pick; + wiki: Pick; + wikiGitWorkspace: Pick; + window: Pick; + workspace: Pick; + workspaceView: Pick; +} + +export async function openWorkspaceTagTiddler(workspace: IWorkspace, service: IWorkspaceMenuRequiredServices): Promise { + const { id, isSubWiki, tagName, mainWikiID } = workspace; + let idToActive = id; + const activeWorkspace = await service.workspace.getActiveWorkspace(); + if (isSubWiki) { + if (typeof tagName === 'string') { + await service.wiki.requestOpenTiddlerInWiki(tagName); + } + if (mainWikiID === null) { + return; + } + idToActive = mainWikiID; + } else { + await service.wiki.requestWikiSendActionMessage('tm-home'); + } + if (idToActive !== null && activeWorkspace?.id !== idToActive) { + await service.workspaceView.setActiveWorkspaceView(idToActive); + } +} + +export function getWorkspaceMenuTemplate(workspace: IWorkspace, t: TFunction, service: IWorkspaceMenuRequiredServices): MenuItemConstructorOptions[] { + const { active, id, hibernated, tagName, isSubWiki, wikiFolderLocation } = workspace; + + const template = [ + { + label: t('WorkspaceSelector.OpenWorkspaceTagTiddler', { tagName }), + click: async () => { + await openWorkspaceTagTiddler(workspace, service); + }, + }, + { + label: t('WorkspaceSelector.EditWorkspace'), + click: async () => { + await service.window.open(WindowNames.editWorkspace, { workspaceID: id }); + }, + }, + { + label: t('WorkspaceSelector.RemoveWorkspace'), + click: async () => await service.wikiGitWorkspace.removeWorkspace(id), + }, + { + label: t('WorkspaceSelector.OpenWorkspaceFolder'), + click: async () => await service.native.open(wikiFolderLocation, true), + }, + { + label: t('ContextMenu.Reload'), + click: async () => await service.view.reloadViewsWebContents(id), + }, + { + label: t('ContextMenu.RestartService'), + click: async () => { + const workspaceToRestart = await service.workspace.get(id); + if (workspaceToRestart !== undefined) { + await service.wiki.restartWiki(workspaceToRestart); + await service.view.reloadViewsWebContents(id); + await service.wiki.wikiOperation(WikiChannel.generalNotification, [t('ContextMenu.RestartServiceComplete')]); + } + }, + }, + ]; + + if (!active && !isSubWiki) { + template.splice(1, 0, { + label: hibernated ? t('WorkspaceSelector.WakeUpWorkspace') : t('WorkspaceSelector.HibernateWorkspace'), + click: async () => { + if (hibernated) { + return await service.workspaceView.wakeUpWorkspaceView(id); + } + return await service.workspaceView.hibernateWorkspaceView(id); + }, + }); + } + + return template; +} diff --git a/src/services/workspaces/index.ts b/src/services/workspaces/index.ts index 51b86e52..cfb1ea3f 100644 --- a/src/services/workspaces/index.ts +++ b/src/services/workspaces/index.ts @@ -18,7 +18,6 @@ import type { IWorkspaceViewService } from '@services/workspacesView/interface'; import type { IWindowService } from '@services/windows/interface'; import type { IMenuService } from '@services/menu/interface'; import { WindowNames } from '@services/windows/WindowProperties'; -import type { IAuthenticationService } from '@services/auth/interface'; import type { IWikiGitWorkspaceService } from '@services/wikiGitWorkspace/interface'; import { SupportedStorageServices } from '@services/types'; import { lazyInject } from '@services/container'; @@ -40,7 +39,6 @@ export class Workspace implements IWorkspaceService { @lazyInject(serviceIdentifier.WorkspaceView) private readonly workspaceViewService!: IWorkspaceViewService; @lazyInject(serviceIdentifier.WikiGitWorkspace) private readonly wikiGitWorkspaceService!: IWikiGitWorkspaceService; @lazyInject(serviceIdentifier.MenuService) private readonly menuService!: IMenuService; - @lazyInject(serviceIdentifier.Authentication) private readonly authenticationService!: IAuthenticationService; constructor() { this.workspaces = this.getInitWorkspacesForCache(); diff --git a/src/services/workspaces/interface.ts b/src/services/workspaces/interface.ts index 56aefb69..f8f671ae 100644 --- a/src/services/workspaces/interface.ts +++ b/src/services/workspaces/interface.ts @@ -34,7 +34,11 @@ export interface IWorkspace { */ lastUrl: string | null; /** - * Only useful when isSubWiki === true , this is the wiki repo that this subwiki's folder soft links to + * ID of main wiki of the sub-wiki. Only useful when isSubWiki === true + */ + mainWikiID: string | null; + /** + * Absolute path of main wiki of the sub-wiki. Only useful when isSubWiki === true , this is the wiki repo that this subwiki's folder soft links to */ mainWikiToLink: string | null; /**