Merge branch 'develop' into dev
This commit is contained in:
commit
f2396b9acb
39 changed files with 732 additions and 154 deletions
|
|
@ -9,6 +9,7 @@ import MkAd from '@/components/global/MkAd.vue';
|
|||
import { isDebuggerEnabled, stackTraceInstances } from '@/debug.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { MisskeyEntity } from '@/types/date-separated-list.js';
|
||||
|
||||
|
|
@ -99,10 +100,10 @@ export default defineComponent({
|
|||
|
||||
return [el, separator];
|
||||
} else {
|
||||
if (props.ad && item._shouldInsertAd_) {
|
||||
if (props.ad && instance.ads.length > 0 && item._shouldInsertAd_) {
|
||||
return [h('div', {
|
||||
key: item.id + ':ad',
|
||||
style: 'padding: 8px; background-size: auto auto; background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--MI_THEME-bg) 8px, var(--MI_THEME-bg) 14px );',
|
||||
class: $style['ad-wrapper'],
|
||||
}, [h(MkAd, {
|
||||
prefer: ['horizontal', 'horizontal-big'],
|
||||
})]), el];
|
||||
|
|
@ -255,5 +256,11 @@ export default defineComponent({
|
|||
.date-2-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.ad-wrapper {
|
||||
padding: 8px;
|
||||
background-size: auto auto;
|
||||
background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--MI_THEME-bg) 8px, var(--MI_THEME-bg) 14px);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkSwitch>
|
||||
<MkButton v-show="mode === 'edit'" transparent :class="$style.testButton" :disabled="!(isActive && events.userCreated)" @click="test('userCreated')"><i class="ti ti-send"></i></MkButton>
|
||||
</div>
|
||||
<div :class="$style.switchBox">
|
||||
<MkSwitch v-model="events.inactiveModeratorsWarning" :disabled="disabledEvents.inactiveModeratorsWarning">
|
||||
<template #label>{{ i18n.ts._webhookSettings._systemEvents.inactiveModeratorsWarning }}</template>
|
||||
</MkSwitch>
|
||||
<MkButton v-show="mode === 'edit'" transparent :class="$style.testButton" :disabled="!(isActive && events.inactiveModeratorsWarning)" @click="test('inactiveModeratorsWarning')"><i class="ti ti-send"></i></MkButton>
|
||||
</div>
|
||||
<div :class="$style.switchBox">
|
||||
<MkSwitch v-model="events.inactiveModeratorsInvitationOnlyChanged" :disabled="disabledEvents.inactiveModeratorsInvitationOnlyChanged">
|
||||
<template #label>{{ i18n.ts._webhookSettings._systemEvents.inactiveModeratorsInvitationOnlyChanged }}</template>
|
||||
</MkSwitch>
|
||||
<MkButton v-show="mode === 'edit'" transparent :class="$style.testButton" :disabled="!(isActive && events.inactiveModeratorsInvitationOnlyChanged)" @click="test('inactiveModeratorsInvitationOnlyChanged')"><i class="ti ti-send"></i></MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="mode === 'edit'" :class="$style.description">
|
||||
|
|
@ -100,6 +112,8 @@ type EventType = {
|
|||
abuseReport: boolean;
|
||||
abuseReportResolved: boolean;
|
||||
userCreated: boolean;
|
||||
inactiveModeratorsWarning: boolean;
|
||||
inactiveModeratorsInvitationOnlyChanged: boolean;
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
@ -123,6 +137,8 @@ const events = ref<EventType>({
|
|||
abuseReport: true,
|
||||
abuseReportResolved: true,
|
||||
userCreated: true,
|
||||
inactiveModeratorsWarning: true,
|
||||
inactiveModeratorsInvitationOnlyChanged: true,
|
||||
});
|
||||
const isActive = ref<boolean>(true);
|
||||
|
||||
|
|
@ -130,6 +146,8 @@ const disabledEvents = ref<EventType>({
|
|||
abuseReport: false,
|
||||
abuseReportResolved: false,
|
||||
userCreated: false,
|
||||
inactiveModeratorsWarning: false,
|
||||
inactiveModeratorsInvitationOnlyChanged: false,
|
||||
});
|
||||
|
||||
const disableSubmitButton = computed(() => {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ watch(name, () => {
|
|||
// 空文字列をnullにしたいので??は使うな
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||
name: name.value || null,
|
||||
}, undefined, {
|
||||
'0b3f9f6a-2f4d-4b1f-9fb4-49d3a2fd7191': {
|
||||
title: i18n.ts.yourNameContainsProhibitedWords,
|
||||
text: i18n.ts.yourNameContainsProhibitedWordsDescription,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div ref="rootEl">
|
||||
<div ref="headerEl" :class="$style.header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
|
|
@ -22,12 +22,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, provide, inject, Ref, ref, watch, shallowRef } from 'vue';
|
||||
import { onMounted, onUnmounted, provide, inject, Ref, ref, watch, useTemplateRef } from 'vue';
|
||||
|
||||
import { CURRENT_STICKY_BOTTOM, CURRENT_STICKY_TOP } from '@@/js/const.js';
|
||||
|
||||
const headerEl = shallowRef<HTMLElement>();
|
||||
const footerEl = shallowRef<HTMLElement>();
|
||||
const rootEl = useTemplateRef('rootEl');
|
||||
const headerEl = useTemplateRef('headerEl');
|
||||
const footerEl = useTemplateRef('footerEl');
|
||||
|
||||
const headerHeight = ref<string | undefined>();
|
||||
const childStickyTop = ref(0);
|
||||
|
|
@ -76,6 +77,10 @@ onMounted(() => {
|
|||
onUnmounted(() => {
|
||||
observer.disconnect();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
rootEl,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang='scss' module>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { EventEmitter } from 'eventemitter3';
|
|||
import * as Misskey from 'misskey-js';
|
||||
import type { ComponentProps as CP } from 'vue-component-type-helpers';
|
||||
import type { Form, GetFormResultType } from '@/scripts/form.js';
|
||||
import type { MenuItem } from '@/types/menu.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -22,7 +23,6 @@ import MkPasswordDialog from '@/components/MkPasswordDialog.vue';
|
|||
import MkEmojiPickerDialog from '@/components/MkEmojiPickerDialog.vue';
|
||||
import MkPopupMenu from '@/components/MkPopupMenu.vue';
|
||||
import MkContextMenu from '@/components/MkContextMenu.vue';
|
||||
import type { MenuItem } from '@/types/menu.js';
|
||||
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
||||
import { pleaseLogin } from '@/scripts/please-login.js';
|
||||
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
|
||||
|
|
@ -35,6 +35,7 @@ export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey
|
|||
endpoint: E,
|
||||
data: P = {} as any,
|
||||
token?: string | null | undefined,
|
||||
customErrors?: Record<string, { title?: string; text: string; }>,
|
||||
) => {
|
||||
const promise = misskeyApi(endpoint, data, token);
|
||||
promiseDialog(promise, null, async (err) => {
|
||||
|
|
@ -77,6 +78,9 @@ export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey
|
|||
} else if (err.message.startsWith('Unexpected token')) {
|
||||
title = i18n.ts.gotInvalidResponseError;
|
||||
text = i18n.ts.gotInvalidResponseErrorDescription;
|
||||
} else if (customErrors && customErrors[err.id] != null) {
|
||||
title = customErrors[err.id].title;
|
||||
text = customErrors[err.id].text;
|
||||
}
|
||||
alert({
|
||||
type: 'error',
|
||||
|
|
@ -86,7 +90,7 @@ export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey
|
|||
});
|
||||
|
||||
return promise;
|
||||
}) as typeof misskeyApi;
|
||||
});
|
||||
|
||||
export function promiseDialog<T extends Promise<any>>(
|
||||
promise: T,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder>
|
||||
<template #icon><i class="ti ti-user-x"></i></template>
|
||||
<template #label>{{ i18n.ts.prohibitedWordsForNameOfUser }}</template>
|
||||
|
||||
<div class="_gaps">
|
||||
<MkTextarea v-model="prohibitedWordsForNameOfUser">
|
||||
<template #caption>{{ i18n.ts.prohibitedWordsForNameOfUserDescription }}<br>{{ i18n.ts.prohibitedWordsDescription2 }}</template>
|
||||
</MkTextarea>
|
||||
<MkButton primary @click="save_prohibitedWordsForNameOfUser">{{ i18n.ts.save }}</MkButton>
|
||||
</div>
|
||||
</MkFolder>
|
||||
|
||||
<MkFolder>
|
||||
<template #icon><i class="ti ti-eye-off"></i></template>
|
||||
<template #label>{{ i18n.ts.hiddenTags }}</template>
|
||||
|
|
@ -131,6 +143,7 @@ const enableRegistration = ref<boolean>(false);
|
|||
const emailRequiredForSignup = ref<boolean>(false);
|
||||
const sensitiveWords = ref<string>('');
|
||||
const prohibitedWords = ref<string>('');
|
||||
const prohibitedWordsForNameOfUser = ref<string>('');
|
||||
const hiddenTags = ref<string>('');
|
||||
const preservedUsernames = ref<string>('');
|
||||
const blockedHosts = ref<string>('');
|
||||
|
|
@ -143,10 +156,11 @@ async function init() {
|
|||
emailRequiredForSignup.value = meta.emailRequiredForSignup;
|
||||
sensitiveWords.value = meta.sensitiveWords.join('\n');
|
||||
prohibitedWords.value = meta.prohibitedWords.join('\n');
|
||||
prohibitedWordsForNameOfUser.value = meta.prohibitedWordsForNameOfUser.join('\n');
|
||||
hiddenTags.value = meta.hiddenTags.join('\n');
|
||||
preservedUsernames.value = meta.preservedUsernames.join('\n');
|
||||
blockedHosts.value = meta.blockedHosts.join('\n');
|
||||
silencedHosts.value = meta.silencedHosts.join('\n');
|
||||
silencedHosts.value = meta.silencedHosts?.join('\n') ?? '';
|
||||
mediaSilencedHosts.value = meta.mediaSilencedHosts.join('\n');
|
||||
}
|
||||
|
||||
|
|
@ -190,6 +204,14 @@ function save_prohibitedWords() {
|
|||
});
|
||||
}
|
||||
|
||||
function save_prohibitedWordsForNameOfUser() {
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
prohibitedWordsForNameOfUser: prohibitedWordsForNameOfUser.value.split('\n'),
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
});
|
||||
}
|
||||
|
||||
function save_hiddenTags() {
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
hiddenTags: hiddenTags.value.split('\n'),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkSwitch>
|
||||
</div>
|
||||
|
||||
<div class="_panel" style="padding: 16px;">
|
||||
<MkSwitch v-model="enableStatsForFederatedInstances" @change="onChange_enableStatsForFederatedInstances">
|
||||
<template #label>{{ i18n.ts.enableStatsForFederatedInstances }}</template>
|
||||
<template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template>
|
||||
</MkSwitch>
|
||||
</div>
|
||||
|
||||
<div class="_panel" style="padding: 16px;">
|
||||
<MkSwitch v-model="enableChartsForFederatedInstances" @change="onChange_enableChartsForFederatedInstances">
|
||||
<template #label>{{ i18n.ts.enableChartsForFederatedInstances }}</template>
|
||||
|
|
@ -120,6 +127,7 @@ const meta = await misskeyApi('admin/meta');
|
|||
const enableServerMachineStats = ref(meta.enableServerMachineStats);
|
||||
const enableIdenticonGeneration = ref(meta.enableIdenticonGeneration);
|
||||
const enableChartsForRemoteUser = ref(meta.enableChartsForRemoteUser);
|
||||
const enableStatsForFederatedInstances = ref(meta.enableStatsForFederatedInstances);
|
||||
const enableChartsForFederatedInstances = ref(meta.enableChartsForFederatedInstances);
|
||||
|
||||
function onChange_enableServerMachineStats(value: boolean) {
|
||||
|
|
@ -146,6 +154,14 @@ function onChange_enableChartsForRemoteUser(value: boolean) {
|
|||
});
|
||||
}
|
||||
|
||||
function onChange_enableStatsForFederatedInstances(value: boolean) {
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
enableStatsForFederatedInstances: value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
});
|
||||
}
|
||||
|
||||
function onChange_enableChartsForFederatedInstances(value: boolean) {
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
enableChartsForFederatedInstances: value,
|
||||
|
|
|
|||
|
|
@ -143,13 +143,17 @@ const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.d
|
|||
|
||||
const reactionAcceptance = computed(defaultStore.makeGetterSetter('reactionAcceptance'));
|
||||
|
||||
function assertVaildLang(lang: string | null): lang is keyof typeof langmap {
|
||||
return lang != null && lang in langmap;
|
||||
}
|
||||
|
||||
const profile = reactive({
|
||||
name: $i.name,
|
||||
description: $i.description,
|
||||
followedMessage: $i.followedMessage,
|
||||
location: $i.location,
|
||||
birthday: $i.birthday,
|
||||
lang: $i.lang,
|
||||
lang: assertVaildLang($i.lang) ? $i.lang : null,
|
||||
isBot: $i.isBot ?? false,
|
||||
isCat: $i.isCat ?? false,
|
||||
isVI: $i.isVI ?? false,
|
||||
|
|
@ -205,6 +209,11 @@ function save() {
|
|||
isBot: !!profile.isBot,
|
||||
isCat: !!profile.isCat,
|
||||
isVI: !!profile.isVI,
|
||||
}, undefined, {
|
||||
'0b3f9f6a-2f4d-4b1f-9fb4-49d3a2fd7191': {
|
||||
title: i18n.ts.yourNameContainsProhibitedWords,
|
||||
text: i18n.ts.yourNameContainsProhibitedWordsDescription,
|
||||
},
|
||||
});
|
||||
globalEvents.emit('requestClearPageCache');
|
||||
claimAchievement('profileFilled');
|
||||
|
|
|
|||
|
|
@ -247,13 +247,10 @@ export function getNoteMenu(props: {
|
|||
function togglePin(pin: boolean): void {
|
||||
os.apiWithDialog(pin ? 'i/pin' : 'i/unpin', {
|
||||
noteId: appearNote.id,
|
||||
}, undefined, null, res => {
|
||||
if (res.id === '72dab508-c64d-498f-8740-a8eec1ba385a') {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: i18n.ts.pinLimitExceeded,
|
||||
});
|
||||
}
|
||||
}, undefined, {
|
||||
'72dab508-c64d-498f-8740-a8eec1ba385a': {
|
||||
text: i18n.ts.pinLimitExceeded,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue