Skip to content

Commit 5d9387c

Browse files
refactor: move folder tree into sidebar, use app for highlighted state (#514)
1 parent c6bb6e0 commit 5d9387c

File tree

9 files changed

+63
-45
lines changed

9 files changed

+63
-45
lines changed

src/renderer/components/sidebar/Sidebar.vue

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<script setup lang="ts">
2-
import type { Node } from '@/components/ui/folder-tree/types'
32
import type { FoldersTreeResponse } from '@/services/api/generated'
3+
import type { Node } from '~/renderer/components/sidebar/folders/types'
44
import { useApp, useGutter, useSnippets } from '@/composables'
55
import { store } from '@/electron'
66
import { api } from '@/services/api'
77
import { Archive, Inbox, Plus, Star, Trash } from 'lucide-vue-next'
88
import { APP_DEFAULTS } from '~/main/store/constants'
9+
import Tree from './folders/Tree.vue'
910
1011
const sidebarRef = ref<HTMLElement>()
1112
const gutterRef = ref<{ $el: HTMLElement }>()
@@ -140,10 +141,10 @@ watch(width, () => {
140141
<div
141142
ref="sidebarRef"
142143
data-sidebar
143-
class="relative pt-[var(--title-bar-height)] flex flex-col h-screen px-1"
144+
class="relative flex h-screen flex-col px-1 pt-[var(--title-bar-height)]"
144145
>
145146
<div class="flex-shrink-0">
146-
<div class="uppercase font-bold text-[10px] pb-1 pl-1">
147+
<div class="pb-1 pl-1 text-[10px] font-bold uppercase">
147148
Library / Tags
148149
</div>
149150
<div class="ml-5.5">
@@ -154,7 +155,7 @@ watch(width, () => {
154155
>
155156
<component
156157
:is="i.icon"
157-
class="w-4 h-4 mr-0.5"
158+
class="mr-0.5 h-4 w-4"
158159
/>
159160
<div class="ml-1 select-none">
160161
{{ i.name }}
@@ -163,18 +164,18 @@ watch(width, () => {
163164
</div>
164165
</div>
165166
<div class="flex items-center justify-between pt-2 pl-1">
166-
<div class="uppercase font-bold text-[10px]">
167+
<div class="text-[10px] font-bold uppercase">
167168
Folders
168169
</div>
169170
<UiButton
170171
variant="icon"
171172
size="sm"
172173
>
173-
<Plus class="w-4 h-4 text-text-muted" />
174+
<Plus class="text-text-muted h-4 w-4" />
174175
</UiButton>
175176
</div>
176177
<div class="flex-grow overflow-auto">
177-
<UiFolderTree
178+
<Tree
178179
v-if="folders"
179180
v-model="folders"
180181
@click-node="onFolderClick"

src/renderer/components/ui/folder-tree/FolderTree.vue renamed to src/renderer/components/sidebar/folders/Tree.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script setup lang="ts">
22
import type { Ref } from 'vue'
33
import type { Node } from './types'
4-
import FolderTreeNode from './FolderTreeNode.vue'
5-
import { folderTreeKeys } from './keys'
4+
import { treeKeys } from './keys'
5+
import TreeNode from './TreeNode.vue'
66
77
interface Props {
88
modelValue: Node[]
@@ -37,7 +37,7 @@ function toggleNode(node: Node) {
3737
return emit('toggleNode', node)
3838
}
3939
40-
provide(folderTreeKeys, {
40+
provide(treeKeys, {
4141
clickNode,
4242
dragNode,
4343
toggleNode,
@@ -51,7 +51,7 @@ provide(folderTreeKeys, {
5151
data-folder-tree
5252
class="pt-1"
5353
>
54-
<FolderTreeNode
54+
<TreeNode
5555
v-for="(node, index) in modelValue"
5656
:key="node.id"
5757
:node="node"
@@ -70,6 +70,6 @@ provide(folderTreeKeys, {
7070
{{ node.name }}
7171
</template>
7272
</template>
73-
</FolderTreeNode>
73+
</TreeNode>
7474
</div>
7575
</template>

src/renderer/components/ui/folder-tree/FolderTreeNode.vue renamed to src/renderer/components/sidebar/folders/TreeNode.vue

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
<script setup lang="ts">
22
import type { CSSProperties } from 'vue'
33
import type { Node, Position } from './types'
4+
import { useApp } from '@/composables'
45
import { onClickOutside } from '@vueuse/core'
56
import { ChevronRight, Folder } from 'lucide-vue-next'
6-
77
import { isAllowed, store } from './composables'
8-
9-
import { folderTreeKeys } from './keys'
8+
import { treeKeys } from './keys'
109
1110
interface Props {
1211
index: number
@@ -24,7 +23,9 @@ const props = withDefaults(defineProps<Props>(), {
2423
})
2524
2625
const { clickNode, dragNode, toggleNode, isHoveredByIdDisabled, focusHandler }
27-
= inject(folderTreeKeys)!
26+
= inject(treeKeys)!
27+
28+
const { highlightedFolderId, selectedFolderId } = useApp()
2829
2930
const hoveredId = ref()
3031
const overPosition = ref<Position>()
@@ -43,8 +44,10 @@ const isHovered = computed(() => {
4344
return props.node.id === hoveredId.value && overPosition.value === 'center'
4445
})
4546
46-
const isSelected = computed(() => store.selectedId === props.node.id)
47-
const isHighlighted = computed(() => store.highlightedId === props.node.id)
47+
const isSelected = computed(() => selectedFolderId.value === props.node.id)
48+
const isHighlighted = computed(
49+
() => highlightedFolderId.value === props.node.id,
50+
)
4851
4952
const isShowBetweenLine = computed(() => {
5053
if (!isAllowed.value)
@@ -82,14 +85,13 @@ function onClickArrow(node: Node) {
8285
}
8386
8487
function onClickNode(id: string | number) {
85-
store.selectedId = id
86-
store.highlightedId = undefined
88+
highlightedFolderId.value = undefined
8789
isFocused.value = true
8890
clickNode(id)
8991
}
9092
9193
async function onClickContextMenu() {
92-
store.highlightedId = props.node.id
94+
highlightedFolderId.value = props.node.id
9395
}
9496
9597
function onDragStart(e: DragEvent) {
@@ -162,7 +164,7 @@ function onDrop() {
162164
163165
onClickOutside(rowRef, () => {
164166
isFocused.value = false
165-
store.highlightedId = undefined
167+
highlightedFolderId.value = undefined
166168
})
167169
168170
if (focusHandler)
@@ -238,7 +240,7 @@ if (focusHandler)
238240
</span>
239241
</div>
240242
<template v-if="node.children">
241-
<FolderTreeNode
243+
<TreeNode
242244
v-for="(children, idx) in node.children"
243245
v-show="node.isOpen"
244246
:key="children.id"
@@ -256,7 +258,7 @@ if (focusHandler)
256258
:hovered-node-id="hoveredNodeId"
257259
/>
258260
</template>
259-
</FolderTreeNode>
261+
</TreeNode>
260262
</template>
261263
<svg
262264
v-if="isShowBetweenLine"

src/renderer/components/ui/folder-tree/composables.ts renamed to src/renderer/components/sidebar/folders/composables/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Node, Store } from './types'
1+
import type { Node, Store } from '../types'
22
import { computed, reactive } from 'vue'
33

44
export const store = reactive<Store>({})
@@ -32,3 +32,11 @@ export const isAllowed = computed(() => {
3232

3333
return !isSameNode && !isChildrenNode
3434
})
35+
36+
export function useFolders() {
37+
return {
38+
dragNodeChildrenIds,
39+
isAllowed,
40+
store,
41+
}
42+
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import type { InjectionKey, Ref } from 'vue'
22
import type { Node } from './types'
33

4-
export interface FolderTreeInjection {
4+
export interface TreeInjection {
55
clickNode: (id: string | number) => void
66
dragNode: (node: Node, target: Node, position: string) => void
7-
toggleNode: (node: Node) => void
8-
isHoveredByIdDisabled: Ref<boolean>
97
focusHandler?: (isFocused: Ref<boolean>) => void
8+
isHoveredByIdDisabled: Ref<boolean>
9+
toggleNode: (node: Node) => void
1010
}
1111

12-
export const folderTreeKeys: InjectionKey<FolderTreeInjection>
13-
= Symbol('folderTree')
12+
export const treeKeys: InjectionKey<TreeInjection> = Symbol('tree')

src/renderer/components/ui/folder-tree/types/index.ts renamed to src/renderer/components/sidebar/folders/types/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,4 @@ export interface Node extends FoldersItem {
99
export interface Store {
1010
dragNode?: Node
1111
dragEnterNode?: Node
12-
selectedId?: string | number
13-
highlightedId?: string | number
1412
}

src/renderer/components/snippet/Item.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,35 @@ import type { SnippetsResponse } from '@/services/api/generated'
33
import { useApp } from '@/composables'
44
import { onClickOutside } from '@vueuse/core'
55
import { format } from 'date-fns'
6-
import { useSnippetsStore } from './composables'
76
87
interface Props {
98
snippet: SnippetsResponse[0]
109
}
1110
1211
const props = defineProps<Props>()
1312
14-
const { selectedSnippetId } = useApp()
15-
const { highlightedId } = useSnippetsStore()
13+
const { selectedSnippetId, highlightedSnippetId } = useApp()
1614
1715
const isFocused = ref(false)
1816
const snippetRef = ref<HTMLDivElement>()
1917
2018
const isSelected = computed(() => selectedSnippetId.value === props.snippet.id)
21-
const isHighlighted = computed(() => highlightedId.value === props.snippet.id)
19+
const isHighlighted = computed(
20+
() => highlightedSnippetId.value === props.snippet.id,
21+
)
2222
2323
function onSnippetClick(id: number) {
2424
selectedSnippetId.value = id
2525
isFocused.value = true
2626
}
2727
2828
function onClickContextMenu() {
29-
highlightedId.value = props.snippet.id
29+
highlightedSnippetId.value = props.snippet.id
3030
}
3131
3232
onClickOutside(snippetRef, () => {
3333
isFocused.value = false
34-
highlightedId.value = undefined
34+
highlightedSnippetId.value = undefined
3535
})
3636
</script>
3737

src/renderer/components/snippet/composables/index.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/renderer/composables/useApp.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const { store } = window.electron
66
const libraryFilterSelected = ref<LibraryFilter>()
77
const selectedFolderId = ref<number>(store.app.get('selectedFolderId'))
88
const selectedSnippetId = ref<number>(store.app.get('selectedSnippetId'))
9+
const highlightedFolderId = ref<number>()
10+
const highlightedSnippetId = ref<number>()
911

1012
const sidebarWidth = useCssVar('--sidebar-width')
1113
const snippetListWidth = useCssVar('--snippet-list-width')
@@ -18,6 +20,19 @@ function selectFolder(folderId: number) {
1820
store.app.set('selectedFolderId', folderId)
1921
}
2022

23+
watch(
24+
[highlightedFolderId, highlightedSnippetId],
25+
([newFolderId, newSnippetId], [oldFolderId, oldSnippetId]) => {
26+
if (newFolderId !== oldFolderId && newFolderId !== undefined) {
27+
highlightedSnippetId.value = undefined
28+
}
29+
30+
if (newSnippetId !== oldSnippetId && newSnippetId !== undefined) {
31+
highlightedFolderId.value = undefined
32+
}
33+
},
34+
)
35+
2136
export function useApp() {
2237
return {
2338
libraryFilterSelected,
@@ -26,5 +41,7 @@ export function useApp() {
2641
sidebarWidth,
2742
snippetListWidth,
2843
selectFolder,
44+
highlightedFolderId,
45+
highlightedSnippetId,
2946
}
3047
}

0 commit comments

Comments
 (0)