diff --git a/apps/dashboard/.dev.vars.example b/apps/dashboard/.dev.vars.example index b1d4674..22ccee5 100644 --- a/apps/dashboard/.dev.vars.example +++ b/apps/dashboard/.dev.vars.example @@ -99,3 +99,18 @@ BETTER_AUTH_URL=http://localhost:3000 # 3. Set the same URL as the webhook URL in your GitHub App settings, # appending /api/webhooks/github DEV_TUNNEL_URL= + +# ----------------------------------------------------------------------------- +# 6. R2 comment media (optional) +# ----------------------------------------------------------------------------- +# Not required for the app to run. Without it, comment image/video uploads stay disabled +# (upload and finalize endpoints return a configuration error). +# +# Set to the public base URL for the SAME bucket Wrangler writes to (custom domain or r2.dev), +# no trailing slash. Example: https://pub-xxxxxxxxxxxxxxxx.r2.dev +# +# Local dev uses Miniflare by default: objects stay under .wrangler/state and do not show in the +# Cloudflare dashboard. wrangler.jsonc enables "remote": true on COMMENT_MEDIA so puts go to the +# real bucket named there (see bucket_name). Your pub URL must be for that bucket — not only +# preview_bucket_name (that name is for local simulation naming when not remote). +R2_PUBLIC_BASE_URL= diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 0c2c8f2..f643b15 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -43,6 +43,7 @@ "octokit": "^5.0.5", "react": "^19.2.0", "react-dom": "^19.2.0", + "react-dropzone": "^15.0.0", "tailwindcss": "^4.1.18" }, "devDependencies": { diff --git a/apps/dashboard/src/components/details/comment-reply-form.tsx b/apps/dashboard/src/components/details/comment-reply-form.tsx index 0281525..5ec2269 100644 --- a/apps/dashboard/src/components/details/comment-reply-form.tsx +++ b/apps/dashboard/src/components/details/comment-reply-form.tsx @@ -1,9 +1,13 @@ import { CommentIcon } from "@diffkit/icons"; -import { MarkdownEditor } from "@diffkit/ui/components/markdown-editor"; +import { + MarkdownEditor, + type MarkdownEditorHandle, +} from "@diffkit/ui/components/markdown-editor"; import { toast } from "@diffkit/ui/components/sonner"; import { Spinner } from "@diffkit/ui/components/spinner"; import { useQueryClient } from "@tanstack/react-query"; -import { useCallback, useState } from "react"; +import { useCallback, useRef, useState } from "react"; +import { useCommentMediaUpload } from "#/hooks/use-comment-media-upload"; import { createComment } from "#/lib/github.functions"; import { githubQueryKeys } from "#/lib/github.query"; import { checkPermissionWarning } from "#/lib/warning-store"; @@ -28,6 +32,10 @@ export function CommentReplyForm({ const [value, setValue] = useState(""); const [isSending, setIsSending] = useState(false); const queryClient = useQueryClient(); + const editorRef = useRef(null); + const commentActionsRef = useRef(null); + const { media: mediaUpload, onPaste: onMediaPaste } = + useCommentMediaUpload(editorRef); const handleSend = useCallback(async () => { if (!value.trim()) return; @@ -79,12 +87,19 @@ export function CommentReplyForm({ return (
-
+