mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
desktop: fix custom title bar on linux
This commit is contained in:
@@ -84,6 +84,7 @@ async function createWindow() {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
titleBarStyle: "hidden",
|
titleBarStyle: "hidden",
|
||||||
|
frame: process.platform === "win32" || process.platform === "darwin",
|
||||||
titleBarOverlay: {
|
titleBarOverlay: {
|
||||||
height: 37,
|
height: 37,
|
||||||
color: "#00000000",
|
color: "#00000000",
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabsScroll,
|
.tabsScroll,
|
||||||
.titlebarLogo {
|
.titlebarLogo,
|
||||||
|
.theme-scope-titleBar {
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-scope-titleBar button,
|
||||||
.tabsScroll .tab {
|
.tabsScroll .tab {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import { FlexScrollContainer } from "./components/scroll-container";
|
|||||||
import CachedRouter from "./components/cached-router";
|
import CachedRouter from "./components/cached-router";
|
||||||
import { WebExtensionRelay } from "./utils/web-extension-relay";
|
import { WebExtensionRelay } from "./utils/web-extension-relay";
|
||||||
import { usePersistentState } from "./hooks/use-persistent-state";
|
import { usePersistentState } from "./hooks/use-persistent-state";
|
||||||
import { EditorActionBar } from "./components/editor/action-bar";
|
|
||||||
|
|
||||||
new WebExtensionRelay();
|
new WebExtensionRelay();
|
||||||
|
|
||||||
@@ -136,7 +135,6 @@ function DesktopAppContents({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{IS_DESKTOP_APP ? <EditorActionBar /> : null}
|
|
||||||
<Flex
|
<Flex
|
||||||
variant="rowFill"
|
variant="rowFill"
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@@ -35,11 +35,7 @@ import {
|
|||||||
Search,
|
Search,
|
||||||
TableOfContents,
|
TableOfContents,
|
||||||
Trash,
|
Trash,
|
||||||
Unlock,
|
Unlock
|
||||||
WindowClose,
|
|
||||||
WindowMaximize,
|
|
||||||
WindowMinimize,
|
|
||||||
WindowRestore
|
|
||||||
} from "../icons";
|
} from "../icons";
|
||||||
import { ScrollContainer } from "@notesnook/ui";
|
import { ScrollContainer } from "@notesnook/ui";
|
||||||
import {
|
import {
|
||||||
@@ -68,16 +64,12 @@ import {
|
|||||||
} from "@dnd-kit/sortable";
|
} from "@dnd-kit/sortable";
|
||||||
import { CSS } from "@dnd-kit/utilities";
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
import { AppEventManager, AppEvents } from "../../common/app-events";
|
import { AppEventManager, AppEvents } from "../../common/app-events";
|
||||||
import { desktop } from "../../common/desktop-bridge";
|
|
||||||
import { useWindowControls } from "../../hooks/use-window-controls";
|
import { useWindowControls } from "../../hooks/use-window-controls";
|
||||||
import { ScopedThemeProvider } from "../theme-provider";
|
|
||||||
import { getPlatform } from "../../utils/platform";
|
|
||||||
|
|
||||||
export function EditorActionBar() {
|
export function EditorActionBar() {
|
||||||
const editorMargins = useEditorStore((store) => store.editorMargins);
|
const editorMargins = useEditorStore((store) => store.editorMargins);
|
||||||
const isFocusMode = useAppStore((store) => store.isFocusMode);
|
const isFocusMode = useAppStore((store) => store.isFocusMode);
|
||||||
const { isMaximized, isFullscreen, hasNativeWindowControls } =
|
const { isFullscreen } = useWindowControls();
|
||||||
useWindowControls();
|
|
||||||
const activeSession = useEditorStore((store) =>
|
const activeSession = useEditorStore((store) =>
|
||||||
store.activeSessionId ? store.getSession(store.activeSessionId) : undefined
|
store.activeSessionId ? store.getSession(store.activeSessionId) : undefined
|
||||||
);
|
);
|
||||||
@@ -153,100 +145,42 @@ export function EditorActionBar() {
|
|||||||
activeSession.type !== "conflicted" &&
|
activeSession.type !== "conflicted" &&
|
||||||
!isFocusMode,
|
!isFocusMode,
|
||||||
onClick: () => useEditorStore.getState().toggleProperties()
|
onClick: () => useEditorStore.getState().toggleProperties()
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
title: "Minimize",
|
|
||||||
icon: WindowMinimize,
|
|
||||||
hidden: hasNativeWindowControls || isFullscreen,
|
|
||||||
enabled: true,
|
|
||||||
onClick: () => desktop?.window.minimze.mutate()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: isMaximized ? "Restore" : "Maximize",
|
|
||||||
icon: isMaximized ? WindowRestore : WindowMaximize,
|
|
||||||
enabled: true,
|
|
||||||
hidden: hasNativeWindowControls || isFullscreen,
|
|
||||||
onClick: () =>
|
|
||||||
isMaximized
|
|
||||||
? desktop?.window.restore.mutate()
|
|
||||||
: desktop?.window.maximize.mutate()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Close",
|
|
||||||
icon: WindowClose,
|
|
||||||
hidden: hasNativeWindowControls || isFullscreen,
|
|
||||||
enabled: true,
|
|
||||||
onClick: () => window.close()
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScopedThemeProvider scope="titleBar" injectCssVars>
|
<>
|
||||||
<Flex
|
<TabStrip />
|
||||||
sx={{
|
{tools.map((tool) => (
|
||||||
gap: 2,
|
<Button
|
||||||
borderBottom: IS_DESKTOP_APP ? "1px solid var(--border)" : "none",
|
data-test-id={tool.title}
|
||||||
px: 1,
|
disabled={!tool.enabled}
|
||||||
...(IS_DESKTOP_APP && !isFullscreen && hasNativeWindowControls
|
variant={tool.title === "Close" ? "error" : "secondary"}
|
||||||
? getPlatform() === "darwin"
|
title={tool.title}
|
||||||
? { pl: "calc(100vw - env(titlebar-area-width))" }
|
key={tool.title}
|
||||||
: { pr: "calc(100vw - env(titlebar-area-width))" }
|
|
||||||
: {})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{IS_DESKTOP_APP && (getPlatform() !== "darwin" || isFullscreen) ? (
|
|
||||||
<svg
|
|
||||||
className="titlebarLogo"
|
|
||||||
style={{
|
|
||||||
alignSelf: "center",
|
|
||||||
height: 24,
|
|
||||||
width: 24
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<use href="#themed-logo" />
|
|
||||||
</svg>
|
|
||||||
) : null}
|
|
||||||
<TabStrip />
|
|
||||||
<Flex
|
|
||||||
bg="transparent"
|
|
||||||
sx={{
|
sx={{
|
||||||
|
height: "100%",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "flex-end"
|
bg: "transparent",
|
||||||
|
display: [
|
||||||
|
tool.hideOnMobile ? "none" : "flex",
|
||||||
|
tool.hidden ? "none" : "flex"
|
||||||
|
],
|
||||||
|
borderRadius: 0,
|
||||||
|
flexShrink: 0,
|
||||||
|
"&:hover svg path": {
|
||||||
|
fill:
|
||||||
|
tool.title === "Close"
|
||||||
|
? "var(--accentForeground-error) !important"
|
||||||
|
: "var(--icon)"
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
onClick={tool.onClick}
|
||||||
>
|
>
|
||||||
{tools.map((tool) => (
|
<tool.icon size={18} />
|
||||||
<Button
|
</Button>
|
||||||
data-test-id={tool.title}
|
))}
|
||||||
disabled={!tool.enabled}
|
</>
|
||||||
variant={tool.title === "Close" ? "error" : "secondary"}
|
|
||||||
title={tool.title}
|
|
||||||
key={tool.title}
|
|
||||||
sx={{
|
|
||||||
height: "100%",
|
|
||||||
alignItems: "center",
|
|
||||||
bg: "transparent",
|
|
||||||
display: [
|
|
||||||
tool.hideOnMobile ? "none" : "flex",
|
|
||||||
tool.hidden ? "none" : "flex"
|
|
||||||
],
|
|
||||||
borderRadius: 0,
|
|
||||||
flexShrink: 0,
|
|
||||||
"&:hover svg path": {
|
|
||||||
fill:
|
|
||||||
tool.title === "Close"
|
|
||||||
? "var(--accentForeground-error) !important"
|
|
||||||
: "var(--icon)"
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onClick={tool.onClick}
|
|
||||||
>
|
|
||||||
<tool.icon size={18} />
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</ScopedThemeProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,17 @@ export default function TabsView() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{IS_DESKTOP_APP ? null : <EditorActionBar />}
|
{IS_DESKTOP_APP ? (
|
||||||
|
ReactDOM.createPortal(
|
||||||
|
<EditorActionBar />,
|
||||||
|
document.getElementById("titlebar-portal-container")!
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Flex>
|
||||||
|
<EditorActionBar />
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
|
||||||
<ScopedThemeProvider
|
<ScopedThemeProvider
|
||||||
scope="editor"
|
scope="editor"
|
||||||
ref={dropRef}
|
ref={dropRef}
|
||||||
|
|||||||
@@ -49,98 +49,105 @@ export function ErrorComponent({ error, resetErrorBoundary }: FallbackProps) {
|
|||||||
height: "100%",
|
height: "100%",
|
||||||
bg: "background",
|
bg: "background",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column"
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
overflowY: "auto"
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
sx={{
|
sx={{
|
||||||
width: ["95%", "50%"],
|
width: "100%",
|
||||||
flexDirection: "column"
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
overflowY: "auto",
|
||||||
|
py: 5
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<Flex
|
||||||
src={colorScheme === "dark" ? LogoDark : Logo}
|
sx={{
|
||||||
sx={{ borderRadius: "default", width: 60, alignSelf: "start" }}
|
width: ["95%", "50%"],
|
||||||
mb={4}
|
flexDirection: "column"
|
||||||
/>
|
}}
|
||||||
<Text
|
|
||||||
variant="heading"
|
|
||||||
sx={{ borderBottom: "1px solid var(--border)", pb: 1 }}
|
|
||||||
>
|
>
|
||||||
Something went wrong
|
<Image
|
||||||
</Text>
|
src={colorScheme === "dark" ? LogoDark : Logo}
|
||||||
<ErrorText error={error} />
|
sx={{ borderRadius: "default", width: 60, alignSelf: "start" }}
|
||||||
{help ? (
|
mb={4}
|
||||||
<>
|
/>
|
||||||
<Text variant="subtitle" sx={{ mt: 2 }}>
|
<Text
|
||||||
What went wrong?
|
variant="heading"
|
||||||
</Text>
|
sx={{ borderBottom: "1px solid var(--border)", pb: 1 }}
|
||||||
<Text variant="body">{help.explanation}</Text>
|
>
|
||||||
<Text variant="subtitle" sx={{ mt: 1 }}>
|
Something went wrong
|
||||||
How to fix it?
|
</Text>
|
||||||
</Text>
|
<ErrorText error={error} />
|
||||||
<Text variant="body">{help.action}</Text>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
<Flex sx={{ gap: 1 }}>
|
|
||||||
{help ? (
|
{help ? (
|
||||||
<Button
|
<>
|
||||||
variant="error"
|
<Text variant="subtitle" sx={{ mt: 2 }}>
|
||||||
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
What went wrong?
|
||||||
onClick={() =>
|
</Text>
|
||||||
help.fix().catch((e) => {
|
<Text variant="body">{help.explanation}</Text>
|
||||||
console.error(e);
|
<Text variant="subtitle" sx={{ mt: 1 }}>
|
||||||
alert(errorToString(e));
|
How to fix it?
|
||||||
})
|
</Text>
|
||||||
}
|
<Text variant="body">{help.action}</Text>
|
||||||
>
|
</>
|
||||||
Fix it
|
) : null}
|
||||||
</Button>
|
<Flex sx={{ gap: 1 }}>
|
||||||
) : (
|
{help ? (
|
||||||
<Button
|
<Button
|
||||||
variant="error"
|
variant="error"
|
||||||
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
||||||
onClick={() => window.location.reload()}
|
onClick={() =>
|
||||||
>
|
help.fix().catch((e) => {
|
||||||
Reload app
|
console.error(e);
|
||||||
</Button>
|
alert(errorToString(e));
|
||||||
)}
|
})
|
||||||
<>
|
}
|
||||||
<Button
|
>
|
||||||
variant="secondary"
|
Fix it
|
||||||
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
</Button>
|
||||||
onClick={async () => {
|
) : (
|
||||||
navigator.clipboard.writeText(errorToString(error));
|
<Button
|
||||||
}}
|
variant="error"
|
||||||
>
|
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
||||||
Copy
|
onClick={() => window.location.reload()}
|
||||||
</Button>
|
>
|
||||||
<Button
|
Reload app
|
||||||
variant="secondary"
|
</Button>
|
||||||
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
)}
|
||||||
onClick={async () => {
|
<>
|
||||||
const { getDeviceInfo } = await import(
|
<Button
|
||||||
"../../dialogs/issue-dialog"
|
variant="secondary"
|
||||||
);
|
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
||||||
const mailto = new URL("mailto:support@streetwriters.co");
|
onClick={async () => {
|
||||||
mailto.searchParams.set(
|
navigator.clipboard.writeText(errorToString(error));
|
||||||
"body",
|
}}
|
||||||
`${errorToString(error)}
|
>
|
||||||
|
Copy
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
sx={{ alignSelf: "start", px: 30, mt: 1 }}
|
||||||
|
onClick={async () => {
|
||||||
|
const { getDeviceInfo } = await import(
|
||||||
|
"../../dialogs/issue-dialog"
|
||||||
|
);
|
||||||
|
const mailto = new URL("mailto:support@streetwriters.co");
|
||||||
|
mailto.searchParams.set(
|
||||||
|
"body",
|
||||||
|
`${errorToString(error)}
|
||||||
|
|
||||||
---
|
---
|
||||||
Device information:
|
Device information:
|
||||||
|
|
||||||
${getDeviceInfo()}`
|
${getDeviceInfo()}`
|
||||||
);
|
);
|
||||||
window.open(mailto.toString(), "_blank");
|
window.open(mailto.toString(), "_blank");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Contact support
|
Contact support
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</BaseThemeProvider>
|
</BaseThemeProvider>
|
||||||
|
|||||||
128
apps/web/src/components/title-bar/index.tsx
Normal file
128
apps/web/src/components/title-bar/index.tsx
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Button } from "@theme-ui/components";
|
||||||
|
import { desktop } from "../../common/desktop-bridge";
|
||||||
|
import { useWindowControls } from "../../hooks/use-window-controls";
|
||||||
|
import { getPlatform } from "../../utils/platform";
|
||||||
|
import {
|
||||||
|
WindowClose,
|
||||||
|
WindowMaximize,
|
||||||
|
WindowMinimize,
|
||||||
|
WindowRestore
|
||||||
|
} from "../icons";
|
||||||
|
import { BaseThemeProvider } from "../theme-provider";
|
||||||
|
|
||||||
|
export function TitleBar() {
|
||||||
|
const { isMaximized, isFullscreen, hasNativeWindowControls } =
|
||||||
|
useWindowControls();
|
||||||
|
|
||||||
|
const tools = [
|
||||||
|
{
|
||||||
|
title: "Minimize",
|
||||||
|
icon: WindowMinimize,
|
||||||
|
hidden: hasNativeWindowControls || isFullscreen,
|
||||||
|
enabled: true,
|
||||||
|
onClick: () => desktop?.window.minimze.mutate()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: isMaximized ? "Restore" : "Maximize",
|
||||||
|
icon: isMaximized ? WindowRestore : WindowMaximize,
|
||||||
|
enabled: true,
|
||||||
|
hidden: hasNativeWindowControls || isFullscreen,
|
||||||
|
onClick: () =>
|
||||||
|
isMaximized
|
||||||
|
? desktop?.window.restore.mutate()
|
||||||
|
: desktop?.window.maximize.mutate()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Close",
|
||||||
|
icon: WindowClose,
|
||||||
|
hidden: hasNativeWindowControls || isFullscreen,
|
||||||
|
enabled: true,
|
||||||
|
onClick: () => window.close()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseThemeProvider
|
||||||
|
scope="titleBar"
|
||||||
|
sx={{
|
||||||
|
background: "background",
|
||||||
|
height: 37.8,
|
||||||
|
display: "flex",
|
||||||
|
borderBottom: "1px solid var(--border)",
|
||||||
|
...(!isFullscreen && hasNativeWindowControls
|
||||||
|
? getPlatform() === "darwin"
|
||||||
|
? { pl: "calc(100vw - env(titlebar-area-width))" }
|
||||||
|
: { pr: "calc(100vw - env(titlebar-area-width))" }
|
||||||
|
: { pl: 2, pr: 0 })
|
||||||
|
}}
|
||||||
|
injectCssVars
|
||||||
|
>
|
||||||
|
{getPlatform() !== "darwin" || isFullscreen ? (
|
||||||
|
<svg
|
||||||
|
className="titlebarLogo"
|
||||||
|
style={{
|
||||||
|
alignSelf: "center",
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
marginRight: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<use href="#themed-logo" />
|
||||||
|
</svg>
|
||||||
|
) : null}
|
||||||
|
<div
|
||||||
|
id="titlebar-portal-container"
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
display: "flex",
|
||||||
|
overflow: "hidden"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{tools.map((tool) => (
|
||||||
|
<Button
|
||||||
|
data-test-id={tool.title}
|
||||||
|
disabled={!tool.enabled}
|
||||||
|
variant={tool.title === "Close" ? "error" : "secondary"}
|
||||||
|
title={tool.title}
|
||||||
|
key={tool.title}
|
||||||
|
sx={{
|
||||||
|
height: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
bg: "transparent",
|
||||||
|
display: tool.hidden ? "none" : "flex",
|
||||||
|
borderRadius: 0,
|
||||||
|
flexShrink: 0,
|
||||||
|
"&:hover svg path": {
|
||||||
|
fill:
|
||||||
|
tool.title === "Close"
|
||||||
|
? "var(--accentForeground-error) !important"
|
||||||
|
: "var(--icon)"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClick={tool.onClick}
|
||||||
|
>
|
||||||
|
<tool.icon size={18} />
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</BaseThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -130,6 +130,11 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes fadeUp {
|
@keyframes fadeUp {
|
||||||
0% {
|
0% {
|
||||||
transform: translateY(500px);
|
transform: translateY(500px);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { BaseThemeProvider } from "./components/theme-provider";
|
|||||||
import { register } from "./utils/stream-saver/mitm";
|
import { register } from "./utils/stream-saver/mitm";
|
||||||
import { getServiceWorkerVersion } from "./utils/version";
|
import { getServiceWorkerVersion } from "./utils/version";
|
||||||
import { ErrorBoundary, ErrorComponent } from "./components/error-boundary";
|
import { ErrorBoundary, ErrorComponent } from "./components/error-boundary";
|
||||||
|
import { TitleBar } from "./components/title-bar";
|
||||||
|
|
||||||
renderApp();
|
renderApp();
|
||||||
|
|
||||||
@@ -36,29 +37,38 @@ async function renderApp() {
|
|||||||
try {
|
try {
|
||||||
const { component, props, path } = await init();
|
const { component, props, path } = await init();
|
||||||
|
|
||||||
|
const { useKeyStore } = await import("./interfaces/key-store");
|
||||||
|
await useKeyStore.getState().init();
|
||||||
|
|
||||||
if (serviceWorkerWhitelist.includes(path)) await initializeServiceWorker();
|
if (serviceWorkerWhitelist.includes(path)) await initializeServiceWorker();
|
||||||
|
|
||||||
const { default: Component } = await component();
|
const { default: Component } = await component();
|
||||||
|
|
||||||
const { default: AppLock } = await import("./views/app-lock");
|
const { default: AppLock } = await import("./views/app-lock");
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<ErrorBoundary>
|
<>
|
||||||
<BaseThemeProvider
|
{IS_DESKTOP_APP ? <TitleBar /> : null}
|
||||||
onRender={() => document.getElementById("splash")?.remove()}
|
<ErrorBoundary>
|
||||||
sx={{ height: "100%", bg: "background" }}
|
<BaseThemeProvider
|
||||||
>
|
onRender={() => document.getElementById("splash")?.remove()}
|
||||||
<AppLock>
|
sx={{ bg: "background", flex: 1 }}
|
||||||
<Component route={props?.route || "login:email"} />
|
>
|
||||||
</AppLock>
|
<AppLock>
|
||||||
</BaseThemeProvider>
|
<Component route={props?.route || "login:email"} />
|
||||||
</ErrorBoundary>
|
</AppLock>
|
||||||
|
</BaseThemeProvider>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
root.render(
|
root.render(
|
||||||
<ErrorComponent
|
<>
|
||||||
error={e}
|
{IS_DESKTOP_APP ? <TitleBar /> : null}
|
||||||
resetErrorBoundary={() => window.location.reload()}
|
<ErrorComponent
|
||||||
/>
|
error={e}
|
||||||
|
resetErrorBoundary={() => window.location.reload()}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import { getDocumentTitle, setDocumentTitle } from "../utils/dom";
|
|||||||
import { CredentialWithoutSecret, useKeyStore } from "../interfaces/key-store";
|
import { CredentialWithoutSecret, useKeyStore } from "../interfaces/key-store";
|
||||||
|
|
||||||
export default function AppLock(props: PropsWithChildren<unknown>) {
|
export default function AppLock(props: PropsWithChildren<unknown>) {
|
||||||
const init = usePromise(() => useKeyStore.getState().init());
|
|
||||||
const credentials = useKeyStore((store) => store.activeCredentials());
|
const credentials = useKeyStore((store) => store.activeCredentials());
|
||||||
const isLocked = useKeyStore((store) => store.isLocked);
|
const isLocked = useKeyStore((store) => store.isLocked);
|
||||||
const _lockAfter = useKeyStore((store) => store.secrets.lockAfter);
|
const _lockAfter = useKeyStore((store) => store.secrets.lockAfter);
|
||||||
@@ -120,8 +119,6 @@ export default function AppLock(props: PropsWithChildren<unknown>) {
|
|||||||
}
|
}
|
||||||
}, [lockAfter, credentials]);
|
}, [lockAfter, credentials]);
|
||||||
|
|
||||||
if (init.status !== "fulfilled") return null;
|
|
||||||
|
|
||||||
if (isLocked)
|
if (isLocked)
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
|||||||
Reference in New Issue
Block a user