mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-15 15:10:31 -08:00
refactor: move WikiBackground and Sidebar outof Main
This commit is contained in:
parent
89cdebdbc8
commit
c1b83b0531
8 changed files with 232 additions and 197 deletions
1
src/constants/style.ts
Normal file
1
src/constants/style.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export const sidebarWidth = 68;
|
||||
163
src/pages/Main/Sidebar.tsx
Normal file
163
src/pages/Main/Sidebar.tsx
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
||||
import { Settings as SettingsIcon, Upgrade as UpgradeIcon } from '@material-ui/icons';
|
||||
import { t } from 'i18next';
|
||||
import SimpleBar from 'simplebar-react';
|
||||
import styled, { css } from 'styled-components';
|
||||
|
||||
import { CommandPaletteIcon } from '@/components/icon/CommandPaletteSVG';
|
||||
import { SortableWorkspaceSelectorList, WorkspaceSelector } from '@/components/WorkspaceIconAndSelector';
|
||||
import { sidebarWidth } from '@/constants/style';
|
||||
import { latestStableUpdateUrl } from '@/constants/urls';
|
||||
import { usePromiseValue } from '@/helpers/useServiceValue';
|
||||
import { IconButton as IconButtonRaw, Tooltip } from '@material-ui/core';
|
||||
import { usePreferenceObservable } from '@services/preferences/hooks';
|
||||
import { useUpdaterObservable } from '@services/updater/hooks';
|
||||
import { IUpdaterStatus } from '@services/updater/interface';
|
||||
import { WindowNames } from '@services/windows/WindowProperties';
|
||||
import { useWorkspacesListObservable } from '@services/workspaces/hooks';
|
||||
|
||||
const SideBarEnd = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const sideBarStyle = css`
|
||||
height: 100%;
|
||||
width: ${sidebarWidth}px;
|
||||
min-width: ${sidebarWidth}px;
|
||||
background-color: ${({ theme }) => theme.palette.background.default};
|
||||
-webkit-app-region: drag;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
`;
|
||||
const SidebarRoot = styled.div`
|
||||
${sideBarStyle}
|
||||
`;
|
||||
const SidebarWithStyle = styled(SimpleBar)`
|
||||
${sideBarStyle}
|
||||
`;
|
||||
|
||||
const SidebarTop = styled.div<{ titleBar?: boolean }>`
|
||||
overflow-y: scroll;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
${({ titleBar }) =>
|
||||
titleBar === true
|
||||
? css`
|
||||
padding-top: 0;
|
||||
`
|
||||
: css`
|
||||
padding-top: 30px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const IconButton = styled(IconButtonRaw)`
|
||||
aspect-ratio: 1;
|
||||
overflow: hidden;
|
||||
width: 80%;
|
||||
color: ${({ theme }) => theme.palette.action.active};
|
||||
`;
|
||||
|
||||
const SidebarContainer = ({ children }: { children: React.ReactNode }): JSX.Element => {
|
||||
const platform = usePromiseValue(async () => await window.service.context.get('platform'));
|
||||
// use native scroll bar on macOS
|
||||
if (platform === 'darwin') {
|
||||
return <SidebarRoot>{children}</SidebarRoot>;
|
||||
}
|
||||
return <SidebarWithStyle>{children}</SidebarWithStyle>;
|
||||
};
|
||||
|
||||
export function SideBar(): JSX.Element {
|
||||
/** 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>(async () => await window.service.preference.get('titleBar'), false)!;
|
||||
|
||||
const workspacesList = useWorkspacesListObservable();
|
||||
const activeWorkspace = workspacesList?.find((workspace) => workspace.active);
|
||||
const preferences = usePreferenceObservable();
|
||||
const updaterMetaData = useUpdaterObservable();
|
||||
if (preferences === undefined) return <div>{t('Loading')}</div>;
|
||||
|
||||
const { sidebarShortcutHints, hideSideBarIcon } = preferences;
|
||||
|
||||
return (
|
||||
<SidebarContainer>
|
||||
<SidebarTop titleBar={titleBar}>
|
||||
{workspacesList === undefined
|
||||
? <div>{t('Loading')}</div>
|
||||
: <SortableWorkspaceSelectorList sidebarShortcutHints={sidebarShortcutHints} workspacesList={workspacesList} hideSideBarIcon={hideSideBarIcon} />}
|
||||
<WorkspaceSelector
|
||||
id='add'
|
||||
hideSideBarIcon={hideSideBarIcon}
|
||||
index={workspacesList?.length ?? 0}
|
||||
showSidebarShortcutHints={sidebarShortcutHints}
|
||||
onClick={() => void window.service.window.open(WindowNames.addWorkspace)}
|
||||
/>
|
||||
{workspacesList === undefined ||
|
||||
(workspacesList.length === 0 && (
|
||||
<WorkspaceSelector
|
||||
id='guide'
|
||||
hideSideBarIcon={hideSideBarIcon}
|
||||
index={workspacesList?.length ? workspacesList.length ?? 0 + 1 : 1}
|
||||
active={activeWorkspace?.id === undefined}
|
||||
showSidebarShortcutHints={sidebarShortcutHints}
|
||||
onClick={() => void window.service.workspace.clearActiveWorkspace(activeWorkspace?.id)}
|
||||
/>
|
||||
))}
|
||||
</SidebarTop>
|
||||
<SideBarEnd>
|
||||
{(workspacesList?.length ?? 0) > 0 && (
|
||||
<>
|
||||
<IconButton
|
||||
id='open-command-palette-button'
|
||||
aria-label={t('SideBar.CommandPalette')}
|
||||
onClick={async () => {
|
||||
await window.service.wiki.requestWikiSendActionMessage('open-command-palette');
|
||||
}}
|
||||
>
|
||||
<Tooltip title={<span>{t('SideBar.CommandPalette')}</span>} placement='top'>
|
||||
<CommandPaletteIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
{updaterMetaData?.status === IUpdaterStatus.updateAvailable && (
|
||||
<IconButton
|
||||
id='update-available'
|
||||
aria-label={t('SideBar.UpdateAvailable')}
|
||||
onClick={async () => {
|
||||
await window.service.native.open(updaterMetaData.info?.latestReleasePageUrl ?? latestStableUpdateUrl);
|
||||
}}
|
||||
>
|
||||
<Tooltip title={<span>{t('SideBar.UpdateAvailable')}</span>} placement='top'>
|
||||
<UpgradeIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
)}
|
||||
<IconButton
|
||||
id='open-preferences-button'
|
||||
aria-label={t('SideBar.Preferences')}
|
||||
onClick={async () => {
|
||||
await window.service.window.open(WindowNames.preferences);
|
||||
}}
|
||||
>
|
||||
<Tooltip title={<span>{t('SideBar.Preferences')}</span>} placement='top'>
|
||||
<SettingsIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
</SideBarEnd>
|
||||
</SidebarContainer>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,35 +1,16 @@
|
|||
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
||||
/* eslint-disable @typescript-eslint/promise-function-async */
|
||||
import React, { useState } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styled, { css } from 'styled-components';
|
||||
import styled from 'styled-components';
|
||||
import is, { isNot } from 'typescript-styled-is';
|
||||
|
||||
import SimpleBar from 'simplebar-react';
|
||||
import 'simplebar/dist/simplebar.min.css';
|
||||
|
||||
import { IconButton as IconButtonRaw, Tooltip, Typography } from '@material-ui/core';
|
||||
import { Settings as SettingsIcon, Upgrade as UpgradeIcon } from '@material-ui/icons';
|
||||
|
||||
import { IUpdaterStatus } from '@services/updater/interface';
|
||||
import { WindowNames } from '@services/windows/WindowProperties';
|
||||
|
||||
import { usePromiseValue } from '@/helpers/useServiceValue';
|
||||
import { useUpdaterObservable } from '@services/updater/hooks';
|
||||
|
||||
import { latestStableUpdateUrl } from '@/constants/urls';
|
||||
import FindInPage from '../../components/FindInPage';
|
||||
|
||||
import { CommandPaletteIcon } from '@/components/icon/CommandPaletteSVG';
|
||||
import { SortableWorkspaceSelectorList, WorkspaceSelector } from '@/components/WorkspaceIconAndSelector';
|
||||
import { sidebarWidth } from '@/constants/style';
|
||||
import { usePreferenceObservable } from '@services/preferences/hooks';
|
||||
import { useWorkspacesListObservable } from '@services/workspaces/hooks';
|
||||
import { Languages } from '../Preferences/sections/Languages';
|
||||
import { TiddlyWiki } from '../Preferences/sections/TiddlyWiki';
|
||||
import { ViewLoadErrorMessages, WikiErrorMessages } from './ErrorMessage';
|
||||
import { NewUserMessage } from './NewUserMessage';
|
||||
import { useAutoCreateFirstWorkspace } from './useAutoCreateFirstWorkspace';
|
||||
import FindInPage from '../../components/FindInPage';
|
||||
import { WikiBackground } from '../WikiBackground';
|
||||
import { SideBar } from './Sidebar';
|
||||
|
||||
const OuterRoot = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -57,67 +38,6 @@ const Root = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
const sidebarWidth = 68;
|
||||
const sideBarStyle = css`
|
||||
height: 100%;
|
||||
width: ${sidebarWidth}px;
|
||||
min-width: ${sidebarWidth}px;
|
||||
background-color: ${({ theme }) => theme.palette.background.default};
|
||||
-webkit-app-region: drag;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
`;
|
||||
const SidebarRoot = styled.div`
|
||||
${sideBarStyle}
|
||||
`;
|
||||
const SidebarWithStyle = styled(SimpleBar)`
|
||||
${sideBarStyle}
|
||||
`;
|
||||
|
||||
const SidebarTop = styled.div<{ titleBar?: boolean }>`
|
||||
overflow-y: scroll;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
${({ titleBar }) =>
|
||||
titleBar === true
|
||||
? css`
|
||||
padding-top: 0;
|
||||
`
|
||||
: css`
|
||||
padding-top: 30px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const IconButton = styled(IconButtonRaw)`
|
||||
aspect-ratio: 1;
|
||||
overflow: hidden;
|
||||
width: 80%;
|
||||
color: ${({ theme }) => theme.palette.action.active};
|
||||
`;
|
||||
|
||||
const InnerContentRoot = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const ContentRoot = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
|
@ -135,41 +55,12 @@ const ContentRoot = styled.div`
|
|||
height: 100%;
|
||||
`;
|
||||
|
||||
const SideBarEnd = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const SidebarContainer = ({ children }: { children: React.ReactNode }): JSX.Element => {
|
||||
const platform = usePromiseValue(async () => await window.service.context.get('platform'));
|
||||
// use native scroll bar on macOS
|
||||
if (platform === 'darwin') {
|
||||
return <SidebarRoot>{children}</SidebarRoot>;
|
||||
}
|
||||
return <SidebarWithStyle>{children}</SidebarWithStyle>;
|
||||
};
|
||||
|
||||
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)!;
|
||||
|
||||
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 <div>{t('Loading')}</div>;
|
||||
const { sidebar } = preferences;
|
||||
|
||||
const { sidebar, themeSource, sidebarShortcutHints, hideSideBarIcon } = preferences;
|
||||
const hasError = typeof activeWorkspaceMetadata?.didFailLoadErrorMessage === 'string' &&
|
||||
activeWorkspaceMetadata?.didFailLoadErrorMessage.length > 0 &&
|
||||
activeWorkspaceMetadata?.isLoading === false;
|
||||
return (
|
||||
<OuterRoot>
|
||||
<div id='test' data-usage='For spectron automating testing' />
|
||||
|
|
@ -177,89 +68,10 @@ export default function Main(): JSX.Element {
|
|||
<title>{t('Menu.TidGi')}</title>
|
||||
</Helmet>
|
||||
<Root>
|
||||
{sidebar && (
|
||||
<SidebarContainer>
|
||||
<SidebarTop titleBar={titleBar}>
|
||||
{workspacesList === undefined
|
||||
? <div>{t('Loading')}</div>
|
||||
: <SortableWorkspaceSelectorList sidebarShortcutHints={sidebarShortcutHints} workspacesList={workspacesList} hideSideBarIcon={hideSideBarIcon} />}
|
||||
<WorkspaceSelector
|
||||
id='add'
|
||||
hideSideBarIcon={hideSideBarIcon}
|
||||
index={workspacesList?.length ?? 0}
|
||||
showSidebarShortcutHints={sidebarShortcutHints}
|
||||
onClick={() => void window.service.window.open(WindowNames.addWorkspace)}
|
||||
/>
|
||||
{workspacesList === undefined ||
|
||||
(workspacesList.length === 0 && (
|
||||
<WorkspaceSelector
|
||||
id='guide'
|
||||
hideSideBarIcon={hideSideBarIcon}
|
||||
index={workspacesList?.length ? workspacesList.length ?? 0 + 1 : 1}
|
||||
active={activeWorkspace?.id === undefined}
|
||||
showSidebarShortcutHints={sidebarShortcutHints}
|
||||
onClick={() => void window.service.workspace.clearActiveWorkspace(activeWorkspace?.id)}
|
||||
/>
|
||||
))}
|
||||
</SidebarTop>
|
||||
<SideBarEnd>
|
||||
{(workspacesList?.length ?? 0) > 0 && (
|
||||
<>
|
||||
<IconButton
|
||||
id='open-command-palette-button'
|
||||
aria-label={t('SideBar.CommandPalette')}
|
||||
onClick={async () => {
|
||||
await window.service.wiki.requestWikiSendActionMessage('open-command-palette');
|
||||
}}
|
||||
>
|
||||
<Tooltip title={<span>{t('SideBar.CommandPalette')}</span>} placement='top'>
|
||||
<CommandPaletteIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
{updaterMetaData?.status === IUpdaterStatus.updateAvailable && (
|
||||
<IconButton
|
||||
id='update-available'
|
||||
aria-label={t('SideBar.UpdateAvailable')}
|
||||
onClick={async () => {
|
||||
await window.service.native.open(updaterMetaData.info?.latestReleasePageUrl ?? latestStableUpdateUrl);
|
||||
}}
|
||||
>
|
||||
<Tooltip title={<span>{t('SideBar.UpdateAvailable')}</span>} placement='top'>
|
||||
<UpgradeIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
)}
|
||||
<IconButton
|
||||
id='open-preferences-button'
|
||||
aria-label={t('SideBar.Preferences')}
|
||||
onClick={async () => {
|
||||
await window.service.window.open(WindowNames.preferences);
|
||||
}}
|
||||
>
|
||||
<Tooltip title={<span>{t('SideBar.Preferences')}</span>} placement='top'>
|
||||
<SettingsIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
</SideBarEnd>
|
||||
</SidebarContainer>
|
||||
)}
|
||||
{sidebar && <SideBar />}
|
||||
<ContentRoot sidebar={sidebar}>
|
||||
<FindInPage />
|
||||
<InnerContentRoot>
|
||||
{activeWorkspace !== undefined && hasError && <WikiErrorMessages activeWorkspace={activeWorkspace} />}
|
||||
{Array.isArray(workspacesList) && activeWorkspace !== undefined && workspacesList.length > 0 && hasError && (
|
||||
<ViewLoadErrorMessages activeWorkspace={activeWorkspace} activeWorkspaceMetadata={activeWorkspaceMetadata} />
|
||||
)}
|
||||
{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 />
|
||||
<TiddlyWiki />
|
||||
<WikiBackground />
|
||||
</ContentRoot>
|
||||
</Root>
|
||||
</OuterRoot>
|
||||
|
|
|
|||
59
src/pages/WikiBackground/index.tsx
Normal file
59
src/pages/WikiBackground/index.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
||||
/* eslint-disable @typescript-eslint/promise-function-async */
|
||||
import { Typography } from '@material-ui/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { usePreferenceObservable } from '@services/preferences/hooks';
|
||||
import { useWorkspacesListObservable } from '@services/workspaces/hooks';
|
||||
import { useState } from 'react';
|
||||
import { useAutoCreateFirstWorkspace } from '../Main/useAutoCreateFirstWorkspace';
|
||||
import { Languages } from '../Preferences/sections/Languages';
|
||||
import { TiddlyWiki } from '../Preferences/sections/TiddlyWiki';
|
||||
import { ViewLoadErrorMessages, WikiErrorMessages } from './ErrorMessage';
|
||||
import { NewUserMessage } from './NewUserMessage';
|
||||
|
||||
const InnerContentRoot = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export function WikiBackground(): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const workspacesList = useWorkspacesListObservable();
|
||||
|
||||
const activeWorkspaceMetadata = workspacesList
|
||||
?.map((workspace) => ({ active: workspace.active, ...workspace.metadata }))
|
||||
?.find((workspace) => workspace.active);
|
||||
const activeWorkspace = workspacesList?.find((workspace) => workspace.active);
|
||||
const hasError = typeof activeWorkspaceMetadata?.didFailLoadErrorMessage === 'string' &&
|
||||
activeWorkspaceMetadata?.didFailLoadErrorMessage.length > 0 &&
|
||||
activeWorkspaceMetadata?.isLoading === false;
|
||||
const [wikiCreationMessage, wikiCreationMessageSetter] = useState('');
|
||||
useAutoCreateFirstWorkspace(workspacesList, wikiCreationMessageSetter);
|
||||
const preferences = usePreferenceObservable();
|
||||
if (preferences === undefined) return <div>{t('Loading')}</div>;
|
||||
|
||||
const { sidebar, themeSource } = preferences;
|
||||
return (
|
||||
<>
|
||||
<InnerContentRoot>
|
||||
{activeWorkspace !== undefined && hasError && <WikiErrorMessages activeWorkspace={activeWorkspace} />}
|
||||
{Array.isArray(workspacesList) && activeWorkspace !== undefined && workspacesList.length > 0 && hasError && (
|
||||
<ViewLoadErrorMessages activeWorkspace={activeWorkspace} activeWorkspaceMetadata={activeWorkspaceMetadata} />
|
||||
)}
|
||||
{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 />
|
||||
<TiddlyWiki />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { WindowNames } from '@services/windows/WindowProperties';
|
||||
import React from 'react';
|
||||
|
||||
import AboutPage from './About';
|
||||
import { AddWorkspace as DialogAddWorkspace } from './AddWorkspace';
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import DateFnsUtils from '@material-ui/lab/AdapterDateFns';
|
|||
import LocalizationProvider from '@material-ui/lab/LocalizationProvider';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import 'typeface-roboto/index.css';
|
||||
import 'simplebar/dist/simplebar.min.css';
|
||||
|
||||
import { darkTheme, lightTheme } from '@services/theme/defaultTheme';
|
||||
import { useThemeObservable } from '@services/theme/hooks';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue