Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/main/api/routes/snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,5 +342,32 @@ app
},
},
)
// Удаление содержимого сниппета
.delete(
'/:id/contents/:contentId',
({ params, set }) => {
const { contentId } = params

const result = db
.prepare(
`
DELETE FROM snippet_contents WHERE id = ?
`,
)
.run(contentId)

if (!result.changes) {
set.status = 404
throw new Error('Snippet content not found')
}

return { message: 'Snippet content deleted' }
},
{
detail: {
tags: ['Snippets'],
},
},
)

export default app
24 changes: 21 additions & 3 deletions src/renderer/components/editor/Tab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@ import { useApp, useSnippets, useSnippetUpdate } from '@/composables'
import { i18n } from '@/electron'

interface Props {
id: number
index: number
name: string
}

const props = defineProps<Props>()

const { selectedSnippetContent, selectedSnippet } = useSnippets()
const { selectedSnippetContent, selectedSnippet, deleteSnippetContent }
= useSnippets()
const { addToUpdateContentQueue } = useSnippetUpdate()
const { highlightedSnippetId, highlightedFolderId } = useApp()
const {
highlightedSnippetId,
highlightedFolderId,
selectedSnippetContentIndex,
} = useApp()

const tabRef = ref<HTMLDivElement>()
const isEdit = ref(false)
Expand All @@ -37,6 +44,17 @@ function onClickContextMenu() {
highlightedSnippetId.value = undefined
highlightedFolderId.value = undefined
}

async function onDelete() {
await deleteSnippetContent(selectedSnippet.value!.id, props.id)

if (selectedSnippetContentIndex.value === props.index) {
selectedSnippetContentIndex.value = 0
}
else if (selectedSnippetContentIndex.value > props.index) {
selectedSnippetContentIndex.value--
}
}
</script>

<template>
Expand All @@ -62,7 +80,7 @@ function onClickContextMenu() {
}}</span>"
</ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item>
<ContextMenu.Item @click="onDelete">
{{ i18n.t("delete") }} "<span class="max-w-36 truncate">{{
name
}}</span>"
Expand Down
27 changes: 21 additions & 6 deletions src/renderer/components/editor/header/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useApp, useSnippets, useSnippetUpdate } from '@/composables'
import { i18n } from '@/electron'
import { Plus, Type } from 'lucide-vue-next'

const { selectedSnippet } = useSnippets()
const { selectedSnippetContentIndex } = useApp()
const { selectedSnippet, createSnippetContent } = useSnippets()
const { selectedSnippetContentIndex, isFocusedSnippetName } = useApp()
const { addToUpdateQueue } = useSnippetUpdate()

const isShowDescription = ref(false)
Expand All @@ -23,6 +23,14 @@ const name = computed({
})
},
})

async function onAddFragment() {
const index = await createSnippetContent(selectedSnippet.value!.id)

if (index) {
selectedSnippetContentIndex.value = index
}
}
</script>

<template>
Expand All @@ -35,18 +43,23 @@ const name = computed({
v-model="name"
variant="ghost"
class="w-full px-0"
:select="isFocusedSnippetName"
@blur="isFocusedSnippetName = false"
/>
</div>
<div class="ml-2 flex">
<EditorHeaderActionButton
<UiActionButton
:tooltip="i18n.t('addDescription')"
@click="isShowDescription = !isShowDescription"
>
<Type class="h-3 w-3" />
</EditorHeaderActionButton>
<EditorHeaderActionButton :tooltip="i18n.t('newFragment')">
</UiActionButton>
<UiActionButton
:tooltip="i18n.t('newFragment')"
@click="onAddFragment"
>
<Plus class="h-4 w-4" />
</EditorHeaderActionButton>
</UiActionButton>
</div>
</div>
<div
Expand All @@ -55,7 +68,9 @@ const name = computed({
>
<EditorTab
v-for="(i, index) in selectedSnippet?.contents"
:id="i.id"
:key="i.id"
:index="index"
:name="i.label"
:class="{
'bg-list-selection text-list-selection-fg':
Expand Down
23 changes: 16 additions & 7 deletions src/renderer/components/snippet/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ const {
getSnippets,
selectSnippet,
selectFirstSnippet,
createSnippet,
} = useSnippets()
const { selectedSnippetContentIndex, selectedSnippetIdBeforeSearch } = useApp()
const {
selectedSnippetContentIndex,
selectedSnippetIdBeforeSearch,
isFocusedSnippetName,
} = useApp()

async function search() {
if (searchQuery.value) {
Expand All @@ -28,6 +33,12 @@ async function search() {
}
}

async function onAddSnippet() {
await createSnippet()
selectFirstSnippet()
isFocusedSnippetName.value = true
}

function clear() {
searchQuery.value = ''
}
Expand Down Expand Up @@ -56,14 +67,12 @@ watch(searchQuery, () => {
>
<X class="h-4 w-4" />
</UiButton>
<UiButton
v-else
variant="icon"
size="icon"
@click="clear"
<UiActionButton
:tooltip="i18n.t('newSnippet')"
@click="onAddSnippet"
>
<Plus class="h-4 w-4" />
</UiButton>
</UiActionButton>
</div>
</div>
</template>
60 changes: 47 additions & 13 deletions src/renderer/components/snippet/Item.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { SnippetsResponse } from '@/services/api/generated'
import * as ContextMenu from '@/components/ui/shadcn/context-menu'
import { useApp, useSnippets } from '@/composables'
import { i18n } from '@/electron'
import { onClickOutside } from '@vueuse/core'
import { format } from 'date-fns'

Expand All @@ -14,8 +16,15 @@ const {
selectedSnippetId,
highlightedSnippetId,
selectedSnippetIdBeforeSearch,
isFocusedSnippetName,
} = useApp()
const { selectSnippet, isSearch } = useSnippets()
const {
selectSnippet,
isSearch,
deleteSnippet,
selectFirstSnippet,
duplicateSnippet,
} = useSnippets()

const isFocused = ref(false)
const snippetRef = ref<HTMLDivElement>()
Expand All @@ -39,6 +48,17 @@ function onClickContextMenu() {
highlightedSnippetId.value = props.snippet.id
}

async function onDelete() {
await deleteSnippet(props.snippet.id)
selectFirstSnippet()
}

async function onDuplicate() {
await duplicateSnippet(props.snippet.id)
selectFirstSnippet()
isFocusedSnippetName.value = true
}

onClickOutside(snippetRef, () => {
isFocused.value = false
highlightedSnippetId.value = undefined
Expand All @@ -58,19 +78,33 @@ onClickOutside(snippetRef, () => {
@click="onSnippetClick(snippet.id)"
@contextmenu="onClickContextMenu"
>
<div class="flex flex-col p-2 select-none">
<div class="mb-2 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap">
{{ snippet.name }}
</div>
<div class="meta text-text-muted flex justify-between text-xs">
<div>
{{ snippet.folder?.name || "Inbox" }}
</div>
<div>
{{ format(new Date(snippet.createdAt), "dd.MM.yyyy") }}
<ContextMenu.Root>
<ContextMenu.Trigger>
<div class="flex flex-col p-2 select-none">
<div
class="mb-2 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap"
>
{{ snippet.name || i18n.t("snippet.untitled") }}
</div>
<div class="meta text-text-muted flex justify-between text-xs">
<div>
{{ snippet.folder?.name || "Inbox" }}
</div>
<div>
{{ format(new Date(snippet.createdAt), "dd.MM.yyyy") }}
</div>
</div>
</div>
</div>
</div>
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item @click="onDuplicate">
{{ i18n.t("duplicate") }}
</ContextMenu.Item>
<ContextMenu.Item @click="onDelete">
{{ i18n.t("delete") }}
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
</div>
</template>

Expand Down
3 changes: 3 additions & 0 deletions src/renderer/composables/useApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const selectedSnippetContentIndex = ref(0)
const highlightedFolderId = ref<number>()
const highlightedSnippetId = ref<number>()

const isFocusedSnippetName = ref(false)

const sidebarWidth = useCssVar('--sidebar-width')
const snippetListWidth = useCssVar('--snippet-list-width')

Expand Down Expand Up @@ -59,5 +61,6 @@ export function useApp() {
selectFolder,
sidebarWidth,
snippetListWidth,
isFocusedSnippetName,
}
}
Loading