diff --git a/apps/native/src/app/title/[id].tsx b/apps/native/src/app/title/[id].tsx
index 0fd13ef..a652810 100644
--- a/apps/native/src/app/title/[id].tsx
+++ b/apps/native/src/app/title/[id].tsx
@@ -104,17 +104,6 @@ export default function TitleDetailScreen() {
}),
);
- const watchAll = useMutation(
- orpc.titles.watchAll.mutationOptions({
- onSuccess: () => {
- toast.success("Marked all episodes as watched");
- queryClient.invalidateQueries({ queryKey: orpc.titles.key() });
- queryClient.invalidateQueries({ queryKey: orpc.dashboard.key() });
- },
- onError: () => toast.error("Failed to mark all episodes as watched"),
- }),
- );
-
const quickAddMutation = useMutation(
orpc.titles.quickAdd.mutationOptions({
onSuccess: () => {
@@ -193,10 +182,10 @@ export default function TitleDetailScreen() {
{/* Actions skeleton */}
-
-
-
-
+
+
+
+
{/* Overview skeleton */}
@@ -415,57 +404,52 @@ export default function TitleDetailScreen() {
entering={FadeInDown.duration(300).delay(200)}
className="mt-4 px-4"
>
- {
- if (status === null) {
- updateStatus.mutate({ id, status: null });
- } else if (status === "watchlist") {
- quickAddMutation.mutate({
- tmdbId: title.tmdbId,
- type: title.type,
- });
- } else if (status === "completed" && title.type === "movie") {
- watchMovie.mutate({ id });
- } else if (status === "completed" && title.type === "tv") {
- watchAll.mutate({ id });
- } else {
- updateStatus.mutate({ id, status });
+
+ {
+ if (status === "watchlist") {
+ quickAddMutation.mutate({
+ tmdbId: title.tmdbId,
+ type: title.type,
+ });
+ } else {
+ updateStatus.mutate({ id, status: null });
+ }
+ }}
+ isPending={
+ updateStatus.isPending ||
+ quickAddMutation.isPending ||
+ watchMovie.isPending
}
- }}
- isPending={
- updateStatus.isPending ||
- quickAddMutation.isPending ||
- watchMovie.isPending ||
- watchAll.isPending
- }
- />
-
-
- updateRating.mutate({ id, stars })}
- accentColor={titleAccent}
/>
{title.type === "movie" && (
watchMovie.mutate({ id })}
disabled={watchMovie.isPending}
- className="flex-row items-center gap-1.5 rounded-full bg-title-accent px-4 py-2"
+ className="flex-row items-center gap-1.5 rounded-lg bg-title-accent px-4 py-2"
>
{watchMovie.isPending ? (
) : (
<>
-
+
Mark Watched
>
)}
)}
+
+
+
+ updateRating.mutate({ id, stars })}
+ accentColor={titleAccent}
+ />
diff --git a/apps/native/src/components/titles/status-action-button.tsx b/apps/native/src/components/titles/status-action-button.tsx
index 5660039..6b20f03 100644
--- a/apps/native/src/components/titles/status-action-button.tsx
+++ b/apps/native/src/components/titles/status-action-button.tsx
@@ -1,15 +1,33 @@
import {
- IconBookmark,
- IconCircleCheck,
- IconPlayerPlay,
+ IconCheck,
+ IconPlayerPlayFilled,
+ IconPlus,
} from "@tabler/icons-react-native";
-import { Pressable, View } from "react-native";
+import { Pressable } from "react-native";
import { useCSSVariable } from "uniwind";
import { Text } from "@/components/ui/text";
import * as Haptics from "@/utils/haptics";
type TitleStatus = "watchlist" | "in_progress" | "completed";
+const watchingStyle = {
+ label: "Watching",
+ Icon: IconPlayerPlayFilled,
+ bgClass: "bg-title-accent/10 border-title-accent/20",
+ textClass: "text-title-accent",
+};
+
+const statusConfig = {
+ watchlist: watchingStyle,
+ in_progress: watchingStyle,
+ completed: {
+ label: "Completed",
+ Icon: IconCheck,
+ bgClass: "bg-status-completed/10 border-status-completed/20",
+ textClass: "text-status-completed",
+ },
+} as const;
+
export function StatusActionButton({
currentStatus,
onStatusChange,
@@ -19,46 +37,49 @@ export function StatusActionButton({
onStatusChange: (status: TitleStatus | null) => void;
isPending: boolean;
}) {
- const statuses: Array<{
- status: TitleStatus;
- label: string;
- Icon: typeof IconBookmark;
- }> = [
- { status: "watchlist", label: "Watchlist", Icon: IconBookmark },
- { status: "in_progress", label: "Watching", Icon: IconPlayerPlay },
- { status: "completed", label: "Completed", Icon: IconCircleCheck },
- ];
+ const [titleAccent, completedColor] = useCSSVariable([
+ "--color-title-accent",
+ "--color-status-completed",
+ ]) as [string, string];
- const primaryColor = useCSSVariable("--color-title-accent") as string;
- const mutedFgColor = useCSSVariable("--color-muted-foreground") as string;
+ const config = currentStatus
+ ? statusConfig[currentStatus as keyof typeof statusConfig]
+ : null;
+
+ if (!config) {
+ return (
+ {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ onStatusChange("watchlist");
+ }}
+ disabled={isPending}
+ className="flex-row items-center gap-1.5 rounded-lg border border-title-accent/20 bg-title-accent/10 px-4 py-2"
+ >
+
+
+ Watchlist
+
+
+ );
+ }
+
+ const iconColor =
+ currentStatus === "completed" ? completedColor : titleAccent;
return (
-
- {statuses.map(({ status, label, Icon }) => {
- const isActive = currentStatus === status;
- return (
- {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
- onStatusChange(isActive ? null : status);
- }}
- disabled={isPending}
- className={`flex-row items-center gap-1.5 rounded-full border px-3 py-2 ${
- isActive
- ? "border-title-accent bg-title-accent/10"
- : "border-border bg-card"
- }`}
- >
-
-
- {label}
-
-
- );
- })}
-
+ {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ onStatusChange(null);
+ }}
+ disabled={isPending}
+ className={`flex-row items-center gap-1.5 rounded-lg border px-4 py-2 ${config.bgClass}`}
+ >
+
+
+ {config.label}
+
+
);
}