feat(reels): collapsing icons hides the 3-dot menu too; add auto-scroll + playback speed

- 3-dot menu button previously rendered unconditionally alongside the
  collapse-toggle ("مثل اندروید" per the old comment, mirroring RN's
  pre-fix behavior) — now hidden when collapsed, matching RN's fix.
- Extended ExploreReelsUiContext with autoScrollEnabled (default off) and
  playbackSpeed (0.5x/1x/1.5x/2x), exposed via new rows in the options menu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
payacom
2026-09-17 17:03:16 +03:30
parent 83c2102afe
commit 1d1d3cd461
5 changed files with 77 additions and 1 deletions

View File

@@ -447,7 +447,9 @@ export default function ReelsPostActions({
className={cn("drop-shadow-lg invert", expanded && "opacity-80")}
/>
</button>
{optionsMenu}
{/* طبق خواسته‌ی کاربر: با جمع‌کردن آیکون‌ها فقط خودِ دکمه‌ی جمع‌کردن باقی
بمونه، پس منوی سه‌نقطه هم باید مثل بقیه‌ی اکشن‌ها مخفی بشه */}
{expanded ? optionsMenu : null}
</div>
)}
</>

View File

@@ -13,6 +13,11 @@ import { useTranslation } from "react-i18next";
import { useAppLanguage } from "@/contexts/LanguageProvider";
import { useQueryClient } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { cn } from "@/lib/utils";
import {
useExploreReelsUi,
type PlaybackSpeed,
} from "@/contexts/ExploreReelsUiContext";
const REPORT_REASON_IDS = [
"inappropriate",
@@ -22,6 +27,8 @@ const REPORT_REASON_IDS = [
"other",
] as const;
const SPEED_OPTIONS: PlaybackSpeed[] = [0.5, 1, 1.5, 2];
type Props = {
postData: Post;
isOwnPost: boolean;
@@ -42,6 +49,7 @@ export default function ReelsPostOptionsMenu({
const queryClient = useQueryClient();
const router = useRouter();
const canEdit = isOwnPost;
const exploreUi = useExploreReelsUi();
const [open, setOpen] = useState(false);
const [reportOpen, setReportOpen] = useState(false);
const [analyticsOpen, setAnalyticsOpen] = useState(false);
@@ -193,6 +201,55 @@ export default function ReelsPostOptionsMenu({
count: viewCount.toLocaleString(numberLocale),
})}
</button>
{exploreUi ? (
<>
<div className="flex items-center justify-between px-5 py-3.5 text-sm">
<span>{t("posts.autoScrollLabel")}</span>
<button
type="button"
role="switch"
aria-checked={exploreUi.autoScrollEnabled}
onClick={() =>
exploreUi.setAutoScrollEnabled(!exploreUi.autoScrollEnabled)
}
className={cn(
"relative h-6 w-11 shrink-0 rounded-full transition-colors",
exploreUi.autoScrollEnabled ? "bg-[#FC8EAC]" : "bg-neutral-300 dark:bg-neutral-700"
)}
>
<span
className={cn(
"absolute top-0.5 h-5 w-5 rounded-full bg-white transition-transform",
exploreUi.autoScrollEnabled ? "translate-x-0.5" : "translate-x-[22px]"
)}
/>
</button>
</div>
<div className="flex flex-wrap items-center justify-between gap-2 px-5 py-3.5 text-sm">
<span>{t("posts.playbackSpeedLabel")}</span>
<div className="flex items-center gap-1.5">
{SPEED_OPTIONS.map((option) => {
const active = exploreUi.playbackSpeed === option;
return (
<button
key={option}
type="button"
onClick={() => exploreUi.setPlaybackSpeed(option)}
className={cn(
"flex h-8 min-w-[40px] items-center justify-center rounded-2xl border px-2 text-xs font-semibold",
active
? "border-[#FC8EAC] bg-[rgba(252,142,172,0.1)] text-[#FC8EAC]"
: "border-[#C3C3C3] text-foreground"
)}
>
{option}x
</button>
);
})}
</div>
</div>
</>
) : null}
{isOwnPost ? (
<>
{canEdit ? (

View File

@@ -2,11 +2,18 @@
import React, { createContext, useContext, useState } from "react";
export type PlaybackSpeed = 0.5 | 1 | 1.5 | 2;
type ExploreReelsUiContextValue = {
chromeHidden: boolean;
setChromeHidden: (hidden: boolean) => void;
actionsExpanded: boolean;
setActionsExpanded: (expanded: boolean) => void;
/** پیش‌فرض غیرفعال، طبق خواسته‌ی کاربر */
autoScrollEnabled: boolean;
setAutoScrollEnabled: (enabled: boolean) => void;
playbackSpeed: PlaybackSpeed;
setPlaybackSpeed: (speed: PlaybackSpeed) => void;
};
const ExploreReelsUiContext = createContext<ExploreReelsUiContextValue | null>(
@@ -20,6 +27,8 @@ export function ExploreReelsUiProvider({
}) {
const [chromeHidden, setChromeHidden] = useState(false);
const [actionsExpanded, setActionsExpanded] = useState(true);
const [autoScrollEnabled, setAutoScrollEnabled] = useState(false);
const [playbackSpeed, setPlaybackSpeed] = useState<PlaybackSpeed>(1);
return (
<ExploreReelsUiContext.Provider
@@ -28,6 +37,10 @@ export function ExploreReelsUiProvider({
setChromeHidden,
actionsExpanded,
setActionsExpanded,
autoScrollEnabled,
setAutoScrollEnabled,
playbackSpeed,
setPlaybackSpeed,
}}
>
{children}

View File

@@ -1182,6 +1182,8 @@
"commentError": "Could not post comment",
"reportPost": "Report post",
"postViews": "Post views — {{count}}",
"autoScrollLabel": "Auto-scroll",
"playbackSpeedLabel": "Playback speed",
"viewAnalytics": "View insights",
"pinPost": "Pin post",
"unpinPost": "Unpin post",

View File

@@ -1182,6 +1182,8 @@
"commentError": "خطا در ثبت نظر",
"reportPost": "گزارش پست",
"postViews": "بازدید پست — {{count}}",
"autoScrollLabel": "پیمایش خودکار",
"playbackSpeedLabel": "سرعت پخش ویدیو",
"viewAnalytics": "دیدن اطلاعات آماری",
"pinPost": "پین کردن پست",
"unpinPost": "برداشتن پین",