mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
feat(guild): require opt-in for emoji and sticker cloning (#2712)
This commit is contained in:
1 parent
7b15e5be0f
commit
3affd295e8
63 files changed
+4189
-1752
No files matched your search
+10
-1
@@ -39,7 +39,10 @@ import {
|
||||
HardwareAccelerationControl,
|
||||
NativeTitleBarControl,
|
||||
} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedDesktopControls';
|
||||
import {UnreadBadgeCustomizationControl} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedExperimentalControls';
|
||||
import {
|
||||
ExpressionCloneShortcutsControl,
|
||||
UnreadBadgeCustomizationControl,
|
||||
} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedExperimentalControls';
|
||||
import {
|
||||
OpenH264Control,
|
||||
ScreenShareAv1OptInControl,
|
||||
@@ -92,6 +95,7 @@ export const DIRECT_CONTROL_ITEM_IDS = new Set([
|
||||
'voice-video-screen-share-preview-behavior',
|
||||
'voice-video-screen-share-encoder-controls',
|
||||
'advanced-unread-badge-customization',
|
||||
'advanced-expression-clone-shortcuts',
|
||||
'client-developer-mode',
|
||||
'accessibility-stay-interactive-unfocused',
|
||||
'advanced-native-title-bar',
|
||||
@@ -129,6 +133,7 @@ export const COMPACT_SWITCH_CONTROL_ITEM_IDS = new Set([
|
||||
'voice-video-screen-share-av1-opt-in',
|
||||
'voice-video-screen-share-hevc-opt-in',
|
||||
'advanced-unread-badge-customization',
|
||||
'advanced-expression-clone-shortcuts',
|
||||
'client-developer-mode',
|
||||
'accessibility-stay-interactive-unfocused',
|
||||
'advanced-native-title-bar',
|
||||
@@ -305,6 +310,10 @@ export const AdvancedSettingControl = observer(({item}: {item: SearchableSetting
|
||||
return (
|
||||
<UnreadBadgeCustomizationControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.unread-badge-customization-control" />
|
||||
);
|
||||
case 'advanced-expression-clone-shortcuts':
|
||||
return (
|
||||
<ExpressionCloneShortcutsControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.expression-clone-shortcuts-control" />
|
||||
);
|
||||
case 'client-developer-mode':
|
||||
return (
|
||||
<DeveloperModeControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.developer-mode-control" />
|
||||
|
||||
+18
@@ -23,3 +23,21 @@ export const UnreadBadgeCustomizationControl = observer(() => {
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const ENABLE_EXPRESSION_CLONE_SHORTCUTS_DESCRIPTOR = msg({
|
||||
message: 'Enable emoji and sticker cloning shortcuts',
|
||||
comment: 'Short label for the experimental advanced setting.',
|
||||
});
|
||||
|
||||
export const ExpressionCloneShortcutsControl = observer(() => {
|
||||
const {i18n} = useLingui();
|
||||
return (
|
||||
<Switch
|
||||
ariaLabel={i18n._(ENABLE_EXPRESSION_CLONE_SHORTCUTS_DESCRIPTOR)}
|
||||
value={AdvancedSettings.expressionCloneShortcutsEnabled}
|
||||
onChange={AdvancedSettings.setExpressionCloneShortcutsEnabled}
|
||||
compact
|
||||
data-flx="user.advanced-settings-tab.switch.expression-clone-shortcuts"
|
||||
/>
|
||||
);
|
||||
});
|
||||
+42
@@ -28,6 +28,31 @@ const OPT_IN_TO_EXPERIMENTAL_UNREAD_BADGE_CONTROLS_DESCRIPTOR = msg({
|
||||
comment: 'Settings search entry description. One-line summary of what the setting controls.',
|
||||
});
|
||||
|
||||
const EMOJI_AND_STICKER_CLONING_SHORTCUTS_DESCRIPTOR = msg({
|
||||
message: 'Emoji and sticker cloning shortcuts',
|
||||
comment: 'Settings search entry label for opting into the emoji and sticker cloning shortcuts.',
|
||||
});
|
||||
const CLONE_EMOJI_DESCRIPTOR = msg({
|
||||
message: 'Clone emoji',
|
||||
comment: 'Settings search synonym. Used to match this term when the user types it in the settings search bar.',
|
||||
});
|
||||
const CLONE_STICKER_DESCRIPTOR = msg({
|
||||
message: 'Clone sticker',
|
||||
comment: 'Settings search synonym. Used to match this term when the user types it in the settings search bar.',
|
||||
});
|
||||
const COPY_EMOJI_DESCRIPTOR = msg({
|
||||
message: 'Copy emoji',
|
||||
comment: 'Settings search synonym. Used to match this term when the user types it in the settings search bar.',
|
||||
});
|
||||
const COPY_STICKER_DESCRIPTOR = msg({
|
||||
message: 'Copy sticker',
|
||||
comment: 'Settings search synonym. Used to match this term when the user types it in the settings search bar.',
|
||||
});
|
||||
const SHOW_A_ONE_CLICK_SHORTCUT_FOR_COPYING_EXPRESSIONS_DESCRIPTOR = msg({
|
||||
message: 'Show a one-click shortcut for copying custom emojis and stickers from communities that allow it',
|
||||
comment: 'Settings search entry description. One-line summary of what the setting controls.',
|
||||
});
|
||||
|
||||
export const advancedSettingsIndex: Array<SearchableSettingDescriptor> = [
|
||||
{
|
||||
id: 'advanced-unread-badge-customization',
|
||||
@@ -45,4 +70,21 @@ export const advancedSettingsIndex: Array<SearchableSettingDescriptor> = [
|
||||
addedAt: '2026-06-04T00:00:00.000Z',
|
||||
badges: ['experimental'],
|
||||
},
|
||||
{
|
||||
id: 'advanced-expression-clone-shortcuts',
|
||||
tabType: 'advanced_settings',
|
||||
label: EMOJI_AND_STICKER_CLONING_SHORTCUTS_DESCRIPTOR,
|
||||
keywords: [
|
||||
CLONE_EMOJI_DESCRIPTOR,
|
||||
CLONE_STICKER_DESCRIPTOR,
|
||||
COPY_EMOJI_DESCRIPTOR,
|
||||
COPY_STICKER_DESCRIPTOR,
|
||||
EXPERIMENTAL_DESCRIPTOR,
|
||||
],
|
||||
description: SHOW_A_ONE_CLICK_SHORTCUT_FOR_COPYING_EXPRESSIONS_DESCRIPTOR,
|
||||
audience: 'advanced',
|
||||
tags: ['chat'],
|
||||
addedAt: '2026-09-11T00:00:00.000Z',
|
||||
badges: ['experimental'],
|
||||
},
|
||||
];
|
||||
@@ -20,4 +20,10 @@ describe('Advanced settings', () => {
|
||||
expect(AdvancedSettings.unreadBadgeCustomizationEnabled).toBe(false);
|
||||
expect(AppStorage.getItem('AdvancedSettings:unreadBadgeCustomizationEnabled')).toBeNull();
|
||||
});
|
||||
|
||||
it('defaults the expression clone shortcuts preference to off and stores it under its own key', () => {
|
||||
expect(AdvancedSettings.expressionCloneShortcutsEnabled).toBe(false);
|
||||
AdvancedSettings.setExpressionCloneShortcutsEnabled(true);
|
||||
expect(AppStorage.getItem('AdvancedSettings:expressionCloneShortcutsEnabled')).toBe('true');
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import {makeAutoObservable} from 'mobx';
|
||||
|
||||
const UNREAD_BADGE_CUSTOMIZATION_STORAGE_KEY = 'AdvancedSettings:unreadBadgeCustomizationEnabled';
|
||||
const KEEP_ATTACHMENTS_ON_EMPTY_MESSAGE_EDIT_STORAGE_KEY = 'AdvancedSettings:keepAttachmentsOnEmptyMessageEdit';
|
||||
const EXPRESSION_CLONE_SHORTCUTS_STORAGE_KEY = 'AdvancedSettings:expressionCloneShortcutsEnabled';
|
||||
|
||||
function readStoredBoolean(key: string, defaultValue = false): boolean {
|
||||
const raw = AppStorage.getItem(key);
|
||||
@@ -20,6 +21,7 @@ function readStoredBoolean(key: string, defaultValue = false): boolean {
|
||||
class AdvancedSettings {
|
||||
unreadBadgeCustomizationEnabled = readStoredBoolean(UNREAD_BADGE_CUSTOMIZATION_STORAGE_KEY);
|
||||
keepAttachmentsOnEmptyMessageEdit = readStoredBoolean(KEEP_ATTACHMENTS_ON_EMPTY_MESSAGE_EDIT_STORAGE_KEY);
|
||||
expressionCloneShortcutsEnabled = readStoredBoolean(EXPRESSION_CLONE_SHORTCUTS_STORAGE_KEY);
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {}, {autoBind: true});
|
||||
@@ -38,6 +40,12 @@ class AdvancedSettings {
|
||||
},
|
||||
{key: KEEP_ATTACHMENTS_ON_EMPTY_MESSAGE_EDIT_STORAGE_KEY, source: 'external'},
|
||||
);
|
||||
AppStorage.subscribe(
|
||||
(event) => {
|
||||
this.expressionCloneShortcutsEnabled = event.newValue === null ? false : readStoredBoolean(event.key ?? '');
|
||||
},
|
||||
{key: EXPRESSION_CLONE_SHORTCUTS_STORAGE_KEY, source: 'external'},
|
||||
);
|
||||
}
|
||||
|
||||
setUnreadBadgeCustomizationEnabled(value: boolean): void {
|
||||
@@ -51,6 +59,12 @@ class AdvancedSettings {
|
||||
this.keepAttachmentsOnEmptyMessageEdit = value;
|
||||
AppStorage.setItem(KEEP_ATTACHMENTS_ON_EMPTY_MESSAGE_EDIT_STORAGE_KEY, JSON.stringify(value));
|
||||
}
|
||||
|
||||
setExpressionCloneShortcutsEnabled(value: boolean): void {
|
||||
if (this.expressionCloneShortcutsEnabled === value) return;
|
||||
this.expressionCloneShortcutsEnabled = value;
|
||||
AppStorage.setItem(EXPRESSION_CLONE_SHORTCUTS_STORAGE_KEY, JSON.stringify(value));
|
||||
}
|
||||
}
|
||||
|
||||
export default new AdvancedSettings();
|
||||
Reference in new issue
Block a user