Skip to content

Commit a7540c9

Browse files
feat: add snippets selection history (#238)
1 parent 3fadd32 commit a7540c9

File tree

13 files changed

+102
-5
lines changed

13 files changed

+102
-5
lines changed

src/main/menu/main.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,27 @@ const editMenu: MenuItemConstructorOptions[] = [
446446
}
447447
]
448448

449+
const historyMenu: MenuItemConstructorOptions[] = [
450+
{
451+
label: i18n.t('menu:history.back'),
452+
accelerator: 'CommandOrControl+[',
453+
click: () => {
454+
BrowserWindow.getFocusedWindow()?.webContents.send(
455+
'main-menu:history-back'
456+
)
457+
}
458+
},
459+
{
460+
label: i18n.t('menu:history.forward'),
461+
accelerator: 'CommandOrControl+]',
462+
click: () => {
463+
BrowserWindow.getFocusedWindow()?.webContents.send(
464+
'main-menu:history-forward'
465+
)
466+
}
467+
}
468+
]
469+
449470
const menuItems: MenuItemConstructorOptions[] = [
450471
{
451472
label: i18n.t('menu:app.label'),
@@ -471,6 +492,10 @@ const menuItems: MenuItemConstructorOptions[] = [
471492
label: i18n.t('menu:markdown.label'),
472493
submenu: markdownMenu
473494
},
495+
{
496+
label: i18n.t('menu:history.label'),
497+
submenu: historyMenu
498+
},
474499
{
475500
label: i18n.t('menu:help.label'),
476501
submenu: helpMenu

src/main/services/i18n/locales/en/menu.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,10 @@
7575
"label": "Markdown",
7676
"presentationMode": "Presentation Mode",
7777
"preview": "Preview"
78+
},
79+
"history": {
80+
"label": "History",
81+
"back": "Back",
82+
"forward": "Forward"
7883
}
7984
}

src/main/services/i18n/locales/ru/menu.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,10 @@
7474
"label": "Markdown",
7575
"presentationMode": "Режим презентации",
7676
"preview": "Просмотр Markdown"
77+
},
78+
"history": {
79+
"label": "История",
80+
"back": "Назад",
81+
"forward": "Вперед"
7782
}
7883
}

src/renderer/App.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ ipc.on('main:focus', () => {
173173
ipc.on('main:app-protocol', (event, payload: string) => {
174174
if (/^masscode:\/\/snippets/.test(payload)) {
175175
const snippetId = payload.split('/').pop()
176-
if (snippetId) goToSnippet(snippetId)
176+
if (snippetId) goToSnippet(snippetId, true)
177177
}
178178
})
179179
@@ -245,6 +245,14 @@ ipc.on('main-menu:font-size-reset', async () => {
245245
emitter.emit('editor:refresh', true)
246246
})
247247
248+
ipc.on('main-menu:history-back', async () => {
249+
appStore.historyBack()
250+
})
251+
252+
ipc.on('main-menu:history-forward', async () => {
253+
appStore.historyForward()
254+
})
255+
248256
ipc.on('api:snippet-create', (event, body: Snippet) => {
249257
onCreateSnippet(body)
250258
})

src/renderer/components/markdown/TheMarkdown.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ const onLink = async (e: Event) => {
217217
218218
if (el.classList.contains('snippet-link')) {
219219
const { snippetId } = el.dataset
220-
if (snippetId) goToSnippet(snippetId)
220+
if (snippetId) goToSnippet(snippetId, true)
221221
}
222222
}
223223

src/renderer/components/sidebar/SidebarList.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
22
<div
3+
ref="listRef"
34
class="sidebar-list"
45
:class="{
56
'is-scrollable': isScrollable || modelValue === 'tags',
@@ -70,6 +71,7 @@ const props = withDefaults(defineProps<Props>(), {
7071
})
7172
7273
const bodyRef = ref<HTMLElement>()
74+
const listRef = ref<HTMLElement>()
7375
7476
const activeTab = computed({
7577
get: () => props.modelValue,
@@ -83,10 +85,21 @@ const onClickTab = (tab: Tab) => {
8385
}
8486
8587
emitter.on('scroll-to:folder', id => {
88+
if (props.isSystem) return
89+
8690
nextTick(() => {
8791
const el = document.querySelector<HTMLElement>(`[data-id='${id}']`)
88-
if (el) {
89-
setScrollPosition(bodyRef.value!, el.getBoundingClientRect().top - 210)
92+
93+
if (!el) return
94+
95+
const bounding = el.getBoundingClientRect()
96+
const listHeight = listRef.value!.offsetHeight
97+
98+
const OFFSET = 210 // высота списка системных папок + заголовки
99+
const SHIFT = bounding.top - OFFSET
100+
101+
if (SHIFT > listHeight || bounding.top < 0) {
102+
setScrollPosition(bodyRef.value!, SHIFT)
90103
}
91104
})
92105
})

src/renderer/components/sidebar/TheSidebar.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ const onClickFolder = async (id: string) => {
132132
folderStore.selectId(id)
133133
await snippetStore.setSnippetsByFolderIds(true)
134134
snippetStore.searchQuery = ''
135+
appStore.addToHistory(snippetStore.snippets[0]?.id)
135136
emitter.emit('folder:click', id)
136137
}
137138

src/renderer/components/snippets/SnippetListItem.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import type { SystemFolderAlias } from '@shared/types/renderer/sidebar'
4545
import { useTagStore } from '@/store/tags'
4646
import { isToday, format } from 'date-fns'
4747
import { emitter } from '@/composable'
48+
import { useAppStore } from '@/store/app'
4849
4950
interface Props {
5051
id: string
@@ -59,6 +60,7 @@ const props = defineProps<Props>()
5960
const snippetStore = useSnippetStore()
6061
const folderStore = useFolderStore()
6162
const tagStore = useTagStore()
63+
const appStore = useAppStore()
6264
6365
const itemRef = ref()
6466
const isFocused = ref(false)
@@ -105,6 +107,7 @@ const onClickSnippet = (e: MouseEvent) => {
105107
snippetStore.selectedMultiple = []
106108
snippetStore.getSnippetsById(props.id)
107109
tagStore.getTags()
110+
appStore.addToHistory(props.id)
108111
}
109112
}
110113

src/renderer/composable/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useSnippetStore } from '@/store/snippets'
77
import { ipc, track } from '@/electron'
88
import type { NotificationRequest } from '@shared/types/main'
99
import type { Snippet, SnippetsSort } from '@shared/types/main/db'
10+
import { useAppStore } from '@/store/app'
1011

1112
export const useApi = createFetch({
1213
baseUrl: `http://localhost:${API_PORT}`
@@ -86,11 +87,12 @@ export const onCopySnippet = () => {
8687
track('snippets/copy')
8788
}
8889

89-
export const goToSnippet = async (snippetId: string) => {
90+
export const goToSnippet = async (snippetId: string, history?: boolean) => {
9091
if (!snippetId) return
9192

9293
const folderStore = useFolderStore()
9394
const snippetStore = useSnippetStore()
95+
const appStore = useAppStore()
9496

9597
const snippet = snippetStore.findSnippetById(snippetId)
9698

@@ -105,6 +107,8 @@ export const goToSnippet = async (snippetId: string) => {
105107
await snippetStore.getSnippetsById(snippetId)
106108
await snippetStore.setSnippetsByFolderIds()
107109

110+
if (history) appStore.history.push(snippetId)
111+
108112
emitter.emit('folder:click', snippet.folderId)
109113
emitter.emit('scroll-to:snippet', snippetId)
110114
emitter.emit('scroll-to:folder', snippet.folderId)

src/renderer/store/app.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { goToSnippet } from '@/composable'
12
import { platform, store } from '@/electron'
23
import type { MarkdownSettings } from '@shared/types/main/store'
34
import type {
@@ -39,6 +40,8 @@ const MARKDOWN_DEFAULTS: MarkdownSettings = {
3940
codeRenderer: 'highlight.js'
4041
}
4142

43+
const HISTORY_LIMIT = 50
44+
4245
export const useAppStore = defineStore('app', {
4346
state: (): State => ({
4447
isInit: false,
@@ -64,6 +67,8 @@ export const useAppStore = defineStore('app', {
6467
markdown: MARKDOWN_DEFAULTS,
6568
selectedPreferencesMenu: 'storage',
6669
language: store.preferences.get('language'),
70+
history: [],
71+
historyIndex: 0,
6772
version,
6873
platform: platform()
6974
}),
@@ -91,6 +96,27 @@ export const useAppStore = defineStore('app', {
9196
setLang (lang: string) {
9297
this.language = lang
9398
store.preferences.set('language', lang)
99+
},
100+
addToHistory (snippetId: string) {
101+
if (!snippetId) return
102+
if (this.history[this.history.length - 1] === snippetId) return
103+
104+
if (this.history.length === HISTORY_LIMIT) this.history.shift()
105+
106+
this.history.push(snippetId)
107+
this.historyIndex = this.history.length - 1
108+
},
109+
historyBack () {
110+
if (this.historyIndex === 0) return
111+
112+
this.historyIndex = this.historyIndex - 1
113+
goToSnippet(this.history[this.historyIndex])
114+
},
115+
historyForward () {
116+
if (this.historyIndex === this.history.length - 1) return
117+
118+
this.historyIndex = this.historyIndex + 1
119+
goToSnippet(this.history[this.historyIndex])
94120
}
95121
}
96122
})

0 commit comments

Comments
 (0)