mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
web: add support for reordering navigation menu items
This commit is contained in:
@@ -20,25 +20,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { EventSourcePolyfill as EventSource } from "event-source-polyfill";
|
||||
import { DatabasePersistence, NNStorage } from "../interfaces/storage";
|
||||
import { logger } from "../utils/logger";
|
||||
import type Database from "@notesnook/core/dist/api";
|
||||
import { showMigrationDialog } from "./dialog-controller";
|
||||
// import { SQLocalKysely } from "sqlocal/kysely";
|
||||
import { WaSqliteWorkerDriver } from "./sqlite/sqlite.kysely";
|
||||
import { SqliteAdapter, SqliteQueryCompiler, SqliteIntrospector } from "kysely";
|
||||
import { database } from "@notesnook/common";
|
||||
// import SQLiteESMFactory from "./sqlite/wa-sqlite-async";
|
||||
// import * as SQLite from "./sqlite/sqlite-api";
|
||||
// import { IDBBatchAtomicVFS } from "./sqlite/IDBBatchAtomicVFS";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
let db: Database = {};
|
||||
const db = database;
|
||||
async function initializeDatabase(persistence: DatabasePersistence) {
|
||||
logger.measure("Database initialization");
|
||||
|
||||
const { database } = await import("@notesnook/common");
|
||||
const { FileStorage } = await import("../interfaces/fs");
|
||||
const { Compressor } = await import("../utils/compressor");
|
||||
db = database;
|
||||
|
||||
// // const ss = wrap<SQLiteWorker>(new Worker());
|
||||
// // await ss.init("test.db", false, uri);
|
||||
|
||||
@@ -17,7 +17,7 @@ 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 { useCallback, useEffect } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { Box, Button, Flex } from "@theme-ui/components";
|
||||
import {
|
||||
Note,
|
||||
@@ -38,7 +38,7 @@ import {
|
||||
Reminders
|
||||
} from "../icons";
|
||||
import { AnimatedFlex } from "../animated";
|
||||
import NavigationItem from "./navigation-item";
|
||||
import NavigationItem, { SortableNavigationItem } from "./navigation-item";
|
||||
import { hardNavigate, hashNavigate, navigate } from "../../navigation";
|
||||
import { db } from "../../common/db";
|
||||
import useMobile from "../../hooks/use-mobile";
|
||||
@@ -49,8 +49,28 @@ import { useStore as useThemeStore } from "../../stores/theme-store";
|
||||
import useLocation from "../../hooks/use-location";
|
||||
import { FlexScrollContainer } from "../scroll-container";
|
||||
import { ScopedThemeProvider } from "../theme-provider";
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
useSensor,
|
||||
useSensors,
|
||||
KeyboardSensor,
|
||||
DragOverlay,
|
||||
MeasuringStrategy,
|
||||
MouseSensor
|
||||
} from "@dnd-kit/core";
|
||||
import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
verticalListSortingStrategy
|
||||
} from "@dnd-kit/sortable";
|
||||
import { isUserPremium } from "../../hooks/use-is-user-premium";
|
||||
import { showToast } from "../../utils/toast";
|
||||
import { usePersistentState } from "../../hooks/use-persistent-state";
|
||||
|
||||
type Route = {
|
||||
id: string;
|
||||
title: string;
|
||||
path: string;
|
||||
icon: Icon;
|
||||
@@ -68,33 +88,38 @@ function shouldSelectNavItem(route: string, pin: { type: string; id: string }) {
|
||||
}
|
||||
|
||||
const routes: Route[] = [
|
||||
{ title: "Notes", path: "/notes", icon: Note },
|
||||
{ id: "notes", title: "Notes", path: "/notes", icon: Note },
|
||||
{
|
||||
id: "notebooks",
|
||||
title: "Notebooks",
|
||||
path: "/notebooks",
|
||||
icon: Notebook
|
||||
},
|
||||
{
|
||||
id: "favorites",
|
||||
title: "Favorites",
|
||||
path: "/favorites",
|
||||
icon: StarOutline
|
||||
},
|
||||
{ title: "Tags", path: "/tags", icon: Tag },
|
||||
{
|
||||
title: "Monographs",
|
||||
path: "/monographs",
|
||||
icon: Monographs
|
||||
},
|
||||
{ id: "tags", title: "Tags", path: "/tags", icon: Tag },
|
||||
{
|
||||
id: "reminders",
|
||||
title: "Reminders",
|
||||
path: "/reminders",
|
||||
icon: Reminders,
|
||||
tag: "Beta"
|
||||
},
|
||||
{ title: "Trash", path: "/trash", icon: Trash }
|
||||
{
|
||||
id: "monographs",
|
||||
title: "Monographs",
|
||||
path: "/monographs",
|
||||
icon: Monographs
|
||||
},
|
||||
{ id: "trash", title: "Trash", path: "/trash", icon: Trash }
|
||||
];
|
||||
|
||||
const settings: Route = {
|
||||
id: "settings",
|
||||
title: "Settings",
|
||||
path: "/settings",
|
||||
icon: Settings
|
||||
@@ -180,97 +205,163 @@ function NavigationMenu(props: NavigationMenuProps) {
|
||||
suppressScrollX={true}
|
||||
>
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
{routes.map((item) => (
|
||||
<NavigationItem
|
||||
isTablet={isTablet}
|
||||
key={item.path}
|
||||
title={item.title}
|
||||
icon={item.icon}
|
||||
tag={item.tag}
|
||||
selected={
|
||||
item.path === "/"
|
||||
? location === item.path
|
||||
: location.startsWith(item.path)
|
||||
}
|
||||
onClick={() => {
|
||||
if (!isMobile && location === item.path)
|
||||
return toggleNavigationContainer();
|
||||
_navigate(item.path);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{colors.map((color, index) => (
|
||||
<NavigationItem
|
||||
animate={!IS_DESKTOP_APP}
|
||||
index={index}
|
||||
isTablet={isTablet}
|
||||
key={color.id}
|
||||
title={color.title}
|
||||
icon={Circle}
|
||||
selected={location === `/colors/${color.id}`}
|
||||
color={color.title.toLowerCase()}
|
||||
onClick={() => {
|
||||
_navigate(`/colors/${color.id}`);
|
||||
}}
|
||||
menuItems={[
|
||||
{
|
||||
type: "button",
|
||||
key: "rename",
|
||||
title: "Rename color",
|
||||
onClick: async () => {
|
||||
await showRenameColorDialog(color.id);
|
||||
}
|
||||
<ReorderableList
|
||||
items={routes}
|
||||
orderKey={`sidebarOrder:builtin`}
|
||||
order={() => db.settings.getSideBarOrder("builtin")}
|
||||
onOrderChanged={(order) =>
|
||||
db.settings.setSideBarOrder("builtin", order)
|
||||
}
|
||||
renderOverlay={({ item }) => (
|
||||
<NavigationItem
|
||||
id={item.id}
|
||||
isTablet={isTablet}
|
||||
title={item.title}
|
||||
icon={item.icon}
|
||||
tag={item.tag}
|
||||
selected={
|
||||
item.path === "/"
|
||||
? location === item.path
|
||||
: location.startsWith(item.path)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
)}
|
||||
renderItem={({ item }) => (
|
||||
<SortableNavigationItem
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
isTablet={isTablet}
|
||||
title={item.title}
|
||||
icon={item.icon}
|
||||
tag={item.tag}
|
||||
selected={
|
||||
item.path === "/"
|
||||
? location === item.path
|
||||
: location.startsWith(item.path)
|
||||
}
|
||||
onClick={() => {
|
||||
if (!isMobile && location === item.path)
|
||||
return toggleNavigationContainer();
|
||||
_navigate(item.path);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<ReorderableList
|
||||
items={colors}
|
||||
orderKey={`sidebarOrder:colors`}
|
||||
order={() => db.settings.getSideBarOrder("colors")}
|
||||
onOrderChanged={(order) =>
|
||||
db.settings.setSideBarOrder("colors", order)
|
||||
}
|
||||
renderOverlay={({ item }) => (
|
||||
<NavigationItem
|
||||
id={item.id}
|
||||
isTablet={isTablet}
|
||||
title={item.title}
|
||||
icon={Circle}
|
||||
color={item.colorCode}
|
||||
selected={location === `/colors/${item.id}`}
|
||||
/>
|
||||
)}
|
||||
renderItem={({ item: color }) => (
|
||||
<SortableNavigationItem
|
||||
id={color.id}
|
||||
isTablet={isTablet}
|
||||
key={color.id}
|
||||
title={color.title}
|
||||
icon={Circle}
|
||||
selected={location === `/colors/${color.id}`}
|
||||
color={color.colorCode}
|
||||
onClick={() => {
|
||||
_navigate(`/colors/${color.id}`);
|
||||
}}
|
||||
menuItems={[
|
||||
{
|
||||
type: "button",
|
||||
key: "rename",
|
||||
title: "Rename color",
|
||||
onClick: async () => {
|
||||
await showRenameColorDialog(color.id);
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Box
|
||||
bg="separator"
|
||||
my={1}
|
||||
sx={{ width: "85%", height: "0.8px", alignSelf: "center" }}
|
||||
/>
|
||||
{shortcuts.map((item, index) => (
|
||||
<NavigationItem
|
||||
animate={!IS_DESKTOP_APP}
|
||||
index={colors.length - 1 + index}
|
||||
isTablet={isTablet}
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
menuItems={[
|
||||
{
|
||||
type: "button",
|
||||
key: "removeshortcut",
|
||||
title: "Remove shortcut",
|
||||
onClick: async () => {
|
||||
await db.shortcuts.remove(item.id);
|
||||
refreshNavItems();
|
||||
<ReorderableList
|
||||
items={shortcuts}
|
||||
orderKey={`sidebarOrder:shortcuts`}
|
||||
order={() => db.settings.getSideBarOrder("shortcuts")}
|
||||
onOrderChanged={(order) =>
|
||||
db.settings.setSideBarOrder("shortcuts", order)
|
||||
}
|
||||
renderOverlay={({ item }) => (
|
||||
<NavigationItem
|
||||
id={item.id}
|
||||
isTablet={isTablet}
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
icon={
|
||||
item.type === "notebook"
|
||||
? Notebook2
|
||||
: item.type === "tag"
|
||||
? Tag2
|
||||
: Topic
|
||||
}
|
||||
isShortcut
|
||||
selected={shouldSelectNavItem(location, item)}
|
||||
/>
|
||||
)}
|
||||
renderItem={({ item }) => (
|
||||
<SortableNavigationItem
|
||||
id={item.id}
|
||||
isTablet={isTablet}
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
menuItems={[
|
||||
{
|
||||
type: "button",
|
||||
key: "removeshortcut",
|
||||
title: "Remove shortcut",
|
||||
onClick: async () => {
|
||||
await db.shortcuts.remove(item.id);
|
||||
refreshNavItems();
|
||||
}
|
||||
}
|
||||
]}
|
||||
icon={
|
||||
item.type === "notebook"
|
||||
? Notebook2
|
||||
: item.type === "tag"
|
||||
? Tag2
|
||||
: Topic
|
||||
}
|
||||
]}
|
||||
icon={
|
||||
item.type === "notebook"
|
||||
? Notebook2
|
||||
: item.type === "tag"
|
||||
? Tag2
|
||||
: Topic
|
||||
}
|
||||
isShortcut
|
||||
selected={shouldSelectNavItem(location, item)}
|
||||
onClick={() => {
|
||||
if (item.type === "notebook") {
|
||||
_navigate(`/notebooks/${item.id}`);
|
||||
} else if (item.type === "tag") {
|
||||
_navigate(`/tags/${item.id}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
isShortcut
|
||||
selected={shouldSelectNavItem(location, item)}
|
||||
onClick={() => {
|
||||
if (item.type === "notebook") {
|
||||
_navigate(`/notebooks/${item.id}`);
|
||||
} else if (item.type === "tag") {
|
||||
_navigate(`/tags/${item.id}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Flex>
|
||||
</FlexScrollContainer>
|
||||
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
{isLoggedIn === false && (
|
||||
<NavigationItem
|
||||
id="login"
|
||||
isTablet={isTablet}
|
||||
title="Login"
|
||||
icon={Login}
|
||||
@@ -279,6 +370,7 @@ function NavigationMenu(props: NavigationMenuProps) {
|
||||
)}
|
||||
{isTablet && (
|
||||
<NavigationItem
|
||||
id="change-theme"
|
||||
isTablet={isTablet}
|
||||
title={theme === "dark" ? "Light mode" : "Dark mode"}
|
||||
icon={theme === "dark" ? LightMode : DarkMode}
|
||||
@@ -289,6 +381,7 @@ function NavigationMenu(props: NavigationMenuProps) {
|
||||
/>
|
||||
)}
|
||||
<NavigationItem
|
||||
id={settings.id}
|
||||
isTablet={isTablet}
|
||||
key={settings.path}
|
||||
title={settings.title}
|
||||
@@ -341,3 +434,99 @@ function findNestedRoute(location: string) {
|
||||
}
|
||||
return nestedRoute;
|
||||
}
|
||||
|
||||
type ReorderableListProps<T> = {
|
||||
orderKey: string;
|
||||
items: T[];
|
||||
renderItem: (props: { item: T }) => JSX.Element;
|
||||
renderOverlay: (props: { item: T }) => JSX.Element;
|
||||
onOrderChanged: (newOrder: string[]) => void;
|
||||
order: () => string[];
|
||||
};
|
||||
|
||||
function ReorderableList<T extends { id: string }>(
|
||||
props: ReorderableListProps<T>
|
||||
) {
|
||||
const {
|
||||
orderKey,
|
||||
items,
|
||||
renderItem: Item,
|
||||
renderOverlay: Overlay,
|
||||
onOrderChanged,
|
||||
order: _order
|
||||
} = props;
|
||||
const sensors = useSensors(
|
||||
useSensor(MouseSensor, {
|
||||
activationConstraint: {
|
||||
distance: 10
|
||||
}
|
||||
}),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates
|
||||
})
|
||||
);
|
||||
const [activeItem, setActiveItem] = useState<T>();
|
||||
const [order, setOrder] = usePersistentState<string[]>(orderKey, _order());
|
||||
const orderedItems = orderItems(items, order);
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragStart={(event) => {
|
||||
if (!isUserPremium()) {
|
||||
showToast("error", "You need to be Pro to customize the sidebar.");
|
||||
return;
|
||||
}
|
||||
setActiveItem(orderedItems.find((i) => i.id === event.active.id));
|
||||
}}
|
||||
onDragEnd={(event) => {
|
||||
const { active, over } = event;
|
||||
|
||||
const overId = over?.id as string;
|
||||
if (overId && active.id !== overId) {
|
||||
const transitionOrder =
|
||||
order.length === 0 ? orderedItems.map((i) => i.id) : order;
|
||||
const newIndex = transitionOrder.indexOf(overId);
|
||||
const oldIndex = transitionOrder.indexOf(active.id as string);
|
||||
const newOrder = arrayMove(transitionOrder, oldIndex, newIndex);
|
||||
setOrder(newOrder);
|
||||
onOrderChanged(newOrder);
|
||||
}
|
||||
setActiveItem(undefined);
|
||||
}}
|
||||
measuring={{
|
||||
droppable: { strategy: MeasuringStrategy.Always }
|
||||
}}
|
||||
>
|
||||
<SortableContext
|
||||
items={orderedItems}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
{orderedItems.map((item) => (
|
||||
<Item key={item.id} item={item} />
|
||||
))}
|
||||
|
||||
<DragOverlay
|
||||
dropAnimation={{
|
||||
duration: 500,
|
||||
easing: "cubic-bezier(0.18, 0.67, 0.6, 1.22)"
|
||||
}}
|
||||
>
|
||||
{activeItem && <Overlay item={activeItem} />}
|
||||
</DragOverlay>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
);
|
||||
}
|
||||
|
||||
function orderItems<T extends { id: string }>(items: T[], order: string[]) {
|
||||
const sorted: T[] = [];
|
||||
order.forEach((id) => {
|
||||
const item = items.find((i) => i.id === id);
|
||||
if (!item) return;
|
||||
sorted.push(item);
|
||||
});
|
||||
sorted.push(...items.filter((i) => !order.includes(i.id)));
|
||||
return sorted;
|
||||
}
|
||||
|
||||
@@ -17,15 +17,16 @@ 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, Text } from "@theme-ui/components";
|
||||
import { Button, Flex, FlexProps, Text } from "@theme-ui/components";
|
||||
import { useStore as useAppStore } from "../../stores/app-store";
|
||||
import { Menu } from "../../hooks/use-menu";
|
||||
import useMobile from "../../hooks/use-mobile";
|
||||
import { PropsWithChildren } from "react";
|
||||
import { Icon, Shortcut } from "../icons";
|
||||
import { AnimatedFlex } from "../animated";
|
||||
import { SchemeColors, createButtonVariant } from "@notesnook/theme";
|
||||
import { MenuItem } from "@notesnook/ui";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
|
||||
type NavigationItemProps = {
|
||||
icon: Icon;
|
||||
@@ -43,7 +44,11 @@ type NavigationItemProps = {
|
||||
menuItems?: MenuItem[];
|
||||
};
|
||||
|
||||
function NavigationItem(props: PropsWithChildren<NavigationItemProps>) {
|
||||
function NavigationItem(
|
||||
props: PropsWithChildren<
|
||||
NavigationItemProps & { containerRef?: React.Ref<HTMLElement> } & FlexProps
|
||||
>
|
||||
) {
|
||||
const {
|
||||
icon: Icon,
|
||||
color,
|
||||
@@ -57,24 +62,17 @@ function NavigationItem(props: PropsWithChildren<NavigationItemProps>) {
|
||||
onClick,
|
||||
menuItems,
|
||||
count,
|
||||
animate = false,
|
||||
index = 0
|
||||
sx,
|
||||
containerRef,
|
||||
...restProps
|
||||
} = props;
|
||||
const toggleSideMenu = useAppStore((store) => store.toggleSideMenu);
|
||||
const isMobile = useMobile();
|
||||
|
||||
return (
|
||||
<AnimatedFlex
|
||||
initial={{
|
||||
opacity: animate ? 0 : 1,
|
||||
// y: animate ? 0 : 0,
|
||||
x: animate ? (isTablet ? 0 : 10) : 0
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
x: 0
|
||||
}}
|
||||
transition={{ duration: 0.1, delay: index * 0.05, ease: "easeIn" }}
|
||||
<Flex
|
||||
{...restProps}
|
||||
ref={containerRef}
|
||||
sx={{
|
||||
...createButtonVariant(
|
||||
selected ? "background-selected" : "transparent",
|
||||
@@ -92,7 +90,8 @@ function NavigationItem(props: PropsWithChildren<NavigationItemProps>) {
|
||||
alignItems: "center",
|
||||
position: "relative",
|
||||
":first-of-type": { mt: 1 },
|
||||
":last-of-type": { mb: 1 }
|
||||
":last-of-type": { mb: 1 },
|
||||
...sx
|
||||
// ":hover:not(:disabled)": {
|
||||
// bg: "hover",
|
||||
// filter: "brightness(100%)"
|
||||
@@ -185,7 +184,29 @@ function NavigationItem(props: PropsWithChildren<NavigationItemProps>) {
|
||||
{tag}
|
||||
</Text>
|
||||
) : null}
|
||||
</AnimatedFlex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
export default NavigationItem;
|
||||
|
||||
export function SortableNavigationItem(
|
||||
props: PropsWithChildren<{ id: string } & NavigationItemProps>
|
||||
) {
|
||||
const { id, ...restProps } = props;
|
||||
const { attributes, listeners, setNodeRef, transform, transition, active } =
|
||||
useSortable({ id });
|
||||
|
||||
return (
|
||||
<NavigationItem
|
||||
{...restProps}
|
||||
containerRef={setNodeRef}
|
||||
style={{
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
visibility: active?.id === id ? "hidden" : "visible"
|
||||
}}
|
||||
{...listeners}
|
||||
{...attributes}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ import {
|
||||
GroupingKey,
|
||||
SettingItem,
|
||||
SettingItemMap,
|
||||
SideBarSectionKey,
|
||||
SideBarHideableSection,
|
||||
SideBarSection,
|
||||
ToolbarConfig,
|
||||
ToolbarConfigPlatforms,
|
||||
TrashCleanupInterval
|
||||
@@ -63,13 +64,12 @@ const defaultSettings: SettingItemMap = {
|
||||
"toolbarConfig:desktop": undefined,
|
||||
"toolbarConfig:mobile": undefined,
|
||||
|
||||
"sideBarOrder:builtin": [],
|
||||
"sideBarOrder:colors": [],
|
||||
"sideBarOrder:menu": [],
|
||||
"sideBarOrder:pinned": [],
|
||||
"sideBarOrder:shortcuts": [],
|
||||
|
||||
"sideBarHiddenItems:colors": [],
|
||||
"sideBarHiddenItems:menu": [],
|
||||
"sideBarHiddenItems:pinned": []
|
||||
"sideBarHiddenItems:builtin": [],
|
||||
"sideBarHiddenItems:colors": []
|
||||
};
|
||||
|
||||
export class Settings implements ICollection {
|
||||
@@ -176,19 +176,19 @@ export class Settings implements ICollection {
|
||||
return this.set("timeFormat", format);
|
||||
}
|
||||
|
||||
getSideBarOrder(section: SideBarSectionKey) {
|
||||
getSideBarOrder(section: SideBarSection) {
|
||||
return this.get(`sideBarOrder:${section}`);
|
||||
}
|
||||
|
||||
setSideBarOrder(section: SideBarSectionKey, order: string[]) {
|
||||
setSideBarOrder(section: SideBarSection, order: string[]) {
|
||||
return this.set(`sideBarOrder:${section}`, order);
|
||||
}
|
||||
|
||||
getSideBarHiddenItems(section: SideBarSectionKey) {
|
||||
getSideBarHiddenItems(section: SideBarHideableSection) {
|
||||
return this.get(`sideBarHiddenItems:${section}`);
|
||||
}
|
||||
|
||||
setSideBarHiddenItems(section: SideBarSectionKey, order: string[]) {
|
||||
setSideBarHiddenItems(section: SideBarHideableSection, order: string[]) {
|
||||
return this.set(`sideBarHiddenItems:${section}`, order);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ export type SortOptions = {
|
||||
sortDirection: "desc" | "asc";
|
||||
};
|
||||
|
||||
export type SideBarSectionKey = "menu" | "colors" | "pinned";
|
||||
|
||||
export type GroupOptions = SortOptions & {
|
||||
groupBy: "none" | "abc" | "year" | "month" | "week" | "default";
|
||||
};
|
||||
@@ -417,6 +415,8 @@ export interface LegacySettingsItem extends BaseItem<"settings"> {
|
||||
}
|
||||
|
||||
export type ToolbarConfigPlatforms = "desktop" | "mobile";
|
||||
export type SideBarSection = "builtin" | "colors" | "shortcuts";
|
||||
export type SideBarHideableSection = "builtin" | "colors";
|
||||
export type SettingItemMap = {
|
||||
trashCleanupInterval: TrashCleanupInterval;
|
||||
titleFormat: string;
|
||||
@@ -425,8 +425,8 @@ export type SettingItemMap = {
|
||||
defaultNotebook: string | undefined;
|
||||
} & Record<`groupOptions:${GroupingKey}`, GroupOptions> &
|
||||
Record<`toolbarConfig:${ToolbarConfigPlatforms}`, ToolbarConfig | undefined> &
|
||||
Record<`sideBarOrder:${SideBarSectionKey}`, string[]> &
|
||||
Record<`sideBarHiddenItems:${SideBarSectionKey}`, string[]>;
|
||||
Record<`sideBarOrder:${SideBarSection}`, string[]> &
|
||||
Record<`sideBarHiddenItems:${SideBarHideableSection}`, string[]>;
|
||||
|
||||
export interface SettingItem<
|
||||
TKey extends keyof SettingItemMap = keyof SettingItemMap
|
||||
|
||||
Reference in New Issue
Block a user