mirror of
https://github.com/kokonect-link/cherrypick
synced 2024-11-27 22:38:34 +09:00
Merge pull request #400
* Feat (Frontend): DefaultStore: Add 'renoteVisibilitySelection' * Impl (Frontend): Add 'addDividersBetweenMenuSections' utility functio… * Fix (Frontend): Fix 'Prefer named exports' warn * Refactor (Frontend): use addDividersBetweenMenuSections instead of us… * Impl (Frontend): Add 'visibilityRenoteItems' to support new feature * Merge branch 'develop' into renote-visibility * Impl (Frontend): Add getQuoteMenu to separate home quote, channel quote * Locale (Frontend): Update ko-KR, en-US * Impl (Frontend): Apply changes to MkSubNoteContent also * Fix (Frontend): renote menu condition * Locale (Frontend): reuse exist string * Fix mistake * Fix mistake (...) * Fix (Frontend): change button order
This commit is contained in:
parent
214047c76b
commit
3b2ffa15ac
@ -1277,6 +1277,7 @@ additionalPermissionsForFlash: "Allow to add permission to Play"
|
||||
thisFlashRequiresTheFollowingPermissions: "This Play requires the following permissions"
|
||||
doYouWantToAllowThisPlayToAccessYourAccount: "Do you want to allow this Play to access your account?"
|
||||
translateProfile: "Translate profile"
|
||||
showRenoteVisibilitySelector: "Show renote visibility selector"
|
||||
_nsfwOpenBehavior:
|
||||
click: "Click to open"
|
||||
doubleClick: "Double click to open"
|
||||
|
1
locales/index.d.ts
vendored
1
locales/index.d.ts
vendored
@ -1289,6 +1289,7 @@ export interface Locale {
|
||||
"thisFlashRequiresTheFollowingPermissions": string;
|
||||
"doYouWantToAllowThisPlayToAccessYourAccount": string;
|
||||
"translateProfile": string;
|
||||
"showRenoteVisibilitySelector": string;
|
||||
"_nsfwOpenBehavior": {
|
||||
"click": string;
|
||||
"doubleClick": string;
|
||||
|
@ -1286,6 +1286,7 @@ additionalPermissionsForFlash: "Playへの追加許可"
|
||||
thisFlashRequiresTheFollowingPermissions: "このPlayは以下の権限を要求しています"
|
||||
doYouWantToAllowThisPlayToAccessYourAccount: "このPlayによるアカウントへのアクセスを許可しますか?"
|
||||
translateProfile: "プロフィールを翻訳する"
|
||||
showRenoteVisibilitySelector: "TRANSLATME-showRenoteVisibilitySelector"
|
||||
|
||||
_nsfwOpenBehavior:
|
||||
click: "タップして開く"
|
||||
|
@ -1277,6 +1277,7 @@ additionalPermissionsForFlash: "Play에 대한 추가 권한"
|
||||
thisFlashRequiresTheFollowingPermissions: "이 Play는 다음 권한을 요구해요"
|
||||
doYouWantToAllowThisPlayToAccessYourAccount: "이 Play가 계정에 접근하도록 허용할까요?"
|
||||
translateProfile: "프로필 번역하기"
|
||||
showRenoteVisibilitySelector: "리노트 공개범위 옵션 표시"
|
||||
_nsfwOpenBehavior:
|
||||
click: "탭하여 열기"
|
||||
doubleClick: "두 번 탭하여 열기"
|
||||
|
@ -146,7 +146,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
v-tooltip="i18n.ts.renote"
|
||||
:class="$style.footerButton"
|
||||
class="_button"
|
||||
@click.stop="defaultStore.state.renoteQuoteButtonSeparation ? renoteOnly() : renote()"
|
||||
@click.stop="(defaultStore.state.renoteQuoteButtonSeparation && !defaultStore.state.renoteVisibilitySelection && !appearNote.channel) || (defaultStore.state.renoteQuoteButtonSeparation && appearNote.channel && !appearNote.channel.allowRenoteToExternal) || (defaultStore.state.renoteQuoteButtonSeparation && appearNote.visibility === 'followers') ? renoteOnly() : renote()"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ appearNote.renoteCount }}</p>
|
||||
@ -164,7 +164,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<button v-if="appearNote.myReaction != null && appearNote.reactionAcceptance == 'likeOnly'" ref="reactButton" v-vibrate="defaultStore.state.vibrateSystem ? [30, 50, 50] : []" v-tooltip="i18n.ts.removeReaction" :class="$style.footerButton" class="_button" @click.stop="undoReact(appearNote)">
|
||||
<i class="ti ti-heart-minus"></i>
|
||||
</button>
|
||||
<button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click.stop="quote()">
|
||||
<button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" ref="quoteButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click.stop="quote()">
|
||||
<i class="ti ti-quote"></i>
|
||||
</button>
|
||||
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.clip" :class="$style.footerButton" class="_button" @click.stop="clip()">
|
||||
@ -222,7 +222,7 @@ import { reactionPicker } from '@/scripts/reaction-picker.js';
|
||||
import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { getAbuseNoteMenu, getCopyNoteLinkMenu, getNoteClipMenu, getNoteMenu, getRenoteMenu, getRenoteOnly } from '@/scripts/get-note-menu.js';
|
||||
import { getAbuseNoteMenu, getCopyNoteLinkMenu, getNoteClipMenu, getNoteMenu, getRenoteMenu, getRenoteOnly, getQuoteMenu } from '@/scripts/get-note-menu.js';
|
||||
import { useNoteCapture } from '@/scripts/use-note-capture.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
import { useTooltip } from '@/scripts/use-tooltip.js';
|
||||
@ -293,6 +293,7 @@ const isRenote = (
|
||||
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const menuButton = shallowRef<HTMLElement>();
|
||||
const quoteButton = shallowRef<HTMLElement>();
|
||||
const renoteButton = shallowRef<HTMLElement>();
|
||||
const renoteTime = shallowRef<HTMLElement>();
|
||||
const reactButton = shallowRef<HTMLElement>();
|
||||
@ -418,19 +419,27 @@ function quote(viaKeyboard = false): void {
|
||||
return;
|
||||
}
|
||||
if (appearNote.value.channel) {
|
||||
if (appearNote.value.channel.allowRenoteToExternal) {
|
||||
const { menu } = getQuoteMenu({ note: note.value, mock: props.mock });
|
||||
os.popupMenu(menu, quoteButton.value, {
|
||||
viaKeyboard,
|
||||
});
|
||||
} else {
|
||||
os.post({
|
||||
renote: appearNote.value,
|
||||
channel: appearNote.value.channel,
|
||||
animation: !viaKeyboard,
|
||||
}, () => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
os.post({
|
||||
renote: appearNote.value,
|
||||
channel: appearNote.value.channel,
|
||||
animation: !viaKeyboard,
|
||||
}, () => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
os.post({
|
||||
renote: appearNote.value,
|
||||
}, () => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
|
||||
function reply(viaKeyboard = false): void {
|
||||
|
@ -80,7 +80,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
v-tooltip="i18n.ts.renote"
|
||||
:class="$style.footerButton"
|
||||
class="_button"
|
||||
@click.stop="defaultStore.state.renoteQuoteButtonSeparation ? renoteOnly() : renote()"
|
||||
@click.stop="(defaultStore.state.renoteQuoteButtonSeparation && !defaultStore.state.renoteVisibilitySelection && !note.channel) || (defaultStore.state.renoteQuoteButtonSeparation && note.channel && !note.channel.allowRenoteToExternal) || (defaultStore.state.renoteQuoteButtonSeparation && note.visibility === 'followers') ? renoteOnly() : renote()"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="note.renoteCount > 0" :class="$style.footerButtonCount">{{ note.renoteCount }}</p>
|
||||
@ -98,7 +98,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<button v-if="note.myReaction != null && note.reactionAcceptance == 'likeOnly'" ref="reactButton" v-vibrate="defaultStore.state.vibrateSystem ? [30, 50, 50] : []" v-tooltip="i18n.ts.removeReaction" :class="$style.footerButton" class="_button" @click.stop="undoReact(note)">
|
||||
<i class="ti ti-heart-minus"></i>
|
||||
</button>
|
||||
<button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click.stop="quote()">
|
||||
<button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" ref="quoteButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click.stop="quote()">
|
||||
<i class="ti ti-quote"></i>
|
||||
</button>
|
||||
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.clip" :class="$style.footerButton" class="_button" @click.stop="clip()">
|
||||
@ -136,7 +136,7 @@ import { notePage } from '@/filters/note.js';
|
||||
import { useTooltip } from '@/scripts/use-tooltip.js';
|
||||
import { pleaseLogin } from '@/scripts/please-login.js';
|
||||
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
|
||||
import { getNoteClipMenu, getNoteMenu, getRenoteMenu, getRenoteOnly } from '@/scripts/get-note-menu.js';
|
||||
import { getNoteClipMenu, getNoteMenu, getRenoteMenu, getRenoteOnly, getQuoteMenu } from '@/scripts/get-note-menu.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
import { reactionPicker } from '@/scripts/reaction-picker.js';
|
||||
import { claimAchievement } from '@/scripts/achievements.js';
|
||||
@ -165,6 +165,7 @@ const note = ref(deepClone(props.note));
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const menuButton = shallowRef<HTMLElement>();
|
||||
const renoteButton = shallowRef<HTMLElement>();
|
||||
const quoteButton = shallowRef<HTMLElement>();
|
||||
const reactButton = shallowRef<HTMLElement>();
|
||||
const heartReactButton = shallowRef<HTMLElement>();
|
||||
const clipButton = shallowRef<HTMLElement>();
|
||||
@ -248,19 +249,27 @@ function quote(viaKeyboard = false): void {
|
||||
return;
|
||||
}
|
||||
if (props.note.channel) {
|
||||
if (props.note.channel.allowRenoteToExternal) {
|
||||
const { menu } = getQuoteMenu({ note: note.value, mock: props.mock });
|
||||
os.popupMenu(menu, quoteButton.value, {
|
||||
viaKeyboard,
|
||||
});
|
||||
} else {
|
||||
os.post({
|
||||
renote: props.note,
|
||||
channel: props.note.channel,
|
||||
animation: !viaKeyboard,
|
||||
}, () => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
os.post({
|
||||
renote: props.note,
|
||||
channel: props.note.channel,
|
||||
animation: !viaKeyboard,
|
||||
}, () => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
os.post({
|
||||
renote: props.note,
|
||||
}, () => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
|
||||
function reply(viaKeyboard = false): void {
|
||||
|
@ -74,6 +74,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkSwitch v-model="infoButtonForNoteActionsEnabled">{{ i18n.ts.infoButtonForNoteActions }}<template #caption>{{ i18n.ts.infoButtonForNoteActionsDescription }}</template> <span class="_beta">CherryPick</span></MkSwitch>
|
||||
<MkSwitch v-model="showReplyInNotification">{{ i18n.ts.showReplyInNotification }} <span class="_beta">CherryPick</span></MkSwitch>
|
||||
<MkSwitch v-model="renoteQuoteButtonSeparation">{{ i18n.ts.renoteQuoteButtonSeparation }} <span class="_beta">CherryPick</span></MkSwitch>
|
||||
<MkSwitch v-model="renoteVisibilitySelection">{{ i18n.ts.showRenoteVisibilitySelector }} <span class="_beta">CherryPick</span></MkSwitch>
|
||||
<MkSwitch v-model="showFixedPostFormInReplies">{{ i18n.ts.showFixedPostFormInReplies }}<template #caption>{{ i18n.ts.showFixedPostFormInRepliesDescription }}</template> <span class="_beta">CherryPick</span></MkSwitch>
|
||||
<MkSwitch v-model="allMediaNoteCollapse">{{ i18n.ts.allMediaNoteCollapse }} <span class="_beta">CherryPick</span></MkSwitch>
|
||||
</div>
|
||||
@ -426,6 +427,7 @@ const showFixedPostFormInReplies = computed(defaultStore.makeGetterSetter('showF
|
||||
const showingAnimatedImages = computed(defaultStore.makeGetterSetter('showingAnimatedImages'));
|
||||
const allMediaNoteCollapse = computed(defaultStore.makeGetterSetter('allMediaNoteCollapse'));
|
||||
const nsfwOpenBehavior = computed(defaultStore.makeGetterSetter('nsfwOpenBehavior'));
|
||||
const renoteVisibilitySelection = computed(defaultStore.makeGetterSetter('renoteVisibilitySelection'));
|
||||
|
||||
watch(lang, () => {
|
||||
miLocalStorage.setItem('lang', lang.value as string);
|
||||
|
@ -0,0 +1,17 @@
|
||||
import { MenuItem } from '@/types/menu.js';
|
||||
|
||||
// Add dividers between menu sections. if some menu section has menu item
|
||||
export function addDividersBetweenMenuSections(...sections:MenuItem[][]): MenuItem[] {
|
||||
const result:MenuItem[] = [];
|
||||
|
||||
let needDivider = false;
|
||||
for (const section of sections) {
|
||||
if (section.length !== 0) {
|
||||
if (needDivider) result.push({ type: 'divider' });
|
||||
needDivider = true;
|
||||
result.push(...section);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -19,6 +19,8 @@ import { clipsCache } from '@/cache.js';
|
||||
import { MenuItem } from '@/types/menu.js';
|
||||
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||
import { isSupportShare } from '@/scripts/navigator.js';
|
||||
import { addDividersBetweenMenuSections } from '@/scripts/add-dividers-between-menu-sections.js';
|
||||
import { ap } from 'vitest/dist/reporters-5f784f42.js';
|
||||
|
||||
export async function getNoteClipMenu(props: {
|
||||
note: Misskey.entities.Note;
|
||||
@ -548,6 +550,49 @@ function smallerVisibility(a: Visibility | string, b: Visibility | string): Visi
|
||||
return 'public';
|
||||
}
|
||||
|
||||
export function getQuoteMenu(props: {
|
||||
note: Misskey.entities.Note,
|
||||
mock?: boolean;
|
||||
}) {
|
||||
const isRenote = (
|
||||
props.note.renote != null &&
|
||||
props.note.text == null &&
|
||||
props.note.fileIds.length === 0 &&
|
||||
props.note.poll == null
|
||||
);
|
||||
const menu: MenuItem[] = [];
|
||||
const appearNote = isRenote ? props.note.renote as Misskey.entities.Note : props.note;
|
||||
|
||||
if (!appearNote.channel || appearNote.channel.allowRenoteToExternal) {
|
||||
menu.push({
|
||||
text: i18n.ts.quote,
|
||||
icon: 'ti ti-quote',
|
||||
action: () => {
|
||||
os.post({
|
||||
renote: appearNote,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (appearNote.channel) {
|
||||
menu.push({
|
||||
text: i18n.ts.inChannelQuote,
|
||||
icon: 'ti ti-device-tv',
|
||||
action: () => {
|
||||
if (!props.mock) {
|
||||
os.post({
|
||||
renote: appearNote,
|
||||
channel: appearNote.channel,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return { menu };
|
||||
}
|
||||
|
||||
export function getRenoteMenu(props: {
|
||||
note: Misskey.entities.Note;
|
||||
renoteButton: Ref<HTMLElement>;
|
||||
@ -564,9 +609,11 @@ export function getRenoteMenu(props: {
|
||||
|
||||
const channelRenoteItems: MenuItem[] = [];
|
||||
const normalRenoteItems: MenuItem[] = [];
|
||||
const visibilityRenoteItems: MenuItem[] = [];
|
||||
|
||||
// Add channel renote/quote buttons
|
||||
if (appearNote.channel) {
|
||||
channelRenoteItems.push(...[{
|
||||
const channelRenoteButton = {
|
||||
text: i18n.ts.inChannelRenote,
|
||||
icon: 'ti ti-repeat',
|
||||
action: () => {
|
||||
@ -587,22 +634,32 @@ export function getRenoteMenu(props: {
|
||||
});
|
||||
}
|
||||
},
|
||||
}, {
|
||||
text: i18n.ts.inChannelQuote,
|
||||
icon: 'ti ti-quote',
|
||||
action: () => {
|
||||
if (!props.mock) {
|
||||
os.post({
|
||||
renote: appearNote,
|
||||
channel: appearNote.channel,
|
||||
});
|
||||
}
|
||||
},
|
||||
}]);
|
||||
};
|
||||
if (defaultStore.state.renoteQuoteButtonSeparation) {
|
||||
normalRenoteItems.unshift(channelRenoteButton);
|
||||
} else {
|
||||
channelRenoteItems.push(channelRenoteButton);
|
||||
}
|
||||
|
||||
// Add quote button if quote button is not separated
|
||||
if (!defaultStore.state.renoteQuoteButtonSeparation) {
|
||||
channelRenoteItems.push({
|
||||
text: i18n.ts.inChannelQuote,
|
||||
icon: 'ti ti-quote',
|
||||
action: () => {
|
||||
if (!props.mock) {
|
||||
os.post({
|
||||
renote: appearNote,
|
||||
channel: appearNote.channel,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!appearNote.channel || appearNote.channel.allowRenoteToExternal) {
|
||||
normalRenoteItems.push(...[{
|
||||
normalRenoteItems.push({
|
||||
text: i18n.ts.renote,
|
||||
icon: 'ti ti-repeat',
|
||||
action: () => {
|
||||
@ -633,22 +690,86 @@ export function getRenoteMenu(props: {
|
||||
});
|
||||
}
|
||||
},
|
||||
}, (props.mock) ? undefined : {
|
||||
text: i18n.ts.quote,
|
||||
icon: 'ti ti-quote',
|
||||
action: () => {
|
||||
os.post({
|
||||
renote: appearNote,
|
||||
});
|
||||
},
|
||||
}]);
|
||||
});
|
||||
|
||||
// Add quote button if quote button is not separated
|
||||
if (!props.mock && !defaultStore.state.renoteQuoteButtonSeparation) {
|
||||
normalRenoteItems.push({
|
||||
text: i18n.ts.quote,
|
||||
icon: 'ti ti-quote',
|
||||
action: () => {
|
||||
os.post({
|
||||
renote: appearNote,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const renoteItems = [
|
||||
...normalRenoteItems,
|
||||
...(channelRenoteItems.length > 0 && normalRenoteItems.length > 0) ? [{ type: 'divider' }] : [],
|
||||
...channelRenoteItems,
|
||||
];
|
||||
// Add visibility section
|
||||
if (
|
||||
defaultStore.state.renoteVisibilitySelection &&
|
||||
!['followers', 'specified'].includes(appearNote.visibility)
|
||||
&& (!appearNote.channel || appearNote.channel.allowRenoteToExternal)
|
||||
) {
|
||||
// renote to public
|
||||
if (appearNote.visibility === 'public') {
|
||||
visibilityRenoteItems.push({
|
||||
text: `${i18n.ts.renote} (${i18n.ts._visibility.public})`,
|
||||
icon: 'ti ti-world',
|
||||
action: () => {
|
||||
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
|
||||
os.api('notes/create', {
|
||||
localOnly,
|
||||
visibility: 'public',
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// renote to home
|
||||
if (['home', 'public'].includes(appearNote.visibility)) {
|
||||
visibilityRenoteItems.push({
|
||||
text: `${i18n.ts.renote} (${i18n.ts._visibility.home})`,
|
||||
icon: 'ti ti-home',
|
||||
action: () => {
|
||||
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
|
||||
os.api('notes/create', {
|
||||
localOnly,
|
||||
visibility: 'home',
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// renote to followers
|
||||
visibilityRenoteItems.push({
|
||||
text: `${i18n.ts.renote} (${i18n.ts._visibility.followers})`,
|
||||
icon: 'ti ti-lock',
|
||||
action: () => {
|
||||
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
|
||||
os.api('notes/create', {
|
||||
localOnly,
|
||||
visibility: 'followers',
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const renoteItems = addDividersBetweenMenuSections(
|
||||
normalRenoteItems,
|
||||
channelRenoteItems,
|
||||
visibilityRenoteItems,
|
||||
);
|
||||
|
||||
return {
|
||||
menu: renoteItems,
|
||||
|
@ -537,6 +537,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
renoteVisibilitySelection: {
|
||||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
showFixedPostFormInReplies: {
|
||||
where: 'device',
|
||||
default: true,
|
||||
|
Loading…
Reference in New Issue
Block a user