diff --git a/apps/web/src/components/notebook/index.tsx b/apps/web/src/components/notebook/index.tsx
index 72e483034..86a7ff6ac 100644
--- a/apps/web/src/components/notebook/index.tsx
+++ b/apps/web/src/components/notebook/index.tsx
@@ -19,7 +19,7 @@ along with this program. If not, see .
import ListItem from "../list-item";
import { Button, Flex, Text } from "@theme-ui/components";
-import { store, useStore as useNotesStore } from "../../stores/note-store";
+import { useStore as useNotesStore } from "../../stores/note-store";
import { Notebook as NotebookType } from "@notesnook/core";
import {
ChevronDown,
@@ -30,7 +30,8 @@ import {
Shortcut,
Trash,
Notebook as NotebookIcon,
- ArrowUp
+ ArrowUp,
+ Move
} from "../icons";
import { MenuItem } from "@notesnook/ui";
import { hashNavigate, navigate } from "../../navigation";
@@ -45,6 +46,7 @@ import { strings } from "@notesnook/intl";
import { db } from "../../common/db";
import { createSetDefaultHomepageMenuItem } from "../../common";
import { useStore as useNotebookStore } from "../../stores/notebook-store";
+import { MoveNotebookDialog } from "../../dialogs/move-notebook-dialog";
type NotebookProps = {
item: NotebookType;
@@ -232,6 +234,15 @@ export const notebookMenuItems: (
onClick: () => appStore.addToShortcuts(notebook)
},
{ key: "sep1", type: "separator" },
+ {
+ type: "button",
+ key: "move",
+ icon: Move.path,
+ title: strings.move(),
+ onClick: () => {
+ MoveNotebookDialog.show({ notebook: notebook });
+ }
+ },
{
type: "button",
key: "move-to-top",
@@ -255,7 +266,7 @@ export const notebookMenuItems: (
},
multiSelect: false
},
- { key: "sep2", type: "separator", isHidden: context?.isRoot },
+ { key: "sep2", type: "separator" },
{
type: "button",
key: "movetotrash",
diff --git a/apps/web/src/dialogs/add-tags-dialog.tsx b/apps/web/src/dialogs/add-tags-dialog.tsx
index 06cddb0d8..0bd257ca5 100644
--- a/apps/web/src/dialogs/add-tags-dialog.tsx
+++ b/apps/web/src/dialogs/add-tags-dialog.tsx
@@ -19,37 +19,22 @@ along with this program. If not, see .
import { useEffect, useState } from "react";
import { Flex, Text } from "@theme-ui/components";
-import {
- CheckCircleOutline,
- CheckRemove,
- CircleEmpty
-} from "../components/icons";
import { db } from "../common/db";
import Dialog from "../components/dialog";
import { useStore, store } from "../stores/tag-store";
import { store as notestore } from "../stores/note-store";
import { FilteredList } from "../components/filtered-list";
import { ItemReference, Tag } from "@notesnook/core";
-import { create } from "zustand";
import { VirtualizedGrouping } from "@notesnook/core";
import { ResolvedItem } from "@notesnook/common";
import { BaseDialogProps, DialogManager } from "../common/dialog-manager";
import { strings } from "@notesnook/intl";
-
-type SelectedReference = {
- id: string;
- new: boolean;
- op: "add" | "remove";
-};
-
-interface ISelectionStore {
- selected: SelectedReference[];
- setSelected(refs: SelectedReference[]): void;
-}
-export const useSelectionStore = create((set) => ({
- selected: [],
- setSelected: (selected) => set({ selected: selected.slice() })
-}));
+import {
+ SelectedCheck,
+ SelectedReference,
+ selectMultiple,
+ useSelectionStore
+} from "./move-note-dialog";
type AddTagsDialogProps = BaseDialogProps & { noteIds: string[] };
export const AddTagsDialog = DialogManager.register(function AddTagsDialog(
@@ -91,8 +76,9 @@ export const AddTagsDialog = DialogManager.register(function AddTagsDialog(
positiveButton={{
text: strings.done(),
onClick: async () => {
+ const { selected } = useSelectionStore.getState();
for (const id of noteIds) {
- for (const item of useSelectionStore.getState().selected) {
+ for (const item of selected) {
const tagRef: ItemReference = { type: "tag", id: item.id };
const noteRef: ItemReference = { id, type: "note" };
if (item.op === "add") await db.relations.add(tagRef, noteRef);
@@ -166,47 +152,15 @@ function TagItem(props: { tag: Tag }) {
}}
onClick={() => {
const { selected, setSelected } = useSelectionStore.getState();
-
- const copy = selected.slice();
- const index = copy.findIndex((item) => item.id === tag.id);
- const isNew = copy[index] && copy[index].new;
- if (isNew) {
- copy.splice(index, 1);
- } else if (index > -1) {
- copy[index] = {
- ...copy[index],
- op: copy[index].op === "add" ? "remove" : "add"
- };
- } else {
- copy.push({ id: tag.id, new: true, op: "add" });
- }
- setSelected(copy);
+ setSelected(selectMultiple(tag, selected));
}}
>
-
-
+
+
#{tag.title}
);
}
-
-function SelectedCheck({ id, size = 20 }: { id: string; size?: number }) {
- const selected = useSelectionStore((store) => store.selected);
- const selectedTag = selected.find((item) => item.id === id);
-
- return selectedTag?.op === "add" ? (
-
- ) : selectedTag?.op === "remove" ? (
-
- ) : (
-
- );
-}
diff --git a/apps/web/src/dialogs/move-note-dialog.tsx b/apps/web/src/dialogs/move-note-dialog.tsx
index ee393ec7b..bd3c03925 100644
--- a/apps/web/src/dialogs/move-note-dialog.tsx
+++ b/apps/web/src/dialogs/move-note-dialog.tsx
@@ -49,16 +49,16 @@ import {
} from "../components/virtualized-tree";
type MoveNoteDialogProps = BaseDialogProps & { noteIds: string[] };
-type NotebookReference = {
+export type SelectedReference = {
id: string;
new: boolean;
op: "add" | "remove";
};
interface ISelectionStore {
- selected: NotebookReference[];
+ selected: SelectedReference[];
isMultiselect: boolean;
- setSelected(refs: NotebookReference[]): void;
+ setSelected(refs: SelectedReference[]): void;
setIsMultiselect(state: boolean): void;
}
export const useSelectionStore = create((set) => ({
@@ -87,7 +87,7 @@ export const MoveNoteDialog = DialogManager.register(function MoveNoteDialog({
useEffect(() => {
(async function () {
- const selected: NotebookReference[] = useSelectionStore
+ const selected: SelectedReference[] = useSelectionStore
.getState()
.selected.slice();
@@ -201,7 +201,7 @@ export const MoveNoteDialog = DialogManager.register(function MoveNoteDialog({