From 5445b023e5cedb7228710637c895c63328e3db74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:08:54 +0900 Subject: [PATCH] =?UTF-8?q?enhance:=20=E9=80=A3=E5=90=88=E3=83=A2=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=81=AB=E3=81=82=E3=82=8F=E3=81=9B=E3=81=A6=E3=83=95?= =?UTF-8?q?=E3=83=AD=E3=83=B3=E3=83=88=E3=82=A8=E3=83=B3=E3=83=89=E3=82=92?= =?UTF-8?q?=E5=A4=89=E5=8C=96=E3=81=95=E3=81=9B=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=20(#15112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(backend): metaã«federation modeã«é–¢ã™ã‚‹æƒ…å ±ã‚’å…¬é–‹ * enhance(frontend): 登録画é¢ã®æ³¨æ„書ãã‚’è¿½åŠ * enhance(frontend): aboutページ・サーãƒãƒ¼æƒ…å ± * enhance(frontend): サーãƒãƒ¼çµ±è¨ˆ * enhance(frontend): ã¿ã¤ã‘るページ * enhance(frontend): 検索 * enhance(frontend): ユーザーé¸æŠž * enhance(frontend): è¨å®šç”»é¢ * enhance(frontend): ウィジェット * enhance(frontend): リモートã§é–‹ãオプション * Update Changelog * enhance(frontend): ステータスãƒãƒ¼ * i18n --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + locales/index.d.ts | 8 ++++ locales/ja-JP.yml | 2 + .../src/core/entities/MetaEntityService.ts | 1 + .../backend/src/models/json-schema/meta.ts | 5 ++ .../src/components/MkInstanceStats.vue | 18 ++++--- .../src/components/MkSignupDialog.rules.vue | 6 ++- .../src/components/MkUserSelectDialog.vue | 11 +++-- .../src/components/MkVisitorDashboard.vue | 6 ++- .../frontend/src/components/MkWidgets.vue | 19 ++++++-- packages/frontend/src/pages/about.vue | 47 ++++++++++++------- packages/frontend/src/pages/explore.users.vue | 3 +- packages/frontend/src/pages/search.note.vue | 22 +++++---- packages/frontend/src/pages/search.user.vue | 5 +- .../frontend/src/pages/settings/general.vue | 3 +- .../src/pages/settings/mute-block.vue | 4 +- .../frontend/src/pages/settings/privacy.vue | 9 ++-- .../pages/settings/statusbar.statusbar.vue | 3 +- packages/frontend/src/scripts/please-login.ts | 12 ++++- packages/frontend/src/ui/_common_/common.ts | 18 ++++--- .../frontend/src/ui/_common_/statusbars.vue | 3 +- packages/frontend/src/widgets/index.ts | 10 +++- packages/misskey-js/src/autogen/types.ts | 2 + 23 files changed, 150 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af5d333927..287d390453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Enhance: PCç”»é¢ã§ãƒãƒ£ãƒ³ãƒãƒ«ãŒè¤‡æ•°åˆ—ã§è¡¨ç¤ºã•ã‚Œã‚‹ã‚ˆã†ã« (Cherry-picked from https://github.com/Otaku-Social/maniakey/pull/13) - Enhance: 照会ã«å¤±æ•—ã—ãŸå ´åˆã€ãã®ç†ç”±ã‚’表示ã™ã‚‹ã‚ˆã†ã« +- Enhance: 連åˆãŒãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆåŒ–・無効化ã•ã‚Œã¦ã„るサーãƒãƒ¼å‘ã‘ã®ãƒ‡ã‚¶ã‚¤ãƒ³ä¿®æ£ - Enhance: AiScriptã®ã‚»ãƒ¼ãƒ–データを明示的ã«å‰Šé™¤ã™ã‚‹é–¢æ•°`Mk:remove`ã‚’è¿½åŠ - Enhance: AiScriptã®æ‹¡å¼µAPI関数ã«ãŠã„ã¦å¼•æ•°ã®åž‹ãƒã‚§ãƒƒã‚¯ã‚’ã‚ˆã‚ŠåŽ³æ ¼ã« - Fix: ç”»é¢ã‚µã‚¤ã‚ºãŒå¤‰ã‚ã£ãŸéš›ã«ãƒŠãƒ“ゲーションãƒãƒ¼ãŒè‡ªå‹•ã§æŠ˜ã‚ŠãŸãŸã¾ã‚Œãªã„å•é¡Œã‚’ä¿®æ£ diff --git a/locales/index.d.ts b/locales/index.d.ts index 7c3ef5d93c..453d40feea 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5230,6 +5230,14 @@ export interface Locale extends ILocale { * 注æ„äº‹é …ã‚’ç†è§£ã—ãŸä¸Šã§ã‚ªãƒ³ã«ã—ã¾ã™ã€‚ */ "acknowledgeNotesAndEnable": string; + /** + * ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¯ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆé€£åˆã§é‹ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚管ç†è€…ãŒæŒ‡å®šã—ãŸã‚µãƒ¼ãƒãƒ¼ä»¥å¤–ã¨ã‚„ã‚Šå–ã‚Šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + */ + "federationSpecified": string; + /** + * ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¯é€£åˆãŒç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã‚„ã‚Šå–ã‚Šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + */ + "federationDisabled": string; "_accountSettings": { /** * コンテンツã®è¡¨ç¤ºã«ãƒã‚°ã‚¤ãƒ³ã‚’å¿…é ˆã«ã™ã‚‹ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 57a88062c1..a3cb9d052a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1303,6 +1303,8 @@ lockdown: "ãƒãƒƒã‚¯ãƒ€ã‚¦ãƒ³" pleaseSelectAccount: "アカウントをé¸æŠžã—ã¦ãã ã•ã„" availableRoles: "利用å¯èƒ½ãªãƒãƒ¼ãƒ«" acknowledgeNotesAndEnable: "注æ„äº‹é …ã‚’ç†è§£ã—ãŸä¸Šã§ã‚ªãƒ³ã«ã—ã¾ã™ã€‚" +federationSpecified: "ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¯ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆé€£åˆã§é‹ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚管ç†è€…ãŒæŒ‡å®šã—ãŸã‚µãƒ¼ãƒãƒ¼ä»¥å¤–ã¨ã‚„ã‚Šå–ã‚Šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" +federationDisabled: "ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¯é€£åˆãŒç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã‚„ã‚Šå–ã‚Šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" _accountSettings: requireSigninToViewContents: "コンテンツã®è¡¨ç¤ºã«ãƒã‚°ã‚¤ãƒ³ã‚’å¿…é ˆã«ã™ã‚‹" diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index 409dca3426..ec0b5360f4 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -132,6 +132,7 @@ export class MetaEntityService { enableUrlPreview: instance.urlPreviewEnabled, noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local', maxFileSize: this.config.maxFileSize, + federation: this.meta.federation, }; return packed; diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts index e3fd63464a..e7ae2ee8e5 100644 --- a/packages/backend/src/models/json-schema/meta.ts +++ b/packages/backend/src/models/json-schema/meta.ts @@ -261,6 +261,11 @@ export const packedMetaLiteSchema = { type: 'number', optional: false, nullable: false, }, + federation: { + type: 'string', + enum: ['all', 'specified', 'none'], + optional: false, nullable: false, + }, }, } as const; diff --git a/packages/frontend/src/components/MkInstanceStats.vue b/packages/frontend/src/components/MkInstanceStats.vue index 8ccbf61e48..d8066857fe 100644 --- a/packages/frontend/src/components/MkInstanceStats.vue +++ b/packages/frontend/src/components/MkInstanceStats.vue @@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only <div :class="$style.chart"> <div class="selects"> <MkSelect v-model="chartSrc" style="margin: 0; flex: 1;"> - <optgroup :label="i18n.ts.federation"> + <optgroup v-if="shouldShowFederation" :label="i18n.ts.federation"> <option value="federation">{{ i18n.ts._charts.federation }}</option> <option value="ap-request">{{ i18n.ts._charts.apRequest }}</option> </optgroup> @@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only <optgroup :label="i18n.ts.notes"> <option value="notes">{{ i18n.ts._charts.notesIncDec }}</option> <option value="local-notes">{{ i18n.ts._charts.localNotesIncDec }}</option> - <option value="remote-notes">{{ i18n.ts._charts.remoteNotesIncDec }}</option> + <option v-if="shouldShowFederation" value="remote-notes">{{ i18n.ts._charts.remoteNotesIncDec }}</option> <option value="notes-total">{{ i18n.ts._charts.notesTotal }}</option> </optgroup> <optgroup :label="i18n.ts.drive"> @@ -46,9 +46,9 @@ SPDX-License-Identifier: AGPL-3.0-only <MkSelect v-model="heatmapSrc" style="margin: 0 0 12px 0;"> <option value="active-users">Active users</option> <option value="notes">Notes</option> - <option value="ap-requests-inbox-received">AP Requests: inboxReceived</option> - <option value="ap-requests-deliver-succeeded">AP Requests: deliverSucceeded</option> - <option value="ap-requests-deliver-failed">AP Requests: deliverFailed</option> + <option v-if="shouldShowFederation" value="ap-requests-inbox-received">AP Requests: inboxReceived</option> + <option v-if="shouldShowFederation" value="ap-requests-deliver-succeeded">AP Requests: deliverSucceeded</option> + <option v-if="shouldShowFederation" value="ap-requests-deliver-failed">AP Requests: deliverFailed</option> </MkSelect> <div class="_panel" :class="$style.heatmap"> <MkHeatmap :src="heatmapSrc" :label="'Read & Write'"/> @@ -65,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </MkFoldableSection> - <MkFoldableSection class="item"> + <MkFoldableSection v-if="shouldShowFederation" class="item"> <template #header>Federation</template> <div :class="$style.federation"> <div class="pies"> @@ -84,13 +84,15 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <script lang="ts" setup> -import { onMounted, ref, shallowRef } from 'vue'; +import { onMounted, ref, computed, shallowRef } from 'vue'; import { Chart } from 'chart.js'; import MkSelect from '@/components/MkSelect.vue'; import MkChart from '@/components/MkChart.vue'; import { useChartTooltip } from '@/scripts/use-chart-tooltip.js'; +import { $i } from '@/account.js'; import * as os from '@/os.js'; import { misskeyApiGet } from '@/scripts/misskey-api.js'; +import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import MkHeatmap, { type HeatmapSource } from '@/components/MkHeatmap.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; @@ -100,6 +102,8 @@ import { initChart } from '@/scripts/init-chart.js'; initChart(); +const shouldShowFederation = computed(() => instance.federation !== 'none' || $i?.isModerator); + const chartLimit = 500; const chartSpan = ref<'hour' | 'day'>('hour'); const chartSrc = ref('active-users'); diff --git a/packages/frontend/src/components/MkSignupDialog.rules.vue b/packages/frontend/src/components/MkSignupDialog.rules.vue index e2a06dd91f..999e843325 100644 --- a/packages/frontend/src/components/MkSignupDialog.rules.vue +++ b/packages/frontend/src/components/MkSignupDialog.rules.vue @@ -10,8 +10,10 @@ SPDX-License-Identifier: AGPL-3.0-only </div> <MkSpacer :marginMin="20" :marginMax="28"> <div class="_gaps_m"> - <div v-if="instance.disableRegistration"> - <MkInfo warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo> + <div v-if="instance.disableRegistration || instance.federation !== 'all'" class="_gaps_s"> + <MkInfo v-if="instance.disableRegistration" warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo> + <MkInfo v-if="instance.federation === 'specified'" warn>{{ i18n.ts.federationSpecified }}</MkInfo> + <MkInfo v-else-if="instance.federation === 'none'" warn>{{ i18n.ts.federationDisabled }}</MkInfo> </div> <div style="text-align: center;"> diff --git a/packages/frontend/src/components/MkUserSelectDialog.vue b/packages/frontend/src/components/MkUserSelectDialog.vue index 764bf74f21..63af652cbc 100644 --- a/packages/frontend/src/components/MkUserSelectDialog.vue +++ b/packages/frontend/src/components/MkUserSelectDialog.vue @@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template #header>{{ i18n.ts.selectUser }}</template> <div> <div :class="$style.form"> - <MkInput v-if="localOnly" v-model="username" :autofocus="true" @update:modelValue="search"> + <MkInput v-if="computedLocalOnly" v-model="username" :autofocus="true" @update:modelValue="search"> <template #label>{{ i18n.ts.username }}</template> <template #prefix>@</template> </MkInput> @@ -61,7 +61,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <script lang="ts" setup> -import { onMounted, ref, shallowRef } from 'vue'; +import { onMounted, ref, computed, shallowRef } from 'vue'; import * as Misskey from 'misskey-js'; import MkInput from '@/components/MkInput.vue'; import FormSplit from '@/components/form/split.vue'; @@ -70,6 +70,7 @@ import { misskeyApi } from '@/scripts/misskey-api.js'; import { defaultStore } from '@/store.js'; import { i18n } from '@/i18n.js'; import { $i } from '@/account.js'; +import { instance } from '@/instance.js'; import { host as currentHost, hostname } from '@@/js/config.js'; const emit = defineEmits<{ @@ -86,6 +87,8 @@ const props = withDefaults(defineProps<{ localOnly: false, }); +const computedLocalOnly = computed(() => props.localOnly || instance.federation === 'none'); + const username = ref(''); const host = ref(''); const users = ref<Misskey.entities.UserLite[]>([]); @@ -100,7 +103,7 @@ function search() { } misskeyApi('users/search-by-username-and-host', { username: username.value, - host: props.localOnly ? '.' : host.value, + host: computedLocalOnly.value ? '.' : host.value, limit: 10, detail: false, }).then(_users => { @@ -142,7 +145,7 @@ onMounted(() => { }).then(foundUsers => { let _users = foundUsers; _users = _users.filter((u) => { - if (props.localOnly) { + if (computedLocalOnly.value) { return u.host == null; } else { return true; diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue index 97c765d81c..9554d6fff0 100644 --- a/packages/frontend/src/components/MkVisitorDashboard.vue +++ b/packages/frontend/src/components/MkVisitorDashboard.vue @@ -18,8 +18,10 @@ SPDX-License-Identifier: AGPL-3.0-only <!-- eslint-disable-next-line vue/no-v-html --> <div v-html="instance.description || i18n.ts.headlineMisskey"></div> </div> - <div v-if="instance.disableRegistration" :class="$style.mainWarn"> - <MkInfo warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo> + <div v-if="instance.disableRegistration || instance.federation !== 'all'" :class="$style.mainWarn" class="_gaps_s"> + <MkInfo v-if="instance.disableRegistration" warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo> + <MkInfo v-if="instance.federation === 'specified'" warn>{{ i18n.ts.federationSpecified }}</MkInfo> + <MkInfo v-else-if="instance.federation === 'none'" warn>{{ i18n.ts.federationDisabled }}</MkInfo> </div> <div class="_gaps_s" :class="$style.mainActions"> <MkButton :class="$style.mainAction" full rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.joinThisServer }}</MkButton> diff --git a/packages/frontend/src/components/MkWidgets.vue b/packages/frontend/src/components/MkWidgets.vue index ba619f6063..44f6921a85 100644 --- a/packages/frontend/src/components/MkWidgets.vue +++ b/packages/frontend/src/components/MkWidgets.vue @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only <header :class="$style.editHeader"> <MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--MI-margin)" data-cy-widget-select> <template #label>{{ i18n.ts.selectWidget }}</template> - <option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.ts._widgets[widget] }}</option> + <option v-for="widget in _widgetDefs" :key="widget" :value="widget">{{ i18n.ts._widgets[widget] }}</option> </MkSelect> <MkButton inline primary data-cy-widget-add @click="addWidget"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton> <MkButton inline @click="emit('exit')">{{ i18n.ts.close }}</MkButton> @@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> </Sortable> </template> - <component :is="`widget-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" :class="$style.widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/> + <component :is="`widget-${widget.name}`" v-for="widget in _widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" :class="$style.widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/> </div> </template> @@ -50,13 +50,14 @@ export type DefaultStoredWidget = { </script> <script lang="ts" setup> -import { defineAsyncComponent, ref } from 'vue'; +import { defineAsyncComponent, ref, computed } from 'vue'; import { v4 as uuid } from 'uuid'; import MkSelect from '@/components/MkSelect.vue'; import MkButton from '@/components/MkButton.vue'; -import { widgets as widgetDefs } from '@/widgets/index.js'; +import { widgets as widgetDefs, federationWidgets } from '@/widgets/index.js'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; import { isLink } from '@@/js/is-link.js'; const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default)); @@ -66,6 +67,16 @@ const props = defineProps<{ edit: boolean; }>(); +const _widgetDefs = computed(() => { + if (instance.federation === 'none') { + return widgetDefs.filter(x => !federationWidgets.includes(x)); + } else { + return widgetDefs; + } +}); + +const _widgets = computed(() => props.widgets.filter(x => _widgetDefs.value.includes(x.name))); + const emit = defineEmits<{ (ev: 'updateWidgets', widgets: Widget[]): void; (ev: 'addWidget', widget: Widget): void; diff --git a/packages/frontend/src/pages/about.vue b/packages/frontend/src/pages/about.vue index 8dfeb6d2a7..ef0fd39ffe 100644 --- a/packages/frontend/src/pages/about.vue +++ b/packages/frontend/src/pages/about.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkSpacer v-else-if="tab === 'emojis'" :contentMax="1000" :marginMin="20"> <XEmojis/> </MkSpacer> - <MkSpacer v-else-if="tab === 'federation'" :contentMax="1000" :marginMin="20"> + <MkSpacer v-else-if="instance.federation !== 'none' && tab === 'federation'" :contentMax="1000" :marginMin="20"> <XFederation/> </MkSpacer> <MkSpacer v-else-if="tab === 'charts'" :contentMax="1000" :marginMin="20"> @@ -25,6 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { computed, defineAsyncComponent, ref, watch } from 'vue'; +import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/scripts/achievements.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; @@ -51,22 +52,34 @@ watch(tab, () => { const headerActions = computed(() => []); -const headerTabs = computed(() => [{ - key: 'overview', - title: i18n.ts.overview, -}, { - key: 'emojis', - title: i18n.ts.customEmojis, - icon: 'ti ti-icons', -}, { - key: 'federation', - title: i18n.ts.federation, - icon: 'ti ti-whirl', -}, { - key: 'charts', - title: i18n.ts.charts, - icon: 'ti ti-chart-line', -}]); +const headerTabs = computed(() => { + const items = []; + + items.push({ + key: 'overview', + title: i18n.ts.overview, + }, { + key: 'emojis', + title: i18n.ts.customEmojis, + icon: 'ti ti-icons', + }); + + if (instance.federation !== 'none') { + items.push({ + key: 'federation', + title: i18n.ts.federation, + icon: 'ti ti-whirl', + }); + } + + items.push({ + key: 'charts', + title: i18n.ts.charts, + icon: 'ti ti-chart-line', + }); + + return items; +}); definePageMetadata(() => ({ title: i18n.ts.instanceInfo, diff --git a/packages/frontend/src/pages/explore.users.vue b/packages/frontend/src/pages/explore.users.vue index c9acfec04f..56ae08b322 100644 --- a/packages/frontend/src/pages/explore.users.vue +++ b/packages/frontend/src/pages/explore.users.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <MkSpacer :contentMax="1200"> - <MkTab v-model="origin" style="margin-bottom: var(--MI-margin);"> + <MkTab v-if="instance.federation !== 'none'" v-model="origin" style="margin-bottom: var(--MI-margin);"> <option value="local">{{ i18n.ts.local }}</option> <option value="remote">{{ i18n.ts.remote }}</option> </MkTab> @@ -69,6 +69,7 @@ import MkUserList from '@/components/MkUserList.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import MkTab from '@/components/MkTab.vue'; import { misskeyApi } from '@/scripts/misskey-api.js'; +import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; const props = defineProps<{ diff --git a/packages/frontend/src/pages/search.note.vue b/packages/frontend/src/pages/search.note.vue index 105c947d25..4cb149a58b 100644 --- a/packages/frontend/src/pages/search.note.vue +++ b/packages/frontend/src/pages/search.note.vue @@ -13,15 +13,17 @@ SPDX-License-Identifier: AGPL-3.0-only <template #header>{{ i18n.ts.options }}</template> <div class="_gaps_m"> - <MkRadios v-model="hostSelect"> - <template #label>{{ i18n.ts.host }}</template> - <option value="all" default>{{ i18n.ts.all }}</option> - <option value="local">{{ i18n.ts.local }}</option> - <option v-if="noteSearchableScope === 'global'" value="specified">{{ i18n.ts.specifyHost }}</option> - </MkRadios> - <MkInput v-if="noteSearchableScope === 'global'" v-model="hostInput" :disabled="hostSelect !== 'specified'" :large="true" type="search"> - <template #prefix><i class="ti ti-server"></i></template> - </MkInput> + <template v-if="instance.federation !== 'none'"> + <MkRadios v-model="hostSelect"> + <template #label>{{ i18n.ts.host }}</template> + <option value="all" default>{{ i18n.ts.all }}</option> + <option value="local">{{ i18n.ts.local }}</option> + <option v-if="noteSearchableScope === 'global'" value="specified">{{ i18n.ts.specifyHost }}</option> + </MkRadios> + <MkInput v-if="noteSearchableScope === 'global'" v-model="hostInput" :disabled="hostSelect !== 'specified'" :large="true" type="search"> + <template #prefix><i class="ti ti-server"></i></template> + </MkInput> + </template> <MkFolder :defaultOpen="true"> <template #label>{{ i18n.ts.specifyUser }}</template> @@ -102,7 +104,7 @@ setHostSelectWithInput(hostInput.value, undefined); watch(hostInput, setHostSelectWithInput); const searchHost = computed(() => { - if (hostSelect.value === 'local') return '.'; + if (hostSelect.value === 'local' || instance.federation === 'none') return '.'; if (hostSelect.value === 'specified') return hostInput.value; return null; }); diff --git a/packages/frontend/src/pages/search.user.vue b/packages/frontend/src/pages/search.user.vue index 724fbfdfbd..e8bc4cd6d3 100644 --- a/packages/frontend/src/pages/search.user.vue +++ b/packages/frontend/src/pages/search.user.vue @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter.prevent="search"> <template #prefix><i class="ti ti-search"></i></template> </MkInput> - <MkRadios v-model="searchOrigin" @update:modelValue="search()"> + <MkRadios v-if="instance.federation !== 'none'" v-model="searchOrigin" @update:modelValue="search()"> <option value="combined">{{ i18n.ts.all }}</option> <option value="local">{{ i18n.ts.local }}</option> <option value="remote">{{ i18n.ts.remote }}</option> @@ -33,6 +33,7 @@ import MkInput from '@/components/MkInput.vue'; import MkRadios from '@/components/MkRadios.vue'; import MkButton from '@/components/MkButton.vue'; import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; import * as os from '@/os.js'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import { misskeyApi } from '@/scripts/misskey-api.js'; @@ -113,7 +114,7 @@ async function search() { limit: 10, params: { query: query, - origin: searchOrigin.value, + origin: instance.federation === 'none' ? 'local' : searchOrigin.value, }, }; diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 1bfdfd0e76..1ee7909aa8 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -64,7 +64,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkSwitch v-model="limitWidthOfReaction">{{ i18n.ts.limitWidthOfReaction }}</MkSwitch> </div> - <MkSelect v-model="instanceTicker"> + <MkSelect v-if="instance.federation !== 'none'" v-model="instanceTicker"> <template #label>{{ i18n.ts.instanceTicker }}</template> <option value="none">{{ i18n.ts._instanceTicker.none }}</option> <option value="remote">{{ i18n.ts._instanceTicker.remote }}</option> @@ -263,6 +263,7 @@ import MkLink from '@/components/MkLink.vue'; import MkInfo from '@/components/MkInfo.vue'; import { defaultStore } from '@/store.js'; import * as os from '@/os.js'; +import { instance } from '@/instance.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { reloadAsk } from '@/scripts/reload-ask.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue index 19dd2468f8..d32d4842bd 100644 --- a/packages/frontend/src/pages/settings/mute-block.vue +++ b/packages/frontend/src/pages/settings/mute-block.vue @@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </MkFolder> - <MkFolder> + <MkFolder v-if="instance.federation !== 'none'"> <template #icon><i class="ti ti-planet-off"></i></template> <template #label>{{ i18n.ts.instanceMute }}</template> @@ -142,7 +142,7 @@ 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 { instance, infoImageUrl } from '@/instance.js'; import { signinRequired } from '@/account.js'; import MkInfo from '@/components/MkInfo.vue'; import MkFolder from '@/components/MkFolder.vue'; diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue index 40d9be0f60..54a5aeb6c1 100644 --- a/packages/frontend/src/pages/settings/privacy.vue +++ b/packages/frontend/src/pages/settings/privacy.vue @@ -53,7 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template #caption> <div>{{ i18n.ts._accountSettings.requireSigninToViewContentsDescription1 }}</div> <div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription2 }}</div> - <div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription3 }}</div> + <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription3 }}</div> </template> </MkSwitch> @@ -89,7 +89,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template #caption> <div>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription }}</div> - <div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div> + <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div> </template> </FormSlot> @@ -125,7 +125,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template #caption> <div>{{ i18n.ts._accountSettings.makeNotesHiddenBeforeDescription }}</div> - <div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div> + <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div> </template> </FormSlot> </div> @@ -167,6 +167,7 @@ import MkFolder from '@/components/MkFolder.vue'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { defaultStore } from '@/store.js'; import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; import { signinRequired } from '@/account.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; import FormSlot from '@/components/form/slot.vue'; @@ -219,7 +220,7 @@ watch([makeNotesFollowersOnlyBefore, makeNotesHiddenBefore], () => { }); async function update_requireSigninToViewContents(value: boolean) { - if (value) { + if (value === true && instance.federation !== 'none') { const { canceled } = await os.confirm({ type: 'warning', text: i18n.ts.acknowledgeNotesAndEnable, diff --git a/packages/frontend/src/pages/settings/statusbar.statusbar.vue b/packages/frontend/src/pages/settings/statusbar.statusbar.vue index 67943524ef..140b6beb14 100644 --- a/packages/frontend/src/pages/settings/statusbar.statusbar.vue +++ b/packages/frontend/src/pages/settings/statusbar.statusbar.vue @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkSelect v-model="statusbar.type" placeholder="Please select"> <template #label>{{ i18n.ts.type }}</template> <option value="rss">RSS</option> - <option value="federation">Federation</option> + <option v-if="instance.federation !== 'none'" value="federation">Federation</option> <option value="userList">User list timeline</option> </MkSelect> @@ -96,6 +96,7 @@ import MkButton from '@/components/MkButton.vue'; import MkRange from '@/components/MkRange.vue'; import { defaultStore } from '@/store.js'; import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; import { deepClone } from '@/scripts/clone.js'; const props = defineProps<{ diff --git a/packages/frontend/src/scripts/please-login.ts b/packages/frontend/src/scripts/please-login.ts index 43dcf11936..a8a330eb6d 100644 --- a/packages/frontend/src/scripts/please-login.ts +++ b/packages/frontend/src/scripts/please-login.ts @@ -5,6 +5,7 @@ import { defineAsyncComponent } from 'vue'; import { $i } from '@/account.js'; +import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { popup } from '@/os.js'; @@ -51,10 +52,17 @@ export function pleaseLogin(opts: { } = {}) { if ($i) return; + let _openOnRemote: OpenOnRemoteOptions | undefined = undefined; + + // 連åˆã§ãã‚‹å ´åˆã¨ã€ï¼ˆé€£åˆãŒã§ããªãã¦ã‚‚)共有ã™ã‚‹å ´åˆã¯å¤–部連æºã‚ªãƒ—ションをè¨å®š + if (opts.openOnRemote != null && (instance.federation !== 'none' || opts.openOnRemote.type === 'share')) { + _openOnRemote = opts.openOnRemote; + } + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), { autoSet: true, - message: opts.message ?? (opts.openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired), - openOnRemote: opts.openOnRemote, + message: opts.message ?? (_openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired), + openOnRemote: _openOnRemote, }, { cancelled: () => { if (opts.path) { diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts index b31254196a..8e5ba8927a 100644 --- a/packages/frontend/src/ui/_common_/common.ts +++ b/packages/frontend/src/ui/_common_/common.ts @@ -56,12 +56,18 @@ export function openInstanceMenu(ev: MouseEvent) { text: i18n.ts.customEmojis, icon: 'ti ti-icons', to: '/about#emojis', - }, { - type: 'link', - text: i18n.ts.federation, - icon: 'ti ti-whirl', - to: '/about#federation', - }, { + }); + + if (instance.federation !== 'none') { + menuItems.push({ + type: 'link', + text: i18n.ts.federation, + icon: 'ti ti-whirl', + to: '/about#federation', + }); + } + + menuItems.push({ type: 'link', text: i18n.ts.charts, icon: 'ti ti-chart-line', diff --git a/packages/frontend/src/ui/_common_/statusbars.vue b/packages/frontend/src/ui/_common_/statusbars.vue index 5f9a938017..ed881bef22 100644 --- a/packages/frontend/src/ui/_common_/statusbars.vue +++ b/packages/frontend/src/ui/_common_/statusbars.vue @@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only > <span :class="$style.name">{{ x.name }}</span> <XRss v-if="x.type === 'rss'" :class="$style.body" :refreshIntervalSec="x.props.refreshIntervalSec" :marqueeDuration="x.props.marqueeDuration" :marqueeReverse="x.props.marqueeReverse" :display="x.props.display" :url="x.props.url" :shuffle="x.props.shuffle"/> - <XFederation v-else-if="x.type === 'federation'" :class="$style.body" :refreshIntervalSec="x.props.refreshIntervalSec" :marqueeDuration="x.props.marqueeDuration" :marqueeReverse="x.props.marqueeReverse" :display="x.props.display" :colored="x.props.colored"/> + <XFederation v-else-if="x.type === 'federation' && instance.federation !== 'none'" :class="$style.body" :refreshIntervalSec="x.props.refreshIntervalSec" :marqueeDuration="x.props.marqueeDuration" :marqueeReverse="x.props.marqueeReverse" :display="x.props.display" :colored="x.props.colored"/> <XUserList v-else-if="x.type === 'userList'" :class="$style.body" :refreshIntervalSec="x.props.refreshIntervalSec" :marqueeDuration="x.props.marqueeDuration" :marqueeReverse="x.props.marqueeReverse" :display="x.props.display" :userListId="x.props.userListId"/> </div> </div> @@ -23,6 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { defineAsyncComponent } from 'vue'; +import { instance } from '@/instance.js'; import { defaultStore } from '@/store.js'; const XRss = defineAsyncComponent(() => import('./statusbar-rss.vue')); const XFederation = defineAsyncComponent(() => import('./statusbar-federation.vue')); diff --git a/packages/frontend/src/widgets/index.ts b/packages/frontend/src/widgets/index.ts index e269fcf9eb..c5be25e7df 100644 --- a/packages/frontend/src/widgets/index.ts +++ b/packages/frontend/src/widgets/index.ts @@ -36,6 +36,12 @@ export default function(app: App) { app.component('WidgetBirthdayFollowings', defineAsyncComponent(() => import('./WidgetBirthdayFollowings.vue'))); } +// 連åˆé–¢é€£ã®ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆï¼ˆé€£åˆç„¡åŠ¹æ™‚ã«éš ã™ï¼‰ +export const federationWidgets = [ + 'federation', + 'instanceCloud', +]; + export const widgets = [ 'profile', 'instanceInfo', @@ -51,8 +57,6 @@ export const widgets = [ 'photos', 'digitalClock', 'unixClock', - 'federation', - 'instanceCloud', 'postForm', 'slideshow', 'serverMetric', @@ -65,4 +69,6 @@ export const widgets = [ 'userList', 'clicker', 'birthdayFollowings', + + ...federationWidgets, ]; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index e6a9df3f5a..ada685604d 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -5047,6 +5047,8 @@ export type components = { */ noteSearchableScope: 'local' | 'global'; maxFileSize: number; + /** @enum {string} */ + federation: 'all' | 'specified' | 'none'; }; MetaDetailedOnly: { features?: { -- GitLab