mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(app): keep slowmode reset visible and localize markers (#1586)
This commit is contained in:
1 parent
27f459e6bd
commit
ab46d16d12
4 files changed
+21
-25
No files matched your search
+15
-24
@@ -3,6 +3,7 @@
|
|||||||
import styles from '@app/features/channel/components/modals/channel_tabs/ChannelOverviewTab.module.css';
|
import styles from '@app/features/channel/components/modals/channel_tabs/ChannelOverviewTab.module.css';
|
||||||
import {SettingsControlRow} from '@app/features/channel/components/modals/channel_tabs/channel_overview_tab/SettingsControlRow';
|
import {SettingsControlRow} from '@app/features/channel/components/modals/channel_tabs/channel_overview_tab/SettingsControlRow';
|
||||||
import type {FormInputs} from '@app/features/channel/components/modals/channel_tabs/channel_overview_tab/shared';
|
import type {FormInputs} from '@app/features/channel/components/modals/channel_tabs/channel_overview_tab/shared';
|
||||||
|
import {getCachedNumberFormat} from '@app/features/i18n/utils/IntlCache';
|
||||||
import {formatPermissionLabel} from '@app/features/permissions/utils/PermissionUtils';
|
import {formatPermissionLabel} from '@app/features/permissions/utils/PermissionUtils';
|
||||||
import {RESET_SLIDER_TO_DEFAULT_VALUE_DESCRIPTOR, Slider} from '@app/features/ui/components/Slider';
|
import {RESET_SLIDER_TO_DEFAULT_VALUE_DESCRIPTOR, Slider} from '@app/features/ui/components/Slider';
|
||||||
import {Permissions} from '@fluxer/constants/src/ChannelConstants';
|
import {Permissions} from '@fluxer/constants/src/ChannelConstants';
|
||||||
@@ -29,35 +30,27 @@ const SLOWMODE_DESCRIPTION_DESCRIPTOR = msg({
|
|||||||
comment:
|
comment:
|
||||||
'Description under the slowmode slider in channel settings. bypassSlowmodePermissionLabel is the localized Bypass Slowmode permission name.',
|
'Description under the slowmode slider in channel settings. bypassSlowmodePermissionLabel is the localized Bypass Slowmode permission name.',
|
||||||
});
|
});
|
||||||
const SLOWMODE_SECONDS_DESCRIPTOR = msg({
|
|
||||||
message: '{count, plural, one {# second} other {# seconds}}',
|
|
||||||
comment: 'Slowmode duration expressed in seconds, shown on the channel settings slowmode slider.',
|
|
||||||
});
|
|
||||||
const SLOWMODE_MINUTES_DESCRIPTOR = msg({
|
|
||||||
message: '{count, plural, one {# minute} other {# minutes}}',
|
|
||||||
comment: 'Slowmode duration expressed in minutes, shown on the channel settings slowmode slider.',
|
|
||||||
});
|
|
||||||
const SLOWMODE_HOURS_DESCRIPTOR = msg({
|
|
||||||
message: '{count, plural, one {# hour} other {# hours}}',
|
|
||||||
comment: 'Slowmode duration expressed in hours, shown on the channel settings slowmode slider.',
|
|
||||||
});
|
|
||||||
|
|
||||||
const SLOWMODE_STOP_SECONDS: ReadonlyArray<number> = [
|
const SLOWMODE_STOP_SECONDS: ReadonlyArray<number> = [
|
||||||
0, 5, 10, 15, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200, 21600,
|
0, 5, 10, 15, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200, 21600,
|
||||||
];
|
];
|
||||||
const SLOWMODE_MARKER_SECONDS: ReadonlyArray<number> = [0, 60, 3600, 21600];
|
|
||||||
|
type SlowmodeDurationUnit = 'second' | 'minute' | 'hour';
|
||||||
|
|
||||||
function formatSlowmodeDuration(i18n: I18n, seconds: number): string {
|
function formatSlowmodeDuration(i18n: I18n, seconds: number): string {
|
||||||
if (seconds === 0) {
|
const roundedSeconds = Math.max(0, Math.round(seconds));
|
||||||
|
if (roundedSeconds === 0) {
|
||||||
return i18n._(OFF_DESCRIPTOR);
|
return i18n._(OFF_DESCRIPTOR);
|
||||||
}
|
}
|
||||||
if (seconds % SECONDS_PER_HOUR === 0) {
|
let unit: SlowmodeDurationUnit = 'second';
|
||||||
return i18n._(SLOWMODE_HOURS_DESCRIPTOR, {count: seconds / SECONDS_PER_HOUR});
|
let value = roundedSeconds;
|
||||||
|
if (roundedSeconds % SECONDS_PER_HOUR === 0) {
|
||||||
|
unit = 'hour';
|
||||||
|
value = roundedSeconds / SECONDS_PER_HOUR;
|
||||||
|
} else if (roundedSeconds % SECONDS_PER_MINUTE === 0) {
|
||||||
|
unit = 'minute';
|
||||||
|
value = roundedSeconds / SECONDS_PER_MINUTE;
|
||||||
}
|
}
|
||||||
if (seconds % SECONDS_PER_MINUTE === 0) {
|
return getCachedNumberFormat(i18n.locale, {style: 'unit', unit, unitDisplay: 'long'}).format(value);
|
||||||
return i18n._(SLOWMODE_MINUTES_DESCRIPTOR, {count: seconds / SECONDS_PER_MINUTE});
|
|
||||||
}
|
|
||||||
return i18n._(SLOWMODE_SECONDS_DESCRIPTOR, {count: seconds});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SlowmodeControlProps {
|
interface SlowmodeControlProps {
|
||||||
@@ -99,9 +92,7 @@ export const SlowmodeControl: React.FC<SlowmodeControlProps> = ({form}) => {
|
|||||||
markers={SLOWMODE_STOP_SECONDS}
|
markers={SLOWMODE_STOP_SECONDS}
|
||||||
ariaLabel={slowmodeLabel}
|
ariaLabel={slowmodeLabel}
|
||||||
ariaValueText={formatSlowmodeDuration(i18n, currentSeconds)}
|
ariaValueText={formatSlowmodeDuration(i18n, currentSeconds)}
|
||||||
onMarkerRender={(seconds) =>
|
onMarkerRender={(seconds) => formatSlowmodeDuration(i18n, seconds)}
|
||||||
SLOWMODE_MARKER_SECONDS.includes(seconds) ? formatSlowmodeDuration(i18n, seconds) : null
|
|
||||||
}
|
|
||||||
onValueRender={(seconds) => formatSlowmodeDuration(i18n, Math.round(seconds))}
|
onValueRender={(seconds) => formatSlowmodeDuration(i18n, Math.round(seconds))}
|
||||||
onValueChange={(seconds) => field.onChange(Math.round(seconds))}
|
onValueChange={(seconds) => field.onChange(Math.round(seconds))}
|
||||||
showResetButton={true}
|
showResetButton={true}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
.resetButton:disabled {
|
.resetButton:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resetRow {
|
.resetRow {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export function SliderResetControls({
|
|||||||
canReset={canReset}
|
canReset={canReset}
|
||||||
onReset={onReset}
|
onReset={onReset}
|
||||||
ariaLabel={inlineLabel}
|
ariaLabel={inlineLabel}
|
||||||
|
alwaysVisible={true}
|
||||||
dataFlx="ui.slider.slider-reset-controls.reset-button"
|
dataFlx="ui.slider.slider-reset-controls.reset-button"
|
||||||
data-flx="ui.slider.slider-reset-controls.slider-reset-icon-button"
|
data-flx="ui.slider.slider-reset-controls.slider-reset-icon-button"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ interface SliderResetIconButtonProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
iconSize?: number;
|
iconSize?: number;
|
||||||
dataFlx?: string;
|
dataFlx?: string;
|
||||||
|
alwaysVisible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canResetSliderValue(value: number, factoryDefaultValue: number, disabled = false): boolean {
|
export function canResetSliderValue(value: number, factoryDefaultValue: number, disabled = false): boolean {
|
||||||
@@ -26,13 +27,15 @@ export function SliderResetIconButton({
|
|||||||
className,
|
className,
|
||||||
iconSize = 14,
|
iconSize = 14,
|
||||||
dataFlx = 'ui.slider.slider-reset-icon-button.button',
|
dataFlx = 'ui.slider.slider-reset-icon-button.button',
|
||||||
|
alwaysVisible = false,
|
||||||
}: SliderResetIconButtonProps): React.ReactElement | null {
|
}: SliderResetIconButtonProps): React.ReactElement | null {
|
||||||
if (!canReset) return null;
|
if (!canReset && !alwaysVisible) return null;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={clsx(styles.resetButton, className)}
|
className={clsx(styles.resetButton, className)}
|
||||||
onClick={onReset}
|
onClick={onReset}
|
||||||
|
disabled={!canReset}
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
data-flx={dataFlx}
|
data-flx={dataFlx}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in new issue
Block a user