feat: add WatchMedium field, general review editing, configurable deploy
Some checks failed
CI / Check / Test (push) Failing after 27m0s
Some checks failed
CI / Check / Test (push) Failing after 27m0s
- WatchMedium enum (cinema/streaming/tv/physical_media/download/media_server/other) - PATCH /api/v1/reviews/:id partial update (rating, comment, watched_at, watch_medium) - edit_review use case w/ ownership + remote review guard, best-effort AP Update broadcast - SPA: icon picker, edit sheet (long-press mobile / pencil desktop), watch medium badge - shared ReviewFormFields, EditableContextMenu, parse_watched_at/format_watched_at - deploy.sh parameterized (--features, --tag), CORS allows PATCH - CONTEXT.md glossary, ADR-0001 general review editing
This commit is contained in:
@@ -15,7 +15,9 @@ import { Textarea } from "@/components/ui/textarea"
|
||||
import { StarRating } from "@/components/star-rating"
|
||||
import { useAuth } from "@/components/auth-provider"
|
||||
import { useQueryClient } from "@tanstack/react-query"
|
||||
import { EditReviewSheet } from "@/components/edit-review-sheet"
|
||||
import { useInfiniteActivityFeed, useDeleteReview } from "@/hooks/use-diary"
|
||||
import type { FeedEntryDto } from "@/lib/api/diary"
|
||||
import { SearchOverlay } from "@/components/search-overlay"
|
||||
import type { MovieSelection } from "@/components/search-overlay"
|
||||
import { useInfiniteWatchlist, useAddToWatchlist, useRemoveFromWatchlist } from "@/hooks/use-watchlist"
|
||||
@@ -66,6 +68,7 @@ function FeedTab() {
|
||||
const { data, isPending, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteActivityFeed({ sort_by: sortBy })
|
||||
const deleteReview = useDeleteReview()
|
||||
const [editingEntry, setEditingEntry] = useState<FeedEntryDto | null>(null)
|
||||
const items = data?.pages.flatMap((p) => p.items) ?? []
|
||||
const loadMore = useCallback(() => fetchNextPage(), [fetchNextPage])
|
||||
|
||||
@@ -110,6 +113,7 @@ function FeedTab() {
|
||||
isFetching={isFetchingNextPage}
|
||||
onLoadMore={loadMore}
|
||||
renderItem={(entry) => {
|
||||
const isOwn = entry.user_id === auth?.user_id
|
||||
const card = (
|
||||
<ReviewCard
|
||||
movie={entry.movie}
|
||||
@@ -118,9 +122,10 @@ function FeedTab() {
|
||||
userId={entry.user_id}
|
||||
isFederated={entry.is_federated}
|
||||
actorUrl={entry.actor_url}
|
||||
onEdit={isOwn ? () => setEditingEntry(entry) : undefined}
|
||||
/>
|
||||
)
|
||||
return entry.user_id === auth?.user_id ? (
|
||||
return isOwn ? (
|
||||
<SwipeToDelete
|
||||
onDelete={() => deleteReview.mutate(entry.review.id)}
|
||||
confirmTitle={t("feed.deleteReview")}
|
||||
@@ -134,6 +139,16 @@ function FeedTab() {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{editingEntry && (
|
||||
<EditReviewSheet
|
||||
key={editingEntry.review.id}
|
||||
open={!!editingEntry}
|
||||
onOpenChange={(open) => !open && setEditingEntry(null)}
|
||||
movie={editingEntry.movie}
|
||||
review={editingEntry.review}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user