diff --git a/apps/web/__tests__/customize-toolbar.test.ts b/apps/web/__tests__/customize-toolbar.test.ts
new file mode 100644
index 000000000..25e79201b
--- /dev/null
+++ b/apps/web/__tests__/customize-toolbar.test.ts
@@ -0,0 +1,182 @@
+/*
+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 {
+ Item,
+ Group,
+ Subgroup,
+ TreeNode,
+ moveItem
+} from "../src/dialogs/settings/components/customize-toolbar";
+import { describe, it, expect } from "vitest";
+
+describe("moveItem function", () => {
+ it("should correctly set depth when moving item from subgroup to main group", () => {
+ const group: Group = {
+ type: "group",
+ id: "group1",
+ title: "Group 1",
+ depth: 0
+ };
+
+ const subgroup: Subgroup = {
+ type: "group",
+ id: "subgroup1",
+ title: "Subgroup 1",
+ depth: 1
+ };
+
+ const item: Item = {
+ type: "item",
+ id: "item1",
+ title: "Item 1",
+ depth: 2, // currently in subgroup
+ toolId: "bold",
+ icon: "bold"
+ };
+
+ const items: TreeNode[] = [group, subgroup, item];
+
+ // move item from subgroup to main group
+ const result = moveItem(items, "item1", "group1");
+
+ // find the moved item
+ const movedItem = result.find((i) => i.id === "item1") as Item;
+
+ // the item should now have depth 1 (group depth + 1)
+ expect(movedItem.depth).toBe(1);
+ });
+
+ it("should correctly set depth when moving item from main group to subgroup", () => {
+ const group: Group = {
+ type: "group",
+ id: "group1",
+ title: "Group 1",
+ depth: 0
+ };
+
+ const item: Item = {
+ type: "item",
+ id: "item1",
+ title: "Item 1",
+ depth: 1, // currently in main group
+ toolId: "bold",
+ icon: "bold"
+ };
+
+ const subgroup: Subgroup = {
+ type: "group",
+ id: "subgroup1",
+ title: "Subgroup 1",
+ depth: 1
+ };
+
+ const items: TreeNode[] = [group, item, subgroup];
+
+ // move item from main group to subgroup
+ const result = moveItem(items, "item1", "subgroup1");
+
+ // find the moved item
+ const movedItem = result.find((i) => i.id === "item1") as Item;
+
+ // the item should now have depth 2 (subgroup depth + 1)
+ expect(movedItem.depth).toBe(2);
+ });
+
+ it("should correctly set depth when moving item to another item at same level", () => {
+ const group: Group = {
+ type: "group",
+ id: "group1",
+ title: "Group 1",
+ depth: 0
+ };
+
+ const item1: Item = {
+ type: "item",
+ id: "item1",
+ title: "Item 1",
+ depth: 1,
+ toolId: "bold",
+ icon: "bold"
+ };
+
+ const item2: Item = {
+ type: "item",
+ id: "item2",
+ title: "Item 2",
+ depth: 1,
+ toolId: "italic",
+ icon: "italic"
+ };
+
+ const items: TreeNode[] = [group, item1, item2];
+
+ // move item1 to item2's position
+ const result = moveItem(items, "item1", "item2");
+
+ // find the moved item
+ const movedItem = result.find((i) => i.id === "item1") as Item;
+
+ // the item should maintain the same depth as the target item
+ expect(movedItem.depth).toBe(1);
+ });
+
+ it("should correctly set depth when moving item from subgroup to another subgroup", () => {
+ const group: Group = {
+ type: "group",
+ id: "group1",
+ title: "Group 1",
+ depth: 0
+ };
+
+ const subgroup1: Subgroup = {
+ type: "group",
+ id: "subgroup1",
+ title: "Subgroup 1",
+ depth: 1
+ };
+
+ const item1: Item = {
+ type: "item",
+ id: "item1",
+ title: "Item 1",
+ depth: 2,
+ toolId: "bold",
+ icon: "bold"
+ };
+
+ const subgroup2: Subgroup = {
+ type: "group",
+ id: "subgroup2",
+ title: "Subgroup 2",
+ depth: 1
+ };
+
+ const items: TreeNode[] = [group, subgroup1, item1, subgroup2];
+
+ // move item from subgroup1 to subgroup2
+ const result = moveItem(items, "item1", "subgroup2");
+
+ // find the moved item
+ const movedItem = result.find((i) => i.id === "item1") as Item;
+
+ // the item should now have depth 2 (subgroup depth + 1)
+ expect(movedItem.depth).toBe(2);
+ });
+});
diff --git a/apps/web/src/dialogs/settings/components/customize-toolbar.tsx b/apps/web/src/dialogs/settings/components/customize-toolbar.tsx
index 0ed7223a3..ac2ee3dd4 100644
--- a/apps/web/src/dialogs/settings/components/customize-toolbar.tsx
+++ b/apps/web/src/dialogs/settings/components/customize-toolbar.tsx
@@ -421,19 +421,19 @@ type BaseTreeNode = {
depth: number;
};
-type Subgroup = BaseTreeNode<"group"> & {
+export type Subgroup = BaseTreeNode<"group"> & {
collapsed?: boolean;
};
-type Group = BaseTreeNode<"group">;
+export type Group = BaseTreeNode<"group">;
-type Item = BaseTreeNode<"item"> & {
+export type Item = BaseTreeNode<"item"> & {
toolId: ToolId;
icon: string;
collapsed?: boolean;
};
-type TreeNode = Group | Item | Subgroup;
+export type TreeNode = Group | Item | Subgroup;
function flatten(tools: ToolbarGroupDefinition[], depth = 0): TreeNode[] {
const nodes: TreeNode[] = [];
@@ -544,7 +544,11 @@ function canMoveGroup(
return true;
}
-function moveItem(items: TreeNode[], fromId: string, toId: string): TreeNode[] {
+export function moveItem(
+ items: TreeNode[],
+ fromId: string,
+ toId: string
+): TreeNode[] {
const fromIndex = items.findIndex((i) => i.id === fromId);
const toIndex = items.findIndex((i) => i.id === toId);
@@ -555,13 +559,14 @@ function moveItem(items: TreeNode[], fromId: string, toId: string): TreeNode[] {
const movingToGroup = isGroup(toItem) || isSubgroup(toItem);
- // we need to adjust the item depth according to where the item
- // is going to be moved.
- if (fromItem.depth !== toItem.depth) fromItem.depth = toItem.depth;
-
- // if we are moving to the start of the group, we need to adjust the
- // depth accordingly.
- if (movingToGroup) fromItem.depth = toItem.depth + 1;
+ // calculate the correct depth based on where the item is being moved
+ if (movingToGroup) {
+ // if moving to a group/subgroup, set depth to group's depth + 1
+ fromItem.depth = toItem.depth + 1;
+ } else {
+ // if moving to another item, set depth to match the target item's depth
+ fromItem.depth = toItem.depth;
+ }
const newArray = arrayMove(items, fromIndex, toIndex);