diff --git a/components/canvas/CanvasRenderer.vue b/components/canvas/CanvasRenderer.vue index ed48fe9..3f1f5c8 100644 --- a/components/canvas/CanvasRenderer.vue +++ b/components/canvas/CanvasRenderer.vue @@ -10,11 +10,26 @@ const props = defineProps(); let dragging = false, posX = 0, posY = 0, dispX = ref(0), dispY = ref(0), minZoom = ref(0.1), zoom = ref(0.5); let lastDistance = 0; +let lastClickTime = 0; const onPointerDown = (event: PointerEvent) => { if (event.isPrimary === false) return; dragging = true; + const now = performance.now(); + if(now - lastClickTime < 500 && Math.abs(event.clientX - posX) < 20 && Math.abs(event.clientY - posY) < 20) + { + if(event.ctrlKey) + { + zoom.value = clamp(zoom.value * 0.9, minZoom.value, 3); + } + else + { + zoom.value = clamp(zoom.value * 1.1, minZoom.value, 3); + } + } + lastClickTime = now; + posX = event.clientX; posY = event.clientY; diff --git a/components/explorer/PreviewContent.vue b/components/explorer/PreviewContent.vue index 907b31a..dd184c3 100644 --- a/components/explorer/PreviewContent.vue +++ b/components/explorer/PreviewContent.vue @@ -1,15 +1,15 @@ + + diff --git a/components/prose/live/LiveH4.vue b/components/prose/live/LiveH4.vue index e149331..d6338c5 100644 --- a/components/prose/live/LiveH4.vue +++ b/components/prose/live/LiveH4.vue @@ -1,3 +1,9 @@ \ No newline at end of file +

+ +

+ + + diff --git a/components/prose/live/LiveH5.vue b/components/prose/live/LiveH5.vue index 9aa8d60..b85ab77 100644 --- a/components/prose/live/LiveH5.vue +++ b/components/prose/live/LiveH5.vue @@ -1,3 +1,11 @@ \ No newline at end of file +
+ +
+ + + diff --git a/components/prose/live/LiveH6.vue b/components/prose/live/LiveH6.vue index 60aeac8..9e63455 100644 --- a/components/prose/live/LiveH6.vue +++ b/components/prose/live/LiveH6.vue @@ -1,3 +1,11 @@ \ No newline at end of file +
+ +
+ + + diff --git a/db.sqlite b/db.sqlite index 382bbec..147e74e 100644 Binary files a/db.sqlite and b/db.sqlite differ diff --git a/layouts/default.vue b/layouts/default.vue index 26f7c15..e251748 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -36,7 +36,7 @@ function toggleNavigation(bool?: boolean)

Copyright Peaceultime - 2024

-
+
diff --git a/server/api/project/[projectId]/comment.get.ts b/server/api/project/[projectId]/comment.get.ts deleted file mode 100644 index 7f3a034..0000000 --- a/server/api/project/[projectId]/comment.get.ts +++ /dev/null @@ -1,27 +0,0 @@ -import useDatabase from '~/composables/useDatabase'; -import { Comment } from '~/types/api'; - -export default defineEventHandler(async (e) => { - const project = getRouterParam(e, "projectId"); - const query = getQuery(e); - - if(!project || !query.path) - { - setResponseStatus(e, 404); - return; - } - - const where = ["project = $project", "path = $path"]; - const criteria: Record = { $project: project, $path: query.path }; - - if(where.length > 1) - { - const db = useDatabase(); - - const content = db.query(`SELECT * FROM explorer_comments WHERE ${where.join(" and ")}`).all(criteria) as Comment[]; - - return content; - } - - setResponseStatus(e, 404); -}); \ No newline at end of file diff --git a/server/api/project/[projectId]/file/[path].get.ts b/server/api/project/[projectId]/file/[path].get.ts new file mode 100644 index 0000000..a03e65f --- /dev/null +++ b/server/api/project/[projectId]/file/[path].get.ts @@ -0,0 +1,41 @@ +import useDatabase from '~/composables/useDatabase'; +import type { CommentedFile, CommentSearch, File } from '~/types/api'; + +export default defineCachedEventHandler(async (e) => { + const project = getRouterParam(e, "projectId"); + const path = decodeURIComponent(getRouterParam(e, "path") ?? ''); + + if(!project) + { + setResponseStatus(e, 404); + return; + } + if(!path) + { + setResponseStatus(e, 404); + return; + } + + const where = ["project = $project", "path = $path"]; + const criteria: Record = { $project: project, $path: path }; + + if(where.length > 1) + { + const db = useDatabase(); + + const content = db.query(`SELECT * FROM explorer_files WHERE ${where.join(" and ")}`).get(criteria) as File; + + if(content !== undefined) + { + const comments = db.query(`SELECT comment.*, user.username FROM explorer_comments comment LEFT JOIN users user ON comment.user_id = user.id WHERE ${where.join(" and ")}`).all(criteria) as CommentSearch[]; + + return { ...content, comments } as CommentedFile; + } + } + + setResponseStatus(e, 404); + return; +}, { + maxAge: 60*60*24, + getKey: (e) => `file-${getRouterParam(e, "projectId")}-${getRouterParam(e, "path")}` + }); \ No newline at end of file diff --git a/server/api/project/[projectId]/tags/[tag].get.ts b/server/api/project/[projectId]/tags/[tag].get.ts new file mode 100644 index 0000000..b1bcb54 --- /dev/null +++ b/server/api/project/[projectId]/tags/[tag].get.ts @@ -0,0 +1,39 @@ +import useDatabase from '~/composables/useDatabase'; +import type { Tag } from '~/types/api'; + +export default defineCachedEventHandler(async (e) => { + const project = getRouterParam(e, "projectId"); + const tag = getRouterParam(e, "tag"); + const query = getQuery(e); + + if(!project) + { + setResponseStatus(e, 404); + return; + } + if(!tag) + { + setResponseStatus(e, 404); + return; + } + + const where = ["project = $project", "tag = $tag"]; + const criteria: Record = { $project: project, $tag: tag }; + + if(where.length > 1) + { + const db = useDatabase(); + + const content = db.query(`SELECT * FROM explorer_tags WHERE ${where.join(" and ")}`).get(criteria) as Tag; + + if(content !== undefined) + { + return content; + } + } + + setResponseStatus(e, 404); +}, { + maxAge: 60*60*24, + getKey: (e) => `tag-${getRouterParam(e, "projectId")}-${getRouterParam(e, "tag")}` + }); \ No newline at end of file diff --git a/types/api.d.ts b/types/api.d.ts index ebb271f..e79d033 100644 --- a/types/api.d.ts +++ b/types/api.d.ts @@ -52,6 +52,13 @@ export interface User { id: number; username: string; } +export interface Tag { + tag: string; + project: number; + description: string; +} + + export type ProjectSearch = Project & { pages: number; @@ -69,6 +76,10 @@ export type CommentSearch = Comment & export type UserSearch = User & { } +export type CommentedFile = File & +{ + comments: CommentSearch[]; +} export interface Search { projects: ProjectSearch[]; files: FileSearch[];