Skip to content

Commit 7e78922

Browse files
feat(snippets): add description (#74)
1 parent e6f24d5 commit 7e78922

File tree

15 files changed

+191
-18
lines changed

15 files changed

+191
-18
lines changed

src/main/menu/main.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,28 @@ const fileMenu: MenuItemConstructorOptions[] = [
236236
)
237237
}
238238
},
239+
{
240+
label: 'Add Description',
241+
accelerator: 'CommandOrControl+Shift+T',
242+
click: () => {
243+
BrowserWindow.getFocusedWindow()?.webContents.send(
244+
'main-menu:add-description'
245+
)
246+
}
247+
},
248+
{
249+
type: 'separator'
250+
},
239251
{
240252
label: 'New Folder',
241253
accelerator: 'CommandOrControl+Shift+N',
242254
click: () => {
243255
BrowserWindow.getFocusedWindow()?.webContents.send('main-menu:new-folder')
244256
}
245257
},
258+
{
259+
type: 'separator'
260+
},
246261
{
247262
label: 'Find',
248263
accelerator: 'CommandOrControl+F',

src/renderer/App.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import {
2626
onAddNewFolder,
2727
onCopySnippet,
2828
emitter,
29-
onCreateSnippet
29+
onCreateSnippet,
30+
onAddDescription
3031
} from '@/composable'
3132
import { createToast, destroyAllToasts } from 'vercel-toast'
3233
import { useRoute } from 'vue-router'
@@ -211,6 +212,10 @@ ipc.on('main-menu:sort-snippets', (event, sort) => {
211212
snippetStore.setSort(sort)
212213
})
213214
215+
ipc.on('main-menu:add-description', async () => {
216+
await onAddDescription()
217+
})
218+
214219
ipc.on('api:snippet-create', (event, body: Snippet) => {
215220
onCreateSnippet(body)
216221
})

src/renderer/assets/scss/base.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ h6 {
4747
font-weight: 700;
4848
}
4949

50+
::placeholder {
51+
color: var(--color-text-3);
52+
}
53+
54+
5055
.gutter-line {
5156
position: absolute;
5257
top: 0;

src/renderer/assets/scss/reset.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ textarea {
6969
font-size: 100%;
7070
line-height: 1.15;
7171
margin: 0;
72+
padding: 0;
7273
}
7374

7475
button,

src/renderer/components/editor/TheEditor.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ const editorHeight = computed(() => {
9595
result += appStore.sizes.editor.tagsHeight
9696
}
9797
98+
if (snippetStore.isDescriptionShow) {
99+
result += appStore.sizes.editor.descriptionHeight
100+
}
101+
98102
return window.innerHeight - result + 'px'
99103
})
100104

src/renderer/components/snippets/SnippetHeader.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,29 @@
2020
<AppActionButton @click="onCopySnippet">
2121
<UniconsArrow />
2222
</AppActionButton>
23+
<AppActionButton @click="onAddDescription">
24+
<UniconsText />
25+
</AppActionButton>
2326
<AppActionButton @click="onAddNewFragment">
2427
<UniconsPlus />
2528
</AppActionButton>
2629
</div>
2730
</div>
2831
<div class="bottom">
32+
<SnippetsDescription v-show="snippetStore.isDescriptionShow" />
2933
<SnippetFragments v-if="snippetStore.isFragmentsShow" />
3034
<SnippetsTags v-if="snippetStore.isTagsShow" />
3135
</div>
3236
</div>
3337
</template>
3438

3539
<script setup lang="ts">
36-
import { emitter, onAddNewFragment, onCopySnippet } from '@/composable'
40+
import {
41+
onAddNewFragment,
42+
onAddDescription,
43+
onCopySnippet,
44+
emitter
45+
} from '@/composable'
3746
import { useSnippetStore } from '@/store/snippets'
3847
import { useDebounceFn } from '@vueuse/core'
3948
import { computed, onUnmounted, ref } from 'vue'
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<template>
2+
<div
3+
class="description"
4+
:class="{ 'no-border-bottom': snippetStore.isFragmentsShow }"
5+
@click="onClick"
6+
>
7+
<PerfectScrollbar>
8+
<div
9+
ref="inputRef"
10+
class="input"
11+
contenteditable="true"
12+
spellcheck="false"
13+
placeholder="Add description"
14+
@blur="onBlur"
15+
>
16+
{{ desc }}
17+
</div>
18+
</PerfectScrollbar>
19+
</div>
20+
</template>
21+
22+
<script setup lang="ts">
23+
import { useAppStore } from '@/store/app'
24+
import { useSnippetStore } from '@/store/snippets'
25+
26+
import { computed, nextTick, ref, watch } from 'vue'
27+
28+
const snippetStore = useSnippetStore()
29+
const appStore = useAppStore()
30+
31+
const desc = computed(() => snippetStore.selected?.description)
32+
33+
const inputRef = ref<HTMLElement>()
34+
const descHeight = appStore.sizes.editor.descriptionHeight + 'px'
35+
36+
const onBlur = (e: Event) => {
37+
snippetStore.patchSnippetsById(snippetStore.selectedId!, {
38+
description: (e.target as HTMLElement).innerText.trimEnd() || null
39+
})
40+
}
41+
42+
const onClick = () => {
43+
inputRef.value?.focus()
44+
}
45+
46+
watch(
47+
() => snippetStore.isDescriptionShow,
48+
v => {
49+
if (v && snippetStore.selected?.description?.length === 0) {
50+
nextTick(() => inputRef.value?.focus())
51+
}
52+
}
53+
)
54+
</script>
55+
56+
<style lang="scss" scoped>
57+
.description {
58+
padding: 0 var(--spacing-xs);
59+
font-size: 12px;
60+
color: var(--color-text);
61+
border-bottom: 1px solid var(--color-border);
62+
:empty::before {
63+
content: attr(placeholder);
64+
position: absolute;
65+
color: var(--color-text-3);
66+
background-color: transparent;
67+
}
68+
&.no-border-bottom {
69+
border-bottom: none;
70+
}
71+
.input {
72+
width: 100%;
73+
border: 0;
74+
outline: 0;
75+
line-height: 14px;
76+
white-space: pre-wrap;
77+
}
78+
:deep(.ps) {
79+
height: v-bind(descHeight);
80+
}
81+
}
82+
</style>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<template>
2+
<div class="debug">
3+
<pre>
4+
<slot />
5+
</pre>
6+
</div>
7+
</template>
8+
9+
<script setup lang="ts"></script>
10+
11+
<style lang="scss" scoped>
12+
.debug {
13+
position: absolute;
14+
right: 10px;
15+
bottom: 10px;
16+
background-color: #fff;
17+
width: 400px;
18+
max-height: 400px;
19+
overflow: scroll;
20+
padding: 0 var(--spacing-xs);
21+
border-radius: 5px;
22+
color: #000;
23+
font-size: 12px;
24+
z-index: 1010;
25+
pre {
26+
font-family: var(--font-code);
27+
}
28+
}
29+
</style>

src/renderer/composable/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ export const onAddNewFragment = () => {
5050
track('snippets/add-fragment')
5151
}
5252

53+
export const onAddDescription = async () => {
54+
const snippetStore = useSnippetStore()
55+
56+
if (typeof snippetStore.selected?.description === 'string') return
57+
58+
if (
59+
snippetStore.selected?.description === undefined ||
60+
snippetStore.selected?.description === null
61+
) {
62+
await snippetStore.patchSnippetsById(snippetStore.selectedId!, {
63+
description: ''
64+
})
65+
}
66+
67+
track('snippets/add-description')
68+
}
69+
5370
export const onAddNewFolder = async () => {
5471
const folderStore = useFolderStore()
5572
const snippetStore = useSnippetStore()

src/renderer/store/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const useAppStore = defineStore('app', {
3434
titleHeight: 34,
3535
fragmentsHeight: 25,
3636
tagsHeight: 40,
37+
descriptionHeight: 58,
3738
footerHeight: 30
3839
}
3940
},

0 commit comments

Comments
 (0)