Skip to content

Commit

Permalink
feat: auto create first workspace
Browse files Browse the repository at this point in the history
fixes #327
  • Loading branch information
linonetwo committed Feb 22, 2023
1 parent 91fd128 commit 04879c7
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 31 deletions.
4 changes: 3 additions & 1 deletion localization/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"Hello": "Hello",
"WorkspaceSelector": {
"Add": "Add",
"Guide": "Guide",
"OpenWorkspaceTagTiddler": "Open {{tagName}}",
"DefaultTiddlers": "Default Tiddlers",
"OpenWorkspaceMenuName": "Open Workspace",
Expand Down Expand Up @@ -229,7 +230,8 @@
"CheckingRebaseStatus": "Analyzing the rebase processing plan",
"InitializeWikiGit": "Initializing Wiki and Git",
"InitializeWorkspaceView": "Initializing workspace and browser view, and loading the web content, please wait",
"GitTokenExpireOrWrong": "The Git credential (Token) has expired and you need to log in again, or the credential does not correspond to the user name"
"GitTokenExpireOrWrong": "The Git credential (Token) has expired and you need to log in again, or the credential does not correspond to the user name",
"InitializeWorkspaceViewDone": "Created successfully, content will be loaded soon"
},
"Cancel": "Cancel",
"Preference": {
Expand Down
2 changes: 2 additions & 0 deletions localization/locales/zh_CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"LinOnetwo": "林一二",
"WorkspaceSelector": {
"Add": "添加",
"Guide": "引导",
"OpenWorkspaceTagTiddler": "打开 {{tagName}}",
"DefaultTiddlers": "默认条目",
"OpenWorkspaceMenuName": "打开工作区",
Expand Down Expand Up @@ -247,6 +248,7 @@
"SynchronizationFinish": "同步完成",
"InitializeWikiGit": "正在初始化 Wiki 和 Git",
"InitializeWorkspaceView": "正在初始化工作区和浏览器窗口,并加载内容,请耐心等待",
"InitializeWorkspaceViewDone": "创建成功,即将加载内容",
"PrepareCloneOnlineWiki": "准备导入线上 Wiki",
"StartFetchingFromGithubRemote": "正在拉取Github远端仓库的数据,需要的时间取决于网速和仓库大小,请耐心等待",
"UsingUrlAndUsername": "使用 Git Url {{githubRepoUrl}} 和用户名 {{username}} 和 accessToken {{accessToken}}"
Expand Down
18 changes: 15 additions & 3 deletions src/components/WorkspaceIconAndSelector/WorkspaceSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const AvatarPicture = styled.img<{ large?: boolean }>`
`}
`;

const ShortcutText = styled.p`
const ShortcutText = styled.p<{ active?: boolean }>`
margin-top: 2px;
margin-bottom: 0;
padding: 0;
Expand All @@ -118,6 +118,12 @@ const ShortcutText = styled.p`
display: inline-block;
word-break: break-all;
text-align: center;
${({ active }) =>
active === true &&
css`
text-decoration: underline;
text-underline-offset: 0.2em;
`}
`;
const Badge = styled(BadgeRaw)`
line-height: 20px;
Expand Down Expand Up @@ -171,15 +177,21 @@ export function WorkspaceSelector({
transparent={transparentBackground}
addAvatar={id === 'add'}
highlightAdd={index === 0}
id={id === 'add' ? 'add-workspace-button' : `workspace-avatar-${id}`}>
id={id === 'add' || id === 'guide' ? 'add-workspace-button' : `workspace-avatar-${id}`}>
{id === 'add' ? (
'+'
) : id === 'guide' ? (
'※'
) : (
<AvatarPicture alt="Icon" large={!showSidebarShortcutHints} src={getAssetsFileUrl(picturePath ?? defaultIcon)} draggable={false} />
)}
</Avatar>
</Badge>
{showSidebarShortcutHints && <ShortcutText>{id === 'add' ? t('WorkspaceSelector.Add') : shortWorkspaceName}</ShortcutText>}
{showSidebarShortcutHints && (
<ShortcutText active={active}>
{id === 'add' ? t('WorkspaceSelector.Add') : id === 'guide' ? t('WorkspaceSelector.Guide') : shortWorkspaceName}
</ShortcutText>
)}
</Root>
);
}
2 changes: 2 additions & 0 deletions src/constants/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ export const LOCALIZATION_FOLDER = isDevelopmentOrTest
? path.resolve(sourcePath, '..', localizationFolderName)
: path.resolve(process.resourcesPath, localizationFolderName);
export const DEFAULT_WIKI_FOLDER = isDevelopmentOrTest ? path.resolve(os.tmpdir(), developmentWikiFolderName) : DESKTOP_PATH;
export const DEFAULT_FIRST_WIKI_NAME = 'wiki';
export const DEFAULT_FIRST_WIKI_PATH = path.join(DEFAULT_WIKI_FOLDER, DEFAULT_FIRST_WIKI_NAME);
9 changes: 7 additions & 2 deletions src/pages/AddWorkspace/useCallWikiInitialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export async function callWikiInitialization(
wikiCreationMessageSetter: (m: string) => void,
t: TFunction<'translation'>,
gitUserInfo: IGitUserInfos | undefined,
notClose?: boolean,
): Promise<void> {
wikiCreationMessageSetter(t('Log.InitializeWikiGit'));
const newWorkspace = await window.service.wikiGitWorkspace.initWikiGitTransaction(newWorkspaceConfig, gitUserInfo);
Expand All @@ -17,7 +18,11 @@ export async function callWikiInitialization(
wikiCreationMessageSetter(t('Log.InitializeWorkspaceView'));
/** create workspace from workspaceService to store workspace configs, and create a BrowserView to actually display wiki web content from viewService */
await window.service.workspaceView.initializeWorkspaceView(newWorkspace, { isNew: true });
wikiCreationMessageSetter(t('Log.InitializeWorkspaceViewDone'));
await window.service.workspaceView.setActiveWorkspaceView(newWorkspace.id);
// wait for wiki to start and close the window now.
await window.remote.closeCurrentWindow();
wikiCreationMessageSetter('');
if (notClose !== true) {
// wait for wiki to start and close the window now.
await window.remote.closeCurrentWindow();
}
}
10 changes: 6 additions & 4 deletions src/pages/AddWorkspace/useForm.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable unicorn/no-null */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
Expand All @@ -10,6 +11,7 @@ import { useStorageServiceUserInfoObservable } from '@services/auth/hooks';
import { SupportedStorageServices } from '@services/types';
import { ISubWikiPluginContent } from '@services/wiki/plugin/subWikiPlugin';
import { INewWorkspaceConfig, IWorkspace } from '@services/workspaces/interface';
import type { INewWikiRequiredFormData } from './useNewWiki';

export function useIsCreateSyncedWorkspace(): [boolean, React.Dispatch<React.SetStateAction<boolean>>] {
const [isCreateSyncedWorkspace, isCreateSyncedWorkspaceSetter] = useState(false);
Expand Down Expand Up @@ -151,15 +153,15 @@ export interface IWikiWorkspaceFormProps {
isCreateMainWorkspace: boolean;
}

export function workspaceConfigFromForm(form: IWikiWorkspaceForm, isCreateMainWorkspace: boolean, isCreateSyncedWorkspace: boolean): INewWorkspaceConfig {
export function workspaceConfigFromForm(form: INewWikiRequiredFormData, isCreateMainWorkspace: boolean, isCreateSyncedWorkspace: boolean): INewWorkspaceConfig {
return {
gitUrl: isCreateSyncedWorkspace ? form.gitRepoUrl : null,
isSubWiki: !isCreateMainWorkspace,
mainWikiToLink: !isCreateMainWorkspace ? form.mainWikiToLink.wikiFolderLocation : null,
mainWikiID: !isCreateMainWorkspace ? form.mainWikiToLink.id : null,
mainWikiToLink: isCreateMainWorkspace ? null : form.mainWikiToLink.wikiFolderLocation,
mainWikiID: isCreateMainWorkspace ? null : form.mainWikiToLink.id,
name: form.wikiFolderName,
storageService: form.storageProvider,
tagName: !isCreateMainWorkspace ? form.tagName : null,
tagName: isCreateMainWorkspace ? null : form.tagName,
port: form.wikiPort,
wikiFolderLocation: form.wikiFolderLocation!,
backupOnInterval: true,
Expand Down
30 changes: 12 additions & 18 deletions src/pages/AddWorkspace/useNewWiki.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { callWikiInitialization } from './useCallWikiInitialization';
import { IErrorInWhichComponent, IWikiWorkspaceForm, workspaceConfigFromForm } from './useForm';
import { updateErrorInWhichComponentSetterByErrorMessage } from './useIndicator';
import { ConditionalExcept } from 'type-fest';

export function useValidateNewWiki(
isCreateMainWorkspace: boolean,
Expand Down Expand Up @@ -56,20 +58,21 @@ export function useValidateNewWiki(
return [hasError, wikiCreationMessage, wikiCreationMessageSetter, hasErrorSetter];
}

export type INewWikiRequiredFormData = ConditionalExcept<IWikiWorkspaceForm, Function>;
export function useNewWiki(
isCreateMainWorkspace: boolean,
isCreateSyncedWorkspace: boolean,
form: IWikiWorkspaceForm,
form: INewWikiRequiredFormData,
wikiCreationMessageSetter: (m: string) => void,
hasErrorSetter: (m: boolean) => void,
errorInWhichComponentSetter: (errors: IErrorInWhichComponent) => void,
options?: { noCopyTemplate?: boolean },
hasErrorSetter?: (m: boolean) => void,
errorInWhichComponentSetter?: (errors: IErrorInWhichComponent) => void,
options?: { noCopyTemplate?: boolean; notClose?: boolean },
): () => Promise<void> {
const { t } = useTranslation();

const onSubmit = useCallback(async () => {
wikiCreationMessageSetter(t('AddWorkspace.Processing'));
hasErrorSetter(false);
hasErrorSetter?.(false);
try {
const newWorkspaceConfig = workspaceConfigFromForm(form, isCreateMainWorkspace, isCreateSyncedWorkspace);
if (isCreateMainWorkspace) {
Expand All @@ -79,22 +82,13 @@ export function useNewWiki(
} else {
await window.service.wiki.createSubWiki(form.parentFolderLocation, form.wikiFolderName, form.mainWikiToLink?.wikiFolderLocation, form.tagName);
}
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo);
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, options?.notClose);
} catch (error) {
wikiCreationMessageSetter((error as Error).message);
updateErrorInWhichComponentSetterByErrorMessage(t, (error as Error).message, errorInWhichComponentSetter);
hasErrorSetter(true);
errorInWhichComponentSetter && updateErrorInWhichComponentSetterByErrorMessage(t, (error as Error).message, errorInWhichComponentSetter);
hasErrorSetter?.(true);
}
}, [
wikiCreationMessageSetter,
t,
hasErrorSetter,
form,
isCreateMainWorkspace,
isCreateSyncedWorkspace,
options?.noCopyTemplate,
errorInWhichComponentSetter,
]);
}, [wikiCreationMessageSetter, t, hasErrorSetter, form, isCreateMainWorkspace, isCreateSyncedWorkspace, options, errorInWhichComponentSetter]);

return onSubmit;
}
14 changes: 13 additions & 1 deletion src/pages/Main/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/* eslint-disable @typescript-eslint/promise-function-async */
import React from 'react';
import React, { useState } from 'react';
import styled, { css } from 'styled-components';
import is, { isNot } from 'typescript-styled-is';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -28,6 +29,7 @@ import { Languages } from '../Preferences/sections/Languages';
import { TiddlyWiki } from '../Preferences/sections/TiddlyWiki';
import { NewUserMessage } from './NewUserMessage';
import { WikiErrorMessages, ViewLoadErrorMessages } from './ErrorMessage';
import { useAutoCreateFirstWorkspace } from './useAutoCreateFirstWorkspace';

const OuterRoot = styled.div`
display: flex;
Expand Down Expand Up @@ -151,6 +153,8 @@ const SidebarContainer = ({ children }: { children: React.ReactNode }): JSX.Elem
export default function Main(): JSX.Element {
const { t } = useTranslation();
const workspacesList = useWorkspacesListObservable();
const [wikiCreationMessage, wikiCreationMessageSetter] = useState('');
useAutoCreateFirstWorkspace(workspacesList, wikiCreationMessageSetter);
const preferences = usePreferenceObservable();
/** is title bar on. This only take effect after reload, so we don't want to get this preference from observable */
const titleBar = usePromiseValue<boolean>(() => window.service.preference.get('titleBar'), false)!;
Expand Down Expand Up @@ -188,6 +192,13 @@ export default function Main(): JSX.Element {
showSidebarShortcutHints={sidebarShortcutHints}
onClick={() => void window.service.window.open(WindowNames.addWorkspace)}
/>
<WorkspaceSelector
id="guide"
index={workspacesList?.length ? workspacesList.length + 1 : 1}
active={activeWorkspace?.id === undefined}
showSidebarShortcutHints={sidebarShortcutHints}
onClick={() => void window.service.workspace.clearActiveWorkspace(activeWorkspace?.id)}
/>
</SidebarTop>
<SideBarEnd>
{(workspacesList?.length ?? 0) > 0 && (
Expand Down Expand Up @@ -233,6 +244,7 @@ export default function Main(): JSX.Element {
{Array.isArray(workspacesList) && workspacesList.length > 0 && activeWorkspaceMetadata?.isLoading === true && (
<Typography color="textSecondary">{t('Loading')}</Typography>
)}
{wikiCreationMessage && <Typography color="textSecondary">{wikiCreationMessage}</Typography>}
{Array.isArray(workspacesList) && workspacesList.length === 0 && <NewUserMessage sidebar={sidebar} themeSource={themeSource} />}
</InnerContentRoot>
<Languages languageSelectorOnly />
Expand Down
40 changes: 40 additions & 0 deletions src/pages/Main/useAutoCreateFirstWorkspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* eslint-disable @typescript-eslint/promise-function-async */
import { useEffect, useState } from 'react';
import { IWorkspaceWithMetadata } from '@services/workspaces/interface';
import { INewWikiRequiredFormData, useNewWiki } from '../AddWorkspace/useNewWiki';
import { SupportedStorageServices } from '@services/types';
import { useWikiWorkspaceForm } from '../AddWorkspace/useForm';
import { usePromiseValue } from '@/helpers/useServiceValue';

export function useAutoCreateFirstWorkspace(workspacesList: IWorkspaceWithMetadata[] | undefined, wikiCreationMessageSetter: (m: string) => void): void {
const form = useWikiWorkspaceForm();
const DEFAULT_FIRST_WIKI_PATH = usePromiseValue<string | undefined>(() => window.service.context.get('DEFAULT_FIRST_WIKI_PATH'));
const DEFAULT_WIKI_FOLDER = usePromiseValue<string | undefined>(() => window.service.context.get('DEFAULT_WIKI_FOLDER'))!;
const defaultNewWorkspaceConfig: INewWikiRequiredFormData = {
...form,
wikiFolderName: 'wiki',
wikiFolderLocation: DEFAULT_FIRST_WIKI_PATH,
parentFolderLocation: DEFAULT_WIKI_FOLDER,
storageProvider: SupportedStorageServices.local,
wikiPort: 5212,
};

/** allow user delete all workspace, to enter the empty list state. */
const [created, createdSetter] = useState(false);
const onSubmit = useNewWiki(true, false, defaultNewWorkspaceConfig, wikiCreationMessageSetter, undefined, undefined, { notClose: true });

useEffect(() => {
if (created) return;
// skip this logic if already have workspaces
if (workspacesList?.length !== undefined && workspacesList?.length > 0) {
createdSetter(true);
return;
}
// if is first opened (or page refreshed) with empty workspace list, create one
if (DEFAULT_WIKI_FOLDER === undefined || DEFAULT_FIRST_WIKI_PATH === undefined) return;
if (workspacesList?.length === 0) {
createdSetter(true);
void onSubmit();
}
}, [workspacesList?.length, created, createdSetter, onSubmit, DEFAULT_WIKI_FOLDER, DEFAULT_FIRST_WIKI_PATH]);
}
2 changes: 2 additions & 0 deletions src/services/context/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ContextChannel } from '@/constants/channels';

export interface IPaths {
CHROME_ERROR_PATH: string;
DEFAULT_FIRST_WIKI_NAME: string;
DEFAULT_FIRST_WIKI_PATH: string;
DEFAULT_WIKI_FOLDER: string;
DESKTOP_PATH: string;
LOCALIZATION_FOLDER: string;
Expand Down
9 changes: 8 additions & 1 deletion src/services/workspaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,14 @@ export class Workspace implements IWorkspaceService {
// active new one
await this.update(id, { active: true, hibernated: false });
// de-active the other one
if (typeof oldActiveWorkspaceID === 'string' && oldActiveWorkspaceID !== id) {
if (oldActiveWorkspaceID !== id) {
await this.clearActiveWorkspace(oldActiveWorkspaceID);
}
}

public async clearActiveWorkspace(oldActiveWorkspaceID: string | undefined): Promise<void> {
// de-active the other one
if (typeof oldActiveWorkspaceID === 'string') {
await this.update(oldActiveWorkspaceID, { active: false });
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/services/workspaces/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ export type INewWorkspaceConfig = SetOptional<
* Manage workspace level preferences and workspace metadata.
*/
export interface IWorkspaceService {
/** Enter a state that no workspace is active (show welcome page) */
clearActiveWorkspace(oldActiveWorkspaceID: string | undefined): Promise<void>;
countWorkspaces(): Promise<number>;
create(newWorkspaceConfig: INewWorkspaceConfig): Promise<IWorkspace>;
get(id: string): Promise<IWorkspace | undefined>;
Expand Down Expand Up @@ -157,6 +159,7 @@ export const WorkspaceServiceIPCDescriptor = {
channel: WorkspaceChannel.name,
properties: {
countWorkspaces: ProxyPropertyType.Function,
clearActiveWorkspace: ProxyPropertyType.Function,
create: ProxyPropertyType.Function,
get: ProxyPropertyType.Function,
get$: ProxyPropertyType.Function$,
Expand Down
2 changes: 1 addition & 1 deletion template/wiki
Submodule wiki updated 35 files
+1 −1 .github/workflows/gh-pages.yml
+3 −2 .gitignore
+4 −2 tiddlers/$__DefaultTiddlers.tid
+1 −1 tiddlers/$__plugins_Gk0Wk_echarts.json
+3 −2 tiddlers/$__plugins_Gk0Wk_echarts.json.meta
+1 −0 tiddlers/$__plugins_Gk0Wk_focused-tiddler.json
+10 −0 tiddlers/$__plugins_Gk0Wk_focused-tiddler.json.meta
+1 −1 tiddlers/$__plugins_Gk0Wk_notionpage-covericon.json
+2 −1 tiddlers/$__plugins_Gk0Wk_notionpage-covericon.json.meta
+1 −1 tiddlers/$__plugins_Gk0Wk_sidebar-resizer.json
+3 −2 tiddlers/$__plugins_Gk0Wk_sidebar-resizer.json.meta
+1 −1 tiddlers/$__plugins_flibbles_relink-titles.json
+1 −1 tiddlers/$__plugins_flibbles_relink-titles.json.meta
+1 −1 tiddlers/$__plugins_flibbles_relink.json
+1 −1 tiddlers/$__plugins_flibbles_relink.json.meta
+1 −1 tiddlers/$__plugins_kookma_commander.json
+1 −1 tiddlers/$__plugins_kookma_commander.json.meta
+1 −1 tiddlers/$__plugins_kookma_hsl.json
+1 −3 tiddlers/$__plugins_kookma_hsl.json.meta
+1 −1 tiddlers/$__plugins_kookma_shiraz.json
+1 −1 tiddlers/$__plugins_kookma_shiraz.json.meta
+1 −1 tiddlers/$__plugins_kookma_utility.json
+1 −1 tiddlers/$__plugins_kookma_utility.json.meta
+1 −1 tiddlers/$__plugins_linonetwo_slate-write.json
+1 −1 tiddlers/$__plugins_linonetwo_slate-write.json.meta
+1 −1 tiddlers/$__plugins_linonetwo_template-list.json
+3 −3 tiddlers/$__plugins_linonetwo_template-list.json.meta
+2 −2 tiddlers/$__plugins_linonetwo_tw-calendar.json
+3 −3 tiddlers/$__plugins_linonetwo_tw-mobile-sync.json
+1 −1 tiddlers/$__themes_linonetwo_itonnote.json
+1 −1 tiddlers/$__themes_linonetwo_itonnote.json.meta
+1 −0 tiddlers/$__themes_tiddlywiki_vanilla.json
+10 −0 tiddlers/$__themes_tiddlywiki_vanilla.json.meta
+8 −2 tiddlers/Index.tid
+4 −8 tiddlywiki.info

0 comments on commit 04879c7

Please sign in to comment.