Feat: マネージドなサービスで使えるように

オブジェクトストレージの設定を秘匿するように
Config で設定できます。

その他バグ修正
This commit is contained in:
mattyatea 2024-07-17 21:24:04 +09:00
parent c2cf3149ab
commit 9f5b0c3ca1
25 changed files with 599 additions and 386 deletions

View file

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: syuilo and misskey-project , Type4ny-project
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
@ -10,7 +10,13 @@ SPDX-License-Identifier: AGPL-3.0-only
v-hotkey="keymap"
tabindex="0"
class="_popup _shadow"
:class="[$style.root, { [$style.center]: align === 'center', [$style.asDrawer]: asDrawer },{[$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
:class="{
[$style.root]: true,
[$style.center]: align === 'center',
[$style.asDrawer]: asDrawer,
[$style.gamingDark]: gamingType === 'dark',
[$style.gamingLight]: gamingType === 'light'
}"
:style="{
width: (width && !asDrawer) ? `${width}px` : '',
maxHeight: maxHeight ? `${maxHeight}px` : '',
@ -20,21 +26,22 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<template v-for="item in (items2 ?? [])">
<div v-if="item.type === 'divider'" role="separator" tabindex="-1" :class="$style.divider"></div>
<span v-else-if="item.type === 'label'" role="menuitem" tabindex="-1" :class="[$style.label, $style.item,{[$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]">
<span v-else-if="item.type === 'label'" role="menuitem" tabindex="-1" :class="[$style.label, $style.item, {[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]">
<span style="opacity: 0.7;">{{ item.text }}</span>
</span>
<span v-else-if="item.type === 'pending'" role="menuitem" tabindex="0" :class="[$style.pending, $style.item,{[$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]">
<span v-else-if="item.type === 'pending'" role="menuitem" tabindex="0" :class="[$style.pending, $style.item,{[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]">
<span><MkEllipsis/></span>
</span>
<MkA
v-else-if="item.type === 'link'"
role="menuitem"
tabindex="0"
:class="['_button', $style.item ,{[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]"
:to="item.to"
class="_button"
:class="[$style.item,{[$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
@click.passive="close(true)"
@mouseenter.passive="onItemMouseEnter"
@mouseleave.passive="onItemMouseLeave">
@mouseleave.passive="onItemMouseLeave"
>
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/>
<div :class="$style.item_content">
@ -45,14 +52,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<a
v-else-if="item.type === 'a'"
role="menuitem"
tabindex="0"
:class="['_button', $style.item,{[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]"
:href="item.href"
:target="item.target"
:rel="item.target === '_blank' ? 'noopener noreferrer' : undefined"
:download="item.download"
class="_button"
:class="[$style.item,{[$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
@click.passive="close(true)"
@mouseenter.passive="onItemMouseEnter"
@mouseleave.passive="onItemMouseLeave">
@mouseleave.passive="onItemMouseLeave"
>
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<div :class="$style.item_content">
<span :class="$style.item_content_text">{{ item.text }}</span>
@ -63,7 +72,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-else-if="item.type === 'user'"
role="menuitem"
tabindex="0"
:class="['_button', $style.item, { [$style.active]: item.active },{[$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
:class="['_button', $style.item, { [$style.active]: item.active },{[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]"
@click.prevent="item.active ? close(false) : clicked(item.action, $event)"
@mouseenter.passive="onItemMouseEnter"
@mouseleave.passive="onItemMouseLeave"
@ -76,14 +85,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<button
v-else-if="item.type === 'switch'"
role="menuitemcheckbox"
class="_button"
:class="[$style.item, $style.switch, { [$style.switchDisabled]: item.disabled } , { [$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
tabindex="0"
:class="['_button', $style.item]"
:disabled="unref(item.disabled)"
@click.prevent="switchItem(item)"
@mouseenter.passive="onItemMouseEnter"
@mouseleave.passive="onItemMouseLeave">
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<MkSwitchButton v-else :class="$style.switchButton" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)" model-value/>
@mouseleave.passive="onItemMouseLeave"
>
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<MkSwitchButton v-else :class="$style.switchButton" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)"/>
<div :class="$style.item_content">
<span :class="[$style.item_content_text, { [$style.switchText]: !item.icon }]">{{ item.text }}</span>
<MkSwitchButton v-if="item.icon" :class="[$style.switchButton, $style.caret]" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)"/>
@ -125,7 +135,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-else-if="item.type === 'parent'"
role="menuitem"
tabindex="0"
:class="['_button', $style.item, $style.parent, { [$style.active]: childShowingItem === item } , { [$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
:class="['_button', $style.item, $style.parent, { [$style.active]: childShowingItem === item },{[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]"
@mouseenter.prevent="preferClick ? null : showChildren(item, $event)"
@keydown.enter.prevent="preferClick ? null : showChildren(item, $event)"
@click.prevent="!preferClick ? null : showChildren(item, $event)"
@ -139,12 +149,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<button
v-else role="menuitem"
tabindex="0"
:class="['_button', $style.item, { [$style.danger]: item.danger, [$style.active]: unref(item.active) }, { [$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"
:class="['_button', $style.item, { [$style.danger]: item.danger, [$style.active]: unref(item.active) },{[$style.gamingDark]: gamingType === 'dark', [$style.gamingLight]: gamingType === 'light'}]"
@click.prevent="unref(item.active) ? close(false) : clicked(item.action, $event)"
@mouseenter.passive="onItemMouseEnter"
@mouseleave.passive="onItemMouseLeave"
>
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon, { [$style.gamingDark]: gamingType === 'dark',[$style.gamingLight]: gamingType === 'light' }]"></i>
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/>
<div :class="$style.item_content">
<span :class="$style.item_content_text">{{ item.text }}</span>
@ -163,18 +173,17 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts">
import { inject, computed, defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch, unref } from 'vue';
import { focusPrev, focusNext } from '@/scripts/focus.js';
import { computed, defineAsyncComponent, inject, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, unref, watch } from 'vue';
import MkSwitchButton from '@/components/MkSwitch.button.vue';
import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuRadio, MenuRadioOption, MenuParent } from '@/types/menu.js';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { isTouchUsing } from '@/scripts/touch.js';
import {defaultStore} from '@/store.js'
import MkSwitchButton from '@/components/MkSwitch.button.vue';
let gamingType = computed(defaultStore.makeGetterSetter('gamingType'));
import { type Keymap } from '@/scripts/hotkey.js';
import { isFocusable } from '@/scripts/focus.js';
import { getNodeOrNull } from '@/scripts/get-dom-node-or-null.js';
import {defaultStore} from '@/store.js'
let gamingType = computed(defaultStore.makeGetterSetter('gamingType'));
const childrenCache = new WeakMap<MenuParent, MenuItem[]>();
</script>
@ -488,35 +497,6 @@ onBeforeUnmount(() => {
border-radius: 6px;
}
&:not(:disabled):hover {
color: var(--accent);
text-decoration: none;
&:before {
background: var(--accentedBg);
}
&.gamingDark{
color:black !important;
}
&.gamingLight{
color:white !important;
}
&.gamingDark:before{
color:black !important;
background: linear-gradient(270deg, #e7a2a2, #e3cfa2, #ebefa1, #b3e7a6, #a6ebe7, #aec5e3, #cabded, #e0b9e3, #f4bddd); background-size: 1800% 1800%;
-webkit-animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
-moz-animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
}
&.gamingLight:before{
color:white !important;
background: linear-gradient(270deg, #c06161, #c0a567, #b6ba69, #81bc72, #63c3be, #8bacd6, #9f8bd6, #d18bd6, #d883b4); background-size: 1800% 1800% !important;
-webkit-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
-moz-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
}
&:focus-visible {
outline: none;
@ -531,6 +511,27 @@ onBeforeUnmount(() => {
&:focus-visible:active,
&:focus-visible.active {
color: var(--menuHoverFg, var(--accent));
&.gamingDark{
color:black !important;
}
&.gamingLight{
color:white !important;
}
&.gamingDark:before{
color:black !important;
background: linear-gradient(270deg, #e7a2a2, #e3cfa2, #ebefa1, #b3e7a6, #a6ebe7, #aec5e3, #cabded, #e0b9e3, #f4bddd); background-size: 1800% 1800%;
-webkit-animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
-moz-animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
}
&.gamingLight:before{
color:white !important;
background: linear-gradient(270deg, #c06161, #c0a567, #b6ba69, #81bc72, #63c3be, #8bacd6, #9f8bd6, #d18bd6, #d883b4); background-size: 1800% 1800% !important;
-webkit-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
-moz-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
}
&::before {
background-color: var(--menuHoverBg, var(--accentedBg));
@ -587,9 +588,6 @@ onBeforeUnmount(() => {
-moz-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
}
&.radio {
--menuActiveFg: var(--accent);
--menuActiveBg: var(--accentedBg);
}
&.parent {
@ -612,45 +610,6 @@ onBeforeUnmount(() => {
pointer-events: none;
opacity: 0.7;
}
&.parent {
pointer-events: auto;
display: flex;
align-items: center;
cursor: default;
&.childShowing {
color: var(--accent);
text-decoration: none;
&:before {
background: var(--accentedBg);
}
&.gamingDark{
color:black !important;
}
&.gamingLight{
color:white !important;
}
&.gamingDark:before{
color:black !important;
background: linear-gradient(270deg, #e7a2a2, #e3cfa2, #ebefa1, #b3e7a6, #a6ebe7, #aec5e3, #cabded, #e0b9e3, #f4bddd); background-size: 1800% 1800%;
-webkit-animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
-moz-animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
animation: AnimationDark var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite;
}
&.gamingLight:before{
color:white !important;
background: linear-gradient(270deg, #c06161, #c0a567, #b6ba69, #81bc72, #63c3be, #8bacd6, #9f8bd6, #d18bd6, #d883b4); background-size: 1800% 1800% !important;
-webkit-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
-moz-animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
animation: AnimationLight var(--gamingspeed) cubic-bezier(0, 0.2, 0.90, 1) infinite !important;
}
}
}
}
.item_content {
@ -696,11 +655,10 @@ onBeforeUnmount(() => {
}
.indicator {
position: absolute;
top: 5px;
right: 18px;
display: flex;
align-items: center;
color: var(--indicator);
font-size: 8px;
font-size: 12px;
animation: global-blink 1s infinite;
}
@ -800,7 +758,5 @@ onBeforeUnmount(() => {
100% {
background-position: 0% 50%
}
}
}
}
</style>

View file

@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</FormLink>
</div>
</FormSection>
<FormSection v-if="instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey'">
<FormSection v-if="instance.repositoryUrl !== 'https://github.com/type4ny-project/type4ny'">
<div class="_gaps_s">
<MkInfo>
{{ i18n.tsx._aboutType4ny.thisIsModifiedVersion({ name: instance.name }) }}

View file

@ -22,14 +22,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<FormSection>
<div class="_gaps_m">
<MkKeyValue :copy="version">
<template #key>Misskey</template>
<template #key>Type4ny</template>
<template #value>{{ version }}</template>
</MkKeyValue>
<div v-html="i18n.tsx.poweredByMisskeyDescription({ name: instance.name ?? host })">
<div v-html="i18n.tsx.poweredByType4nyDescription({ name: instance.name ?? host })">
</div>
<FormLink to="/about-misskey">
<FormLink to="/about-type4ny">
<template #icon><i class="ti ti-info-circle"></i></template>
{{ i18n.ts.aboutMisskey }}
{{ i18n.ts.aboutType4ny }}
</FormLink>
<FormLink v-if="instance.repositoryUrl || instance.providesTarball" :to="instance.repositoryUrl || `/tarball/misskey-${version}.tar.gz`" external>
<template #icon><i class="ti ti-code"></i></template>
@ -138,6 +138,7 @@ import FormSuspense from '@/components/form/suspense.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkKeyValue from '@/components/MkKeyValue.vue';
import MkLink from '@/components/MkLink.vue';
import MkInfo from "@/components/MkInfo.vue";
const initStats = () => misskeyApi('stats', {});
</script>

View file

@ -10,8 +10,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<FormSuspense :p="init">
<div class="_gaps_m">
<MkSwitch v-model="enableRegistration">
<template #label>{{ i18n.ts.enableRegistration }}</template>
<MkSwitch v-model="enableRegistration" :disabled="isManaged" >
<template #label>
{{ i18n.ts.enableRegistration }}
</template>
<template #caption v-if="isManaged">{{ i18n.ts.managedInstanceIsNotEditable }}</template>
</MkSwitch>
<MkSwitch v-model="emailRequiredForSignup">
@ -89,6 +92,7 @@ import MkButton from '@/components/MkButton.vue';
import FormLink from '@/components/form/link.vue';
const enableRegistration = ref<boolean>(false);
const isManaged = ref<boolean>(false);
const emailRequiredForSignup = ref<boolean>(false);
const sensitiveWords = ref<string>('');
const prohibitedWords = ref<string>('');
@ -101,6 +105,7 @@ const enableGDPRMode = ref<boolean>(false);
async function init() {
const meta = await misskeyApi('admin/meta');
isManaged.value = meta.isManaged;
enableRegistration.value = !meta.disableRegistration;
emailRequiredForSignup.value = meta.emailRequiredForSignup;
sensitiveWords.value = meta.sensitiveWords.join('\n');

View file

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><XHeader :tabs="headerTabs"/></template>
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<FormSuspense :p="init">
<div class="_gaps_m">
<div v-if="!isManaged" class="_gaps_m">
<MkSwitch v-model="useObjectStorage">{{ i18n.ts.useObjectStorage }}</MkSwitch>
<template v-if="useObjectStorage">
@ -70,12 +70,15 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSwitch>
</template>
</div>
<div v-else class="_gaps_m">
{{i18n.ts.managedInstanceIsNotEditable}}
</div>
</FormSuspense>
</MkSpacer>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
<MkButton primary rounded @click="save" v-if="!isManaged"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</MkSpacer>
</div>
</template>
@ -109,9 +112,11 @@ const objectStorageUseSSL = ref<boolean>(false);
const objectStorageUseProxy = ref<boolean>(false);
const objectStorageSetPublicRead = ref<boolean>(false);
const objectStorageS3ForcePathStyle = ref<boolean>(true);
const isManaged = ref<boolean>(false);
async function init() {
const meta = await misskeyApi('admin/meta');
isManaged.value = meta.isManaged;
useObjectStorage.value = meta.useObjectStorage;
objectStorageBaseUrl.value = meta.objectStorageBaseUrl;
objectStorageBucket.value = meta.objectStorageBucket;

View file

@ -10,9 +10,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<FormSuspense :p="init">
<div class="_gaps">
<div class="_panel" style="padding: 16px;">
<MkSwitch v-model="enableServerMachineStats">
<MkSwitch v-model="enableServerMachineStats" :disabled="isManaged">
<template #label>{{ i18n.ts.enableServerMachineStats }}</template>
<template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template>
<template #caption>
{{ i18n.ts.turnOffToImprovePerformance }}
<span v-if="isManaged">{{ i18n.ts.managedInstanceIsNotEditable }}</span>
</template>
</MkSwitch>
</div>
@ -78,6 +81,7 @@ const enableIdenticonGeneration = ref<boolean>(false);
const enableChartsForRemoteUser = ref<boolean>(false);
const enableChartsForFederatedInstances = ref<boolean>(false);
const requestEmojiAllOk = ref(false);
const isManaged = ref(false);
let DiscordWebhookUrl = ref(null);
let DiscordWebhookUrlWordBlock = ref(null);
let EmojiBotToken = ref(null);
@ -89,6 +93,7 @@ async function init() {
enableIdenticonGeneration.value = meta.enableIdenticonGeneration;
enableChartsForRemoteUser.value = meta.enableChartsForRemoteUser;
enableChartsForFederatedInstances.value = meta.enableChartsForFederatedInstances;
isManaged.value = meta.isManaged;
requestEmojiAllOk.value = meta.requestEmojiAllOk;
DiscordWebhookUrl.value = meta.DiscordWebhookUrl;
DiscordWebhookUrlWordBlock.value = meta.DiscordWebhookUrlWordBlock;

View file

@ -57,9 +57,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<FormSection>
<template #label>{{ i18n.ts.files }}</template>
<template #description v-if="isManaged">{{ i18n.ts.managedInstanceIsNotEditable }}</template>
<div class="_gaps_m">
<MkSwitch v-model="cacheRemoteFiles">
<MkSwitch v-model="cacheRemoteFiles" :disabled="isManaged">
<template #label>{{ i18n.ts.cacheRemoteFiles }}</template>
<template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}{{ i18n.ts.youCanCleanRemoteFilesCache }}</template>
</MkSwitch>
@ -98,31 +98,32 @@ SPDX-License-Identifier: AGPL-3.0-only
<FormSection>
<template #label>Misskey® Fan-out Timeline Technology (FTT)</template>
<template #description v-if="isManaged">{{ i18n.ts.managedInstanceIsNotEditable }}</template>
<div class="_gaps_m">
<MkSwitch v-model="enableFanoutTimeline">
<MkSwitch v-model="enableFanoutTimeline" :disabled="isManaged">
<template #label>{{ i18n.ts.enable }}</template>
<template #caption>{{ i18n.ts._serverSettings.fanoutTimelineDescription }}</template>
</MkSwitch>
<MkSwitch v-model="enableFanoutTimelineDbFallback">
<MkSwitch v-model="enableFanoutTimelineDbFallback" :disabled="isManaged">
<template #label>{{ i18n.ts._serverSettings.fanoutTimelineDbFallback }}</template>
<template #caption>{{ i18n.ts._serverSettings.fanoutTimelineDbFallbackDescription }}</template>
</MkSwitch>
<MkInput v-model="perLocalUserUserTimelineCacheMax" type="number">
<MkInput v-model="perLocalUserUserTimelineCacheMax" type="number" :disabled="isManaged">
<template #label>perLocalUserUserTimelineCacheMax</template>
</MkInput>
<MkInput v-model="perRemoteUserUserTimelineCacheMax" type="number">
<MkInput v-model="perRemoteUserUserTimelineCacheMax" type="number" :disabled="isManaged">
<template #label>perRemoteUserUserTimelineCacheMax</template>
</MkInput>
<MkInput v-model="perUserHomeTimelineCacheMax" type="number">
<MkInput v-model="perUserHomeTimelineCacheMax" type="number" :disabled="isManaged">
<template #label>perUserHomeTimelineCacheMax</template>
</MkInput>
<MkInput v-model="perUserListTimelineCacheMax" type="number">
<MkInput v-model="perUserListTimelineCacheMax" type="number" :disabled="isManaged">
<template #label>perUserListTimelineCacheMax</template>
</MkInput>
</div>
@ -249,7 +250,7 @@ const urlPreviewMaximumContentLength = ref<number>(1024 * 1024 * 10);
const urlPreviewRequireContentLength = ref<boolean>(true);
const urlPreviewUserAgent = ref<string | null>(null);
const urlPreviewSummaryProxyUrl = ref<string | null>(null);
const isManaged = ref<boolean>(false);
async function init(): Promise<void> {
const meta = await misskeyApi('admin/meta');
name.value = meta.name;
@ -278,6 +279,7 @@ async function init(): Promise<void> {
urlPreviewRequireContentLength.value = meta.urlPreviewRequireContentLength;
urlPreviewUserAgent.value = meta.urlPreviewUserAgent;
urlPreviewSummaryProxyUrl.value = meta.urlPreviewSummaryProxyUrl;
isManaged.value = meta.isManaged;
}
async function save() {

View file

@ -4,5 +4,7 @@
*/
import { $i } from '@/account.js';
import { instance } from '@/instance.js';
export const isLocalTimelineAvailable = ($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable);
export const isGlobalTimelineAvailable = ($i == null && instance.policies.gtlAvailable) || ($i != null && $i.policies.gtlAvailable);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
export const isLocalTimelineAvailable = ($i == null && instance?.policies?.ltlAvailable) || ($i != null && $i?.policies?.ltlAvailable);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
export const isGlobalTimelineAvailable = ($i == null && instance?.policies?.gtlAvailable) || ($i != null && $i?.policies?.gtlAvailable);

View file

@ -4,7 +4,7 @@ SPDX-FileCopyrightText: syuilo and misskey-project , Type4ny-projectSPDX-License
<template>
<div class="mk-app">
<a v-if="isRoot" href="https://github.com/misskey-dev/misskey" target="_blank" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:var(--panel); color:var(--fg); position: fixed; z-index: 10; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>
<a v-if="isRoot" href="https://github.com/type4ny-project/type4ny" target="_blank" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:var(--panel); color:var(--fg); position: fixed; z-index: 10; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>
<div v-if="!narrow && !isRoot" class="side">
<div class="banner" :style="{ backgroundImage: instance.backgroundImageUrl ? `url(${ instance.backgroundImageUrl })` : 'none' }"></div>