diff --git a/apps/web/src/components/note/index.tsx b/apps/web/src/components/note/index.tsx
index 113edb0e1..0a9f3c736 100644
--- a/apps/web/src/components/note/index.tsx
+++ b/apps/web/src/components/note/index.tsx
@@ -233,7 +233,9 @@ function Note(props: NoteProps) {
{note.readonly && }
- {note.favorite && }
+ {note.favorite && (
+
+ )}
{tags?.items.map((tag) => {
return (
diff --git a/apps/web/src/components/notebook/index.tsx b/apps/web/src/components/notebook/index.tsx
index 8dc482f6e..f3902a7f2 100644
--- a/apps/web/src/components/notebook/index.tsx
+++ b/apps/web/src/components/notebook/index.tsx
@@ -43,44 +43,7 @@ import { getFormattedDate } from "@notesnook/common";
import { MenuItem } from "@notesnook/ui";
import { Notebook } from "@notesnook/core";
import { handleDrop } from "../../common/drop-handler";
-
-function useDragHandler(id: string) {
- const isDraggingOver = useRef(false);
- const bounds = useRef();
-
- const isDragLeaving = useCallback((e: React.DragEvent) => {
- if (
- !isDraggingOver.current ||
- !bounds.current ||
- (e.clientX >= bounds.current.x &&
- e.clientX <= bounds.current.right &&
- e.clientY >= bounds.current.y &&
- e.clientY <= bounds.current.bottom)
- )
- return false;
-
- isDraggingOver.current = false;
- bounds.current = undefined;
- return true;
- }, []);
-
- const isDragEntering = useCallback(
- (e: React.DragEvent) => {
- if (
- isDraggingOver.current ||
- !(e.target instanceof HTMLElement) ||
- (e.target.id !== id && !e.target.closest(`#${id}`))
- )
- return false;
- isDraggingOver.current = true;
- bounds.current = e.target.closest(`#${id}`)!.getBoundingClientRect();
- return true;
- },
- [id]
- );
-
- return { isDragEntering, isDragLeaving };
-}
+import { useDragHandler } from "../../hooks/use-drag-handler";
type NotebookProps = {
item: Notebook;
diff --git a/apps/web/src/components/sub-notebook/index.tsx b/apps/web/src/components/sub-notebook/index.tsx
index 14d7c87ae..4b58e1709 100644
--- a/apps/web/src/components/sub-notebook/index.tsx
+++ b/apps/web/src/components/sub-notebook/index.tsx
@@ -27,8 +27,8 @@ import { MenuItem } from "@notesnook/ui";
import { showAddNotebookDialog } from "../../common/dialog-controller";
import { navigate } from "../../navigation";
import { useCallback, useRef } from "react";
-import { getDragData } from "../../utils/data-transfer";
import { handleDrop } from "../../common/drop-handler";
+import { useDragHandler } from "../../hooks/use-drag-handler";
type SubNotebookProps = {
item: Notebook;
@@ -60,6 +60,7 @@ function SubNotebook(props: SubNotebookProps) {
store.context?.type === "notebook" && store.context.id === item.id
);
const dragTimeout = useRef(0);
+ const { isDragEntering, isDragLeaving } = useDragHandler(`id_${item.id}`);
const openNotebook = useCallback(async () => {
if (isOpened) return;
@@ -82,17 +83,18 @@ function SubNotebook(props: SubNotebookProps) {
item={item}
onClick={() => openNotebook()}
onDragEnter={(e) => {
+ if (!isDragEntering(e)) return;
e.currentTarget.focus();
focus();
- const noteIds = getDragData(e.dataTransfer, "note");
- const notebookIds = getDragData(e.dataTransfer, "notebook");
dragTimeout.current = setTimeout(() => {
- if (notebookIds.length > 0) expand();
- else if (noteIds.length > 0) openNotebook();
+ openNotebook();
}, 1000) as unknown as number;
}}
- onDragLeave={() => clearTimeout(dragTimeout.current)}
+ onDragLeave={(e) => {
+ if (!isDragLeaving(e)) return;
+ clearTimeout(dragTimeout.current);
+ }}
onDrop={async (e) => {
clearTimeout(dragTimeout.current);
handleDrop(e.dataTransfer, item);
diff --git a/apps/web/src/hooks/use-drag-handler.ts b/apps/web/src/hooks/use-drag-handler.ts
new file mode 100644
index 000000000..901645d6b
--- /dev/null
+++ b/apps/web/src/hooks/use-drag-handler.ts
@@ -0,0 +1,58 @@
+/*
+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 .
+*/
+
+import { useCallback, useRef } from "react";
+
+export function useDragHandler(id: string) {
+ const isDraggingOver = useRef(false);
+ const bounds = useRef();
+
+ const isDragLeaving = useCallback((e: React.DragEvent) => {
+ if (
+ !isDraggingOver.current ||
+ !bounds.current ||
+ (e.clientX >= bounds.current.x &&
+ e.clientX <= bounds.current.right &&
+ e.clientY >= bounds.current.y &&
+ e.clientY <= bounds.current.bottom)
+ )
+ return false;
+
+ isDraggingOver.current = false;
+ bounds.current = undefined;
+ return true;
+ }, []);
+
+ const isDragEntering = useCallback(
+ (e: React.DragEvent) => {
+ if (
+ isDraggingOver.current ||
+ !(e.target instanceof HTMLElement) ||
+ (e.target.id !== id && !e.target.closest(`#${id}`))
+ )
+ return false;
+ isDraggingOver.current = true;
+ bounds.current = e.target.closest(`#${id}`)!.getBoundingClientRect();
+ return true;
+ },
+ [id]
+ );
+
+ return { isDragEntering, isDragLeaving };
+}
diff --git a/apps/web/src/views/notebook.tsx b/apps/web/src/views/notebook.tsx
index c9d61f42e..8e794a1b5 100644
--- a/apps/web/src/views/notebook.tsx
+++ b/apps/web/src/views/notebook.tsx
@@ -442,7 +442,12 @@ function NotebookHeader({
const { title, description, dateEdited } = notebook;
return (
-
+