// ...existing code... import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { usePromiseValue } from '@/helpers/useServiceValue'; import { useStorageServiceUserInfoObservable } from '@services/auth/hooks'; import { SupportedStorageServices } from '@services/types'; import type { INewWikiWorkspaceConfig, IWikiWorkspace } from '@services/workspaces/interface'; import { isWikiWorkspace } from '@services/workspaces/interface'; import type { INewWikiRequiredFormData } from './useNewWiki'; type IMainWikiInfo = Pick; export function useIsCreateSyncedWorkspace(): [boolean, React.Dispatch>] { const [isCreateSyncedWorkspace, isCreateSyncedWorkspaceSetter] = useState(false); useEffect(() => { void window.service.auth.getRandomStorageServiceUserInfo().then((result) => { isCreateSyncedWorkspaceSetter(result !== undefined); }); }, []); return [isCreateSyncedWorkspace, isCreateSyncedWorkspaceSetter]; } export function useWikiWorkspaceForm(options?: { fromExisted: boolean }) { const { t } = useTranslation(); const workspaceList = usePromiseValue(async () => await window.service.workspace.getWorkspacesAsList(), []); const [wikiPort, wikiPortSetter] = useState(5212); useEffect(() => { // only update default port on component mount void window.service.workspace.countWorkspaces().then((workspaceCount) => { wikiPortSetter(wikiPort + workspaceCount); }); }, []); /** * Set storage service used by this workspace, for example, Github. */ const [storageProvider, storageProviderSetter] = useState(SupportedStorageServices.local); const gitUserInfo = useStorageServiceUserInfoObservable(storageProvider); /** * For sub-wiki, we need to link it to a main wiki's folder, so all wiki contents can be loaded together. */ const mainWorkspaceList = useMemo(() => workspaceList?.filter((workspace) => isWikiWorkspace(workspace) && !workspace.isSubWiki) ?? [], [workspaceList]); const [mainWikiToLink, mainWikiToLinkSetter] = useState( () => { const firstMainWiki = mainWorkspaceList.find(isWikiWorkspace); return firstMainWiki ? { wikiFolderLocation: firstMainWiki.wikiFolderLocation, port: firstMainWiki.port, id: firstMainWiki.id } : { wikiFolderLocation: '', port: 0, id: '' }; }, ); const [tagName, tagNameSetter] = useState(''); let mainWikiToLinkIndex = mainWorkspaceList.findIndex((workspace) => workspace.id === mainWikiToLink.id); if (mainWikiToLinkIndex < 0) { mainWikiToLinkIndex = 0; } useEffect(() => { const selectedWorkspace = mainWorkspaceList[mainWikiToLinkIndex]; if (selectedWorkspace && isWikiWorkspace(selectedWorkspace) && selectedWorkspace.wikiFolderLocation) { mainWikiToLinkSetter({ wikiFolderLocation: selectedWorkspace.wikiFolderLocation, port: selectedWorkspace.port, id: selectedWorkspace.id }); } }, [mainWorkspaceList, mainWikiToLinkIndex]); /** * For creating new wiki, we use parentFolderLocation to determine in which folder we create the new wiki folder. * New folder will basically be created in `${parentFolderLocation}/${wikiFolderName}` */ const [parentFolderLocation, parentFolderLocationSetter] = useState(''); /** * For creating new wiki, we put `tiddlers` folder in this `${parentFolderLocation}/${wikiFolderName}` folder */ const [wikiFolderName, wikiFolderNameSetter] = useState('tiddlywiki'); /** * Initialize a folder path for user */ useEffect(() => { void (async function getDefaultExistedWikiFolderPathEffect() { const desktopPathAsDefaultExistedWikiFolderPath = await window.service.context.get('DEFAULT_FIRST_WIKI_FOLDER_PATH'); const lastMainWiki = mainWorkspaceList.at(-1); const defaultWikiFolderName = (lastMainWiki && isWikiWorkspace(lastMainWiki)) ? lastMainWiki.wikiFolderLocation : 'wiki'; wikiFolderNameSetter(defaultWikiFolderName); parentFolderLocationSetter(desktopPathAsDefaultExistedWikiFolderPath); })(); // we only do this on component init }, []); const [gitRepoUrl, gitRepoUrlSetter] = useState(''); // derived values /** full path of created wiki folder */ const wikiFolderLocation = usePromiseValue( async () => await window.service.native.path('join', parentFolderLocation ?? t('Error') ?? 'Error', wikiFolderName), 'Error', [parentFolderLocation, wikiFolderName], ); /** * For importing existed nodejs wiki into TidGi, we parse git url from the folder to import */ useEffect(() => { void (async function getWorkspaceRemoteEffect(): Promise { if (options?.fromExisted) { const url = await window.service.git.getWorkspacesRemote(wikiFolderLocation); if (typeof url === 'string' && url.length > 0) { gitRepoUrlSetter(url); } } })(); }, [gitRepoUrlSetter, wikiFolderLocation, options?.fromExisted]); /* * For wikiHTML */ const [wikiHtmlPath, wikiHtmlPathSetter] = useState(''); useEffect(() => { void (async function getDefaultWikiHtmlPathEffect() {})(); }, []); return { storageProvider, storageProviderSetter, wikiPort, wikiPortSetter, mainWikiToLink, mainWikiToLinkSetter, tagName, tagNameSetter, gitRepoUrl, gitRepoUrlSetter, parentFolderLocation, parentFolderLocationSetter, wikiFolderName, wikiFolderNameSetter, gitUserInfo, wikiFolderLocation, workspaceList, mainWorkspaceList, mainWikiToLinkIndex, wikiHtmlPath, wikiHtmlPathSetter, }; } export type IWikiWorkspaceForm = ReturnType; export type IErrorInWhichComponent = Partial>; export interface IWikiWorkspaceFormProps { errorInWhichComponent: IErrorInWhichComponent; errorInWhichComponentSetter: (errors: IErrorInWhichComponent) => void; form: IWikiWorkspaceForm; isCreateMainWorkspace: boolean; } /** * Fill in default value for newly created wiki. * @param form New wiki form value */ export function workspaceConfigFromForm(form: INewWikiRequiredFormData, isCreateMainWorkspace: boolean, isCreateSyncedWorkspace: boolean): INewWikiWorkspaceConfig { return { gitUrl: isCreateSyncedWorkspace ? form.gitRepoUrl : null, isSubWiki: !isCreateMainWorkspace, mainWikiToLink: isCreateMainWorkspace ? null : form.mainWikiToLink.wikiFolderLocation, mainWikiID: isCreateMainWorkspace ? null : form.mainWikiToLink.id, name: form.wikiFolderName, storageService: form.storageProvider, tagName: isCreateMainWorkspace ? null : form.tagName, port: form.wikiPort, wikiFolderLocation: form.wikiFolderLocation!, backupOnInterval: true, readOnlyMode: false, tokenAuth: false, // let global config override this userName: undefined, excludedPlugins: [], enableHTTPAPI: false, enableFileSystemWatch: true, includeTagTree: false, lastNodeJSArgv: [], }; }