Skip to content

Commit a1e41b3

Browse files
feat: resizable layout (#19)
1 parent 820ae8f commit a1e41b3

File tree

12 files changed

+86
-14
lines changed

12 files changed

+86
-14
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"electron-store": "^8.0.1",
4141
"fs-extra": "^10.0.1",
4242
"highlight.js": "^11.5.1",
43+
"interactjs": "^1.10.11",
4344
"lowdb": "^3.0.0",
4445
"markdown-it": "^12.3.2",
4546
"markdown-it-link-attributes": "^4.0.0",

src/main/store/module/app.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export default new Store<AppStore>({
66
cwd: 'v2',
77

88
defaults: {
9-
bounds: {}
9+
bounds: {},
10+
sidebarWidth: 180,
11+
snippetListWidth: 250
1012
}
1113
})

src/renderer/App.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ const init = () => {
3636
store.preferences.get('editor')
3737
)
3838
if (isValid) appStore.editor = store.preferences.get('editor')
39+
40+
appStore.sizes.sidebar = store.app.get('sidebarWidth')
41+
appStore.sizes.snippetList = store.app.get('snippetListWidth')
3942
}
4043
4144
const setTheme = (theme: string) => {

src/renderer/components/editor/TheEditor.vue

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,6 @@ watch(
213213
}
214214
)
215215
216-
appStore.$subscribe(mutation => {
217-
console.log(mutation)
218-
})
219-
220216
window.addEventListener('resize', () => {
221217
forceRefresh.value = Math.random()
222218
})

src/renderer/components/sidebar/TheSidebar.vue

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div class="sidebar">
2+
<div
3+
ref="sidebarRef"
4+
class="sidebar"
5+
>
36
<SidebarList
47
v-model="activeTab"
58
:tabs="tabs"
@@ -70,14 +73,14 @@
7073
</AppTree>
7174
</SidebarList>
7275
<div
73-
ref="gutter"
76+
ref="gutterRef"
7477
class="gutter-line"
7578
/>
7679
</div>
7780
</template>
7881

7982
<script setup lang="ts">
80-
import { computed, ref, watch } from 'vue'
83+
import { computed, onMounted, ref, watch } from 'vue'
8184
import type {
8285
SidebarSystemFolder,
8386
SystemFolderAlias,
@@ -91,15 +94,20 @@ import Trash from '~icons/unicons/trash'
9194
import LabelAlt from '~icons/unicons/label-alt'
9295
import { useFolderStore } from '@/store/folders'
9396
import { useSnippetStore } from '@/store/snippets'
94-
import { ipc, track } from '@/electron'
97+
import { ipc, store, track } from '@/electron'
9598
import { useTagStore } from '@/store/tags'
9699
import { emitter } from '@/composable'
100+
import interact from 'interactjs'
101+
import { useAppStore } from '@/store/app'
97102
98103
const folderStore = useFolderStore()
99104
const snippetStore = useSnippetStore()
100105
const tagStore = useTagStore()
106+
const appStore = useAppStore()
101107
102108
const treeRef = ref()
109+
const sidebarRef = ref()
110+
const gutterRef = ref()
103111
104112
const systemFolders = computed(() => {
105113
const folders = folderStore.system.map(i => {
@@ -178,6 +186,21 @@ const onDragEnter = (id: string) => {
178186
folderStore.hoveredId = id
179187
}
180188
189+
onMounted(() => {
190+
interact(sidebarRef.value).resizable({
191+
allowFrom: gutterRef.value,
192+
onmove: e => {
193+
const { pageX } = e
194+
const minWidth = 100
195+
196+
if (pageX < minWidth) return
197+
const width = Math.floor(pageX)
198+
appStore.sizes.sidebar = width
199+
store.app.set('sidebarWidth', width)
200+
}
201+
})
202+
})
203+
181204
watch(
182205
() => folderStore.hoveredId,
183206
v => {

src/renderer/components/snippets/SnippetList.vue

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<SnippetListHeader />
88
</div>
99
<div
10-
ref="listRef"
10+
ref="bodyRef"
1111
class="body"
1212
>
1313
<PerfectScrollbar>
@@ -23,25 +23,48 @@
2323
/>
2424
</PerfectScrollbar>
2525
</div>
26+
<div
27+
ref="gutterRef"
28+
class="gutter-line"
29+
/>
2630
</div>
2731
</template>
2832

2933
<script setup lang="ts">
3034
import { emitter } from '@/composable'
3135
import { useAppStore } from '@/store/app'
3236
import { useSnippetStore } from '@/store/snippets'
33-
import { ref, watch } from 'vue'
37+
import { onMounted, ref, watch } from 'vue'
38+
import interact from 'interactjs'
39+
import { store } from '@/electron'
3440
3541
const snippetStore = useSnippetStore()
3642
const appStore = useAppStore()
3743
38-
const listRef = ref<HTMLElement>()
44+
const listRef = ref()
45+
const bodyRef = ref<HTMLElement>()
46+
const gutterRef = ref()
3947
4048
const setScrollPosition = (offset: number) => {
41-
const ps = listRef.value?.querySelector<HTMLElement>('.ps')
49+
const ps = bodyRef.value?.querySelector<HTMLElement>('.ps')
4250
if (ps) ps.scrollTop = offset
4351
}
4452
53+
onMounted(() => {
54+
interact(listRef.value).resizable({
55+
allowFrom: gutterRef.value,
56+
onmove: e => {
57+
const { pageX } = e
58+
const minWidth = appStore.sizes.sidebar + 100
59+
const width = Math.floor(pageX - appStore.sizes.sidebar)
60+
61+
if (pageX < minWidth) return
62+
appStore.sizes.snippetList = width
63+
store.app.set('snippetListWidth', width)
64+
}
65+
})
66+
})
67+
4568
watch(
4669
() => appStore.isInit,
4770
() => {
@@ -59,6 +82,7 @@ emitter.on('folder:click', () => {
5982

6083
<style lang="scss" scoped>
6184
.snippet-list {
85+
position: relative;
6286
border-right: 1px solid var(--color-border);
6387
display: grid;
6488
grid-template-rows: 50px 1fr 10px;

src/renderer/components/snippets/SnippetListHeader.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ const onReset = () => {
6868
padding: 0 var(--spacing-sm);
6969
position: relative;
7070
top: var(--title-bar-height-offset);
71+
width: 100%;
7172
input {
7273
outline: none;
7374
border: none;

src/renderer/store/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export const useAppStore = defineStore('app', {
1818
showTags: true,
1919
sizes: {
2020
titlebar: 15,
21+
sidebar: 180,
22+
snippetList: 250,
2123
editor: {
2224
titleHeight: 34,
2325
fragmentsHeight: 25,

src/renderer/views/Main.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ import { useFolderStore } from '@/store/folders'
1212
import { useSnippetStore } from '@/store/snippets'
1313
import { useTagStore } from '@/store/tags'
1414
import { useAppStore } from '@/store/app'
15+
import { computed } from 'vue'
1516
1617
const folderStore = useFolderStore()
1718
const snippetStore = useSnippetStore()
1819
const tagStore = useTagStore()
1920
const appStore = useAppStore()
2021
22+
const sidebarWidth = computed(() => appStore.sizes.sidebar + 'px')
23+
const snippetListWidth = computed(() => appStore.sizes.snippetList + 'px')
24+
2125
const init = async () => {
2226
const storedFolderId = store.app.get('selectedFolderId')
2327
const storedFolderAlias = store.app.get('selectedFolderAlias')
@@ -62,7 +66,7 @@ track('main')
6266
height: 100vh;
6367
background-color: var(--color-bg);
6468
overflow: hidden;
65-
grid-template-columns: var(--sidebar-width) var(--snippets-list-width) 1fr;
69+
grid-template-columns: v-bind(sidebarWidth) v-bind(snippetListWidth) 1fr;
6670
}
6771
.update-available {
6872
position: absolute;

src/shared/types/main/store.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ export interface AppStore {
44
selectedFolderAlias?: string
55
selectedFolderIds?: string[]
66
selectedSnippetId?: string
7+
sidebarWidth: number
8+
snippetListWidth: number
79
}
810

911
interface Editor {

0 commit comments

Comments
 (0)