Skip to content

Commit bc306fe

Browse files
committed
feat(snippets): add delete, duplicate & add to favorites
1 parent f895d97 commit bc306fe

File tree

3 files changed

+82
-5
lines changed

3 files changed

+82
-5
lines changed

src/renderer/components/snippets/SnippetList.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
</div>
66
<div class="body">
77
<SnippetListItem
8-
v-for="i in snippetStore.snippets"
8+
v-for="i in snippetStore.snippetsNonDeleted"
9+
:id="i.id"
910
:key="i.id"
1011
:folder="i.folder.name"
1112
:date="i.updatedAt"

src/renderer/components/snippets/SnippetListItem.vue

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
class="item"
55
:class="{
66
'is-selected': !isFocused && isSelected,
7-
'is-focused': isFocused
7+
'is-focused': isFocused,
8+
'is-highlighted': isHighlighted
89
}"
910
@click="isFocused = true"
11+
@contextmenu="onClickContextMenu"
1012
>
1113
<div class="header">
1214
<div class="name">
@@ -27,10 +29,15 @@
2729
</template>
2830

2931
<script setup lang="ts">
32+
import { ipc } from '@/electron'
33+
import { useFolderStore } from '@/store/folders'
34+
import { useSnippetStore } from '@/store/snippets'
35+
import type { ContextMenuPayload, ContextMenuResponse } from '@@/types'
3036
import { onClickOutside } from '@vueuse/core'
3137
import { computed, ref } from 'vue'
3238
3339
interface Props {
40+
id: string
3441
name: string
3542
folder: string
3643
date: number
@@ -39,13 +46,52 @@ interface Props {
3946
4047
const props = defineProps<Props>()
4148
49+
const snippetStore = useSnippetStore()
50+
const folderStore = useFolderStore()
51+
4252
const itemRef = ref()
4353
const isFocused = ref(false)
54+
const isHighlighted = ref(false)
4455
4556
onClickOutside(itemRef, () => {
4657
isFocused.value = false
58+
isHighlighted.value = false
4759
})
4860
61+
const onClickContextMenu = async () => {
62+
isHighlighted.value = true
63+
64+
const { action } = await ipc.invoke<ContextMenuResponse, ContextMenuPayload>(
65+
'context-menu:snippet',
66+
{
67+
name: props.name
68+
}
69+
)
70+
71+
if (action === 'delete') {
72+
snippetStore.patchSnippetsById(props.id, {
73+
isDeleted: true
74+
})
75+
76+
await snippetStore.getSnippetsByFolderIds(folderStore.selectedIds!)
77+
snippetStore.snippet = snippetStore.snippetsNonDeleted[0]
78+
}
79+
80+
if (action === 'duplicate') {
81+
await snippetStore.duplicateSnippetById(props.id)
82+
await snippetStore.getSnippetsByFolderIds(folderStore.selectedIds!)
83+
}
84+
85+
if (action === 'favorites') {
86+
snippetStore.patchSnippetsById(props.id, {
87+
isFavorites: true
88+
})
89+
await snippetStore.getSnippetsByFolderIds(folderStore.selectedIds!)
90+
}
91+
92+
isHighlighted.value = false
93+
}
94+
4995
const dateFormat = computed(() =>
5096
new Intl.DateTimeFormat('ru').format(props.date)
5197
)
@@ -56,6 +102,7 @@ const dateFormat = computed(() =>
56102
padding: var(--spacing-xs) var(--spacing-sm);
57103
position: relative;
58104
z-index: 2;
105+
user-select: none;
59106
&::after {
60107
content: '';
61108
height: 1px;
@@ -65,11 +112,12 @@ const dateFormat = computed(() =>
65112
bottom: 1px;
66113
}
67114
&.is-focused,
68-
&.is-selected {
115+
&.is-selected,
116+
&.is-highlighted {
69117
&::before {
70118
content: '';
71119
position: absolute;
72-
top: -2px;
120+
top: 0px;
73121
left: 8px;
74122
right: 8px;
75123
bottom: 0px;
@@ -95,6 +143,17 @@ const dateFormat = computed(() =>
95143
color: var(--color-text);
96144
}
97145
}
146+
&.is-highlighted {
147+
&::before {
148+
top: 0px;
149+
left: 10px;
150+
right: 10px;
151+
bottom: 2px;
152+
border-radius: 5px;
153+
// z-index: 3;
154+
outline: 2px solid var(--color-primary);
155+
}
156+
}
98157
}
99158
.name {
100159
display: table;

src/renderer/store/snippets.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const useSnippetStore = defineStore('snippets', {
1818
snippetsNonDeleted: state =>
1919
state.snippets.filter(i => !i.isDeleted) as SnippetWithFolder[],
2020
snippetsDeleted: state =>
21-
state.snippets.filter(i => i.isDeleted) as SnippetWithFolder[],
21+
state.snippets.filter(i => !i.isDeleted) as SnippetWithFolder[],
2222
selectedId: state => state.snippet?.id,
2323
currentContent: state => state.snippet?.content[state.fragment]?.value,
2424
currentLanguage: state =>
@@ -67,6 +67,7 @@ export const useSnippetStore = defineStore('snippets', {
6767
key: keyof SnippetContent,
6868
value: string | Language
6969
) {
70+
const folderStore = useFolderStore()
7071
const body: Partial<Snippet> = {}
7172
const content = this.snippet?.content
7273

@@ -76,6 +77,7 @@ export const useSnippetStore = defineStore('snippets', {
7677
body.updatedAt = new Date().valueOf()
7778

7879
await useApi(`/snippets/${this.selectedId}`).patch(body)
80+
await this.getSnippetsByFolderIds(folderStore.selectedIds)
7981
}
8082
},
8183
async addNewSnippet () {
@@ -97,6 +99,20 @@ export const useSnippetStore = defineStore('snippets', {
9799
this.snippet = data.value
98100
store.app.set('selectedSnippetId', this.snippet!.id)
99101
},
102+
async duplicateSnippetById (id: string) {
103+
const snippet = this.snippets.find(i => i.id === id)
104+
105+
if (snippet) {
106+
const body = Object.assign({}, snippet)
107+
body.name = body.name + ' Copy'
108+
109+
const { data } = await useApi('/snippets').post(body).json()
110+
this.snippet = data.value
111+
this.fragment = 0
112+
113+
store.app.set('selectedSnippetId', this.snippet!.id)
114+
}
115+
},
100116
async addNewFragmentToSnippetsById (id: string) {
101117
const folderStore = useFolderStore()
102118
const content = [...this.snippet!.content]
@@ -112,6 +128,7 @@ export const useSnippetStore = defineStore('snippets', {
112128
body.content = content
113129

114130
await this.patchSnippetsById(id, body)
131+
await this.getSnippetsByFolderIds(folderStore.selectedIds)
115132
await this.getSnippetsById(id)
116133
},
117134
async deleteCurrentSnippetFragmentByIndex (index: number) {

0 commit comments

Comments
 (0)