修复bug
This commit is contained in:
@@ -13,6 +13,7 @@ import { useState, useEffect, useRef, useMemo } from "react";
|
||||
import BottomNav from "@/components/BottomNav";
|
||||
import { FeatureGate } from "@/components/FeatureGate";
|
||||
import { navigateToSelect } from "./SelectPage";
|
||||
import { cn } from "@/lib/utils";
|
||||
import localeZh from "@/locales/data-zh.json";
|
||||
import localeZhHK from "@/locales/data-zh-HK.json";
|
||||
import localeEn from "@/locales/data-en.json";
|
||||
@@ -33,7 +34,15 @@ function IOSToggle({ checked, onChange }: { checked: boolean; onChange: (v: bool
|
||||
);
|
||||
}
|
||||
|
||||
function CyanSlider({ value, min, max, step = 0.1, onChange, onRelease }: {
|
||||
function CyanSlider({
|
||||
value,
|
||||
min,
|
||||
max,
|
||||
step = 0.1,
|
||||
onChange,
|
||||
onRelease,
|
||||
disabled = false,
|
||||
}: {
|
||||
value: number;
|
||||
min: number;
|
||||
max: number;
|
||||
@@ -41,19 +50,36 @@ function CyanSlider({ value, min, max, step = 0.1, onChange, onRelease }: {
|
||||
onChange: (v: number) => void;
|
||||
/** Fires once when the user releases the thumb (pointer/mouse/touch). Read value from DOM to avoid stale React state. */
|
||||
onRelease?: (v: number) => void;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const fillPct = ((value - min) / (max - min)) * 100;
|
||||
const emitRelease = (el: EventTarget | null) => {
|
||||
if (disabled) return;
|
||||
if (!(el instanceof HTMLInputElement)) return;
|
||||
onRelease?.(Number(el.value));
|
||||
};
|
||||
return (
|
||||
<div className="relative flex items-center w-full mt-3">
|
||||
<div className="absolute left-0 h-[4px] rounded-full pointer-events-none"
|
||||
style={{ width: `${fillPct}%`, background: "#00FFF6", boxShadow: "0 0 6px rgba(0,255,246,0.5)" }} />
|
||||
<input type="range" min={min} max={max} step={step} value={value}
|
||||
<div className={cn("relative flex items-center w-full mt-3", disabled && "opacity-60")}>
|
||||
<div
|
||||
className="absolute left-0 h-[4px] rounded-full pointer-events-none"
|
||||
style={{
|
||||
width: `${fillPct}%`,
|
||||
background: disabled ? "rgba(148,163,184,0.7)" : "#00FFF6",
|
||||
boxShadow: disabled ? "none" : "0 0 6px rgba(0,255,246,0.5)",
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
className="cyan-slider relative z-10"
|
||||
onChange={(e) => onChange(Number(e.target.value))}
|
||||
onChange={(e) => {
|
||||
if (disabled) return;
|
||||
onChange(Number(e.target.value));
|
||||
}}
|
||||
onPointerUp={(e) => emitRelease(e.currentTarget)}
|
||||
onPointerCancel={(e) => emitRelease(e.currentTarget)}
|
||||
onKeyUp={(e) => {
|
||||
@@ -190,8 +216,17 @@ export default function EffectsPage() {
|
||||
<IOSToggle checked={sceneOn} onChange={(v) => updateSetting({ effect_enable: v ? 1 : 0 })} />
|
||||
</div>
|
||||
<button
|
||||
className="flex items-center justify-between w-full active:opacity-70 transition-opacity"
|
||||
onClick={() => goSelect(effectText.selectStyleTitle, sceneLabels, sceneVal, "effect_value")}>
|
||||
type="button"
|
||||
disabled={!sceneOn}
|
||||
className={cn(
|
||||
"flex items-center justify-between w-full transition-opacity",
|
||||
sceneOn ? "active:opacity-70" : "opacity-45 cursor-not-allowed",
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!sceneOn) return;
|
||||
goSelect(effectText.selectStyleTitle, sceneLabels, sceneVal, "effect_value");
|
||||
}}
|
||||
>
|
||||
<span className="text-[15px] text-white/55">{sceneDisplay}</span>
|
||||
<ChevronRight size={16} className="ios-chevron" />
|
||||
</button>
|
||||
@@ -211,16 +246,20 @@ export default function EffectsPage() {
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
disabled={!widthOn}
|
||||
onChange={(v) => {
|
||||
if (!widthOn) return;
|
||||
isDragging.current = true;
|
||||
setLocalWidth(Math.round(v));
|
||||
}}
|
||||
onRelease={(v) => {
|
||||
if (!widthOn) return;
|
||||
isDragging.current = false;
|
||||
const w = Math.round(v);
|
||||
setLocalWidth(w);
|
||||
updateSetting({ width_value: w });
|
||||
}} />
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* ── 交叉反馈 ── */}
|
||||
@@ -230,8 +269,17 @@ export default function EffectsPage() {
|
||||
<IOSToggle checked={crossfeedOn} onChange={(v) => updateSetting({ crossfeed_enable: v ? 1 : 0 })} />
|
||||
</div>
|
||||
<button
|
||||
className="flex items-center justify-between w-full active:opacity-70 transition-opacity"
|
||||
onClick={() => goSelect(effectText.selectCrossfeedTitle, crossfeedLabels, crossfeedVal, "crossfeed_value")}>
|
||||
type="button"
|
||||
disabled={!crossfeedOn}
|
||||
className={cn(
|
||||
"flex items-center justify-between w-full transition-opacity",
|
||||
crossfeedOn ? "active:opacity-70" : "opacity-45 cursor-not-allowed",
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!crossfeedOn) return;
|
||||
goSelect(effectText.selectCrossfeedTitle, crossfeedLabels, crossfeedVal, "crossfeed_value");
|
||||
}}
|
||||
>
|
||||
<span className="text-[14px] text-white/45">{crossfeedDisplay}</span>
|
||||
<ChevronRight size={16} className="ios-chevron" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user