diff --git a/src/pages/Main/ErrorMessage.tsx b/src/pages/Main/ErrorMessage.tsx
new file mode 100644
index 00000000..c03d106f
--- /dev/null
+++ b/src/pages/Main/ErrorMessage.tsx
@@ -0,0 +1,93 @@
+import { useCallback } from 'react';
+import Button from '@material-ui/core/Button';
+import { Trans, useTranslation } from 'react-i18next';
+import styled from 'styled-components';
+
+import { usePromiseValue } from '@/helpers/useServiceValue';
+import { IWorkspaceWithMetadata, IWorkspaceMetaData } from '@services/workspaces/interface';
+import { Typography } from '@material-ui/core';
+
+const HelperTextsList = styled.ul`
+ margin-top: 0;
+ margin-bottom: 1.5rem;
+ max-width: 70vw;
+`;
+
+interface IWikiErrorMessagesProps {
+ activeWorkspace: IWorkspaceWithMetadata;
+}
+
+export function WikiErrorMessages(props: IWikiErrorMessagesProps): JSX.Element {
+ const { t } = useTranslation();
+ const wikiLogs = usePromiseValue(async () => await window.service.wiki.getWikiLogs(props.activeWorkspace.wikiFolderLocation));
+ if (wikiLogs !== undefined) {
+ return (
+
+
+
+
+ {wikiLogs.content}
+
+
+
+ );
+ }
+ return ;
+}
+
+interface IViewLoadErrorMessagesProps {
+ activeWorkspaceMetadata: IWorkspaceMetaData;
+}
+
+export function ViewLoadErrorMessages(props: IViewLoadErrorMessagesProps): JSX.Element {
+ const { t } = useTranslation();
+ const requestReload = useCallback(async (): Promise => {
+ await window.service.window.reload(window.meta.windowName);
+ }, []);
+
+ return (
+
+
+ {t('AddWorkspace.WikiNotStarted')}
+
+
+ {props.activeWorkspaceMetadata.didFailLoadErrorMessage}
+
+
+
+
+
+ <>
+ Try:
+
+
+ Click{' '}
+
+ Reload
+ {' '}
+ button below or press CMD_or_Ctrl + R to reload the page.
+
+
+ Check the{' '}
+ await window.service.native.open(await window.service.context.get('LOG_FOLDER'), true)}
+ onKeyPress={async () => await window.service.native.open(await window.service.context.get('LOG_FOLDER'), true)}
+ role="button"
+ tabIndex={0}
+ style={{ cursor: 'pointer' }}>
+ Log Folder
+ {' '}
+ to see what happened.
+
+ Backup your file, remove workspace and recreate one.
+
+ >
+
+
+
+
+
+ );
+}
diff --git a/src/pages/Main/NewUserMessage.tsx b/src/pages/Main/NewUserMessage.tsx
new file mode 100644
index 00000000..a85c7ffd
--- /dev/null
+++ b/src/pages/Main/NewUserMessage.tsx
@@ -0,0 +1,97 @@
+import { Trans, useTranslation } from 'react-i18next';
+import styled from 'styled-components';
+
+import { WindowNames } from '@services/windows/WindowProperties';
+import { IPreferences } from '@services/preferences/interface';
+
+import arrowWhite from '@/images/arrow-white.png';
+import arrowBlack from '@/images/arrow-black.png';
+
+const Arrow = styled.div<{ image: string }>`
+ height: 202px;
+ width: 150px;
+ position: absolute;
+ top: 50px;
+ left: 72px;
+
+ background-image: url(${({ image }) => image});
+ background-size: 150px 202px;
+`;
+
+const Avatar = styled.div`
+ display: inline-block;
+ height: 32px;
+ width: 32px;
+ /** // TODO: dark theme */
+ /* background: theme.palette.type === 'dark' ? theme.palette.common.white : theme.palette.common.black; */
+ border-radius: 4;
+ /** // TODO: dark theme */
+ /* color: theme.palette.getContrastText(theme.palette.type === 'dark' ? theme.palette.common.white: theme.palette.common.black); */
+ line-height: 32px;
+ text-align: center;
+ font-weight: 500;
+ text-transform: uppercase;
+ margin-left: 10px;
+ margin-right: 10px;
+ /** // TODO: dark theme */
+ /* border: theme.palette.type === 'dark' ? 'none' : 1px solid rgba(0, 0, 0, 0.12); */
+`;
+
+const Tip2Text = styled.span`
+ display: inline-block;
+ font-size: 18px;
+ /** // TODO: dark theme */
+ /* color: theme.palette.type === 'dark' ? theme.palette.common.white : theme.palette.common.black; */
+`;
+
+const TipWithSidebar = styled.div`
+ position: absolute;
+ top: 112px;
+ left: 180px;
+ user-select: none;
+`;
+
+const TipWithoutSidebar = styled.div`
+ user-select: none;
+`;
+
+const AddWorkspaceGuideInfoContainer = styled.div`
+ cursor: pointer;
+`;
+
+export interface IProps {
+ sidebar: IPreferences['sidebar'];
+ themeSource: IPreferences['themeSource'];
+}
+
+export function NewUserMessage(props: IProps): JSX.Element {
+ const { t } = useTranslation();
+ return (
+ await window.service.window.open(WindowNames.addWorkspace)}>
+ {props.sidebar ? (
+ <>
+
+
+
+ Click
+ +
+ to get started!
+
+
+ >
+ ) : (
+
+
+
+ Click
+ Workspaces > Add Workspace
+ Or
+ Click Here
+ to get started!
+
+
+
+ )}
+
+ );
+}
diff --git a/src/pages/Main/index.tsx b/src/pages/Main/index.tsx
index 3debd7b7..6ff9d7cd 100644
--- a/src/pages/Main/index.tsx
+++ b/src/pages/Main/index.tsx
@@ -1,6 +1,6 @@
import React, { useCallback } from 'react';
import styled, { css } from 'styled-components';
-import { useTranslation, Trans } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
import { Helmet } from 'react-helmet';
import { DndContext, useSensor, useSensors, PointerSensor } from '@dnd-kit/core';
import { SortableContext, arrayMove, verticalListSortingStrategy } from '@dnd-kit/sortable';
@@ -9,7 +9,7 @@ import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import SimpleBar from 'simplebar-react';
import 'simplebar/dist/simplebar.min.css';
-import { Button, Typography, Tooltip, IconButton as IconButtonRaw } from '@material-ui/core';
+import { Typography, Tooltip, IconButton as IconButtonRaw } from '@material-ui/core';
import { Settings as SettingsIcon, Upgrade as UpgradeIcon } from '@material-ui/icons';
import { WindowNames } from '@services/windows/WindowProperties';
@@ -22,14 +22,14 @@ import WorkspaceSelector from './WorkspaceSelector';
import FindInPage from '../../components/FindInPage';
import { latestUpdateUrl } from '@/constants/urls';
-import arrowWhite from '@/images/arrow-white.png';
-import arrowBlack from '@/images/arrow-black.png';
import { SortableWorkspaceSelector } from './SortableWorkspaceSelector';
import { IWorkspace } from '@services/workspaces/interface';
import { useWorkspacesListObservable } from '@services/workspaces/hooks';
import { usePreferenceObservable } from '@services/preferences/hooks';
import { CommandPaletteIcon } from '@/components/icon/CommandPaletteSVG';
import { Languages } from '../Preferences/sections/Languages';
+import { NewUserMessage } from './NewUserMessage';
+import { WikiErrorMessages, ViewLoadErrorMessages } from './ErrorMessage';
const OuterRoot = styled.div`
display: flex;
@@ -116,70 +116,12 @@ const ContentRoot = styled.div`
width: 100%;
`;
-const Arrow = styled.div<{ image: string }>`
- height: 202px;
- width: 150px;
- position: absolute;
- top: 50px;
- left: 72px;
-
- background-image: url(${({ image }) => image});
- background-size: 150px 202px;
-`;
-
-const Avatar = styled.div`
- display: inline-block;
- height: 32px;
- width: 32px;
- /** // TODO: dark theme */
- /* background: theme.palette.type === 'dark' ? theme.palette.common.white : theme.palette.common.black; */
- border-radius: 4;
- /** // TODO: dark theme */
- /* color: theme.palette.getContrastText(theme.palette.type === 'dark' ? theme.palette.common.white: theme.palette.common.black); */
- line-height: 32px;
- text-align: center;
- font-weight: 500;
- text-transform: uppercase;
- margin-left: 10px;
- margin-right: 10px;
- /** // TODO: dark theme */
- /* border: theme.palette.type === 'dark' ? 'none' : 1px solid rgba(0, 0, 0, 0.12); */
-`;
-
-const Tip2Text = styled.span`
- display: inline-block;
- font-size: 18px;
- /** // TODO: dark theme */
- /* color: theme.palette.type === 'dark' ? theme.palette.common.white : theme.palette.common.black; */
-`;
-
-const TipWithSidebar = styled.div`
- position: absolute;
- top: 112px;
- left: 180px;
- user-select: none;
-`;
-
-const TipWithoutSidebar = styled.div`
- user-select: none;
-`;
-
-const AddWorkspaceGuideInfoContainer = styled.div`
- cursor: pointer;
-`;
-
const SideBarEnd = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`;
-const HelperTextsList = styled.ul`
- margin-top: 0;
- margin-bottom: 1.5rem;
- max-width: 70vw;
-`;
-
const SidebarContainer = ({ children }: { children: React.ReactNode }): JSX.Element => {
const platform = usePromiseValue(async () => await window.service.context.get('platform'));
// use native scroll bar on macOS
@@ -194,9 +136,6 @@ export default function Main(): JSX.Element {
const workspacesList = useWorkspacesListObservable();
const preferences = usePreferenceObservable();
const isFullScreen = usePromiseValue(window.service.window.isFullScreen, false)!;
- const requestReload = useCallback(async (): Promise => {
- await window.service.window.reload(window.meta.windowName);
- }, []);
const dndSensors = useSensors(
useSensor(PointerSensor, {
@@ -210,6 +149,7 @@ export default function Main(): JSX.Element {
const activeWorkspaceMetadata = workspacesList
?.map((workspace) => ({ active: workspace.active, ...workspace.metadata }))
?.find((workspace) => workspace.active);
+ const activeWorkspace = workspacesList?.find((workspace) => workspace.active);
const updaterMetaData = useUpdaterObservable();
if (preferences === undefined) return {t('Loading')}
;
@@ -302,86 +242,16 @@ export default function Main(): JSX.Element {
+ {activeWorkspace !== undefined && }
{Array.isArray(workspacesList) &&
workspacesList.length > 0 &&
typeof activeWorkspaceMetadata?.didFailLoadErrorMessage === 'string' &&
activeWorkspaceMetadata?.didFailLoadErrorMessage.length > 0 &&
- activeWorkspaceMetadata?.isLoading === false && (
-
-
- {t('AddWorkspace.WikiNotStarted')}
-
-
- {activeWorkspaceMetadata.didFailLoadErrorMessage}
-
-
-
-
-
- <>
- Try:
-
-
- Click{' '}
-
- Reload
- {' '}
- button below or press CMD_or_Ctrl + R to reload the page.
-
-
- Check the{' '}
- await window.service.native.open(await window.service.context.get('LOG_FOLDER'), true)}
- onKeyPress={async () => await window.service.native.open(await window.service.context.get('LOG_FOLDER'), true)}
- role="button"
- tabIndex={0}
- style={{ cursor: 'pointer' }}>
- Log Folder
- {' '}
- to see what happened.
-
- Backup your file, remove workspace and recreate one.
-
- >
-
-
-
-
-
- )}
+ activeWorkspaceMetadata?.isLoading === false && }
{Array.isArray(workspacesList) && workspacesList.length > 0 && activeWorkspaceMetadata?.isLoading && (
{t('Loading')}
)}
- {Array.isArray(workspacesList) && workspacesList.length === 0 && (
- await window.service.window.open(WindowNames.addWorkspace)}>
- {sidebar ? (
- <>
-
-
-
- Click
- +
- to get started!
-
-
- >
- ) : (
-
-
-
- Click
- Workspaces > Add Workspace
- Or
- Click Here
- to get started!
-
-
-
- )}
-
- )}
+ {Array.isArray(workspacesList) && workspacesList.length === 0 && }
diff --git a/src/services/libs/log/wikiOutput.ts b/src/services/libs/log/wikiOutput.ts
index b2ae2e98..6d435567 100644
--- a/src/services/libs/log/wikiOutput.ts
+++ b/src/services/libs/log/wikiOutput.ts
@@ -3,7 +3,7 @@ import fs from 'fs-extra';
import { LOG_FOLDER } from '@/constants/paths';
-function getWikiLogFilePath(wikiName: string): string {
+export function getWikiLogFilePath(wikiName: string): string {
const logFileName = wikiName.replace(/["*/:<>?\\|]/g, '_');
const logFilePath = path.join(LOG_FOLDER, `${logFileName}.log`);
return logFilePath;
diff --git a/src/services/view/index.ts b/src/services/view/index.ts
index 2480daf0..85c0cbd4 100644
--- a/src/services/view/index.ts
+++ b/src/services/view/index.ts
@@ -304,6 +304,12 @@ export class View implements IViewService {
workspace.name
}`,
);
+ // will set again in view.webContents.on('did-start-loading'), but that one sometimes is too late to block services that wait for `isLoading`
+ await this.workspaceService.updateMetaData(workspace.id, {
+ // eslint-disable-next-line unicorn/no-null
+ didFailLoadErrorMessage: null,
+ isLoading: true,
+ });
await view.webContents.loadURL(hostReplacedUrl);
logger.debug('loadInitialUrlWithCatch() await loadURL() done');
const unregisterContextMenu = await this.menuService.initContextMenuForWindowWebContents(view.webContents);
diff --git a/src/services/view/setupViewEventHandlers.ts b/src/services/view/setupViewEventHandlers.ts
index f0f02a41..b917643b 100644
--- a/src/services/view/setupViewEventHandlers.ts
+++ b/src/services/view/setupViewEventHandlers.ts
@@ -128,6 +128,7 @@ export default function setupViewEventHandlers(
return;
}
await workspaceService.updateMetaData(workspace.id, {
+ isLoading: false,
didFailLoadErrorMessage: `${errorCode} ${errorDesc}`,
});
if (workspaceObject.active && browserWindow !== undefined && !browserWindow.isDestroyed()) {
diff --git a/src/services/wiki/index.ts b/src/services/wiki/index.ts
index 0164ccf6..1eff91a9 100644
--- a/src/services/wiki/index.ts
+++ b/src/services/wiki/index.ts
@@ -19,7 +19,7 @@ import type { IWorkspaceService, IWorkspace } from '@services/workspaces/interfa
import type { IGitService, IGitUserInfos } from '@services/git/interface';
import type { IWorkspaceViewService } from '@services/workspacesView/interface';
import { WindowNames } from '@services/windows/WindowProperties';
-import { logger, wikiOutputToFile, refreshOutputFile } from '@services/libs/log';
+import { logger, wikiOutputToFile, refreshOutputFile, getWikiLogFilePath } from '@services/libs/log';
import i18n from '@services/libs/i18n';
import { lazyInject } from '@services/container';
import { TIDDLYWIKI_TEMPLATE_FOLDER_PATH, TIDDLERS_PATH } from '@/constants/paths';
@@ -636,4 +636,13 @@ export class Wiki implements IWikiService {
}
}
}
+
+ public async getWikiLogs(homePath: string): Promise<{ content: string; filePath: string }> {
+ const filePath = getWikiLogFilePath(homePath);
+ const content = await fs.readFile(filePath, 'utf-8');
+ return {
+ content,
+ filePath,
+ };
+ }
}
diff --git a/src/services/wiki/interface.ts b/src/services/wiki/interface.ts
index d05e3d68..1777231c 100644
--- a/src/services/wiki/interface.ts
+++ b/src/services/wiki/interface.ts
@@ -51,6 +51,7 @@ export interface IWikiService {
createSubWiki(parentFolderLocation: string, folderName: string, mainWikiPath: string, tagName?: string, onlyLink?: boolean): Promise;
ensureWikiExist(wikiPath: string, shouldBeMainWiki: boolean): Promise;
getSubWikiPluginContent(mainWikiPath: string): Promise;
+ getWikiLogs(homePath: string): Promise<{ content: string; filePath: string }>;
linkWiki(mainWikiPath: string, folderName: string, subWikiPath: string): Promise;
/**
* Open image or PDF in OS native viewer or some else usage like this.
@@ -91,6 +92,7 @@ export const WikiServiceIPCDescriptor = {
createSubWiki: ProxyPropertyType.Function,
ensureWikiExist: ProxyPropertyType.Function,
getSubWikiPluginContent: ProxyPropertyType.Function,
+ getWikiLogs: ProxyPropertyType.Function,
linkWiki: ProxyPropertyType.Function,
openTiddlerInExternal: ProxyPropertyType.Function,
removeWiki: ProxyPropertyType.Function,
diff --git a/src/services/wiki/wikiWorker.ts b/src/services/wiki/wikiWorker.ts
index 2b6e4de9..ebc07cfc 100644
--- a/src/services/wiki/wikiWorker.ts
+++ b/src/services/wiki/wikiWorker.ts
@@ -5,7 +5,6 @@ import tiddlywiki, { I$TW } from '@tiddlygit/tiddlywiki';
import { Observable } from 'rxjs';
import intercept from 'intercept-stdout';
import { Server } from 'http';
-import { shell } from 'electron';
import { IWikiMessage, WikiControlActions } from './interface';
import { defaultServerIP } from '@/constants/urls';