wip
This commit is contained in:
parent
e7171d9ab2
commit
aab1c76981
|
@ -25,9 +25,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, ref } from 'vue';
|
||||
import { getProxiedImageUrl } from '@/to-be-shared/media-proxy.js';
|
||||
import { customEmojisMap } from '@/custom-emojis.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
name: string;
|
||||
normal?: boolean;
|
||||
|
@ -59,7 +60,7 @@ const url = computed(() => {
|
|||
const proxied =
|
||||
(rawUrl.value.startsWith('/emoji/') || (props.useOriginalSize && isLocal.value))
|
||||
? rawUrl.value
|
||||
: getProxiedImageUrl(
|
||||
: mediaProxy.getProxiedImageUrl(
|
||||
rawUrl.value,
|
||||
props.useOriginalSize ? undefined : 'emoji',
|
||||
false,
|
||||
|
|
|
@ -11,26 +11,19 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { instanceName } from '@/config.js';
|
||||
import { instance as Instance } from '@/instance.js';
|
||||
import { getProxiedImageUrlNullable } from '@/to-be-shared/media-proxy.js';
|
||||
import { computed, inject } from 'vue';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
instance?: {
|
||||
instance: {
|
||||
faviconUrl?: string | null
|
||||
name?: string | null
|
||||
themeColor?: string | null
|
||||
}
|
||||
}>();
|
||||
|
||||
// if no instance data is given, this is for the local instance
|
||||
const instance = props.instance ?? {
|
||||
name: instanceName,
|
||||
themeColor: (document.querySelector('meta[name="theme-color-orig"]') as HTMLMetaElement).content,
|
||||
};
|
||||
|
||||
const faviconUrl = computed(() => props.instance ? getProxiedImageUrlNullable(props.instance.faviconUrl, 'preview') : getProxiedImageUrlNullable(Instance.iconUrl, 'preview') ?? '/favicon.ico');
|
||||
const faviconUrl = computed(() => mediaProxy.getProxiedImageUrlNullable(props.instance.faviconUrl, 'preview'));
|
||||
|
||||
const themeColor = instance.themeColor ?? '#777777';
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ import { userPage } from '@/utils.js';
|
|||
import { notePage } from '@/utils.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { shouldCollapsed } from '@/to-be-shared/collapsed.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { instance } from '@/server-metadata.js';
|
||||
import { url } from '@/config.js';
|
||||
import EmMfm from '@/components/EmMfm.js';
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ import XNotFound from '@/pages/not-found.vue';
|
|||
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { instance } from '@/server-metadata.js';
|
||||
import { url, instanceName } from '@/config.js';
|
||||
import { scrollToTop } from '@@/js/scroll.js';
|
||||
import { isLink } from '@/scripts/is-link.js';
|
||||
|
|
|
@ -45,7 +45,7 @@ import EmNotes from '@/components/EmNotes.vue';
|
|||
import XNotFound from '@/pages/not-found.vue';
|
||||
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { instance } from '@/server-metadata.js';
|
||||
import { url, instanceName } from '@/config.js';
|
||||
import { scrollToTop } from '@@/js/scroll.js';
|
||||
import { isLink } from '@/scripts/is-link.js';
|
||||
|
|
|
@ -62,7 +62,7 @@ import XNotFound from '@/pages/not-found.vue';
|
|||
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
||||
import { misskeyApi } from '@/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { instance } from '@/server-metadata.js';
|
||||
import { url, instanceName } from '@/config.js';
|
||||
import { defaultEmbedParams } from '@/embed-page.js';
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { query } from '@@/js/url.js';
|
||||
import { url } from '@/config.js';
|
||||
import { instance } from '@/instance.js';
|
||||
|
||||
export function getProxiedImageUrl(imageUrl: string, type?: 'preview' | 'emoji' | 'avatar', mustOrigin = false, noFallback = false): string {
|
||||
const localProxy = `${url}/proxy`;
|
||||
|
||||
if (imageUrl.startsWith(instance.mediaProxy + '/') || imageUrl.startsWith('/proxy/') || imageUrl.startsWith(localProxy + '/')) {
|
||||
// もう既にproxyっぽそうだったらurlを取り出す
|
||||
imageUrl = (new URL(imageUrl)).searchParams.get('url') ?? imageUrl;
|
||||
}
|
||||
|
||||
return `${mustOrigin ? localProxy : instance.mediaProxy}/${
|
||||
type === 'preview' ? 'preview.webp'
|
||||
: 'image.webp'
|
||||
}?${query({
|
||||
url: imageUrl,
|
||||
...(!noFallback ? { 'fallback': '1' } : {}),
|
||||
...(type ? { [type]: '1' } : {}),
|
||||
...(mustOrigin ? { origin: '1' } : {}),
|
||||
})}`;
|
||||
}
|
||||
|
||||
export function getProxiedImageUrlNullable(imageUrl: string | null | undefined, type?: 'preview'): string | null {
|
||||
if (imageUrl == null) return null;
|
||||
return getProxiedImageUrl(imageUrl, type);
|
||||
}
|
||||
|
||||
export function getStaticImageUrl(baseUrl: string): string {
|
||||
const u = baseUrl.startsWith('http') ? new URL(baseUrl) : new URL(baseUrl, url);
|
||||
|
||||
if (u.href.startsWith(`${url}/emoji/`)) {
|
||||
// もう既にemojiっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
|
||||
if (u.href.startsWith(instance.mediaProxy + '/')) {
|
||||
// もう既にproxyっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
|
||||
return `${instance.mediaProxy}/static.webp?${query({
|
||||
url: u.href,
|
||||
static: '1',
|
||||
})}`;
|
||||
}
|
|
@ -106,10 +106,6 @@ export const ROLE_POLICIES = [
|
|||
export const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP';
|
||||
export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM';
|
||||
|
||||
export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg';
|
||||
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
||||
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
||||
|
||||
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime'];
|
||||
export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
|
||||
tada: ['speed=', 'delay='],
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { query } from '@@/js/url.js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
|
||||
export class MediaProxy {
|
||||
private serverMetadata: Misskey.entities.MetaDetailed;
|
||||
private url: string;
|
||||
|
||||
constructor(serverMetadata: Misskey.entities.MetaDetailed, url: string) {
|
||||
this.serverMetadata = serverMetadata;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public getProxiedImageUrl(imageUrl: string, type?: 'preview' | 'emoji' | 'avatar', mustOrigin = false, noFallback = false): string {
|
||||
const localProxy = `${this.url}/proxy`;
|
||||
|
||||
if (imageUrl.startsWith(this.serverMetadata.mediaProxy + '/') || imageUrl.startsWith('/proxy/') || imageUrl.startsWith(localProxy + '/')) {
|
||||
// もう既にproxyっぽそうだったらurlを取り出す
|
||||
imageUrl = (new URL(imageUrl)).searchParams.get('url') ?? imageUrl;
|
||||
}
|
||||
|
||||
return `${mustOrigin ? localProxy : this.serverMetadata.mediaProxy}/${
|
||||
type === 'preview' ? 'preview.webp'
|
||||
: 'image.webp'
|
||||
}?${query({
|
||||
url: imageUrl,
|
||||
...(!noFallback ? { 'fallback': '1' } : {}),
|
||||
...(type ? { [type]: '1' } : {}),
|
||||
...(mustOrigin ? { origin: '1' } : {}),
|
||||
})}`;
|
||||
}
|
||||
|
||||
public getProxiedImageUrlNullable(imageUrl: string | null | undefined, type?: 'preview'): string | null {
|
||||
if (imageUrl == null) return null;
|
||||
return this.getProxiedImageUrl(imageUrl, type);
|
||||
}
|
||||
|
||||
public getStaticImageUrl(baseUrl: string): string {
|
||||
const u = baseUrl.startsWith('http') ? new URL(baseUrl) : new URL(baseUrl, this.url);
|
||||
|
||||
if (u.href.startsWith(`${this.url}/emoji/`)) {
|
||||
// もう既にemojiっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
|
||||
if (u.href.startsWith(this.serverMetadata.mediaProxy + '/')) {
|
||||
// もう既にproxyっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
|
||||
return `${this.serverMetadata.mediaProxy}/static.webp?${query({
|
||||
url: u.href,
|
||||
static: '1',
|
||||
})}`;
|
||||
}
|
||||
}
|
|
@ -5,16 +5,17 @@
|
|||
|
||||
import { computed, watch, version as vueVersion, App } from 'vue';
|
||||
import { compareVersions } from 'compare-versions';
|
||||
import { MediaProxy } from '@@/js/media-proxy.js';
|
||||
import widgets from '@/widgets/index.js';
|
||||
import directives from '@/directives/index.js';
|
||||
import components from '@/components/index.js';
|
||||
import { version, lang, updateLocale, locale } from '@/config.js';
|
||||
import { version, lang, updateLocale, locale, url } from '@/config.js';
|
||||
import { applyTheme } from '@/scripts/theme.js';
|
||||
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js';
|
||||
import { updateI18n } from '@/i18n.js';
|
||||
import { $i, refreshAccount, login } from '@/account.js';
|
||||
import { defaultStore, ColdDeviceStorage } from '@/store.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { deviceKind } from '@/scripts/device-kind.js';
|
||||
import { reloadChannel } from '@/scripts/unison-reload.js';
|
||||
import { getUrlWithoutLoginId } from '@/scripts/login-id.js';
|
||||
|
@ -119,11 +120,7 @@ export async function common(createVue: () => App<Element>) {
|
|||
await defaultStore.ready;
|
||||
await deckStore.ready;
|
||||
|
||||
const fetchInstanceMetaPromise = fetchInstance();
|
||||
|
||||
fetchInstanceMetaPromise.then(() => {
|
||||
miLocalStorage.setItem('v', instance.version);
|
||||
});
|
||||
const serverMetadata = await fetchServerMetadata();
|
||||
|
||||
//#region loginId
|
||||
const params = new URLSearchParams(location.search);
|
||||
|
@ -178,19 +175,17 @@ export async function common(createVue: () => App<Element>) {
|
|||
});
|
||||
//#endregion
|
||||
|
||||
fetchInstanceMetaPromise.then(() => {
|
||||
if (defaultStore.state.themeInitial) {
|
||||
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON.parse(instance.defaultLightTheme));
|
||||
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON.parse(instance.defaultDarkTheme));
|
||||
defaultStore.set('themeInitial', false);
|
||||
if (defaultStore.state.themeInitial) {
|
||||
if (serverMetadata.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON.parse(serverMetadata.defaultLightTheme));
|
||||
if (serverMetadata.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON.parse(serverMetadata.defaultDarkTheme));
|
||||
defaultStore.set('themeInitial', false);
|
||||
} else {
|
||||
if (defaultStore.state.darkMode) {
|
||||
applyTheme(darkTheme.value);
|
||||
} else {
|
||||
if (defaultStore.state.darkMode) {
|
||||
applyTheme(darkTheme.value);
|
||||
} else {
|
||||
applyTheme(lightTheme.value);
|
||||
}
|
||||
applyTheme(lightTheme.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
|
||||
document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none');
|
||||
|
@ -239,6 +234,8 @@ export async function common(createVue: () => App<Element>) {
|
|||
} catch (err) { /* empty */ }
|
||||
|
||||
const app = createVue();
|
||||
app.provide('serverMetadata', serverMetadata);
|
||||
app.provide('mediaProxy', new MediaProxy(serverMetadata, url));
|
||||
|
||||
setupRouter(app, createMainRouter);
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import { alert, confirm, popup, post, toast } from '@/os.js';
|
|||
import { useStream } from '@/stream.js';
|
||||
import * as sound from '@/scripts/sound.js';
|
||||
import { $i, signout, updateAccount } from '@/account.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { ColdDeviceStorage, defaultStore } from '@/store.js';
|
||||
import { reactionPicker } from '@/scripts/reaction-picker.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
|
@ -23,6 +22,7 @@ import { emojiPicker } from '@/scripts/emoji-picker.js';
|
|||
import { mainRouter } from '@/router/main.js';
|
||||
import { type Keymap, makeHotkey } from '@/scripts/hotkey.js';
|
||||
import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom-emojis.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
|
||||
export async function mainBoot() {
|
||||
const { isClientUpdated } = await common(() => createApp(
|
||||
|
@ -267,8 +267,9 @@ export async function mainBoot() {
|
|||
}
|
||||
}
|
||||
|
||||
const serverMetadata = await fetchServerMetadata();
|
||||
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
||||
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
||||
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && serverMetadata.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
||||
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {
|
||||
closed: () => dispose(),
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.notFound }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -19,10 +19,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import MkChannelPreview from '@/components/MkChannelPreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
pagination: Paging;
|
||||
|
|
|
@ -31,7 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, shallowRef, ref } from 'vue';
|
||||
import { onMounted, shallowRef, ref, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import Cropper from 'cropperjs';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
@ -41,7 +41,8 @@ import { $i } from '@/account.js';
|
|||
import { defaultStore } from '@/store.js';
|
||||
import { apiUrl } from '@/config.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { getProxiedImageUrl } from '@/scripts/media-proxy.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'ok', cropped: Misskey.entities.DriveFile): void;
|
||||
|
@ -55,7 +56,7 @@ const props = defineProps<{
|
|||
uploadFolder?: string | null;
|
||||
}>();
|
||||
|
||||
const imgUrl = getProxiedImageUrl(props.file.url, undefined, true);
|
||||
const imgUrl = mediaProxy.getProxiedImageUrl(props.file.url, undefined, true);
|
||||
const dialogEl = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||
const imgEl = shallowRef<HTMLImageElement>();
|
||||
let cropper: Cropper | null = null;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { action } from '@storybook/addon-actions';
|
|||
import { StoryObj } from '@storybook/vue3';
|
||||
import { onBeforeUnmount } from 'vue';
|
||||
import MkDonation from './MkDonation.vue';
|
||||
import { instance } from '@/instance.js';
|
||||
import { instance } from '@/server-metadata.js';
|
||||
export const Default = {
|
||||
render(args) {
|
||||
return {
|
||||
|
|
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.text">
|
||||
<I18n :src="i18n.ts.pleaseDonate" tag="span">
|
||||
<template #host>
|
||||
{{ instance.name ?? host }}
|
||||
{{ serverMetadata.name ?? host }}
|
||||
</template>
|
||||
</I18n>
|
||||
<div style="margin-top: 0.2em;">
|
||||
|
@ -36,13 +36,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkLink from '@/components/MkLink.vue';
|
||||
import { host } from '@/config.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { instance } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
|
|
|
@ -4,11 +4,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="instance" :class="$style.root" :style="{ backgroundImage: `url(${ instance.backgroundImageUrl })` }"></div>
|
||||
<div :class="$style.root" :style="{ backgroundImage: `url(${ serverMetadata.backgroundImageUrl })` }"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { instance } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #header>{{ i18n.ts.forgotPassword }}</template>
|
||||
|
||||
<MkSpacer :marginMin="20" :marginMax="28">
|
||||
<form v-if="instance.enableEmail" @submit.prevent="onSubmit">
|
||||
<form v-if="serverMetadata.enableEmail" @submit.prevent="onSubmit">
|
||||
<div class="_gaps_m">
|
||||
<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" :spellcheck="false" autofocus required>
|
||||
<template #label>{{ i18n.ts.username }}</template>
|
||||
|
@ -39,15 +39,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { inject, ref } from 'vue';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'done'): void;
|
||||
(ev: 'closed'): void;
|
||||
|
|
|
@ -63,7 +63,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
</div>
|
||||
<div v-else class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
|
@ -72,6 +72,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, shallowRef } from 'vue';
|
||||
import { inject } from 'vue';
|
||||
import MkInput from './MkInput.vue';
|
||||
import MkTextarea from './MkTextarea.vue';
|
||||
import MkSwitch from './MkSwitch.vue';
|
||||
|
@ -83,7 +84,7 @@ import XFile from './MkFormDialog.file.vue';
|
|||
import type { Form } from '@/scripts/form.js';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = defineProps<{
|
||||
title: string;
|
||||
|
|
|
@ -15,11 +15,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { inject, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkMiniChart from '@/components/MkMiniChart.vue';
|
||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
instance: Misskey.entities.FederationInstance;
|
||||
|
@ -34,7 +35,7 @@ misskeyApiGet('charts/instance', { host: props.instance.host, limit: 16 + 1, spa
|
|||
});
|
||||
|
||||
function getInstanceIcon(instance): string {
|
||||
return getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
|
||||
return mediaProxy.getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? mediaProxy.getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, inject } from 'vue';
|
||||
import { instanceName } from '@/config.js';
|
||||
import { instance as Instance } from '@/instance.js';
|
||||
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
instance?: {
|
||||
|
@ -30,7 +30,7 @@ const instance = props.instance ?? {
|
|||
themeColor: (document.querySelector('meta[name="theme-color-orig"]') as HTMLMetaElement).content,
|
||||
};
|
||||
|
||||
const faviconUrl = computed(() => props.instance ? getProxiedImageUrlNullable(props.instance.faviconUrl, 'preview') : getProxiedImageUrlNullable(Instance.iconUrl, 'preview') ?? '/favicon.ico');
|
||||
const faviconUrl = computed(() => props.instance ? mediaProxy.getProxiedImageUrlNullable(props.instance.faviconUrl, 'preview') : mediaProxy.getProxiedImageUrlNullable(Instance.iconUrl, 'preview') ?? '/favicon.ico');
|
||||
|
||||
const themeColor = instance.themeColor ?? '#777777';
|
||||
|
||||
|
|
|
@ -15,13 +15,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, ref } from 'vue';
|
||||
import { defineAsyncComponent, inject, ref } from 'vue';
|
||||
import { url as local } from '@/config.js';
|
||||
import { useTooltip } from '@/scripts/use-tooltip.js';
|
||||
import * as os from '@/os.js';
|
||||
import { isEnabledUrlPreview } from '@/instance.js';
|
||||
import { MkABehavior } from '@/components/global/MkA.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
url: string;
|
||||
rel?: null | string;
|
||||
|
@ -35,7 +36,7 @@ const target = self ? null : '_blank';
|
|||
|
||||
const el = ref<HTMLElement | { $el: HTMLElement }>();
|
||||
|
||||
if (isEnabledUrlPreview.value) {
|
||||
if (serverMetadata.enableUrlPreview) {
|
||||
useTooltip(el, (showing) => {
|
||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
||||
showing,
|
||||
|
|
|
@ -51,9 +51,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, ref, computed } from 'vue';
|
||||
import { watch, ref, computed, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import bytes from '@/filters/bytes.js';
|
||||
import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
|
@ -61,6 +60,8 @@ import { i18n } from '@/i18n.js';
|
|||
import * as os from '@/os.js';
|
||||
import { $i, iAmModerator } from '@/account.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
image: Misskey.entities.DriveFile;
|
||||
raw?: boolean;
|
||||
|
@ -79,7 +80,7 @@ const darkMode = ref<boolean>(defaultStore.state.darkMode);
|
|||
const url = computed(() => (props.raw || defaultStore.state.loadRawImages)
|
||||
? props.image.url
|
||||
: defaultStore.state.disableShowingAnimatedImages
|
||||
? getStaticImageUrl(props.image.url)
|
||||
? mediaProxy.getStaticImageUrl(props.image.url)
|
||||
: props.image.thumbnailUrl,
|
||||
);
|
||||
|
||||
|
|
|
@ -15,14 +15,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { toUnicode } from 'punycode';
|
||||
import { computed } from 'vue';
|
||||
import { computed, inject } from 'vue';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { host as localHost } from '@/config.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { MkABehavior } from '@/components/global/MkA.vue';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
username: string;
|
||||
host: string;
|
||||
|
@ -42,7 +43,7 @@ bg.setAlpha(0.1);
|
|||
const bgCss = bg.toRgbString();
|
||||
|
||||
const avatarUrl = computed(() => defaultStore.state.disableShowingAnimatedImages
|
||||
? getStaticImageUrl(`/avatar/@${props.username}@${props.host}`)
|
||||
? mediaProxy.getStaticImageUrl(`/avatar/@${props.username}@${props.host}`)
|
||||
: `/avatar/@${props.username}@${props.host}`,
|
||||
);
|
||||
</script>
|
||||
|
|
|
@ -82,7 +82,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
|
||||
</div>
|
||||
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/>
|
||||
<div v-if="isEnabledUrlPreview">
|
||||
<div v-if="serverMetadata.enableUrlPreview">
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/>
|
||||
</div>
|
||||
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
|
||||
|
@ -197,11 +197,12 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
|||
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
|
||||
import { shouldCollapsed } from '@/scripts/collapsed.js';
|
||||
import { host } from '@/config.js';
|
||||
import { isEnabledUrlPreview } from '@/instance.js';
|
||||
import { type Keymap } from '@/scripts/hotkey.js';
|
||||
import { focusPrev, focusNext } from '@/scripts/focus.js';
|
||||
import { getAppearNote } from '@/scripts/get-appear-note.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
note: Misskey.entities.Note;
|
||||
pinned?: boolean;
|
||||
|
@ -523,7 +524,7 @@ function onContextmenu(ev: MouseEvent): void {
|
|||
ev.preventDefault();
|
||||
react();
|
||||
} else {
|
||||
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
|
||||
const { menu, cleanup } = getNoteMenu({ serverMetadata }, { note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
|
||||
os.contextMenu(menu, ev).then(focus).finally(cleanup);
|
||||
}
|
||||
}
|
||||
|
@ -533,7 +534,7 @@ function showMenu(): void {
|
|||
return;
|
||||
}
|
||||
|
||||
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
|
||||
const { menu, cleanup } = getNoteMenu({ serverMetadata }, { note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
|
||||
os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
|
||||
</div>
|
||||
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/>
|
||||
<div v-if="isEnabledUrlPreview">
|
||||
<div v-if="serverMetadata.enableUrlPreview">
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/>
|
||||
</div>
|
||||
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
|
||||
|
@ -234,10 +234,11 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
|||
import MkPagination, { type Paging } from '@/components/MkPagination.vue';
|
||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { isEnabledUrlPreview } from '@/instance.js';
|
||||
import { getAppearNote } from '@/scripts/get-appear-note.js';
|
||||
import { type Keymap } from '@/scripts/hotkey.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
note: Misskey.entities.Note;
|
||||
initialTab: string;
|
||||
|
@ -483,13 +484,13 @@ function onContextmenu(ev: MouseEvent): void {
|
|||
ev.preventDefault();
|
||||
react();
|
||||
} else {
|
||||
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
|
||||
const { menu, cleanup } = getNoteMenu({ serverMetadata }, { note: note.value, translating, translation, isDeleted });
|
||||
os.contextMenu(menu, ev).then(focus).finally(cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
function showMenu(): void {
|
||||
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
|
||||
const { menu, cleanup } = getNoteMenu({ serverMetadata }, { note: note.value, translating, translation, isDeleted });
|
||||
os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination ref="pagingComponent" :pagination="pagination" :disableAutoLoad="disableAutoLoad">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noNotes }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -33,11 +33,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef } from 'vue';
|
||||
import { inject } from 'vue';
|
||||
import MkNote from '@/components/MkNote.vue';
|
||||
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = defineProps<{
|
||||
pagination: Paging;
|
||||
|
|
|
@ -148,7 +148,8 @@ import { userPage } from '@/filters/user.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { signinRequired } from '@/account.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const $i = signinRequired();
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination ref="pagingComponent" :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noNotifications }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -32,7 +32,8 @@ import MkNote from '@/components/MkNote.vue';
|
|||
import { useStream } from '@/stream.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { notificationTypes } from '@/const.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
import { defaultStore } from '@/store.js';
|
||||
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
|
|
|
@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div v-else-if="empty" key="_empty_" class="empty">
|
||||
<slot name="empty">
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</slot>
|
||||
|
@ -90,7 +90,8 @@ function concatMapWithArray(map: MisskeyEntityMap, entities: MisskeyEntity[]): M
|
|||
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
|
|
|
@ -120,7 +120,6 @@ import { selectFiles } from '@/scripts/select-file.js';
|
|||
import { defaultStore, notePostInterruptors, postFormActions } from '@/store.js';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { signinRequired, notesCount, incNotesCount, getAccounts, openAccountMenu as openAccountMenu_ } from '@/account.js';
|
||||
import { uploadFile } from '@/scripts/upload.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
|
@ -130,6 +129,8 @@ import { claimAchievement } from '@/scripts/achievements.js';
|
|||
import { emojiPicker } from '@/scripts/emoji-picker.js';
|
||||
import { mfmFunctionPicker } from '@/scripts/mfm-function-picker.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const $i = signinRequired();
|
||||
|
||||
const modal = inject('modal');
|
||||
|
@ -249,7 +250,7 @@ const textLength = computed((): number => {
|
|||
});
|
||||
|
||||
const maxTextLength = computed((): number => {
|
||||
return instance ? instance.maxNoteTextLength : 1000;
|
||||
return serverMetadata.maxNoteTextLength;
|
||||
});
|
||||
|
||||
const canPost = computed((): boolean => {
|
||||
|
|
|
@ -41,14 +41,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { inject, ref } from 'vue';
|
||||
import { $i, getAccounts } from '@/account.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { instance } from '@/instance.js';
|
||||
import { apiWithDialog, promiseDialog } from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
defineProps<{
|
||||
primary?: boolean;
|
||||
gradate?: boolean;
|
||||
|
@ -72,12 +73,12 @@ const pushSubscription = ref<PushSubscription | null>(null);
|
|||
const pushRegistrationInServer = ref<{ state?: string; key?: string; userId: string; endpoint: string; sendReadMessage: boolean; } | undefined>();
|
||||
|
||||
function subscribe() {
|
||||
if (!registration.value || !supported.value || !instance.swPublickey) return;
|
||||
if (!registration.value || !supported.value || !serverMetadata.swPublickey) return;
|
||||
|
||||
// SEE: https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe#Parameters
|
||||
return promiseDialog(registration.value.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(instance.swPublickey),
|
||||
applicationServerKey: urlBase64ToUint8Array(serverMetadata.swPublickey),
|
||||
})
|
||||
.then(async subscription => {
|
||||
pushSubscription.value = subscription;
|
||||
|
@ -156,7 +157,7 @@ if (navigator.serviceWorker == null) {
|
|||
|
||||
pushSubscription.value = await registration.value.pushManager.getSubscription();
|
||||
|
||||
if (instance.swPublickey && ('PushManager' in window) && $i && $i.token) {
|
||||
if (serverMetadata.swPublickey && ('PushManager' in window) && $i && $i.token) {
|
||||
supported.value = true;
|
||||
|
||||
if (pushSubscription.value) {
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
<MkSpacer :marginMin="20" :marginMax="32">
|
||||
<form class="_gaps_m" autocomplete="new-password" @submit.prevent="onSubmit">
|
||||
<MkInput v-if="instance.disableRegistration" v-model="invitationCode" type="text" :spellcheck="false" required>
|
||||
<MkInput v-if="serverMetadata.disableRegistration" v-model="invitationCode" type="text" :spellcheck="false" required>
|
||||
<template #label>{{ i18n.ts.invitationCode }}</template>
|
||||
<template #prefix><i class="ti ti-key"></i></template>
|
||||
</MkInput>
|
||||
|
@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span v-else-if="usernameState === 'max-range'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.tooLong }}</span>
|
||||
</template>
|
||||
</MkInput>
|
||||
<MkInput v-if="instance.emailRequiredForSignup" v-model="email" :debounce="true" type="email" :spellcheck="false" required data-cy-signup-email @update:modelValue="onChangeEmail">
|
||||
<MkInput v-if="serverMetadata.emailRequiredForSignup" v-model="email" :debounce="true" type="email" :spellcheck="false" required data-cy-signup-email @update:modelValue="onChangeEmail">
|
||||
<template #label>{{ i18n.ts.emailAddress }} <div v-tooltip:dialog="i18n.ts._signup.emailAddressInfo" class="_button _help"><i class="ti ti-help-circle"></i></div></template>
|
||||
<template #prefix><i class="ti ti-mail"></i></template>
|
||||
<template #caption>
|
||||
|
@ -62,10 +62,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.passwordNotMatched }}</span>
|
||||
</template>
|
||||
</MkInput>
|
||||
<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :class="$style.captcha" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/>
|
||||
<MkCaptcha v-if="instance.enableMcaptcha" ref="mcaptcha" v-model="mCaptchaResponse" :class="$style.captcha" provider="mcaptcha" :sitekey="instance.mcaptchaSiteKey" :instanceUrl="instance.mcaptchaInstanceUrl"/>
|
||||
<MkCaptcha v-if="instance.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" :class="$style.captcha" provider="recaptcha" :sitekey="instance.recaptchaSiteKey"/>
|
||||
<MkCaptcha v-if="instance.enableTurnstile" ref="turnstile" v-model="turnstileResponse" :class="$style.captcha" provider="turnstile" :sitekey="instance.turnstileSiteKey"/>
|
||||
<MkCaptcha v-if="serverMetadata.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :class="$style.captcha" provider="hcaptcha" :sitekey="serverMetadata.hcaptchaSiteKey"/>
|
||||
<MkCaptcha v-if="serverMetadata.enableMcaptcha" ref="mcaptcha" v-model="mCaptchaResponse" :class="$style.captcha" provider="mcaptcha" :sitekey="serverMetadata.mcaptchaSiteKey" :instanceUrl="serverMetadata.mcaptchaInstanceUrl"/>
|
||||
<MkCaptcha v-if="serverMetadata.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" :class="$style.captcha" provider="recaptcha" :sitekey="serverMetadata.recaptchaSiteKey"/>
|
||||
<MkCaptcha v-if="serverMetadata.enableTurnstile" ref="turnstile" v-model="turnstileResponse" :class="$style.captcha" provider="turnstile" :sitekey="serverMetadata.turnstileSiteKey"/>
|
||||
<MkButton type="submit" :disabled="shouldDisableSubmitting" large gradate rounded data-cy-signup-submit style="margin: 0 auto;">
|
||||
<template v-if="submitting">
|
||||
<MkLoading :em="true" :colored="false"/>
|
||||
|
@ -78,7 +78,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import { toUnicode } from 'punycode/';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkButton from './MkButton.vue';
|
||||
|
@ -88,9 +88,10 @@ import * as config from '@/config.js';
|
|||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { login } from '@/account.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
autoSet?: boolean;
|
||||
}>(), {
|
||||
|
@ -127,11 +128,11 @@ const emailAbortController = ref<null | AbortController>(null);
|
|||
|
||||
const shouldDisableSubmitting = computed((): boolean => {
|
||||
return submitting.value ||
|
||||
instance.enableHcaptcha && !hCaptchaResponse.value ||
|
||||
instance.enableMcaptcha && !mCaptchaResponse.value ||
|
||||
instance.enableRecaptcha && !reCaptchaResponse.value ||
|
||||
instance.enableTurnstile && !turnstileResponse.value ||
|
||||
instance.emailRequiredForSignup && emailState.value !== 'ok' ||
|
||||
serverMetadata.enableHcaptcha && !hCaptchaResponse.value ||
|
||||
serverMetadata.enableMcaptcha && !mCaptchaResponse.value ||
|
||||
serverMetadata.enableRecaptcha && !reCaptchaResponse.value ||
|
||||
serverMetadata.enableTurnstile && !turnstileResponse.value ||
|
||||
serverMetadata.emailRequiredForSignup && emailState.value !== 'ok' ||
|
||||
usernameState.value !== 'ok' ||
|
||||
passwordRetypeState.value !== 'match';
|
||||
});
|
||||
|
@ -260,7 +261,7 @@ async function onSubmit(): Promise<void> {
|
|||
'g-recaptcha-response': reCaptchaResponse.value,
|
||||
'turnstile-response': turnstileResponse.value,
|
||||
});
|
||||
if (instance.emailRequiredForSignup) {
|
||||
if (serverMetadata.emailRequiredForSignup) {
|
||||
os.alert({
|
||||
type: 'success',
|
||||
title: i18n.ts._signup.almostThere,
|
||||
|
|
|
@ -9,7 +9,7 @@ import { StoryObj } from '@storybook/vue3';
|
|||
import { onBeforeUnmount } from 'vue';
|
||||
import MkSignupServerRules from './MkSignupDialog.rules.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { instance } from '@/server-metadata.js';
|
||||
export const Empty = {
|
||||
render(args) {
|
||||
return {
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
<MkSpacer :marginMin="20" :marginMax="28">
|
||||
<div class="_gaps_m">
|
||||
<div v-if="instance.disableRegistration">
|
||||
<div v-if="serverMetadata.disableRegistration">
|
||||
<MkInfo warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo>
|
||||
</div>
|
||||
|
||||
|
@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #suffix><i v-if="agreeServerRules" class="ti ti-check" style="color: var(--success)"></i></template>
|
||||
|
||||
<ol class="_gaps_s" :class="$style.rules">
|
||||
<li v-for="item in instance.serverRules" :class="$style.rule"><div :class="$style.ruleText" v-html="item"></div></li>
|
||||
<li v-for="item in serverMetadata.serverRules" :class="$style.rule"><div :class="$style.ruleText" v-html="item"></div></li>
|
||||
</ol>
|
||||
|
||||
<MkSwitch :modelValue="agreeServerRules" style="margin-top: 16px;" @update:modelValue="updateAgreeServerRules">{{ i18n.ts.agree }}</MkSwitch>
|
||||
|
@ -34,8 +34,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ tosPrivacyPolicyLabel }}</template>
|
||||
<template #suffix><i v-if="agreeTosAndPrivacyPolicy" class="ti ti-check" style="color: var(--success)"></i></template>
|
||||
<div class="_gaps_s">
|
||||
<div v-if="availableTos"><a :href="instance.tosUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.termsOfService }} <i class="ti ti-external-link"></i></a></div>
|
||||
<div v-if="availablePrivacyPolicy"><a :href="instance.privacyPolicyUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.privacyPolicy }} <i class="ti ti-external-link"></i></a></div>
|
||||
<div v-if="availableTos"><a :href="serverMetadata.tosUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.termsOfService }} <i class="ti ti-external-link"></i></a></div>
|
||||
<div v-if="availablePrivacyPolicy"><a :href="serverMetadata.privacyPolicyUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.privacyPolicy }} <i class="ti ti-external-link"></i></a></div>
|
||||
</div>
|
||||
|
||||
<MkSwitch :modelValue="agreeTosAndPrivacyPolicy" style="margin-top: 16px;" @update:modelValue="updateAgreeTosAndPrivacyPolicy">{{ i18n.ts.agree }}</MkSwitch>
|
||||
|
@ -62,8 +62,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { instance } from '@/instance.js';
|
||||
import { computed, inject, ref } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
|
@ -71,9 +70,11 @@ import MkSwitch from '@/components/MkSwitch.vue';
|
|||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
const availableServerRules = instance.serverRules.length > 0;
|
||||
const availableTos = instance.tosUrl != null && instance.tosUrl !== '';
|
||||
const availablePrivacyPolicy = instance.privacyPolicyUrl != null && instance.privacyPolicyUrl !== '';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const availableServerRules = serverMetadata.serverRules.length > 0;
|
||||
const availableTos = serverMetadata.tosUrl != null && serverMetadata.tosUrl !== '';
|
||||
const availablePrivacyPolicy = serverMetadata.privacyPolicyUrl != null && serverMetadata.privacyPolicyUrl !== '';
|
||||
|
||||
const agreeServerRules = ref(false);
|
||||
const agreeTosAndPrivacyPolicy = ref(false);
|
||||
|
|
|
@ -15,14 +15,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.title">
|
||||
<I18n :src="i18n.ts.aboutX" tag="span">
|
||||
<template #x>
|
||||
{{ instance.name ?? host }}
|
||||
{{ serverMetadata.name ?? host }}
|
||||
</template>
|
||||
</I18n>
|
||||
</div>
|
||||
<div :class="$style.text">
|
||||
<I18n :src="i18n.ts._aboutMisskey.thisIsModifiedVersion" tag="span">
|
||||
<template #name>
|
||||
{{ instance.name ?? host }}
|
||||
{{ serverMetadata.name ?? host }}
|
||||
</template>
|
||||
</I18n>
|
||||
<I18n :src="i18n.ts.correspondingSourceIsAvailable" tag="span">
|
||||
|
@ -40,13 +40,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { host } from '@/config.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
|
|
@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, watch, onUnmounted, provide, ref, shallowRef } from 'vue';
|
||||
import { computed, watch, onUnmounted, provide, ref, shallowRef, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import type { BasicTimelineType } from '@/timelines.js';
|
||||
import MkNotes from '@/components/MkNotes.vue';
|
||||
|
@ -25,10 +25,11 @@ import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
|
|||
import { useStream } from '@/stream.js';
|
||||
import * as sound from '@/scripts/sound.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { Paging } from '@/components/MkPagination.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
src: BasicTimelineType | 'mentions' | 'directs' | 'list' | 'antenna' | 'channel' | 'role';
|
||||
list?: string;
|
||||
|
|
|
@ -133,7 +133,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<a href="https://misskey-hub.net/docs/for-users/" target="_blank" class="_link">{{ i18n.ts.help }}</a>
|
||||
</template>
|
||||
</I18n>
|
||||
<div>{{ i18n.tsx._initialAccountSetting.haveFun({ name: instance.name ?? host }) }}</div>
|
||||
<div>{{ i18n.tsx._initialAccountSetting.haveFun({ name: serverMetadata.name ?? host }) }}</div>
|
||||
<div class="_buttonsCenter" style="margin-top: 16px;">
|
||||
<MkButton v-if="initialPage !== 4" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
|
||||
<MkButton rounded primary gradate @click="close(false)">{{ i18n.ts.close }}</MkButton>
|
||||
|
@ -148,7 +148,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef, watch } from 'vue';
|
||||
import { inject, ref, shallowRef, watch } from 'vue';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import XNote from '@/components/MkTutorialDialog.Note.vue';
|
||||
|
@ -157,11 +157,12 @@ import XPostNote from '@/components/MkTutorialDialog.PostNote.vue';
|
|||
import XSensitive from '@/components/MkTutorialDialog.Sensitive.vue';
|
||||
import MkAnimBg from '@/components/MkAnimBg.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { host } from '@/config.js';
|
||||
import { claimAchievement } from '@/scripts/achievements.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = defineProps<{
|
||||
initialPage?: number;
|
||||
}>();
|
||||
|
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div class="_panel" :class="$style.root">
|
||||
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` : ''"></div>
|
||||
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${defaultStore.state.disableShowingAnimatedImages ? mediaProxy.getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` : ''"></div>
|
||||
<MkAvatar :class="$style.avatar" :user="user" indicator/>
|
||||
<div :class="$style.title">
|
||||
<MkA :class="$style.name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA>
|
||||
|
@ -35,15 +35,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { inject } from 'vue';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
import number from '@/filters/number.js';
|
||||
import { userPage } from '@/filters/user.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
defineProps<{
|
||||
user: Misskey.entities.UserDetailed;
|
||||
}>();
|
||||
|
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -21,10 +21,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import MkUserInfo from '@/components/MkUserInfo.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
pagination: Paging;
|
||||
|
|
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
>
|
||||
<div v-if="showing" :class="$style.root" class="_popup _shadow" :style="{ zIndex, top: top + 'px', left: left + 'px' }" @mouseover="() => { emit('mouseover'); }" @mouseleave="() => { emit('mouseleave'); }">
|
||||
<div v-if="user != null">
|
||||
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` : ''">
|
||||
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${defaultStore.state.disableShowingAnimatedImages ? mediaProxy.getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` : ''">
|
||||
<span v-if="$i && $i.id != user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
|
||||
</div>
|
||||
<svg viewBox="0 0 128 128" :class="$style.avatarBack">
|
||||
|
@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { inject, onMounted, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
import { userPage } from '@/filters/user.js';
|
||||
|
@ -67,7 +67,9 @@ import { i18n } from '@/i18n.js';
|
|||
import { defaultStore } from '@/store.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
showing: boolean;
|
||||
|
@ -88,7 +90,7 @@ const left = ref(0);
|
|||
|
||||
function showMenu(ev: MouseEvent) {
|
||||
if (user.value == null) return;
|
||||
const { menu, cleanup } = getUserMenu(user.value);
|
||||
const { menu, cleanup } = getUserMenu({ serverMetadata }, user.value);
|
||||
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div class="_gaps" style="text-align: center;">
|
||||
<i class="ti ti-bell-ringing-2" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
|
||||
<div style="font-size: 120%;">{{ i18n.ts.pushNotification }}</div>
|
||||
<div style="padding: 0 16px;">{{ i18n.tsx._initialAccountSetting.pushNotificationDescription({ name: instance.name ?? host }) }}</div>
|
||||
<div style="padding: 0 16px;">{{ i18n.tsx._initialAccountSetting.pushNotificationDescription({ name: serverMetadata.name ?? host }) }}</div>
|
||||
<MkPushNotificationAllowButton primary showOnlyToRegister style="margin: 0 auto;"/>
|
||||
<div class="_buttonsCenter" style="margin-top: 16px;">
|
||||
<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
|
||||
|
@ -110,7 +110,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div class="_gaps" style="text-align: center;">
|
||||
<i class="ti ti-check" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
|
||||
<div style="font-size: 120%;">{{ i18n.ts._initialAccountSetting.initialAccountSettingCompleted }}</div>
|
||||
<div>{{ i18n.tsx._initialAccountSetting.youCanContinueTutorial({ name: instance.name ?? host }) }}</div>
|
||||
<div>{{ i18n.tsx._initialAccountSetting.youCanContinueTutorial({ name: serverMetadata.name ?? host }) }}</div>
|
||||
<div class="_buttonsCenter" style="margin-top: 16px;">
|
||||
<MkButton rounded primary gradate data-cy-user-setup-continue @click="launchTutorial()">{{ i18n.ts._initialAccountSetting.startTutorial }} <i class="ti ti-arrow-right"></i></MkButton>
|
||||
</div>
|
||||
|
@ -128,7 +128,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef, watch, nextTick, defineAsyncComponent } from 'vue';
|
||||
import { ref, shallowRef, watch, nextTick, defineAsyncComponent, inject } from 'vue';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import XProfile from '@/components/MkUserSetupDialog.Profile.vue';
|
||||
|
@ -136,19 +136,19 @@ import XFollow from '@/components/MkUserSetupDialog.Follow.vue';
|
|||
import XPrivacy from '@/components/MkUserSetupDialog.Privacy.vue';
|
||||
import MkAnimBg from '@/components/MkAnimBg.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { host } from '@/config.js';
|
||||
import MkPushNotificationAllowButton from '@/components/MkPushNotificationAllowButton.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||
|
||||
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
||||
const page = ref(defaultStore.state.accountSetupWizard);
|
||||
|
||||
watch(page, () => {
|
||||
|
|
|
@ -6,19 +6,19 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<div v-if="instance" :class="$style.root">
|
||||
<div :class="[$style.main, $style.panel]">
|
||||
<img :src="instance.iconUrl || '/favicon.ico'" alt="" :class="$style.mainIcon"/>
|
||||
<img :src="serverMetadata.iconUrl || '/favicon.ico'" alt="" :class="$style.mainIcon"/>
|
||||
<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
|
||||
<div :class="$style.mainFg">
|
||||
<h1 :class="$style.mainTitle">
|
||||
<!-- 背景色によってはロゴが見えなくなるのでとりあえず無効に -->
|
||||
<!-- <img class="logo" v-if="instance.logoImageUrl" :src="instance.logoImageUrl"><span v-else class="text">{{ instanceName }}</span> -->
|
||||
<!-- <img class="logo" v-if="serverMetadata.logoImageUrl" :src="serverMetadata.logoImageUrl"><span v-else class="text">{{ instanceName }}</span> -->
|
||||
<span>{{ instanceName }}</span>
|
||||
</h1>
|
||||
<div :class="$style.mainAbout">
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div v-html="instance.description || i18n.ts.headlineMisskey"></div>
|
||||
<div v-html="serverMetadata.description || i18n.ts.headlineMisskey"></div>
|
||||
</div>
|
||||
<div v-if="instance.disableRegistration" :class="$style.mainWarn">
|
||||
<div v-if="serverMetadata.disableRegistration" :class="$style.mainWarn">
|
||||
<MkInfo warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo>
|
||||
</div>
|
||||
<div class="_gaps_s" :class="$style.mainActions">
|
||||
|
@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.statsItemCount"><MkNumber :value="stats.originalNotesCount"/></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="instance.policies.ltlAvailable" :class="[$style.tl, $style.panel]">
|
||||
<div v-if="serverMetadata.policies.ltlAvailable" :class="[$style.tl, $style.panel]">
|
||||
<div :class="$style.tlHeader">{{ i18n.ts.letsLookAtTimeline }}</div>
|
||||
<div :class="$style.tlBody">
|
||||
<MkTimeline src="local"/>
|
||||
|
@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { inject, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XSigninDialog from '@/components/MkSigninDialog.vue';
|
||||
import XSignupDialog from '@/components/MkSignupDialog.vue';
|
||||
|
@ -62,11 +62,11 @@ import { instanceName } from '@/config.js';
|
|||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import MkNumber from '@/components/MkNumber.vue';
|
||||
import XActiveUsersChart from '@/components/MkVisitorDashboard.ActiveUsersChart.vue';
|
||||
import { openInstanceMenu } from '@/ui/_common_/common.js';
|
||||
import type { MenuItem } from '@/types/menu.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const stats = ref<Misskey.entities.StatsResponse | null>(null);
|
||||
|
||||
|
|
|
@ -42,16 +42,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { url as local, host } from '@/config.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import * as os from '@/os.js';
|
||||
import { $i } from '@/account.js';
|
||||
|
||||
type Ad = (typeof instance)['ads'][number];
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
type Ad = (typeof serverMetadata)['ads'][number];
|
||||
|
||||
const props = defineProps<{
|
||||
prefer: string[];
|
||||
|
@ -68,7 +69,7 @@ const choseAd = (): Ad | null => {
|
|||
return props.specify;
|
||||
}
|
||||
|
||||
const allAds = instance.ads.map(ad => defaultStore.state.mutedAds.includes(ad.id) ? {
|
||||
const allAds = serverMetadata.ads.map(ad => defaultStore.state.mutedAds.includes(ad.id) ? {
|
||||
...ad,
|
||||
ratio: 0,
|
||||
} : ad);
|
||||
|
|
|
@ -40,16 +40,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, ref, computed } from 'vue';
|
||||
import { watch, ref, computed, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { extractAvgColorFromBlurhash } from '@@/js/extract-avg-color-from-blurhash.js';
|
||||
import MkImgWithBlurhash from '../MkImgWithBlurhash.vue';
|
||||
import MkA from './MkA.vue';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { acct, userPage } from '@/filters/user.js';
|
||||
import MkUserOnlineIndicator from '@/components/MkUserOnlineIndicator.vue';
|
||||
import { defaultStore } from '@/store.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const animation = ref(defaultStore.state.animation);
|
||||
const squareAvatars = ref(defaultStore.state.squareAvatars);
|
||||
const useBlurEffect = ref(defaultStore.state.useBlurEffect);
|
||||
|
@ -83,7 +84,7 @@ const bound = computed(() => props.link
|
|||
|
||||
const url = computed(() => {
|
||||
if (props.user.avatarUrl == null) return null;
|
||||
if (defaultStore.state.disableShowingAnimatedImages || defaultStore.state.dataSaver.avatar) return getStaticImageUrl(props.user.avatarUrl);
|
||||
if (defaultStore.state.disableShowingAnimatedImages || defaultStore.state.dataSaver.avatar) return mediaProxy.getStaticImageUrl(props.user.avatarUrl);
|
||||
return props.user.avatarUrl;
|
||||
});
|
||||
|
||||
|
@ -93,7 +94,7 @@ function onClick(ev: MouseEvent): void {
|
|||
}
|
||||
|
||||
function getDecorationUrl(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
if (defaultStore.state.disableShowingAnimatedImages || defaultStore.state.dataSaver.avatar) return getStaticImageUrl(decoration.url);
|
||||
if (defaultStore.state.disableShowingAnimatedImages || defaultStore.state.dataSaver.avatar) return mediaProxy.getStaticImageUrl(decoration.url);
|
||||
return decoration.url;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, ref } from 'vue';
|
||||
import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { customEmojisMap } from '@/custom-emojis.js';
|
||||
import * as os from '@/os.js';
|
||||
|
@ -36,6 +35,8 @@ import * as sound from '@/scripts/sound.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
name: string;
|
||||
normal?: boolean;
|
||||
|
@ -69,14 +70,14 @@ const url = computed(() => {
|
|||
const proxied =
|
||||
(rawUrl.value.startsWith('/emoji/') || (props.useOriginalSize && isLocal.value))
|
||||
? rawUrl.value
|
||||
: getProxiedImageUrl(
|
||||
: mediaProxy.getProxiedImageUrl(
|
||||
rawUrl.value,
|
||||
props.useOriginalSize ? undefined : 'emoji',
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return defaultStore.reactiveState.disableShowingAnimatedImages.value
|
||||
? getStaticImageUrl(proxied)
|
||||
? mediaProxy.getStaticImageUrl(proxied)
|
||||
: proxied;
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear>
|
||||
<div :class="$style.root">
|
||||
<img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.serverErrorImageUrl" :class="$style.img" :src="serverMetadata.serverErrorImageUrl" class="_ghost"/>
|
||||
<p :class="$style.text"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.somethingHappened }}</p>
|
||||
<MkButton :class="$style.button" @click="() => emit('retry')">{{ i18n.ts.retry }}</MkButton>
|
||||
</div>
|
||||
|
@ -14,10 +14,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { serverErrorImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'retry'): void;
|
||||
|
|
|
@ -25,14 +25,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, ref } from 'vue';
|
||||
import { defineAsyncComponent, inject, ref } from 'vue';
|
||||
import { toUnicode as decodePunycode } from 'punycode/';
|
||||
import { url as local } from '@/config.js';
|
||||
import * as os from '@/os.js';
|
||||
import { useTooltip } from '@/scripts/use-tooltip.js';
|
||||
import { isEnabledUrlPreview } from '@/instance.js';
|
||||
import { MkABehavior } from '@/components/global/MkA.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
function safeURIDecode(str: string): string {
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
|
@ -55,7 +56,7 @@ const url = new URL(props.url);
|
|||
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('invalid url');
|
||||
const el = ref();
|
||||
|
||||
if (props.showUrlPreview && isEnabledUrlPreview.value) {
|
||||
if (props.showUrlPreview && serverMetadata.enableUrlPreview) {
|
||||
useTooltip(el, (showing) => {
|
||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
||||
showing,
|
||||
|
|
|
@ -6,18 +6,19 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<div class="_gaps" :class="$style.textRoot">
|
||||
<Mfm :text="block.text ?? ''" :isNote="false"/>
|
||||
<div v-if="isEnabledUrlPreview" class="_gaps_s">
|
||||
<div v-if="serverMetadata.enableUrlPreview" class="_gaps_s">
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { defineAsyncComponent, inject } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm.js';
|
||||
import { isEnabledUrlPreview } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const MkUrlPreview = defineAsyncComponent(() => import('@/components/MkUrlPreview.vue'));
|
||||
|
||||
|
|
|
@ -106,10 +106,6 @@ export const ROLE_POLICIES = [
|
|||
export const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP';
|
||||
export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM';
|
||||
|
||||
export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg';
|
||||
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
||||
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
||||
|
||||
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime'];
|
||||
export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
|
||||
tada: ['speed=', 'delay='],
|
||||
|
@ -127,7 +123,7 @@ export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
|
|||
position: ['x=', 'y='],
|
||||
fg: ['color='],
|
||||
bg: ['color='],
|
||||
border: ['width=', 'style=', 'color=', 'radius=', 'noclip'],
|
||||
border: ['width=', 'style=', 'color=', 'radius=', 'noclip'],
|
||||
font: ['serif', 'monospace', 'cursive', 'fantasy', 'emoji', 'math'],
|
||||
blur: [],
|
||||
rainbow: ['speed=', 'delay='],
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
export type Keys =
|
||||
'v' |
|
||||
'lastVersion' |
|
||||
'instance' |
|
||||
'instanceCachedAt' |
|
||||
|
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkLoading v-if="!loaded"/>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear>
|
||||
<div v-show="loaded" :class="$style.root">
|
||||
<img :src="serverErrorImageUrl" class="_ghost" :class="$style.img"/>
|
||||
<img v-if="serverMetadata.serverErrorImageUrl" :src="serverMetadata.serverErrorImageUrl" class="_ghost" :class="$style.img"/>
|
||||
<div class="_gaps">
|
||||
<div><b><i class="ti ti-alert-triangle"></i> {{ i18n.ts.pageLoadError }}</b></div>
|
||||
<div v-if="meta && (version === meta.version)">{{ i18n.ts.pageLoadErrorDescription }}</div>
|
||||
|
@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkLink from '@/components/MkLink.vue';
|
||||
|
@ -36,7 +36,8 @@ import { i18n } from '@/i18n.js';
|
|||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { serverErrorImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
error?: Error;
|
||||
|
|
|
@ -46,21 +46,21 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</FormLink>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection v-if="instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey'">
|
||||
<FormSection v-if="serverMetadata.repositoryUrl !== 'https://github.com/misskey-dev/misskey'">
|
||||
<div class="_gaps_s">
|
||||
<MkInfo>
|
||||
{{ i18n.tsx._aboutMisskey.thisIsModifiedVersion({ name: instance.name }) }}
|
||||
{{ i18n.tsx._aboutMisskey.thisIsModifiedVersion({ name: serverMetadata.name }) }}
|
||||
</MkInfo>
|
||||
<FormLink v-if="instance.repositoryUrl" :to="instance.repositoryUrl" external>
|
||||
<FormLink v-if="serverMetadata.repositoryUrl" :to="serverMetadata.repositoryUrl" external>
|
||||
<template #icon><i class="ti ti-code"></i></template>
|
||||
{{ i18n.ts._aboutMisskey.source }}
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.providesTarball" :to="`/tarball/misskey-${version}.tar.gz`" external>
|
||||
<FormLink v-if="serverMetadata.providesTarball" :to="`/tarball/misskey-${version}.tar.gz`" external>
|
||||
<template #icon><i class="ti ti-download"></i></template>
|
||||
{{ i18n.ts._aboutMisskey.source }}
|
||||
<template #suffix>Tarball</template>
|
||||
</FormLink>
|
||||
<MkInfo v-if="!instance.repositoryUrl && !instance.providesTarball" warn>
|
||||
<MkInfo v-if="!serverMetadata.repositoryUrl && !serverMetadata.providesTarball" warn>
|
||||
{{ i18n.ts.sourceCodeIsNotYetProvided }}
|
||||
</MkInfo>
|
||||
</div>
|
||||
|
@ -131,7 +131,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onBeforeUnmount, ref, shallowRef, computed } from 'vue';
|
||||
import { nextTick, onBeforeUnmount, ref, shallowRef, computed, inject } from 'vue';
|
||||
import { version } from '@/config.js';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
|
@ -139,13 +139,14 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { physics } from '@/scripts/physics.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import * as os from '@/os.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js';
|
||||
import { $i } from '@/account.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const patronsWithIcon = [{
|
||||
name: 'カイヤン',
|
||||
icon: 'https://assets.misskey-hub.net/patrons/a2820716883e408cb87773e377ce7c8d.jpg',
|
||||
|
|
|
@ -5,18 +5,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div class="_gaps_m">
|
||||
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }">
|
||||
<div :class="$style.banner" :style="{ backgroundImage: `url(${ serverMetadata.bannerUrl })` }">
|
||||
<div style="overflow: clip;">
|
||||
<img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.bannerIcon"/>
|
||||
<img :src="serverMetadata.iconUrl ?? serverMetadata.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.bannerIcon"/>
|
||||
<div :class="$style.bannerName">
|
||||
<b>{{ instance.name ?? host }}</b>
|
||||
<b>{{ serverMetadata.name ?? host }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MkKeyValue>
|
||||
<template #key>{{ i18n.ts.description }}</template>
|
||||
<template #value><div v-html="instance.description"></div></template>
|
||||
<template #value><div v-html="serverMetadata.description"></div></template>
|
||||
</MkKeyValue>
|
||||
|
||||
<FormSection>
|
||||
|
@ -25,13 +25,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #key>Misskey</template>
|
||||
<template #value>{{ version }}</template>
|
||||
</MkKeyValue>
|
||||
<div v-html="i18n.tsx.poweredByMisskeyDescription({ name: instance.name ?? host })">
|
||||
<div v-html="i18n.tsx.poweredByMisskeyDescription({ name: serverMetadata.name ?? host })">
|
||||
</div>
|
||||
<FormLink to="/about-misskey">
|
||||
<template #icon><i class="ti ti-info-circle"></i></template>
|
||||
{{ i18n.ts.aboutMisskey }}
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.repositoryUrl || instance.providesTarball" :to="instance.repositoryUrl || `/tarball/misskey-${version}.tar.gz`" external>
|
||||
<FormLink v-if="serverMetadata.repositoryUrl || serverMetadata.providesTarball" :to="serverMetadata.repositoryUrl || `/tarball/misskey-${version}.tar.gz`" external>
|
||||
<template #icon><i class="ti ti-code"></i></template>
|
||||
{{ i18n.ts.sourceCode }}
|
||||
</FormLink>
|
||||
|
@ -44,51 +44,51 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<FormSection>
|
||||
<div class="_gaps_m">
|
||||
<FormSplit>
|
||||
<MkKeyValue :copy="instance.maintainerName">
|
||||
<MkKeyValue :copy="serverMetadata.maintainerName">
|
||||
<template #key>{{ i18n.ts.administrator }}</template>
|
||||
<template #value>
|
||||
<template v-if="instance.maintainerName">{{ instance.maintainerName }}</template>
|
||||
<template v-if="serverMetadata.maintainerName">{{ serverMetadata.maintainerName }}</template>
|
||||
<span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span>
|
||||
</template>
|
||||
</MkKeyValue>
|
||||
<MkKeyValue :copy="instance.maintainerEmail">
|
||||
<MkKeyValue :copy="serverMetadata.maintainerEmail">
|
||||
<template #key>{{ i18n.ts.contact }}</template>
|
||||
<template #value>
|
||||
<template v-if="instance.maintainerEmail">{{ instance.maintainerEmail }}</template>
|
||||
<template v-if="serverMetadata.maintainerEmail">{{ serverMetadata.maintainerEmail }}</template>
|
||||
<span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span>
|
||||
</template>
|
||||
</MkKeyValue>
|
||||
<MkKeyValue>
|
||||
<template #key>{{ i18n.ts.inquiry }}</template>
|
||||
<template #value>
|
||||
<MkLink v-if="instance.inquiryUrl" :url="instance.inquiryUrl" target="_blank">{{ instance.inquiryUrl }}</MkLink>
|
||||
<MkLink v-if="serverMetadata.inquiryUrl" :url="serverMetadata.inquiryUrl" target="_blank">{{ serverMetadata.inquiryUrl }}</MkLink>
|
||||
<span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span>
|
||||
</template>
|
||||
</MkKeyValue>
|
||||
</FormSplit>
|
||||
<div class="_gaps_s">
|
||||
<FormLink v-if="instance.impressumUrl" :to="instance.impressumUrl" external>
|
||||
<FormLink v-if="serverMetadata.impressumUrl" :to="serverMetadata.impressumUrl" external>
|
||||
<template #icon><i class="ti ti-user-shield"></i></template>
|
||||
<template #default>{{ i18n.ts.impressum }}</template>
|
||||
</FormLink>
|
||||
<MkFolder v-if="instance.serverRules.length > 0">
|
||||
<MkFolder v-if="serverMetadata.serverRules.length > 0">
|
||||
<template #icon><i class="ti ti-checkup-list"></i></template>
|
||||
<template #label>{{ i18n.ts.serverRules }}</template>
|
||||
<ol class="_gaps_s" :class="$style.rules">
|
||||
<li v-for="item in instance.serverRules" :key="item" :class="$style.rule">
|
||||
<li v-for="item in serverMetadata.serverRules" :key="item" :class="$style.rule">
|
||||
<div :class="$style.ruleText" v-html="item"></div>
|
||||
</li>
|
||||
</ol>
|
||||
</MkFolder>
|
||||
<FormLink v-if="instance.tosUrl" :to="instance.tosUrl" external>
|
||||
<FormLink v-if="serverMetadata.tosUrl" :to="serverMetadata.tosUrl" external>
|
||||
<template #icon><i class="ti ti-license"></i></template>
|
||||
<template #default>{{ i18n.ts.termsOfService }}</template>
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.privacyPolicyUrl" :to="instance.privacyPolicyUrl" external>
|
||||
<FormLink v-if="serverMetadata.privacyPolicyUrl" :to="serverMetadata.privacyPolicyUrl" external>
|
||||
<template #icon><i class="ti ti-shield-lock"></i></template>
|
||||
<template #default>{{ i18n.ts.privacyPolicy }}</template>
|
||||
</FormLink>
|
||||
<FormLink v-if="instance.feedbackUrl" :to="instance.feedbackUrl" external>
|
||||
<FormLink v-if="serverMetadata.feedbackUrl" :to="serverMetadata.feedbackUrl" external>
|
||||
<template #icon><i class="ti ti-message"></i></template>
|
||||
<template #default>{{ i18n.ts.feedback }}</template>
|
||||
</FormLink>
|
||||
|
@ -126,9 +126,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import { host, version } from '@/config.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import number from '@/filters/number.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
|
@ -139,6 +139,8 @@ import MkFolder from '@/components/MkFolder.vue';
|
|||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import MkLink from '@/components/MkLink.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const initStats = () => misskeyApi('stats', {});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ import FormSuspense from '@/components/form/suspense.vue';
|
|||
import FormSlot from '@/components/form/slot.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const MkCaptcha = defineAsyncComponent(() => import('@/components/MkCaptcha.vue'));
|
||||
|
@ -142,7 +142,7 @@ function save() {
|
|||
turnstileSiteKey: turnstileSiteKey.value,
|
||||
turnstileSecretKey: turnstileSecretKey.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -112,7 +112,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { instance, fetchInstance } from '@/instance.js';
|
||||
import { instance, fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
@ -169,7 +169,7 @@ function save() {
|
|||
feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value,
|
||||
manifestJsonOverride: manifestJsonOverride.value === '' ? '{}' : JSON.stringify(JSON5.parse(manifestJsonOverride.value)),
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ import FormSplit from '@/components/form/split.vue';
|
|||
import FormSection from '@/components/form/section.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
@ -99,10 +99,11 @@ async function init() {
|
|||
}
|
||||
|
||||
async function testEmail() {
|
||||
const serverMetadata = await fetchServerMetadata();
|
||||
const { canceled, result: destination } = await os.inputText({
|
||||
title: i18n.ts.destination,
|
||||
type: 'email',
|
||||
default: instance.maintainerEmail ?? '',
|
||||
default: serverMetadata.maintainerEmail ?? '',
|
||||
placeholder: 'test@example.com',
|
||||
minLength: 1,
|
||||
});
|
||||
|
@ -124,7 +125,7 @@ function save() {
|
|||
smtpUser: smtpUser.value,
|
||||
smtpPass: smtpPass.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ import FormSuspense from '@/components/form/suspense.vue';
|
|||
import FormSection from '@/components/form/section.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
|
@ -61,7 +61,7 @@ function save() {
|
|||
deeplAuthKey: deeplAuthKey.value,
|
||||
deeplIsPro: deeplIsPro.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkSpacer :contentMax="700" :marginMin="16">
|
||||
<div class="lxpfedzu _gaps">
|
||||
<div class="banner">
|
||||
<img :src="instance.iconUrl || '/favicon.ico'" alt="" class="icon"/>
|
||||
<img :src="serverMetadata.iconUrl || '/favicon.ico'" alt="" class="icon"/>
|
||||
</div>
|
||||
|
||||
<div class="_gaps_s">
|
||||
|
@ -31,11 +31,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted, onUnmounted, provide, watch, ref, computed } from 'vue';
|
||||
import { onActivated, onMounted, onUnmounted, provide, watch, ref, computed, inject } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkSuperMenu from '@/components/MkSuperMenu.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { instance } from '@/instance.js';
|
||||
import { lookup } from '@/scripts/lookup.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
|
@ -43,6 +42,8 @@ import { lookupUser, lookupUserByEmail, lookupFile } from '@/scripts/admin-looku
|
|||
import { PageMetadata, definePageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const isEmpty = (x: string | null) => x == null || x === '';
|
||||
|
||||
const router = useRouter();
|
||||
|
@ -61,10 +62,10 @@ const narrow = ref(false);
|
|||
const view = ref(null);
|
||||
const el = ref<HTMLDivElement | null>(null);
|
||||
const pageProps = ref({});
|
||||
const noMaintainerInformation = computed(() => isEmpty(instance.maintainerName) || isEmpty(instance.maintainerEmail));
|
||||
const noBotProtection = computed(() => !instance.disableRegistration && !instance.enableHcaptcha && !instance.enableRecaptcha && !instance.enableTurnstile && !instance.enableMcaptcha);
|
||||
const noEmailServer = computed(() => !instance.enableEmail);
|
||||
const noInquiryUrl = computed(() => isEmpty(instance.inquiryUrl));
|
||||
const noMaintainerInformation = computed(() => isEmpty(serverMetadata.maintainerName) || isEmpty(serverMetadata.maintainerEmail));
|
||||
const noBotProtection = computed(() => !serverMetadata.disableRegistration && !serverMetadata.enableHcaptcha && !serverMetadata.enableRecaptcha && !serverMetadata.enableTurnstile && !serverMetadata.enableMcaptcha);
|
||||
const noEmailServer = computed(() => !serverMetadata.enableEmail);
|
||||
const noInquiryUrl = computed(() => isEmpty(serverMetadata.inquiryUrl));
|
||||
const thereIsUnresolvedAbuseReport = ref(false);
|
||||
const currentPage = computed(() => router.currentRef.value.child);
|
||||
|
||||
|
@ -88,7 +89,7 @@ const menuDef = computed(() => [{
|
|||
icon: 'ti ti-search',
|
||||
text: i18n.ts.lookup,
|
||||
action: adminLookup,
|
||||
}, ...(instance.disableRegistration ? [{
|
||||
}, ...(serverMetadata.disableRegistration ? [{
|
||||
type: 'button',
|
||||
icon: 'ti ti-user-plus',
|
||||
text: i18n.ts.createInviteCode,
|
||||
|
|
|
@ -38,7 +38,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
|
@ -61,7 +61,7 @@ function save() {
|
|||
mediaSilencedHosts: mediaSilencedHosts.value.split('\n') || [],
|
||||
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
@ -119,7 +119,7 @@ function save() {
|
|||
hiddenTags: hiddenTags.value.split('\n'),
|
||||
preservedUsernames: preservedUsernames.value.split('\n'),
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ import FormSuspense from '@/components/form/suspense.vue';
|
|||
import FormSplit from '@/components/form/split.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
@ -143,7 +143,7 @@ function save() {
|
|||
objectStorageSetPublicRead: objectStorageSetPublicRead.value,
|
||||
objectStorageS3ForcePathStyle: objectStorageS3ForcePathStyle.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ import XHeader from './_header_.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
|
@ -73,7 +73,7 @@ function save() {
|
|||
enableChartsForRemoteUser: enableChartsForRemoteUser.value,
|
||||
enableChartsForFederatedInstances: enableChartsForFederatedInstances.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import MkInfo from '@/components/MkInfo.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
|
@ -56,7 +56,7 @@ function save() {
|
|||
os.apiWithDialog('admin/update-meta', {
|
||||
proxyAccountId: proxyAccountId.value,
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -596,7 +596,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, ref, computed } from 'vue';
|
||||
import { watch, ref, computed, inject } from 'vue';
|
||||
import { throttle } from 'throttle-debounce';
|
||||
import RolesEditorFormula from './RolesEditorFormula.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
@ -609,9 +609,10 @@ import MkRange from '@/components/MkRange.vue';
|
|||
import FormSlot from '@/components/form/slot.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { ROLE_POLICIES } from '@/const.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { deepClone } from '@/scripts/clone.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'update:modelValue', v: any): void;
|
||||
}>();
|
||||
|
@ -629,7 +630,7 @@ for (const ROLE_POLICY of ROLE_POLICIES) {
|
|||
role.value.policies[ROLE_POLICY] = {
|
||||
useDefault: true,
|
||||
priority: 0,
|
||||
value: instance.policies[ROLE_POLICY],
|
||||
value: serverMetadata.policies[ROLE_POLICY],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="usersPagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -74,7 +74,8 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
|
|
@ -251,7 +251,7 @@ import * as os from '@/os.js';
|
|||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { instance, fetchInstance } from '@/instance.js';
|
||||
import { instance, fetchServerMetadata } from '@/server-metadata.js';
|
||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
import { ROLE_POLICIES } from '@/const.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
|
@ -275,7 +275,7 @@ async function updateBaseRole() {
|
|||
await os.apiWithDialog('admin/roles/update-default-policies', {
|
||||
policies,
|
||||
});
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
}
|
||||
|
||||
function create() {
|
||||
|
|
|
@ -138,7 +138,7 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import MkTextarea from '@/components/MkTextarea.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
|
@ -205,7 +205,7 @@ function save() {
|
|||
truemailAuthKey: truemailAuthKey.value,
|
||||
bannedEmailDomains: bannedEmailDomains.value.split('\n'),
|
||||
}).then(() => {
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -41,24 +41,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, ref, computed } from 'vue';
|
||||
import { defineAsyncComponent, ref, computed, inject } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
|
||||
|
||||
const serverRules = ref<string[]>(instance.serverRules);
|
||||
const serverRules = ref<string[]>(serverMetadata.serverRules);
|
||||
|
||||
const save = async () => {
|
||||
await os.apiWithDialog('admin/update-meta', {
|
||||
serverRules: serverRules.value,
|
||||
});
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
};
|
||||
|
||||
const remove = (index: number): void => {
|
||||
|
|
|
@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #caption>{{ i18n.ts.repositoryUrlDescription }}</template>
|
||||
</MkInput>
|
||||
|
||||
<MkInfo v-if="!instance.providesTarball && !repositoryUrl" warn>
|
||||
<MkInfo v-if="!serverMetadata.providesTarball && !repositoryUrl" warn>
|
||||
{{ i18n.ts.repositoryUrlOrTarballRequired }}
|
||||
</MkInfo>
|
||||
|
||||
|
@ -205,7 +205,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
@ -216,13 +216,15 @@ import FormSplit from '@/components/form/split.vue';
|
|||
import FormSuspense from '@/components/form/suspense.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { fetchInstance, instance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const name = ref<string | null>(null);
|
||||
const shortName = ref<string | null>(null);
|
||||
const description = ref<string | null>(null);
|
||||
|
@ -310,7 +312,7 @@ async function save() {
|
|||
urlPreviewSummaryProxyUrl: urlPreviewSummaryProxyUrl.value,
|
||||
});
|
||||
|
||||
fetchInstance(true);
|
||||
fetchServerMetadata(true);
|
||||
}
|
||||
|
||||
const headerTabs = computed(() => []);
|
||||
|
|
|
@ -9,16 +9,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<MkSpacer :contentMax="500">
|
||||
<div class="_gaps">
|
||||
<MkAd v-for="ad in instance.ads" :key="ad.id" :specify="ad"/>
|
||||
<MkAd v-for="ad in serverMetadata.ads" :key="ad.id" :specify="ad"/>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
definePageMetadata(() => ({
|
||||
title: i18n.ts.ads,
|
||||
|
|
|
@ -8,24 +8,24 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #header><MkPageHeader/></template>
|
||||
<MkSpacer :contentMax="600" :marginMin="20">
|
||||
<div class="_gaps_m">
|
||||
<MkKeyValue :copy="instance.maintainerName">
|
||||
<MkKeyValue :copy="serverMetadata.maintainerName">
|
||||
<template #key>{{ i18n.ts.administrator }}</template>
|
||||
<template #value>
|
||||
<template v-if="instance.maintainerName">{{ instance.maintainerName }}</template>
|
||||
<template v-if="serverMetadata.maintainerName">{{ serverMetadata.maintainerName }}</template>
|
||||
<span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span>
|
||||
</template>
|
||||
</MkKeyValue>
|
||||
<MkKeyValue :copy="instance.maintainerEmail">
|
||||
<MkKeyValue :copy="serverMetadata.maintainerEmail">
|
||||
<template #key>{{ i18n.ts.contact }}</template>
|
||||
<template #value>
|
||||
<template v-if="instance.maintainerEmail">{{ instance.maintainerEmail }}</template>
|
||||
<template v-if="serverMetadata.maintainerEmail">{{ serverMetadata.maintainerEmail }}</template>
|
||||
<span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span>
|
||||
</template>
|
||||
</MkKeyValue>
|
||||
<MkKeyValue :copy="instance.inquiryUrl">
|
||||
<MkKeyValue :copy="serverMetadata.inquiryUrl">
|
||||
<template #key>{{ i18n.ts.inquiry }}</template>
|
||||
<template #value>
|
||||
<MkLink v-if="instance.inquiryUrl" :url="instance.inquiryUrl" target="_blank">{{ instance.inquiryUrl }}</MkLink>
|
||||
<MkLink v-if="serverMetadata.inquiryUrl" :url="serverMetadata.inquiryUrl" target="_blank">{{ serverMetadata.inquiryUrl }}</MkLink>
|
||||
<span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span>
|
||||
</template>
|
||||
</MkKeyValue>
|
||||
|
@ -35,12 +35,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import MkLink from '@/components/MkLink.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
definePageMetadata(() => ({
|
||||
title: i18n.ts.inquiry,
|
||||
icon: 'ti ti-help-circle',
|
||||
|
|
|
@ -69,7 +69,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</div>
|
||||
<div v-else class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,7 +82,8 @@ import MkInfo from '@/components/MkInfo.vue';
|
|||
import MkMediaList from '@/components/MkMediaList.vue';
|
||||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import bytes from '@/filters/bytes.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noNotes }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -31,7 +31,8 @@ import MkNote from '@/components/MkNote.vue';
|
|||
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const pagination = {
|
||||
endpoint: 'i/favorites' as const,
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination ref="paginationComponent" :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noFollowRequests }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -44,7 +44,8 @@ import { userPage, acct } from '@/filters/user.js';
|
|||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { ref, computed, watch, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkChart from '@/components/MkChart.vue';
|
||||
import MkObjectView from '@/components/MkObjectView.vue';
|
||||
|
@ -152,10 +152,11 @@ import { i18n } from '@/i18n.js';
|
|||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
|
||||
import { dateString } from '@/filters/date.js';
|
||||
import MkTextarea from '@/components/MkTextarea.vue';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
host: string;
|
||||
}>();
|
||||
|
@ -198,7 +199,7 @@ async function fetch(): Promise<void> {
|
|||
isBlocked.value = instance.value?.isBlocked ?? false;
|
||||
isSilenced.value = instance.value?.isSilenced ?? false;
|
||||
isMediaSilenced.value = instance.value?.isMediaSilenced ?? false;
|
||||
faviconUrl.value = getProxiedImageUrlNullable(instance.value?.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.value?.iconUrl, 'preview');
|
||||
faviconUrl.value = mediaProxy.getProxiedImageUrlNullable(instance.value?.faviconUrl, 'preview') ?? mediaProxy.getProxiedImageUrlNullable(instance.value?.iconUrl, 'preview');
|
||||
moderationNote.value = instance.value?.moderationNote ?? '';
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #header>
|
||||
<MkPageHeader/>
|
||||
</template>
|
||||
<MKSpacer v-if="!instance.disableRegistration || !($i && ($i.isAdmin || $i.policies.canInvite))" :contentMax="1200">
|
||||
<MKSpacer v-if="!serverMetadata.disableRegistration || !($i && ($i.isAdmin || $i.policies.canInvite))" :contentMax="1200">
|
||||
<div :class="$style.root">
|
||||
<img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.serverErrorImageUrl" :class="$style.img" :src="serverMetadata.serverErrorImageUrl" class="_ghost"/>
|
||||
<div :class="$style.text">
|
||||
<i class="ti ti-alert-triangle"></i>
|
||||
{{ i18n.ts.nothing }}
|
||||
|
@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, shallowRef } from 'vue';
|
||||
import { computed, inject, ref, shallowRef } from 'vue';
|
||||
import type * as Misskey from 'misskey-js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
|
@ -45,13 +45,14 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkInviteCode from '@/components/MkInviteCode.vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { serverErrorImageUrl, instance } from '@/instance.js';
|
||||
import { $i } from '@/account.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
const currentInviteLimit = ref<null | number>(null);
|
||||
const inviteLimit = (($i != null && $i.policies.inviteLimit) || (($i == null && instance.policies.inviteLimit))) as number;
|
||||
const inviteLimitCycle = (($i != null && $i.policies.inviteLimitCycle) || ($i == null && instance.policies.inviteLimitCycle)) as number;
|
||||
const inviteLimit = (($i != null && $i.policies.inviteLimit) || (($i == null && serverMetadata.policies.inviteLimit))) as number;
|
||||
const inviteLimitCycle = (($i != null && $i.policies.inviteLimitCycle) || ($i == null && serverMetadata.policies.inviteLimitCycle)) as number;
|
||||
|
||||
const pagination: Paging = {
|
||||
endpoint: 'invite/list' as const,
|
||||
|
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MKSpacer v-if="!(typeof error === 'undefined')" :contentMax="1200">
|
||||
<div :class="$style.root">
|
||||
<img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.serverErrorImageUrl" :class="$style.img" :src="serverMetadata.serverErrorImageUrl" class="_ghost"/>
|
||||
<p :class="$style.text">
|
||||
<i class="ti ti-alert-triangle"></i>
|
||||
{{ i18n.ts.nothing }}
|
||||
|
@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, computed, ref } from 'vue';
|
||||
import { watch, computed, ref, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
|
@ -43,7 +43,8 @@ import { i18n } from '@/i18n.js';
|
|||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { serverErrorImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = defineProps<{
|
||||
listId: string;
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div>
|
||||
<div v-if="antennas.length === 0" class="empty">
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -33,7 +33,8 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { antennasCache } from '@/cache.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const antennas = computed(() => antennasCache.value.value ?? []);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div class="_gaps">
|
||||
<div v-if="items.length === 0" class="empty">
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,7 +36,8 @@ import * as os from '@/os.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { userListsCache } from '@/cache.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
import { signinRequired } from '@/account.js';
|
||||
|
||||
const $i = signinRequired();
|
||||
|
|
|
@ -6,18 +6,19 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<div>
|
||||
<div class="_fullinfo">
|
||||
<img :src="notFoundImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.notFoundImageUrl" :src="serverMetadata.notFoundImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.notFoundDescription }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, inject } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { pleaseLogin } from '@/scripts/please-login.js';
|
||||
import { notFoundImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = defineProps<{
|
||||
showLoginPopup?: boolean;
|
||||
|
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<img
|
||||
v-else-if="instance.backgroundImageUrl || instance.bannerUrl"
|
||||
:class="[$style.pageBannerBg, $style.pageBannerBgFallback1]"
|
||||
:src="getStaticImageUrl(instance.backgroundImageUrl ?? instance.bannerUrl!)"
|
||||
:src="mediaProxy.getStaticImageUrl(instance.backgroundImageUrl ?? instance.bannerUrl!)"
|
||||
/>
|
||||
<div v-else :class="[$style.pageBannerBg, $style.pageBannerBgFallback2]"></div>
|
||||
</div>
|
||||
|
@ -98,7 +98,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, watch, ref, defineAsyncComponent } from 'vue';
|
||||
import { computed, watch, ref, defineAsyncComponent, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XPage from '@/components/page/page.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
@ -117,12 +117,13 @@ import { pageViewInterruptors, defaultStore } from '@/store.js';
|
|||
import { deepClone } from '@/scripts/clone.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { isSupportShare } from '@/scripts/navigator.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
import { MenuItem } from '@/types/menu';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div v-if="role">{{ role.description }}</div>
|
||||
<MkUserList v-if="visible" :pagination="users" :extractor="(item) => item.user"/>
|
||||
<div v-else-if="!visible" class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkSpacer v-else-if="tab === 'timeline'" :contentMax="700">
|
||||
<MkTimeline v-if="visible" ref="timeline" src="role" :role="props.role"/>
|
||||
<div v-else-if="!visible" class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
|
@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, watch, ref } from 'vue';
|
||||
import { computed, watch, ref, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import MkUserList from '@/components/MkUserList.vue';
|
||||
|
@ -44,7 +44,8 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import MkTimeline from '@/components/MkTimeline.vue';
|
||||
import { instanceName } from '@/config.js';
|
||||
import { serverErrorImageUrl, infoImageUrl } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
role: string;
|
||||
|
|
|
@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, toRef, watch } from 'vue';
|
||||
import { computed, inject, ref, toRef, watch } from 'vue';
|
||||
import type { UserDetailed } from 'misskey-js/entities.js';
|
||||
import type { Paging } from '@/components/MkPagination.vue';
|
||||
import MkNotes from '@/components/MkNotes.vue';
|
||||
|
@ -66,7 +66,8 @@ import { useRouter } from '@/router/supplier.js';
|
|||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkRadios from '@/components/MkRadios.vue';
|
||||
import { $i } from '@/account.js';
|
||||
import { instance } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
query?: string;
|
||||
|
@ -87,7 +88,7 @@ const notePagination = ref<Paging>();
|
|||
const user = ref<UserDetailed | null>(null);
|
||||
const hostInput = ref(toRef(props, 'host').value);
|
||||
|
||||
const noteSearchableScope = instance.noteSearchableScope ?? 'local';
|
||||
const noteSearchableScope = serverMetadata.noteSearchableScope ?? 'local';
|
||||
|
||||
const hostSelect = ref<'all' | 'local' | 'specified'>('all');
|
||||
|
||||
|
@ -121,7 +122,7 @@ if (props.userId != null) {
|
|||
}
|
||||
|
||||
function selectUser() {
|
||||
os.selectUser({ includeSelf: true, localOnly: instance.noteSearchableScope === 'local' }).then(_user => {
|
||||
os.selectUser({ includeSelf: true, localOnly: serverMetadata.noteSearchableScope === 'local' }).then(_user => {
|
||||
user.value = _user;
|
||||
hostInput.value = _user.host ?? '';
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<MkHorizontalSwipe v-model:tab="tab" :tabs="headerTabs">
|
||||
<MkSpacer v-if="tab === 'note'" key="note" :contentMax="800">
|
||||
<div v-if="notesSearchAvailable || ignoreNotesSearchAvailable">
|
||||
<div v-if="isNotesSearchAvailable(serverMetadata) || ignoreNotesSearchAvailable">
|
||||
<XNote v-bind="props"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
|
@ -25,13 +25,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineAsyncComponent, ref, toRef } from 'vue';
|
||||
import { computed, defineAsyncComponent, inject, ref, toRef } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { notesSearchAvailable } from '@/scripts/check-permissions.js';
|
||||
import { isNotesSearchAvailable } from '@/scripts/check-permissions.js';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
query?: string,
|
||||
userId?: string,
|
||||
|
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<FormPagination ref="list" :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -52,7 +52,8 @@ import { i18n } from '@/i18n.js';
|
|||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const list = ref<InstanceType<typeof FormPagination>>();
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="instance.enableEmail" class="_gaps_m">
|
||||
<div v-if="serverMetadata.enableEmail" class="_gaps_m">
|
||||
<FormSection first>
|
||||
<template #label>{{ i18n.ts.emailAddress }}</template>
|
||||
<MkInput v-model="emailAddress" type="email" manualSave>
|
||||
|
@ -42,13 +42,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</FormSection>
|
||||
</div>
|
||||
<div v-if="!instance.enableEmail" class="_gaps_m">
|
||||
<div v-if="!serverMetadata.enableEmail" class="_gaps_m">
|
||||
<MkInfo>{{ i18n.ts.emailNotSupported }}</MkInfo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch, computed } from 'vue';
|
||||
import { onMounted, ref, watch, computed, inject } from 'vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
@ -58,7 +58,8 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
|
|||
import { signinRequired } from '@/account.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { instance } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const $i = signinRequired();
|
||||
|
||||
|
|
|
@ -28,17 +28,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onActivated, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue';
|
||||
import { computed, inject, onActivated, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkSuperMenu from '@/components/MkSuperMenu.vue';
|
||||
import { signout, $i } from '@/account.js';
|
||||
import { clearCache } from '@/scripts/clear-cache.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { PageMetadata, definePageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||
import * as os from '@/os.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const indexInfo = {
|
||||
title: i18n.ts.settings,
|
||||
icon: 'ti ti-settings',
|
||||
|
|
|
@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="renoteMutingPagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -64,7 +64,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="mutingPagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -97,7 +97,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagination :pagination="blockingPagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<img v-if="serverMetadata.infoImageUrl" :src="serverMetadata.infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -136,7 +136,8 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
|||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
import { inject } from 'vue';
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
import { signinRequired } from '@/account.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onActivated, ref, watch } from 'vue';
|
||||
import { computed, inject, onActivated, ref, watch } from 'vue';
|
||||
import JSON5 from 'json5';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
|
@ -83,7 +83,6 @@ import { selectFile } from '@/scripts/select-file.js';
|
|||
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js';
|
||||
import { ColdDeviceStorage, defaultStore } from '@/store.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { uniqueBy } from '@/scripts/array.js';
|
||||
import { fetchThemes, getThemes } from '@/theme-store.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
@ -91,6 +90,8 @@ import { miLocalStorage } from '@/local-storage.js';
|
|||
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
async function reloadAsk() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'info',
|
||||
|
@ -104,10 +105,10 @@ async function reloadAsk() {
|
|||
const installedThemes = ref(getThemes());
|
||||
const builtinThemes = getBuiltinThemesRef();
|
||||
|
||||
const instanceDarkTheme = computed(() => instance.defaultDarkTheme ? JSON5.parse(instance.defaultDarkTheme) : null);
|
||||
const instanceDarkTheme = computed(() => serverMetadata.defaultDarkTheme ? JSON5.parse(serverMetadata.defaultDarkTheme) : null);
|
||||
const installedDarkThemes = computed(() => installedThemes.value.filter(t => t.base === 'dark' || t.kind === 'dark'));
|
||||
const builtinDarkThemes = computed(() => builtinThemes.value.filter(t => t.base === 'dark' || t.kind === 'dark'));
|
||||
const instanceLightTheme = computed(() => instance.defaultLightTheme ? JSON5.parse(instance.defaultLightTheme) : null);
|
||||
const instanceLightTheme = computed(() => serverMetadata.defaultLightTheme ? JSON5.parse(serverMetadata.defaultLightTheme) : null);
|
||||
const installedLightThemes = computed(() => installedThemes.value.filter(t => t.base === 'light' || t.kind === 'light'));
|
||||
const builtinLightThemes = computed(() => builtinThemes.value.filter(t => t.base === 'light' || t.kind === 'light'));
|
||||
const themes = computed(() => uniqueBy([instanceDarkTheme.value, instanceLightTheme.value, ...builtinThemes.value, ...installedThemes.value].filter(x => x != null), theme => theme.id));
|
||||
|
|
|
@ -34,13 +34,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, watch, provide, shallowRef, ref, onMounted, onActivated } from 'vue';
|
||||
import { computed, watch, provide, shallowRef, ref, onMounted, onActivated, inject } from 'vue';
|
||||
import { scroll } from '@@/js/scroll.js';
|
||||
import type { Tab } from '@/components/global/MkPageHeader.tabs.vue';
|
||||
import type { BasicTimelineType } from '@/timelines.js';
|
||||
import MkTimeline from '@/components/MkTimeline.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkPostForm from '@/components/MkPostForm.vue';
|
||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||
import { scroll } from '@@/js/scroll.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
|
@ -53,17 +54,18 @@ import { deepMerge } from '@/scripts/merge.js';
|
|||
import { MenuItem } from '@/types/menu.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { availableBasicTimelines, hasWithReplies, isAvailableBasicTimeline, isBasicTimeline, basicTimelineIconClass } from '@/timelines.js';
|
||||
import type { BasicTimelineType } from '@/timelines.js';
|
||||
|
||||
provide('shouldOmitHeaderTitle', true);
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
|
||||
const tlComponent = shallowRef<InstanceType<typeof MkTimeline>>();
|
||||
const rootEl = shallowRef<HTMLElement>();
|
||||
|
||||
type TimelinePageSrc = BasicTimelineType | `list:${string}`;
|
||||
|
||||
const queue = ref(0);
|
||||
const srcWhenNotSignin = ref<'local' | 'global'>(isAvailableBasicTimeline('local') ? 'local' : 'global');
|
||||
const srcWhenNotSignin = ref<'local' | 'global'>(isAvailableBasicTimeline(serverMetadata, 'local') ? 'local' : 'global');
|
||||
const src = computed<TimelinePageSrc>({
|
||||
get: () => ($i ? defaultStore.reactiveState.tl.value.src : srcWhenNotSignin.value),
|
||||
set: (x) => saveSrc(x),
|
||||
|
@ -240,8 +242,8 @@ function closeTutorial(): void {
|
|||
}
|
||||
|
||||
function switchTlIfNeeded() {
|
||||
if (isBasicTimeline(src.value) && !isAvailableBasicTimeline(src.value)) {
|
||||
src.value = availableBasicTimelines()[0];
|
||||
if (isBasicTimeline(src.value) && !isAvailableBasicTimeline(serverMetadata, src.value)) {
|
||||
src.value = availableBasicTimelines(serverMetadata)[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +299,7 @@ const headerTabs = computed(() => [...(defaultStore.reactiveState.pinnedUserList
|
|||
title: l.name,
|
||||
icon: 'ti ti-star',
|
||||
iconOnly: true,
|
||||
}))), ...availableBasicTimelines().map(tl => ({
|
||||
}))), ...availableBasicTimelines(serverMetadata).map(tl => ({
|
||||
key: tl,
|
||||
title: i18n.ts._timelines[tl],
|
||||
icon: basicTimelineIconClass(tl),
|
||||
|
@ -319,7 +321,7 @@ const headerTabs = computed(() => [...(defaultStore.reactiveState.pinnedUserList
|
|||
onClick: chooseChannel,
|
||||
}] as Tab[]);
|
||||
|
||||
const headerTabsWhenNotLogin = computed(() => [...availableBasicTimelines().map(tl => ({
|
||||
const headerTabsWhenNotLogin = computed(() => [...availableBasicTimelines(serverMetadata).map(tl => ({
|
||||
key: tl,
|
||||
title: i18n.ts._timelines[tl],
|
||||
icon: basicTimelineIconClass(tl),
|
||||
|
|
|
@ -151,8 +151,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, computed, onMounted, onUnmounted, nextTick, watch, ref } from 'vue';
|
||||
import { defineAsyncComponent, computed, onMounted, onUnmounted, nextTick, watch, ref, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { getScrollPosition } from '@@/js/scroll.js';
|
||||
import MkNote from '@/components/MkNote.vue';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
import MkAccountMoved from '@/components/MkAccountMoved.vue';
|
||||
|
@ -161,7 +162,6 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import MkOmit from '@/components/MkOmit.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { getScrollPosition } from '@@/js/scroll.js';
|
||||
import { getUserMenu } from '@/scripts/get-user-menu.js';
|
||||
import number from '@/filters/number.js';
|
||||
import { userPage } from '@/filters/user.js';
|
||||
|
@ -174,7 +174,9 @@ import { confetti } from '@/scripts/confetti.js';
|
|||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js';
|
||||
import { useRouter } from '@/router/supplier.js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
function calcAge(birthdate: string): number {
|
||||
const date = new Date(birthdate);
|
||||
|
@ -224,7 +226,7 @@ const style = computed(() => {
|
|||
if (props.user.bannerUrl == null) return {};
|
||||
if (defaultStore.state.disableShowingAnimatedImages) {
|
||||
return {
|
||||
backgroundImage: `url(${ getStaticImageUrl(props.user.bannerUrl) })`,
|
||||
backgroundImage: `url(${ mediaProxy.getStaticImageUrl(props.user.bannerUrl) })`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
|
@ -238,7 +240,7 @@ const age = computed(() => {
|
|||
});
|
||||
|
||||
function menu(ev: MouseEvent) {
|
||||
const { menu, cleanup } = getUserMenu(user.value, router);
|
||||
const { menu, cleanup } = getUserMenu({ serverMetadata }, user.value, router);
|
||||
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { inject, onMounted, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { notePage } from '@/filters/note.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import MkContainer from '@/components/MkContainer.vue';
|
||||
|
@ -43,6 +42,8 @@ import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
|
|||
import { defaultStore } from '@/store.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const props = defineProps<{
|
||||
user: Misskey.entities.UserDetailed;
|
||||
}>();
|
||||
|
@ -56,7 +57,7 @@ const showingFiles = ref<string[]>([]);
|
|||
|
||||
function thumbnail(image: Misskey.entities.DriveFile): string {
|
||||
return defaultStore.state.disableShowingAnimatedImages
|
||||
? getStaticImageUrl(image.url)
|
||||
? mediaProxy.getStaticImageUrl(image.url)
|
||||
: image.thumbnailUrl;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="meta" class="rsqzvsbo">
|
||||
<div class="rsqzvsbo">
|
||||
<MkFeaturedPhotos class="bg"/>
|
||||
<XTimeline class="tl"/>
|
||||
<div class="shape1"></div>
|
||||
|
@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { inject, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XTimeline from './welcome.timeline.vue';
|
||||
import MarqueeText from '@/components/MkMarquee.vue';
|
||||
|
@ -44,8 +44,9 @@ import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue';
|
|||
import misskeysvg from '/client-assets/misskey.svg';
|
||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import MkVisitorDashboard from '@/components/MkVisitorDashboard.vue';
|
||||
import { getProxiedImageUrl } from '@/scripts/media-proxy.js';
|
||||
import { instance as meta } from '@/instance.js';
|
||||
|
||||
const serverMetadata = inject('serverMetadata');
|
||||
const mediaProxy = inject('mediaProxy');
|
||||
|
||||
const instances = ref<Misskey.entities.FederationInstance[]>();
|
||||
|
||||
|
@ -53,7 +54,7 @@ function getInstanceIcon(instance: Misskey.entities.FederationInstance): string
|
|||
if (!instance.iconUrl) {
|
||||
return '';
|
||||
}
|
||||
return getProxiedImageUrl(instance.iconUrl, 'preview');
|
||||
return mediaProxy.getProxiedImageUrl(instance.iconUrl, 'preview');
|
||||
}
|
||||
|
||||
misskeyApiGet('federation/instances', {
|
||||
|
|
|
@ -17,11 +17,11 @@ import XSetup from './welcome.setup.vue';
|
|||
import XEntrance from './welcome.entrance.a.vue';
|
||||
import { instanceName } from '@/config.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
|
||||
const instance = ref<Misskey.entities.MetaDetailed | null>(null);
|
||||
|
||||
fetchInstance(true).then((res) => {
|
||||
fetchServerMetadata(true).then((res) => {
|
||||
instance.value = res;
|
||||
});
|
||||
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { instance } from '@/instance.js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { $i } from '@/account.js';
|
||||
|
||||
export const notesSearchAvailable = (
|
||||
// FIXME: instance.policies would be null in Vitest
|
||||
export function isNotesSearchAvailable(serverMetadata: Misskey.entities.MetaDetailed): boolean {
|
||||
// FIXME: serverMetadata.policies would be null in Vitest
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
($i == null && instance.policies != null && instance.policies.canSearchNotes) ||
|
||||
return ($i == null && serverMetadata.policies != null && serverMetadata.policies.canSearchNotes) ||
|
||||
($i != null && $i.policies.canSearchNotes) ||
|
||||
false
|
||||
) as boolean;
|
||||
false;
|
||||
}
|
||||
|
||||
export const canSearchNonLocalNotes = (
|
||||
instance.noteSearchableScope === 'global'
|
||||
);
|
||||
export function canSearchNonLocalNotes(serverMetadata: Misskey.entities.MetaDetailed): boolean {
|
||||
return serverMetadata.noteSearchableScope === 'global';
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { unisonReload } from '@/scripts/unison-reload.js';
|
|||
import * as os from '@/os.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { fetchCustomEmojis } from '@/custom-emojis.js';
|
||||
import { fetchInstance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
|
||||
export async function clearCache() {
|
||||
os.waiting();
|
||||
|
@ -18,7 +18,7 @@ export async function clearCache() {
|
|||
miLocalStorage.removeItem('theme');
|
||||
miLocalStorage.removeItem('emojis');
|
||||
miLocalStorage.removeItem('lastEmojisFetchedAt');
|
||||
await fetchInstance(true);
|
||||
await fetchServerMetadata(true);
|
||||
await fetchCustomEmojis(true);
|
||||
unisonReload();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import * as Misskey from 'misskey-js';
|
|||
import { claimAchievement } from './achievements.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
||||
|
@ -170,7 +169,7 @@ function getNoteEmbedCodeMenu(note: Misskey.entities.Note, text: string): MenuIt
|
|||
};
|
||||
}
|
||||
|
||||
export function getNoteMenu(props: {
|
||||
export function getNoteMenu(ctx: { serverMetadata: Misskey.entities.MetaDetailed }, props: {
|
||||
note: Misskey.entities.Note;
|
||||
translation: Ref<Misskey.entities.NotesTranslateResponse | null>;
|
||||
translating: Ref<boolean>;
|
||||
|
@ -330,7 +329,7 @@ export function getNoteMenu(props: {
|
|||
text: i18n.ts.share,
|
||||
action: share,
|
||||
}] : []),
|
||||
$i && $i.policies.canUseTranslator && instance.translatorAvailable ? {
|
||||
$i && $i.policies.canUseTranslator && ctx.serverMetadata.translatorAvailable ? {
|
||||
icon: 'ti ti-language-hiragana',
|
||||
text: i18n.ts.translate,
|
||||
action: translate,
|
||||
|
@ -375,7 +374,7 @@ export function getNoteMenu(props: {
|
|||
text: i18n.ts.user,
|
||||
children: async () => {
|
||||
const user = appearNote.userId === $i?.id ? $i : await misskeyApi('users/show', { userId: appearNote.userId });
|
||||
const { menu, cleanup } = getUserMenu(user);
|
||||
const { menu, cleanup } = getUserMenu(ctx, user);
|
||||
cleanups.push(cleanup);
|
||||
return menu;
|
||||
},
|
||||
|
@ -458,13 +457,13 @@ export function getNoteMenu(props: {
|
|||
text: i18n.ts.copyContent,
|
||||
action: copyContent,
|
||||
}, getCopyNoteLinkMenu(appearNote, i18n.ts.copyLink),
|
||||
(appearNote.url || appearNote.uri) ? {
|
||||
icon: 'ti ti-external-link',
|
||||
text: i18n.ts.showOnRemote,
|
||||
action: () => {
|
||||
window.open(appearNote.url ?? appearNote.uri, '_blank', 'noopener');
|
||||
},
|
||||
} : getNoteEmbedCodeMenu(appearNote, i18n.ts.genEmbedCode)]
|
||||
(appearNote.url || appearNote.uri) ? {
|
||||
icon: 'ti ti-external-link',
|
||||
text: i18n.ts.showOnRemote,
|
||||
action: () => {
|
||||
window.open(appearNote.url ?? appearNote.uri, '_blank', 'noopener');
|
||||
},
|
||||
} : getNoteEmbedCodeMenu(appearNote, i18n.ts.genEmbedCode)]
|
||||
.filter(x => x !== undefined);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ import * as os from '@/os.js';
|
|||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { defaultStore, userActions } from '@/store.js';
|
||||
import { $i, iAmModerator } from '@/account.js';
|
||||
import { notesSearchAvailable, canSearchNonLocalNotes } from '@/scripts/check-permissions.js';
|
||||
import { isNotesSearchAvailable, canSearchNonLocalNotes } from '@/scripts/check-permissions.js';
|
||||
import { IRouter } from '@/nirax.js';
|
||||
import { antennasCache, rolesCache, userListsCache } from '@/cache.js';
|
||||
import { mainRouter } from '@/router/main.js';
|
||||
import { genEmbedCode } from '@/scripts/get-embed-code.js';
|
||||
import { MenuItem } from '@/types/menu.js';
|
||||
|
||||
export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter = mainRouter) {
|
||||
export function getUserMenu(ctx: { serverMetadata: Misskey.entities.MetaDetailed }, user: Misskey.entities.UserDetailed, router: IRouter = mainRouter) {
|
||||
const meId = $i ? $i.id : null;
|
||||
|
||||
const cleanups = [] as (() => void)[];
|
||||
|
@ -154,7 +154,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
|
|||
action: () => {
|
||||
copyToClipboard(`@${user.username}@${user.host ?? host}`);
|
||||
},
|
||||
}, ...( notesSearchAvailable && (user.host == null || canSearchNonLocalNotes) ? [{
|
||||
}, ...(isNotesSearchAvailable(ctx.serverMetadata) && (user.host == null || canSearchNonLocalNotes(ctx.serverMetadata)) ? [{
|
||||
icon: 'ti ti-search',
|
||||
text: i18n.ts.searchThisUsersNotes,
|
||||
action: () => {
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { query } from '@@/js/url.js';
|
||||
import { url } from '@/config.js';
|
||||
import { instance } from '@/instance.js';
|
||||
|
||||
export function getProxiedImageUrl(imageUrl: string, type?: 'preview' | 'emoji' | 'avatar', mustOrigin = false, noFallback = false): string {
|
||||
const localProxy = `${url}/proxy`;
|
||||
|
||||
if (imageUrl.startsWith(instance.mediaProxy + '/') || imageUrl.startsWith('/proxy/') || imageUrl.startsWith(localProxy + '/')) {
|
||||
// もう既にproxyっぽそうだったらurlを取り出す
|
||||
imageUrl = (new URL(imageUrl)).searchParams.get('url') ?? imageUrl;
|
||||
}
|
||||
|
||||
return `${mustOrigin ? localProxy : instance.mediaProxy}/${
|
||||
type === 'preview' ? 'preview.webp'
|
||||
: 'image.webp'
|
||||
}?${query({
|
||||
url: imageUrl,
|
||||
...(!noFallback ? { 'fallback': '1' } : {}),
|
||||
...(type ? { [type]: '1' } : {}),
|
||||
...(mustOrigin ? { origin: '1' } : {}),
|
||||
})}`;
|
||||
}
|
||||
|
||||
export function getProxiedImageUrlNullable(imageUrl: string | null | undefined, type?: 'preview'): string | null {
|
||||
if (imageUrl == null) return null;
|
||||
return getProxiedImageUrl(imageUrl, type);
|
||||
}
|
||||
|
||||
export function getStaticImageUrl(baseUrl: string): string {
|
||||
const u = baseUrl.startsWith('http') ? new URL(baseUrl) : new URL(baseUrl, url);
|
||||
|
||||
if (u.href.startsWith(`${url}/emoji/`)) {
|
||||
// もう既にemojiっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
|
||||
if (u.href.startsWith(instance.mediaProxy + '/')) {
|
||||
// もう既にproxyっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
|
||||
return `${instance.mediaProxy}/static.webp?${query({
|
||||
url: u.href,
|
||||
static: '1',
|
||||
})}`;
|
||||
}
|
|
@ -13,7 +13,7 @@ import { apiUrl } from '@/config.js';
|
|||
import { $i } from '@/account.js';
|
||||
import { alert } from '@/os.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { fetchServerMetadata } from '@/server-metadata.js';
|
||||
|
||||
type Uploading = {
|
||||
id: string;
|
||||
|
@ -40,16 +40,16 @@ export function uploadFile(
|
|||
|
||||
if (folder && typeof folder === 'object') folder = folder.id;
|
||||
|
||||
if (file.size > instance.maxFileSize) {
|
||||
alert({
|
||||
type: 'error',
|
||||
title: i18n.ts.failedToUpload,
|
||||
text: i18n.ts.cannotUploadBecauseExceedsFileSizeLimit,
|
||||
});
|
||||
return Promise.reject();
|
||||
}
|
||||
return fetchServerMetadata().then((serverMetadata) => new Promise((resolve, reject) => {
|
||||
if (file.size > serverMetadata.maxFileSize) {
|
||||
alert({
|
||||
type: 'error',
|
||||
title: i18n.ts.failedToUpload,
|
||||
text: i18n.ts.cannotUploadBecauseExceedsFileSizeLimit,
|
||||
});
|
||||
return reject();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = uuid();
|
||||
|
||||
const reader = new FileReader();
|
||||
|
@ -158,5 +158,5 @@ export function uploadFile(
|
|||
xhr.send(formData);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue