mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-03 12:41:45 +02:00
feat: add status bar
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
showAccountDeletedNotice,
|
||||
showPasswordChangedNotice,
|
||||
} from "./components/dialogs/confirm";
|
||||
import StatusBar from "./components/statusbar";
|
||||
|
||||
function App() {
|
||||
const [show, setShow] = useState(true);
|
||||
@@ -104,39 +105,48 @@ function App() {
|
||||
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<Flex id="app" bg="background" height="100%">
|
||||
<NavigationMenu
|
||||
toggleNavigationContainer={(state) => setShow(state || !show)}
|
||||
/>
|
||||
<Flex variant="rowFill">
|
||||
<Animated.Flex
|
||||
className="listMenu"
|
||||
variant="columnFill"
|
||||
initial={{ width: "30%", opacity: 1, x: 0 }}
|
||||
animate={{
|
||||
width: show ? "30%" : "0%",
|
||||
x: show ? 0 : "-30%",
|
||||
opacity: show ? 1 : 0,
|
||||
}}
|
||||
transition={{ duration: 0.2, ease: "easeOut" }}
|
||||
sx={{
|
||||
borderRight: "1px solid",
|
||||
borderColor: "border",
|
||||
borderRightWidth: show ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
{isMobile && <Banner />}
|
||||
{routeResult}
|
||||
</Animated.Flex>
|
||||
<Flex
|
||||
width={[show ? 0 : "100%", show ? 0 : "100%", "100%"]}
|
||||
flexDirection="column"
|
||||
>
|
||||
<Editor />
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
id="app"
|
||||
bg="background"
|
||||
height="100%"
|
||||
sx={{ overflow: "hidden" }}
|
||||
>
|
||||
<Flex flex={1} sx={{ overflow: "hidden" }}>
|
||||
<NavigationMenu
|
||||
toggleNavigationContainer={(state) => setShow(state || !show)}
|
||||
/>
|
||||
<Flex variant="rowFill">
|
||||
<Animated.Flex
|
||||
className="listMenu"
|
||||
variant="columnFill"
|
||||
initial={{ width: "30%", opacity: 1, x: 0 }}
|
||||
animate={{
|
||||
width: show ? "30%" : "0%",
|
||||
x: show ? 0 : "-30%",
|
||||
opacity: show ? 1 : 0,
|
||||
}}
|
||||
transition={{ duration: 0.2, ease: "easeOut" }}
|
||||
sx={{
|
||||
borderRight: "1px solid",
|
||||
borderColor: "border",
|
||||
borderRightWidth: show ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
{isMobile && <Banner />}
|
||||
{routeResult}
|
||||
</Animated.Flex>
|
||||
<Flex
|
||||
width={[show ? 0 : "100%", show ? 0 : "100%", "100%"]}
|
||||
flexDirection="column"
|
||||
>
|
||||
<Editor />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Box id="dialogContainer" />
|
||||
<GlobalMenuWrapper />
|
||||
</Flex>
|
||||
<Box id="dialogContainer" />
|
||||
<GlobalMenuWrapper />
|
||||
<StatusBar />
|
||||
</Flex>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
@@ -3,24 +3,25 @@ import { Flex, Text } from "rebass";
|
||||
import { useStore } from "../../stores/editor-store";
|
||||
import { timeConverter } from "../../utils/time";
|
||||
|
||||
function Footer() {
|
||||
function EditorFooter() {
|
||||
const dateEdited = useStore((store) => store.session.dateEdited);
|
||||
const id = useStore((store) => store.session.id);
|
||||
const totalWords = useStore((store) => store.session.totalWords);
|
||||
const isSaving = useStore((store) => store.session.isSaving);
|
||||
if (!id) return null;
|
||||
return (
|
||||
<Flex m={2} justifyContent="flex-end" alignItems="center">
|
||||
<Text fontSize={"subBody"} color="fontTertiary">
|
||||
{id ? totalWords + " words" : "-"}
|
||||
<Flex alignItems="center">
|
||||
<Text variant="subBody">
|
||||
{totalWords + " words"}
|
||||
<TextSeperator />
|
||||
{timeConverter(dateEdited) || "-"}
|
||||
{timeConverter(dateEdited)}
|
||||
<TextSeperator />
|
||||
{id ? (isSaving ? "Saving" : "Saved") : "-"}
|
||||
{isSaving ? "Saving" : "Saved"}
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
export default Footer;
|
||||
export default EditorFooter;
|
||||
|
||||
const TextSeperator = () => {
|
||||
return (
|
||||
|
||||
@@ -19,7 +19,6 @@ import useMobile from "../../utils/use-mobile";
|
||||
import useTablet from "../../utils/use-tablet";
|
||||
import { SUBSCRIPTION_STATUS } from "../../common";
|
||||
import Toolbar from "./toolbar";
|
||||
import Footer from "./footer";
|
||||
import ObservableArray from "../../utils/observablearray";
|
||||
import Banner from "../banner";
|
||||
import EditorLoading from "./loading";
|
||||
@@ -170,7 +169,6 @@ function Editor() {
|
||||
)}
|
||||
</Animated.Flex>
|
||||
</Flex>
|
||||
<Footer />
|
||||
<Properties />
|
||||
</Flex>
|
||||
);
|
||||
|
||||
76
apps/web/src/components/status-bar/index.js
Normal file
76
apps/web/src/components/status-bar/index.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import React from "react";
|
||||
import { Button, Flex, Text } from "rebass";
|
||||
import EditorFooter from "../editor/footer";
|
||||
import * as Icon from "../icons";
|
||||
import { useStore as useUserStore } from "../../stores/user-store";
|
||||
import { showLogInDialog } from "../dialogs/logindialog";
|
||||
import TimeAgo from "timeago-react";
|
||||
import { navigate } from "raviger";
|
||||
|
||||
function StatusBar() {
|
||||
const user = useUserStore((state) => state.user);
|
||||
const sync = useUserStore((state) => state.sync);
|
||||
const lastSynced = useUserStore((state) => state.lastSynced);
|
||||
const isLoggedIn = useUserStore((state) => state.isLoggedIn);
|
||||
const isSyncing = useUserStore((state) => state.isSyncing);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
bg="bgSecondary"
|
||||
sx={{ borderTop: "1px solid", borderTopColor: "border" }}
|
||||
justifyContent="space-between"
|
||||
px={2}
|
||||
>
|
||||
{isLoggedIn ? (
|
||||
<Flex>
|
||||
<Button
|
||||
onClick={() => navigate("/settings")}
|
||||
variant="statusitem"
|
||||
display="flex"
|
||||
sx={{ alignItems: "center", justifyContent: "center" }}
|
||||
>
|
||||
<Icon.Circle
|
||||
size={7}
|
||||
color={user.isEmailConfirmed ? "success" : "warn"}
|
||||
/>
|
||||
<Text variant="subBody" ml={1}>
|
||||
{user.email}
|
||||
{user.isEmailConfirmed ? "" : " (not verified)"}
|
||||
</Text>
|
||||
</Button>
|
||||
<Button
|
||||
variant="statusitem"
|
||||
display="flex"
|
||||
onClick={sync}
|
||||
sx={{ alignItems: "center", justifyContent: "center" }}
|
||||
>
|
||||
<Icon.Sync size={10} rotate={isSyncing} />
|
||||
<Text variant="subBody" ml={1}>
|
||||
{"Synced "}
|
||||
{lastSynced ? (
|
||||
<TimeAgo live={true} datetime={lastSynced} />
|
||||
) : (
|
||||
"never"
|
||||
)}
|
||||
</Text>
|
||||
</Button>
|
||||
</Flex>
|
||||
) : (
|
||||
<Button
|
||||
variant="statusitem"
|
||||
display="flex"
|
||||
onClick={showLogInDialog}
|
||||
sx={{ alignItems: "center", justifyContent: "center" }}
|
||||
>
|
||||
<Icon.Circle size={7} color="error" />
|
||||
<Text variant="subBody" ml={1}>
|
||||
Not logged in
|
||||
</Text>
|
||||
</Button>
|
||||
)}
|
||||
<EditorFooter />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default StatusBar;
|
||||
@@ -15,6 +15,7 @@ class UserStore extends BaseStore {
|
||||
isSigningIn = false;
|
||||
isSyncing = false;
|
||||
user = undefined;
|
||||
lastSynced = 0;
|
||||
|
||||
init = () => {
|
||||
return db.user.getUser().then(async (user) => {
|
||||
@@ -97,8 +98,10 @@ class UserStore extends BaseStore {
|
||||
this.set((state) => (state.isSyncing = true));
|
||||
return db
|
||||
.sync(full)
|
||||
.then(() => {
|
||||
return appStore.refresh();
|
||||
.then(async () => {
|
||||
const lastSynced = await db.lastSynced();
|
||||
this.set((state) => (state.lastSynced = lastSynced));
|
||||
return await appStore.refresh();
|
||||
})
|
||||
.catch(async (err) => {
|
||||
if (err.code === "MERGE_CONFLICT") await appStore.refresh();
|
||||
|
||||
@@ -11,6 +11,7 @@ class StaticColorSchemeFactory {
|
||||
error: "#E53935",
|
||||
errorBg: "#E5393520",
|
||||
success: "#4F8A10",
|
||||
warn: "#FF5722",
|
||||
favorite: "#ffd700",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ class ButtonFactory {
|
||||
anchor: new Anchor(),
|
||||
tool: new Tool(),
|
||||
icon: new Icon(),
|
||||
statusitem: new StatusItem(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -123,3 +124,14 @@ class Tool {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class StatusItem {
|
||||
constructor() {
|
||||
return {
|
||||
variant: "buttons.icon",
|
||||
p: 0,
|
||||
py: 1,
|
||||
px: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user