1
0
Fork 0
mirror of https://github.com/paricafe/misskey.git synced 2025-04-21 15:33:07 -05:00

tweak preferences

This commit is contained in:
FLY_MC 2025-03-11 05:49:32 +08:00
parent 17e5524c0a
commit 93e9bbd35c
11 changed files with 139 additions and 74 deletions

View file

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-show="!isDeleted"
ref="rootEl"
v-hotkey="keymap"
:class="[$style.root, { [$style.showActionsOnlyHover]: prefer.s.showNoteActionsOnlyHover, [$style.skipRender]: prefer.s.skipNoteRender || store.s.enableRenderingOptimization }]"
:class="[$style.root, { [$style.showActionsOnlyHover]: prefer.s.showNoteActionsOnlyHover, [$style.skipRender]: prefer.s.skipNoteRender || prefer.s.enableRenderingOptimization }]"
:tabindex="isDeleted ? '-1' : '0'"
>
<div v-if="appearNote.reply && inReplyToCollapsed && !isRenote" :class="$style.collapsedInReplyTo">
@ -57,7 +57,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkNoteHeader :note="appearNote" :mini="true" @click.stop/>
</div>
</div>
<div :class="[{ [$style.noteClickToOpen]: store.s.noteClickToOpen }]" @click.stop="store.s.noteClickToOpen ? noteClickToOpen(appearNote.id) : undefined">
<div :class="[{ [$style.noteClickToOpen]: prefer.s.noteClickToOpen }]" @click.stop="prefer.s.noteClickToOpen ? noteClickToOpen(appearNote.id) : undefined">
<div style="container-type: inline-size;">
<p v-if="appearNote.cw != null" :class="$style.cw">
<Mfm
@ -137,7 +137,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-else :class="$style.footerButton" class="_button" disabled>
<i class="ti ti-ban"></i>
</button>
<button v-if="store.s.enableFallbackReactButton && appearNote.myReaction == null && appearNote.reactionAcceptance !== 'likeOnly' && !disableReactionsViewer" ref="likeButton" :class="$style.footerButton" class="_button" @click.stop="like()">
<button v-if="prefer.s.enableFallbackReactButton && appearNote.myReaction == null && appearNote.reactionAcceptance !== 'likeOnly' && !disableReactionsViewer" ref="likeButton" :class="$style.footerButton" class="_button" @click.stop="like()">
<i class="ti ti-heart"></i>
</button>
<button ref="reactButton" :class="$style.footerButton" class="_button" @click.stop="toggleReact()">
@ -240,7 +240,6 @@ import { getPluginHandlers } from '@/plugin.js';
import { useRouter } from '@/router/supplier.js';
import { miLocalStorage } from '@/local-storage.js';
import { spacingNote } from '@/utility/autospacing.js';
import { store } from '@/store.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@ -318,12 +317,12 @@ const renoteCollapsed = ref(
),
);
const defaultLike = computed(() => store.s.like ?? '❤️');
const defaultLike = computed(() => prefer.s.like ?? '❤️');
const enableTranslateButton = ref(store.s.enableTranslateButton);
const enableTranslateButton = ref(prefer.s.enableTranslateButton);
const inReplyToCollapsed = ref(store.s.collapseNotesRepliedTo);
const disableReactionsViewer = ref(store.s.disableReactionsViewer);
const inReplyToCollapsed = ref(prefer.s.collapseNotesRepliedTo);
const disableReactionsViewer = ref(prefer.s.disableReactionsViewer);
const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
type: 'lookup',

View file

@ -74,7 +74,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<i class="ti ti-rocket-off"></i>
</span>
</div>
<MkInstanceTicker v-if="showTicker" :style="{ cursor: store.s.clickToShowInstanceTickerWindow ? 'pointer' : 'default' }" :instance="appearNote.user.instance" :host="appearNote.user.host"/>
<MkInstanceTicker v-if="showTicker" :style="{ cursor: prefer.s.clickToShowInstanceTickerWindow ? 'pointer' : 'default' }" :instance="appearNote.user.instance" :host="appearNote.user.host"/>
</div>
</header>
<div :class="$style.noteContent">
@ -294,7 +294,6 @@ import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
import { miLocalStorage } from '@/local-storage.js';
import { spacingNote } from '@/utility/autospacing.js';
import { store } from '@/store.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@ -351,7 +350,7 @@ const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceT
const conversation = ref<Misskey.entities.Note[]>([]);
const replies = ref<Misskey.entities.Note[]>([]);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || appearNote.value.userId === $i?.id);
const defaultLike = computed(() => store.s.like ?? '❤️');
const defaultLike = computed(() => prefer.s.like ?? '❤️');
type ShowingNoteHistoryState = {
createdAt: string | null;
@ -360,9 +359,9 @@ type ShowingNoteHistoryState = {
} | null;
const showingNoteHistoryRef = ref<ShowingNoteHistoryState>(null);
const disableReactionsViewer = ref(store.s.disableReactionsViewer);
const disableReactionsViewer = ref(prefer.s.disableReactionsViewer);
const enableTranslateButton = ref(store.s.enableTranslateButton);
const enableTranslateButton = ref(prefer.s.enableTranslateButton);
const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
type: 'lookup',

View file

@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkA v-else :to="notePage(note)" :style="{ textDecoration: 'none', userSelect: 'none' }" @mouseenter="setDetail(true)" @mouseleave="setDetail(false)">
<MkTime
:time="note.createdAt"
:mode="(store.s.showDetailTimeWhenHover && isDetail) ? 'detail' : undefined"
:mode="(prefer.s.showDetailTimeWhenHover && isDetail) ? 'detail' : undefined"
colored
/>
</MkA>
@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
</div>
<div :class="$style.info"><MkInstanceTicker v-if="showTicker" :style="{ cursor: store.s.clickToShowInstanceTickerWindow ? 'pointer' : 'default' }" :instance="note.user.instance" :host="note.user.host"/></div>
<div :class="$style.info"><MkInstanceTicker v-if="showTicker" :style="{ cursor: prefer.s.clickToShowInstanceTickerWindow ? 'pointer' : 'default' }" :instance="note.user.instance" :host="note.user.host"/></div>
</div>
</header>
</template>
@ -52,7 +52,7 @@ import * as Misskey from 'misskey-js';
import { i18n } from '@/i18n.js';
import { notePage } from '@/filters/note.js';
import { userPage } from '@/filters/user.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
import MkInstanceTicker from '@/components/MkInstanceTicker.vue';
const isDetail = ref(false);
@ -64,7 +64,7 @@ const props = defineProps<{
note: Misskey.entities.Note;
}>();
const showTicker = (store.s.instanceTicker === 'always') || (store.s.instanceTicker === 'remote' && props.note.user.instance);
const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceTicker === 'remote' && props.note.user.instance);
const mock = inject<boolean>('mock', false);
</script>

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div :class="[$style.root, { [$style.collapsed]: collapsed }]">
<div :class="[{ [$style.noteClickToOpen]: store.s.noteClickToOpen }]" @click.stop="store.s.noteClickToOpen ? noteClickToOpen(note.id) : undefined">
<div :class="[{ [$style.noteClickToOpen]: prefer.s.noteClickToOpen }]" @click.stop="prefer.s.noteClickToOpen ? noteClickToOpen(note.id) : undefined">
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deletedNote }})</span>
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`" @click.stop><i class="ti ti-arrow-back-up"></i></MkA>
@ -36,7 +36,7 @@ import { shouldCollapsed } from '@@/js/collapsed.js';
import MkMediaList from '@/components/MkMediaList.vue';
import MkPoll from '@/components/MkPoll.vue';
import { i18n } from '@/i18n.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
import { useRouter } from '@/router/supplier.js';
const props = defineProps<{

View file

@ -178,7 +178,7 @@ const removeReaction = (reaction: string, ev: MouseEvent) => remove(pinnedEmojis
const chooseReaction = (ev: MouseEvent) => pickEmoji(pinnedEmojisForReaction, ev);
const setDefaultReaction = () => setDefault(pinnedEmojisForReaction);
const like = computed(defaultStore.makeGetterSetter('like'));
const like = computed(store.makeGetterSetter('like'));
const removeEmoji = (reaction: string, ev: MouseEvent) => remove(pinnedEmojis, reaction, ev);
const chooseEmoji = (ev: MouseEvent) => pickEmoji(pinnedEmojis, ev);
@ -252,12 +252,12 @@ function chooseNewLike(ev: MouseEvent) {
os.pickEmoji(getHTMLElement(ev), {
showPinned: false,
}).then(async emoji => {
defaultStore.set('like', emoji as string);
store.set('like', emoji as string);
});
}
async function resetLike() {
defaultStore.set('like', null);
store.set('like', null);
}
function getHTMLElement(ev: MouseEvent): HTMLElement {

View file

@ -12,7 +12,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m">
<div class="label">{{ i18n.ts.pariPlusSystemSettings }}</div>
<div class="_gaps_s">
<MkSwitch v-model="enableRenderingOptimization">{{ i18n.ts.enableRenderingOptimization }}</MkSwitch>
<MkPreferenceContainer k="enableRenderingOptimization">
<MkSwitch v-model="enableRenderingOptimization">{{ i18n.ts.enableRenderingOptimization }}</MkSwitch>
</MkPreferenceContainer>
</div>
</div>
</FormSection>
@ -64,24 +66,46 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m">
<div class="label">{{ i18n.ts.pariPlusNoteSettings }}</div>
<div class="_gaps_s">
<MkSwitch v-model="enableTranslateButton">{{ i18n.ts.enableTranslateButton }}</MkSwitch>
<MkSwitch v-model="showDetailTimeWhenHover">{{ i18n.ts.showDetailTimeWhenHover }}</MkSwitch>
<MkSwitch v-model="noteClickToOpen">{{ i18n.ts.noteClickToOpen }}</MkSwitch>
<MkSwitch v-model="enableFallbackReactButton">{{ i18n.ts.enableFallbackReactButton }}</MkSwitch>
<MkSwitch v-model="enableMFMCheatsheet">{{ i18n.ts.enableMFMCheatsheet }}</MkSwitch>
<MkSwitch v-model="enableUndoClearPostForm">{{ i18n.ts.enableUndoClearPostForm }}</MkSwitch>
<MkSwitch v-model="collapseNotesRepliedTo">{{ i18n.ts.collapseNotesRepliedTo }}</MkSwitch>
<MkSwitch v-model="disableReactionsViewer">{{ i18n.ts.disableReactionsViewer }}</MkSwitch>
<MkSwitch v-model="emojiAutoSpacing">{{ i18n.ts.emojiAutoSpacing }}</MkSwitch>
<MkSwitch v-model="clickToShowInstanceTickerWindow">{{ i18n.ts.clickToShowInstanceTickerWindow }}</MkSwitch>
<MkSelect v-model="autoSpacingBehaviour">
<template #label>{{ i18n.ts.autoSpacing }}</template>
<option :value="null">{{ i18n.ts.disabled }}</option>
<option value="special">Auto</option>
<option value="all">{{ i18n.ts.all }}</option>
<template #caption>{{ i18n.ts.autoSpacingDescription }}</template>
</MkSelect>
</div>
<MkPreferenceContainer k="enableTranslateButton">
<MkSwitch v-model="enableTranslateButton">{{ i18n.ts.enableTranslateButton }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="showDetailTimeWhenHover">
<MkSwitch v-model="showDetailTimeWhenHover">{{ i18n.ts.showDetailTimeWhenHover }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="noteClickToOpen">
<MkSwitch v-model="noteClickToOpen">{{ i18n.ts.noteClickToOpen }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="enableFallbackReactButton">
<MkSwitch v-model="enableFallbackReactButton">{{ i18n.ts.enableFallbackReactButton }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="enableMFMCheatsheet">
<MkSwitch v-model="enableMFMCheatsheet">{{ i18n.ts.enableMFMCheatsheet }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="enableUndoClearPostForm">
<MkSwitch v-model="enableUndoClearPostForm">{{ i18n.ts.enableUndoClearPostForm }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="collapseNotesRepliedTo">
<MkSwitch v-model="collapseNotesRepliedTo">{{ i18n.ts.collapseNotesRepliedTo }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="disableReactionsViewer">
<MkSwitch v-model="disableReactionsViewer">{{ i18n.ts.disableReactionsViewer }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="emojiAutoSpacing">
<MkSwitch v-model="emojiAutoSpacing">{{ i18n.ts.emojiAutoSpacing }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="clickToShowInstanceTickerWindow">
<MkSwitch v-model="clickToShowInstanceTickerWindow">{{ i18n.ts.clickToShowInstanceTickerWindow }}</MkSwitch>
</MkPreferenceContainer>
<MkPreferenceContainer k="autoSpacingBehaviour">
<MkSelect v-model="autoSpacingBehaviour">
<template #label>{{ i18n.ts.autoSpacing }}</template>
<option :value="null">{{ i18n.ts.disabled }}</option>
<option value="special">Auto</option>
<option value="all">{{ i18n.ts.all }}</option>
<template #caption>{{ i18n.ts.autoSpacingDescription }}</template>
</MkSelect>
</MkPreferenceContainer>
</div>
</div>
</FormSection>
</div>
@ -91,7 +115,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, ref } from 'vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
import { miLocalStorage } from '@/local-storage.js';
import { getDefaultFontSettings } from '@/utility/font-settings.js';
import MkSwitch from '@/components/MkSwitch.vue';
@ -101,6 +125,7 @@ import MkInfo from '@/components/MkInfo.vue';
import MkRange from '@/components/MkRange.vue';
import MkButton from '@/components/MkButton.vue';
import FormSection from '@/components/form/section.vue';
import MkPreferenceContainer from '@/components/MkPreferenceContainer.vue';
const defaultFont = getDefaultFontSettings();
console.log(defaultFont);
@ -117,19 +142,19 @@ function saveFontSize() {
fontSizeNumberOld.value = fontSizeNumber.value;
}
const enableRenderingOptimization = computed(store.makeGetterSetter('enableRenderingOptimization'));
const enableRenderingOptimization = prefer.model('enableRenderingOptimization');
const enableTranslateButton = computed(store.makeGetterSetter('enableTranslateButton'));
const showDetailTimeWhenHover = computed(store.makeGetterSetter('showDetailTimeWhenHover'));
const noteClickToOpen = computed(store.makeGetterSetter('noteClickToOpen'));
const enableFallbackReactButton = computed(store.makeGetterSetter('enableFallbackReactButton'));
const enableMFMCheatsheet = computed(store.makeGetterSetter('enableMFMCheatsheet'));
const enableUndoClearPostForm = computed(store.makeGetterSetter('enableUndoClearPostForm'));
const autoSpacingBehaviour = computed(store.makeGetterSetter('autoSpacingBehaviour'));
const collapseNotesRepliedTo = computed(store.makeGetterSetter('collapseNotesRepliedTo'));
const disableReactionsViewer = computed(store.makeGetterSetter('disableReactionsViewer'));
const emojiAutoSpacing = computed(store.makeGetterSetter('emojiAutoSpacing'));
const clickToShowInstanceTickerWindow = computed(store.makeGetterSetter('clickToShowInstanceTickerWindow'));
const enableTranslateButton = prefer.model('enableTranslateButton');
const showDetailTimeWhenHover = prefer.model('showDetailTimeWhenHover');
const noteClickToOpen = prefer.model('noteClickToOpen');
const enableFallbackReactButton = prefer.model('enableFallbackReactButton');
const enableMFMCheatsheet = prefer.model('enableMFMCheatsheet');
const enableUndoClearPostForm = prefer.model('enableUndoClearPostForm');
const autoSpacingBehaviour = prefer.model('autoSpacingBehaviour');
const collapseNotesRepliedTo = prefer.model('collapseNotesRepliedTo');
const disableReactionsViewer = prefer.model('disableReactionsViewer');
const emojiAutoSpacing = prefer.model('emojiAutoSpacing');
const clickToShowInstanceTickerWindow = prefer.model('clickToShowInstanceTickerWindow');
definePage(() => ({
title: 'Pari Plus!',

View file

@ -256,7 +256,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkPreferenceContainer k="serverDisconnectedBehavior">
<MkSelect v-model="serverDisconnectedBehavior">
<template #label><SearchLabel>{{ i18n.ts.whenServerDisconnected }}</SearchLabel></template>
<option value="null">{{ i18n.ts.doNothing }}</option>
<option value="doNothing">{{ i18n.ts.doNothing }}</option>
<option value="reload">{{ i18n.ts._serverDisconnectedBehavior.reload }}</option>
<option value="dialog">{{ i18n.ts._serverDisconnectedBehavior.dialog }}</option>
<option value="quiet">{{ i18n.ts._serverDisconnectedBehavior.quiet }}</option>

View file

@ -111,7 +111,7 @@ export const PREF_DEF = {
}[],
},
serverDisconnectedBehavior: {
default: 'quiet' as 'quiet' | 'reload' | 'dialog',
default: 'doNothing' as 'doNothing' | 'quiet' | 'reload' | 'dialog',
},
nsfw: {
default: 'respect' as 'respect' | 'force' | 'ignore',
@ -129,10 +129,10 @@ export const PREF_DEF = {
default: true,
},
showReactionsCount: {
default: false,
default: true,
},
enableQuickAddMfmFunction: {
default: false,
default: true,
},
loadRawImages: {
default: false,
@ -150,7 +150,7 @@ export const PREF_DEF = {
default: 'auto' as 'auto' | 'popup' | 'drawer',
},
useBlurEffectForModal: {
default: DEFAULT_DEVICE_KIND === 'desktop',
default: true,
},
useBlurEffect: {
default: DEFAULT_DEVICE_KIND === 'desktop',
@ -165,22 +165,22 @@ export const PREF_DEF = {
default: true,
},
useReactionPickerForContextMenu: {
default: false,
default: true,
},
showGapBetweenNotesInTimeline: {
default: false,
default: true,
},
instanceTicker: {
default: 'remote' as 'none' | 'remote' | 'always',
},
emojiPickerScale: {
default: 1,
default: 2,
},
emojiPickerWidth: {
default: 1,
default: 2,
},
emojiPickerHeight: {
default: 2,
default: 4,
},
emojiPickerStyle: {
default: 'auto' as 'auto' | 'popup' | 'drawer',
@ -219,13 +219,16 @@ export const PREF_DEF = {
default: 'expand' as 'expand' | '16_9' | '1_1' | '2_3',
},
notificationPosition: {
default: 'rightBottom' as 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom',
default: 'rightBottom' as 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom' | 'close',
},
notificationStackAxis: {
default: 'horizontal' as 'vertical' | 'horizontal',
},
notificationClickable: {
default: false,
},
enableCondensedLine: {
default: true,
default: false,
},
keepScreenOn: {
default: false,
@ -248,7 +251,7 @@ export const PREF_DEF = {
default: hemisphere as 'N' | 'S',
},
enableSeasonalScreenEffect: {
default: false,
default: DEFAULT_DEVICE_KIND === 'desktop',
},
enableHorizontalSwipe: {
default: true,
@ -269,7 +272,7 @@ export const PREF_DEF = {
default: 'app' as 'app' | 'appWithShift' | 'native',
},
skipNoteRender: {
default: true,
default: false,
},
showSoftWordMutedWord: {
default: false,
@ -319,6 +322,45 @@ export const PREF_DEF = {
sfxVolume: 1,
},
},
enableRenderingOptimization: {
default: true,
},
enableTranslateButton: {
default: false,
},
showDetailTimeWhenHover: {
default: true,
},
noteClickToOpen: {
default: true,
},
enableFallbackReactButton: {
default: true,
},
enableMFMCheatsheet: {
default: true,
},
enableUndoClearPostForm: {
default: true,
},
autoSpacingBehaviour: {
default: null as 'all' | 'special' | null,
},
collapseNotesRepliedTo: {
default: false,
},
disableReactionsViewer: {
default: false,
},
collapsedUnexpectedLangs: {
default: false,
},
emojiAutoSpacing: {
default: true,
},
clickToShowInstanceTickerWindow: {
default: true,
},
} satisfies Record<string, {
default: any;
accountDependent?: boolean;

View file

@ -210,7 +210,7 @@ export const store = markRaw(new Storage('base', {
},
serverDisconnectedBehavior: {
where: 'device',
default: 'null' as 'null' | 'quiet' | 'reload' | 'dialog',
default: 'doNothing' as 'doNothing' | 'quiet' | 'reload' | 'dialog',
},
nsfw: {
where: 'device',

View file

@ -8,7 +8,7 @@ import getCaretCoordinates from 'textarea-caret';
import { toASCII } from 'punycode.js';
import type { Ref } from 'vue';
import { popup } from '@/os.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
export type SuggestionType = 'user' | 'hashtag' | 'emoji' | 'mfmTag' | 'mfmParam';
@ -277,7 +277,7 @@ export class Autocomplete {
const trimmedBefore = before.substring(0, before.lastIndexOf(':'));
const after = source.substring(caret ?? 0);
if (store.s.emojiAutoSpacing) {
if (prefer.s.emojiAutoSpacing) {
const needSpaceBefore = trimmedBefore.length > 0 && !trimmedBefore.endsWith(' ');
const needSpaceAfter = !after.startsWith(' ');

View file

@ -1,5 +1,5 @@
import * as misskey from 'misskey-js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
const NO_SPACEING_LIST = [
'A股',
@ -45,12 +45,12 @@ function restoreHashtags(text: string): string {
}
export function autoSpacing(plainText: string) {
if (store.r.autoSpacingBehaviour.value == null) return plainText;
if (prefer.r.autoSpacingBehaviour.value == null) return plainText;
const textWithPlaceholders = preserveHashtags(plainText);
const rep = (matched: string, c1: string, c2: string, position: number) => {
if (store.r.autoSpacingBehaviour.value === 'all') return `${c1} ${c2}`;
if (prefer.r.autoSpacingBehaviour.value === 'all') return `${c1} ${c2}`;
const context = plainText
.slice(Math.max(0, position - LIST_WINDOW), position + LIST_WINDOW)
.toUpperCase();