Merge remote-tracking branch 'misskey-dev/develop' into io
This commit is contained in:
commit
9ab785c48f
94 changed files with 4169 additions and 2564 deletions
|
|
@ -9,6 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkSelect v-model="type" :class="$style.typeSelect">
|
||||
<option value="isLocal">{{ i18n.ts._role._condition.isLocal }}</option>
|
||||
<option value="isRemote">{{ i18n.ts._role._condition.isRemote }}</option>
|
||||
<option value="roleAssignedTo">{{ i18n.ts._role._condition.roleAssignedTo }}</option>
|
||||
<option value="createdLessThan">{{ i18n.ts._role._condition.createdLessThan }}</option>
|
||||
<option value="createdMoreThan">{{ i18n.ts._role._condition.createdMoreThan }}</option>
|
||||
<option value="followersLessThanOrEq">{{ i18n.ts._role._condition.followersLessThanOrEq }}</option>
|
||||
|
|
@ -51,6 +52,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<MkInput v-else-if="['followersLessThanOrEq', 'followersMoreThanOrEq', 'followingLessThanOrEq', 'followingMoreThanOrEq', 'notesLessThanOrEq', 'notesMoreThanOrEq'].includes(type)" v-model="v.value" type="number">
|
||||
</MkInput>
|
||||
|
||||
<MkSelect v-else-if="type === 'roleAssignedTo'" v-model="v.roleId">
|
||||
<option v-for="role in roles.filter(r => r.target === 'manual')" :key="role.id" :value="role.id">{{ role.name }}</option>
|
||||
</MkSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -62,6 +67,7 @@ import MkSelect from '@/components/MkSelect.vue';
|
|||
import MkButton from '@/components/MkButton.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
import { rolesCache } from '@/cache.js';
|
||||
|
||||
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
|
||||
|
||||
|
|
@ -77,6 +83,8 @@ const props = defineProps<{
|
|||
|
||||
const v = ref(deepClone(props.modelValue));
|
||||
|
||||
const roles = await rolesCache.fetch();
|
||||
|
||||
watch(() => props.modelValue, () => {
|
||||
if (JSON.stringify(props.modelValue) === JSON.stringify(v.value)) return;
|
||||
v.value = deepClone(props.modelValue);
|
||||
|
|
@ -92,6 +100,7 @@ const type = computed({
|
|||
if (t === 'and') v.value.values = [];
|
||||
if (t === 'or') v.value.values = [];
|
||||
if (t === 'not') v.value.value = { id: uuid(), type: 'isRemote' };
|
||||
if (t === 'roleAssignedTo') v.value.roleId = '';
|
||||
if (t === 'createdLessThan') v.value.sec = 86400;
|
||||
if (t === 'createdMoreThan') v.value.sec = 86400;
|
||||
if (t === 'followersLessThanOrEq') v.value.value = 10;
|
||||
|
|
|
|||
|
|
@ -280,6 +280,25 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionMax, 'mentionLimit'])">
|
||||
<template #label>{{ i18n.ts._role._options.mentionMax }}</template>
|
||||
<template #suffix>
|
||||
<span v-if="role.policies.mentionLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||
<span v-else>{{ role.policies.mentionLimit.value }}</span>
|
||||
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.mentionLimit)"></i></span>
|
||||
</template>
|
||||
<div class="_gaps">
|
||||
<MkSwitch v-model="role.policies.mentionLimit.useDefault" :readonly="readonly">
|
||||
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
|
||||
</MkSwitch>
|
||||
<MkInput v-model="role.policies.mentionLimit.value" :disabled="role.policies.mentionLimit.useDefault" type="number" :readonly="readonly">
|
||||
</MkInput>
|
||||
<MkRange v-model="role.policies.mentionLimit.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''">
|
||||
<template #label>{{ i18n.ts._role.priority }}</template>
|
||||
</MkRange>
|
||||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canInvite, 'canInvite'])">
|
||||
<template #label>{{ i18n.ts._role._options.canInvite }}</template>
|
||||
<template #suffix>
|
||||
|
|
|
|||
|
|
@ -96,6 +96,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkSwitch>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionMax, 'mentionLimit'])">
|
||||
<template #label>{{ i18n.ts._role._options.mentionMax }}</template>
|
||||
<template #suffix>{{ policies.mentionLimit }}</template>
|
||||
<MkInput v-model="policies.mentionLimit" type="number">
|
||||
</MkInput>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canInvite, 'canInvite'])">
|
||||
<template #label>{{ i18n.ts._role._options.canInvite }}</template>
|
||||
<template #suffix>{{ policies.canInvite ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ async function addRole(type: boolean) {
|
|||
const { canceled, result: role } = await os.select({
|
||||
items: roles.filter(r => r.isPublic).filter(r => !currentRoleIds.includes(r.id)).map(r => ({ text: r.name, value: r })),
|
||||
});
|
||||
if (canceled) return;
|
||||
if (canceled || role == null) return;
|
||||
|
||||
if (type) rolesThatCanBeUsedThisEmojiAsReaction.value.push(role);
|
||||
else rolesThatCanNotBeUsedThisEmojiAsReaction.value.push(role);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const directNotesPagination = {
|
|||
function setFilter(ev) {
|
||||
const typeItems = notificationTypes.map(t => ({
|
||||
text: i18n.ts._notification._types[t],
|
||||
active: includeTypes.value && includeTypes.value.includes(t),
|
||||
active: (includeTypes.value && includeTypes.value.includes(t)) ?? false,
|
||||
action: () => {
|
||||
includeTypes.value = [t];
|
||||
},
|
||||
|
|
@ -63,7 +63,7 @@ function setFilter(ev) {
|
|||
action: () => {
|
||||
includeTypes.value = null;
|
||||
},
|
||||
}, { type: 'divider' }, ...typeItems] : typeItems;
|
||||
}, { type: 'divider' as const }, ...typeItems] : typeItems;
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ if (defaultStore.state.uploadFolder) {
|
|||
|
||||
function chooseUploadFolder() {
|
||||
os.selectDriveFolder(false).then(async folder => {
|
||||
defaultStore.set('uploadFolder', folder ? folder.id : null);
|
||||
defaultStore.set('uploadFolder', folder[0] ? folder[0].id : null);
|
||||
os.success();
|
||||
if (defaultStore.state.uploadFolder) {
|
||||
uploadFolder.value = await misskeyApi('drive/folders/show', {
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ async function pickEmoji(itemsRef: Ref<string[]>, ev: MouseEvent) {
|
|||
os.pickEmoji(getHTMLElement(ev), {
|
||||
showPinned: false,
|
||||
}).then(it => {
|
||||
const emoji = it as string;
|
||||
const emoji = it;
|
||||
if (!itemsRef.value.includes(emoji)) {
|
||||
itemsRef.value.push(emoji);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<option value="following">{{ i18n.ts.following }}</option>
|
||||
<option value="follower">{{ i18n.ts.followers }}</option>
|
||||
<option value="mutualFollow">{{ i18n.ts.mutualFollow }}</option>
|
||||
<option value="followingOrFollower">{{ i18n.ts.followingOrFollower }}</option>
|
||||
<option value="list">{{ i18n.ts.userList }}</option>
|
||||
<option value="never">{{ i18n.ts.none }}</option>
|
||||
</MkSelect>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
$i.notificationRecieveConfig[type]?.type === 'following' ? i18n.ts.following :
|
||||
$i.notificationRecieveConfig[type]?.type === 'follower' ? i18n.ts.followers :
|
||||
$i.notificationRecieveConfig[type]?.type === 'mutualFollow' ? i18n.ts.mutualFollow :
|
||||
$i.notificationRecieveConfig[type]?.type === 'followingOrFollower' ? i18n.ts.followingOrFollower :
|
||||
$i.notificationRecieveConfig[type]?.type === 'list' ? i18n.ts.userList :
|
||||
i18n.ts.all
|
||||
}}
|
||||
|
|
@ -34,6 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<FormSection>
|
||||
<div class="_gaps_m">
|
||||
<FormLink @click="testNotification">{{ i18n.ts._notification.sendTestNotification }}</FormLink>
|
||||
<FormLink @click="flushNotification">{{ i18n.ts._notification.flushNotification }}</FormLink>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection>
|
||||
|
|
@ -113,6 +115,17 @@ function testNotification(): void {
|
|||
misskeyApi('notifications/test-notification');
|
||||
}
|
||||
|
||||
async function flushNotification() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts.resetAreYouSure,
|
||||
});
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
os.apiWithDialog('notifications/flush');
|
||||
}
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
const headerTabs = computed(() => []);
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ async function saveNew(): Promise<void> {
|
|||
|
||||
const { canceled, result: name } = await os.inputText({
|
||||
title: ts._preferencesBackups.inputName,
|
||||
default: '',
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
|
|
@ -372,6 +373,7 @@ async function rename(id: string): Promise<void> {
|
|||
|
||||
const { canceled: cancel1, result: name } = await os.inputText({
|
||||
title: ts._preferencesBackups.inputName,
|
||||
default: '',
|
||||
});
|
||||
if (cancel1 || profiles.value[id].name === name) return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue