summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/components/global/PageWithHeader.vue7
-rw-r--r--packages/frontend/src/pages/about.vue29
-rw-r--r--packages/frontend/src/pages/announcements.vue71
-rw-r--r--packages/frontend/src/pages/channel.vue91
-rw-r--r--packages/frontend/src/pages/channels.vue95
-rw-r--r--packages/frontend/src/pages/chat/home.vue13
-rw-r--r--packages/frontend/src/pages/explore.vue24
-rw-r--r--packages/frontend/src/pages/flash/flash-index.vue43
-rw-r--r--packages/frontend/src/pages/follow-requests.vue55
-rw-r--r--packages/frontend/src/pages/gallery/index.vue57
-rw-r--r--packages/frontend/src/pages/instance-info.vue229
-rw-r--r--packages/frontend/src/pages/my-clips/index.vue23
-rw-r--r--packages/frontend/src/pages/notifications.vue23
-rw-r--r--packages/frontend/src/pages/pages.vue49
-rw-r--r--packages/frontend/src/pages/search.vue27
-rw-r--r--packages/frontend/src/pages/user/index.vue33
16 files changed, 414 insertions, 455 deletions
diff --git a/packages/frontend/src/components/global/PageWithHeader.vue b/packages/frontend/src/components/global/PageWithHeader.vue
index 4d26f8031b..2cc7979ce4 100644
--- a/packages/frontend/src/components/global/PageWithHeader.vue
+++ b/packages/frontend/src/components/global/PageWithHeader.vue
@@ -8,7 +8,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkStickyContainer>
<template #header><MkPageHeader v-model:tab="tab" v-bind="pageHeaderProps"/></template>
<div :class="$style.body">
- <slot></slot>
+ <MkSwiper v-if="swipable" v-model:tab="tab" :tabs="props.tabs">
+ <slot></slot>
+ </MkSwiper>
+ <slot v-else></slot>
</div>
<template #footer><slot name="footer"></slot></template>
</MkStickyContainer>
@@ -20,9 +23,11 @@ import { computed, useTemplateRef } from 'vue';
import { scrollInContainer } from '@@/js/scroll.js';
import type { PageHeaderProps } from './MkPageHeader.vue';
import { useScrollPositionKeeper } from '@/use/use-scroll-position-keeper.js';
+import MkSwiper from '@/components/MkSwiper.vue';
const props = defineProps<PageHeaderProps & {
reversed?: boolean;
+ swipable?: boolean;
}>();
const pageHeaderProps = computed(() => {
diff --git a/packages/frontend/src/pages/about.vue b/packages/frontend/src/pages/about.vue
index ec286f109f..b4ccd55452 100644
--- a/packages/frontend/src/pages/about.vue
+++ b/packages/frontend/src/pages/about.vue
@@ -4,21 +4,19 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <MkSpacer v-if="tab === 'overview'" :contentMax="600" :marginMin="20">
- <XOverview/>
- </MkSpacer>
- <MkSpacer v-else-if="tab === 'emojis'" :contentMax="1000" :marginMin="20">
- <XEmojis/>
- </MkSpacer>
- <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">
- <MkInstanceStats/>
- </MkSpacer>
- </MkSwiper>
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
+ <MkSpacer v-if="tab === 'overview'" :contentMax="600" :marginMin="20">
+ <XOverview/>
+ </MkSpacer>
+ <MkSpacer v-else-if="tab === 'emojis'" :contentMax="1000" :marginMin="20">
+ <XEmojis/>
+ </MkSpacer>
+ <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">
+ <MkInstanceStats/>
+ </MkSpacer>
</PageWithHeader>
</template>
@@ -28,7 +26,6 @@ import { instance } from '@/instance.js';
import { i18n } from '@/i18n.js';
import { claimAchievement } from '@/utility/achievements.js';
import { definePage } from '@/page.js';
-import MkSwiper from '@/components/MkSwiper.vue';
const XOverview = defineAsyncComponent(() => import('@/pages/about.overview.vue'));
const XEmojis = defineAsyncComponent(() => import('@/pages/about.emojis.vue'));
diff --git a/packages/frontend/src/pages/announcements.vue b/packages/frontend/src/pages/announcements.vue
index c82cde1600..23626782b4 100644
--- a/packages/frontend/src/pages/announcements.vue
+++ b/packages/frontend/src/pages/announcements.vue
@@ -4,43 +4,41 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="800">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div class="_gaps">
- <MkInfo v-if="$i && $i.hasUnreadAnnouncement && tab === 'current'" warn>{{ i18n.ts.youHaveUnreadAnnouncements }}</MkInfo>
- <MkPagination ref="paginationEl" :key="tab" v-slot="{items}" :pagination="tab === 'current' ? paginationCurrent : paginationPast" class="_gaps">
- <section v-for="announcement in items" :key="announcement.id" class="_panel" :class="$style.announcement">
- <div v-if="announcement.forYou" :class="$style.forYou"><i class="ti ti-pin"></i> {{ i18n.ts.forYou }}</div>
- <div :class="$style.header">
- <span v-if="$i && !announcement.silence && !announcement.isRead" style="margin-right: 0.5em;">🆕</span>
- <span style="margin-right: 0.5em;">
- <i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
- <i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i>
- <i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i>
- <i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--MI_THEME-success);"></i>
- </span>
- <MkA :to="`/announcements/${announcement.id}`"><span>{{ announcement.title }}</span></MkA>
- </div>
- <div :class="$style.content">
- <Mfm :text="announcement.text" class="_selectable"/>
- <img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
- <MkA :to="`/announcements/${announcement.id}`">
- <div style="margin-top: 8px; opacity: 0.7; font-size: 85%;">
- {{ i18n.ts.createdAt }}: <MkTime :time="announcement.createdAt" mode="detail"/>
- </div>
- <div v-if="announcement.updatedAt" style="opacity: 0.7; font-size: 85%;">
- {{ i18n.ts.updatedAt }}: <MkTime :time="announcement.updatedAt" mode="detail"/>
- </div>
- </MkA>
- </div>
- <div v-if="tab !== 'past' && $i && !announcement.silence && !announcement.isRead" :class="$style.footer">
- <MkButton primary @click="read(announcement)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
- </div>
- </section>
- </MkPagination>
- </div>
- </MkSwiper>
+ <div class="_gaps">
+ <MkInfo v-if="$i && $i.hasUnreadAnnouncement && tab === 'current'" warn>{{ i18n.ts.youHaveUnreadAnnouncements }}</MkInfo>
+ <MkPagination ref="paginationEl" :key="tab" v-slot="{items}" :pagination="tab === 'current' ? paginationCurrent : paginationPast" class="_gaps">
+ <section v-for="announcement in items" :key="announcement.id" class="_panel" :class="$style.announcement">
+ <div v-if="announcement.forYou" :class="$style.forYou"><i class="ti ti-pin"></i> {{ i18n.ts.forYou }}</div>
+ <div :class="$style.header">
+ <span v-if="$i && !announcement.silence && !announcement.isRead" style="margin-right: 0.5em;">🆕</span>
+ <span style="margin-right: 0.5em;">
+ <i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
+ <i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i>
+ <i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i>
+ <i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--MI_THEME-success);"></i>
+ </span>
+ <MkA :to="`/announcements/${announcement.id}`"><span>{{ announcement.title }}</span></MkA>
+ </div>
+ <div :class="$style.content">
+ <Mfm :text="announcement.text" class="_selectable"/>
+ <img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
+ <MkA :to="`/announcements/${announcement.id}`">
+ <div style="margin-top: 8px; opacity: 0.7; font-size: 85%;">
+ {{ i18n.ts.createdAt }}: <MkTime :time="announcement.createdAt" mode="detail"/>
+ </div>
+ <div v-if="announcement.updatedAt" style="opacity: 0.7; font-size: 85%;">
+ {{ i18n.ts.updatedAt }}: <MkTime :time="announcement.updatedAt" mode="detail"/>
+ </div>
+ </MkA>
+ </div>
+ <div v-if="tab !== 'past' && $i && !announcement.silence && !announcement.isRead" :class="$style.footer">
+ <MkButton primary @click="read(announcement)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
+ </div>
+ </section>
+ </MkPagination>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -50,7 +48,6 @@ import { ref, computed } from 'vue';
import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
import MkInfo from '@/components/MkInfo.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue
index e71d372722..ed54fff5ce 100644
--- a/packages/frontend/src/pages/channel.vue
+++ b/packages/frontend/src/pages/channel.vue
@@ -4,60 +4,58 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="700">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="channel && tab === 'overview'" class="_gaps">
- <div class="_panel" :class="$style.bannerContainer">
- <XChannelFollowButton :channel="channel" :full="true" :class="$style.subscribe"/>
- <MkButton v-if="favorited" v-tooltip="i18n.ts.unfavorite" asLike class="button" rounded primary :class="$style.favorite" @click="unfavorite()"><i class="ti ti-star"></i></MkButton>
- <MkButton v-else v-tooltip="i18n.ts.favorite" asLike class="button" rounded :class="$style.favorite" @click="favorite()"><i class="ti ti-star"></i></MkButton>
- <div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : undefined }" :class="$style.banner">
- <div :class="$style.bannerStatus">
- <div><i class="ti ti-users ti-fw"></i><I18n :src="i18n.ts._channel.usersCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.usersCount }}</b></template></I18n></div>
- <div><i class="ti ti-pencil ti-fw"></i><I18n :src="i18n.ts._channel.notesCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.notesCount }}</b></template></I18n></div>
- </div>
- <div v-if="channel.isSensitive" :class="$style.sensitiveIndicator">{{ i18n.ts.sensitive }}</div>
- <div :class="$style.bannerFade"></div>
- </div>
- <div v-if="channel.description" :class="$style.description">
- <Mfm :text="channel.description" :isNote="false"/>
+ <div v-if="channel && tab === 'overview'" class="_gaps">
+ <div class="_panel" :class="$style.bannerContainer">
+ <XChannelFollowButton :channel="channel" :full="true" :class="$style.subscribe"/>
+ <MkButton v-if="favorited" v-tooltip="i18n.ts.unfavorite" asLike class="button" rounded primary :class="$style.favorite" @click="unfavorite()"><i class="ti ti-star"></i></MkButton>
+ <MkButton v-else v-tooltip="i18n.ts.favorite" asLike class="button" rounded :class="$style.favorite" @click="favorite()"><i class="ti ti-star"></i></MkButton>
+ <div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : undefined }" :class="$style.banner">
+ <div :class="$style.bannerStatus">
+ <div><i class="ti ti-users ti-fw"></i><I18n :src="i18n.ts._channel.usersCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.usersCount }}</b></template></I18n></div>
+ <div><i class="ti ti-pencil ti-fw"></i><I18n :src="i18n.ts._channel.notesCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.notesCount }}</b></template></I18n></div>
</div>
+ <div v-if="channel.isSensitive" :class="$style.sensitiveIndicator">{{ i18n.ts.sensitive }}</div>
+ <div :class="$style.bannerFade"></div>
+ </div>
+ <div v-if="channel.description" :class="$style.description">
+ <Mfm :text="channel.description" :isNote="false"/>
</div>
-
- <MkFoldableSection>
- <template #header><i class="ti ti-pin ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.pinnedNotes }}</template>
- <div v-if="channel.pinnedNotes && channel.pinnedNotes.length > 0" class="_gaps">
- <MkNote v-for="note in channel.pinnedNotes" :key="note.id" class="_panel" :note="note"/>
- </div>
- </MkFoldableSection>
</div>
- <div v-if="channel && tab === 'timeline'" class="_gaps">
- <MkInfo v-if="channel.isArchived" warn>{{ i18n.ts.thisChannelArchived }}</MkInfo>
- <!-- スマホ・タブレットの場合、キーボードが表示されると投稿が見づらくなるので、デスクトップ場合のみ自動でフォーカスを当てる -->
- <MkPostForm v-if="$i && prefer.r.showFixedPostFormInChannel.value" :channel="channel" class="post-form _panel" fixed :autofocus="deviceKind === 'desktop'"/>
-
- <MkTimeline :key="channelId" src="channel" :channel="channelId" @before="before" @after="after" @note="miLocalStorage.setItemAsJson(`channelLastReadedAt:${channel.id}`, Date.now())"/>
- </div>
- <div v-else-if="tab === 'featured'">
- <MkNotes :pagination="featuredPagination"/>
- </div>
- <div v-else-if="tab === 'search'">
- <div v-if="notesSearchAvailable" class="_gaps">
- <div>
- <MkInput v-model="searchQuery" @enter="search()">
- <template #prefix><i class="ti ti-search"></i></template>
- </MkInput>
- <MkButton primary rounded style="margin-top: 8px;" @click="search()">{{ i18n.ts.search }}</MkButton>
- </div>
- <MkNotes v-if="searchPagination" :key="searchKey" :pagination="searchPagination"/>
+ <MkFoldableSection>
+ <template #header><i class="ti ti-pin ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.pinnedNotes }}</template>
+ <div v-if="channel.pinnedNotes && channel.pinnedNotes.length > 0" class="_gaps">
+ <MkNote v-for="note in channel.pinnedNotes" :key="note.id" class="_panel" :note="note"/>
</div>
- <div v-else>
- <MkInfo warn>{{ i18n.ts.notesSearchNotAvailable }}</MkInfo>
+ </MkFoldableSection>
+ </div>
+ <div v-if="channel && tab === 'timeline'" class="_gaps">
+ <MkInfo v-if="channel.isArchived" warn>{{ i18n.ts.thisChannelArchived }}</MkInfo>
+
+ <!-- スマホ・タブレットの場合、キーボードが表示されると投稿が見づらくなるので、デスクトップ場合のみ自動でフォーカスを当てる -->
+ <MkPostForm v-if="$i && prefer.r.showFixedPostFormInChannel.value" :channel="channel" class="post-form _panel" fixed :autofocus="deviceKind === 'desktop'"/>
+
+ <MkTimeline :key="channelId" src="channel" :channel="channelId" @before="before" @after="after" @note="miLocalStorage.setItemAsJson(`channelLastReadedAt:${channel.id}`, Date.now())"/>
+ </div>
+ <div v-else-if="tab === 'featured'">
+ <MkNotes :pagination="featuredPagination"/>
+ </div>
+ <div v-else-if="tab === 'search'">
+ <div v-if="notesSearchAvailable" class="_gaps">
+ <div>
+ <MkInput v-model="searchQuery" @enter="search()">
+ <template #prefix><i class="ti ti-search"></i></template>
+ </MkInput>
+ <MkButton primary rounded style="margin-top: 8px;" @click="search()">{{ i18n.ts.search }}</MkButton>
</div>
+ <MkNotes v-if="searchPagination" :key="searchKey" :pagination="searchPagination"/>
+ </div>
+ <div v-else>
+ <MkInfo warn>{{ i18n.ts.notesSearchNotAvailable }}</MkInfo>
</div>
- </MkSwiper>
+ </div>
</MkSpacer>
<template #footer>
<div :class="$style.footer">
@@ -93,7 +91,6 @@ import { prefer } from '@/preferences.js';
import MkNote from '@/components/MkNote.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { isSupportShare } from '@/utility/navigator.js';
import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import { notesSearchAvailable } from '@/utility/check-permissions.js';
diff --git a/packages/frontend/src/pages/channels.vue b/packages/frontend/src/pages/channels.vue
index 27a6a6168d..80f0c9ca3b 100644
--- a/packages/frontend/src/pages/channels.vue
+++ b/packages/frontend/src/pages/channels.vue
@@ -4,56 +4,54 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="1200">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'search'" :class="$style.searchRoot">
- <div class="_gaps">
- <MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
- <template #prefix><i class="ti ti-search"></i></template>
- </MkInput>
- <MkRadios v-model="searchType" @update:modelValue="search()">
- <option value="nameAndDescription">{{ i18n.ts._channel.nameAndDescription }}</option>
- <option value="nameOnly">{{ i18n.ts._channel.nameOnly }}</option>
- </MkRadios>
- <MkButton large primary gradate rounded @click="search">{{ i18n.ts.search }}</MkButton>
- </div>
-
- <MkFoldableSection v-if="channelPagination">
- <template #header>{{ i18n.ts.searchResult }}</template>
- <MkChannelList :key="key" :pagination="channelPagination"/>
- </MkFoldableSection>
- </div>
- <div v-if="tab === 'featured'">
- <MkPagination v-slot="{items}" :pagination="featuredPagination">
- <div :class="$style.root">
- <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
- </div>
- </MkPagination>
- </div>
- <div v-else-if="tab === 'favorites'">
- <MkPagination v-slot="{items}" :pagination="favoritesPagination">
- <div :class="$style.root">
- <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
- </div>
- </MkPagination>
- </div>
- <div v-else-if="tab === 'following'">
- <MkPagination v-slot="{items}" :pagination="followingPagination">
- <div :class="$style.root">
- <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
- </div>
- </MkPagination>
- </div>
- <div v-else-if="tab === 'owned'">
- <MkButton class="new" @click="create()"><i class="ti ti-plus"></i></MkButton>
- <MkPagination v-slot="{items}" :pagination="ownedPagination">
- <div :class="$style.root">
- <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
- </div>
- </MkPagination>
+ <div v-if="tab === 'search'" :class="$style.searchRoot">
+ <div class="_gaps">
+ <MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
+ <template #prefix><i class="ti ti-search"></i></template>
+ </MkInput>
+ <MkRadios v-model="searchType" @update:modelValue="search()">
+ <option value="nameAndDescription">{{ i18n.ts._channel.nameAndDescription }}</option>
+ <option value="nameOnly">{{ i18n.ts._channel.nameOnly }}</option>
+ </MkRadios>
+ <MkButton large primary gradate rounded @click="search">{{ i18n.ts.search }}</MkButton>
</div>
- </MkSwiper>
+
+ <MkFoldableSection v-if="channelPagination">
+ <template #header>{{ i18n.ts.searchResult }}</template>
+ <MkChannelList :key="key" :pagination="channelPagination"/>
+ </MkFoldableSection>
+ </div>
+ <div v-if="tab === 'featured'">
+ <MkPagination v-slot="{items}" :pagination="featuredPagination">
+ <div :class="$style.root">
+ <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
+ </div>
+ </MkPagination>
+ </div>
+ <div v-else-if="tab === 'favorites'">
+ <MkPagination v-slot="{items}" :pagination="favoritesPagination">
+ <div :class="$style.root">
+ <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
+ </div>
+ </MkPagination>
+ </div>
+ <div v-else-if="tab === 'following'">
+ <MkPagination v-slot="{items}" :pagination="followingPagination">
+ <div :class="$style.root">
+ <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
+ </div>
+ </MkPagination>
+ </div>
+ <div v-else-if="tab === 'owned'">
+ <MkButton class="new" @click="create()"><i class="ti ti-plus"></i></MkButton>
+ <MkPagination v-slot="{items}" :pagination="ownedPagination">
+ <div :class="$style.root">
+ <MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
+ </div>
+ </MkPagination>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -67,7 +65,6 @@ import MkInput from '@/components/MkInput.vue';
import MkRadios from '@/components/MkRadios.vue';
import MkButton from '@/components/MkButton.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import { useRouter } from '@/router.js';
diff --git a/packages/frontend/src/pages/chat/home.vue b/packages/frontend/src/pages/chat/home.vue
index 1edd18ddf0..e37634b4b3 100644
--- a/packages/frontend/src/pages/chat/home.vue
+++ b/packages/frontend/src/pages/chat/home.vue
@@ -4,15 +4,13 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkPolkadots v-if="tab === 'home'" accented/>
<MkSpacer :contentMax="700">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <XHome v-if="tab === 'home'"/>
- <XInvitations v-else-if="tab === 'invitations'"/>
- <XJoiningRooms v-else-if="tab === 'joiningRooms'"/>
- <XOwnedRooms v-else-if="tab === 'ownedRooms'"/>
- </MkSwiper>
+ <XHome v-if="tab === 'home'"/>
+ <XInvitations v-else-if="tab === 'invitations'"/>
+ <XJoiningRooms v-else-if="tab === 'joiningRooms'"/>
+ <XOwnedRooms v-else-if="tab === 'ownedRooms'"/>
</MkSpacer>
</PageWithHeader>
</template>
@@ -25,7 +23,6 @@ import XJoiningRooms from './home.joiningRooms.vue';
import XOwnedRooms from './home.ownedRooms.vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
-import MkSwiper from '@/components/MkSwiper.vue';
import MkPolkadots from '@/components/MkPolkadots.vue';
const tab = ref('home');
diff --git a/packages/frontend/src/pages/explore.vue b/packages/frontend/src/pages/explore.vue
index bcece47e35..c4f6ddc33e 100644
--- a/packages/frontend/src/pages/explore.vue
+++ b/packages/frontend/src/pages/explore.vue
@@ -4,18 +4,16 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'featured'">
- <XFeatured/>
- </div>
- <div v-else-if="tab === 'users'">
- <XUsers/>
- </div>
- <div v-else-if="tab === 'roles'">
- <XRoles/>
- </div>
- </MkSwiper>
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
+ <div v-if="tab === 'featured'">
+ <XFeatured/>
+ </div>
+ <div v-else-if="tab === 'users'">
+ <XUsers/>
+ </div>
+ <div v-else-if="tab === 'roles'">
+ <XRoles/>
+ </div>
</PageWithHeader>
</template>
@@ -24,8 +22,6 @@ import { computed, watch, ref, useTemplateRef } from 'vue';
import XFeatured from './explore.featured.vue';
import XUsers from './explore.users.vue';
import XRoles from './explore.roles.vue';
-import MkFoldableSection from '@/components/MkFoldableSection.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/pages/flash/flash-index.vue b/packages/frontend/src/pages/flash/flash-index.vue
index 4ef33cbe0f..c05552a041 100644
--- a/packages/frontend/src/pages/flash/flash-index.vue
+++ b/packages/frontend/src/pages/flash/flash-index.vue
@@ -4,36 +4,34 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="700">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'featured'">
- <MkPagination v-slot="{items}" :pagination="featuredFlashsPagination">
+ <div v-if="tab === 'featured'">
+ <MkPagination v-slot="{items}" :pagination="featuredFlashsPagination">
+ <div class="_gaps_s">
+ <MkFlashPreview v-for="flash in items" :key="flash.id" :flash="flash"/>
+ </div>
+ </MkPagination>
+ </div>
+
+ <div v-else-if="tab === 'my'">
+ <div class="_gaps">
+ <MkButton gradate rounded style="margin: 0 auto;" @click="create()"><i class="ti ti-plus"></i></MkButton>
+ <MkPagination v-slot="{items}" :pagination="myFlashsPagination">
<div class="_gaps_s">
<MkFlashPreview v-for="flash in items" :key="flash.id" :flash="flash"/>
</div>
</MkPagination>
</div>
+ </div>
- <div v-else-if="tab === 'my'">
- <div class="_gaps">
- <MkButton gradate rounded style="margin: 0 auto;" @click="create()"><i class="ti ti-plus"></i></MkButton>
- <MkPagination v-slot="{items}" :pagination="myFlashsPagination">
- <div class="_gaps_s">
- <MkFlashPreview v-for="flash in items" :key="flash.id" :flash="flash"/>
- </div>
- </MkPagination>
+ <div v-else-if="tab === 'liked'">
+ <MkPagination v-slot="{items}" :pagination="likedFlashsPagination">
+ <div class="_gaps_s">
+ <MkFlashPreview v-for="like in items" :key="like.flash.id" :flash="like.flash"/>
</div>
- </div>
-
- <div v-else-if="tab === 'liked'">
- <MkPagination v-slot="{items}" :pagination="likedFlashsPagination">
- <div class="_gaps_s">
- <MkFlashPreview v-for="like in items" :key="like.flash.id" :flash="like.flash"/>
- </div>
- </MkPagination>
- </div>
- </MkSwiper>
+ </MkPagination>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -43,7 +41,6 @@ import { computed, ref } from 'vue';
import MkFlashPreview from '@/components/MkFlashPreview.vue';
import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { useRouter } from '@/router.js';
diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue
index d467d875fd..e11bd80a1c 100644
--- a/packages/frontend/src/pages/follow-requests.vue
+++ b/packages/frontend/src/pages/follow-requests.vue
@@ -4,38 +4,36 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="800">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <MkPagination ref="paginationComponent" :pagination="pagination">
- <template #empty>
- <div class="_fullinfo">
- <img :src="infoImageUrl" draggable="false"/>
- <div>{{ i18n.ts.noFollowRequests }}</div>
- </div>
- </template>
- <template #default="{items}">
- <div class="mk-follow-requests _gaps">
- <div v-for="req in items" :key="req.id" class="user _panel">
- <MkAvatar class="avatar" :user="displayUser(req)" indicator link preview/>
- <div class="body">
- <div class="name">
- <MkA v-user-preview="displayUser(req).id" class="name" :to="userPage(displayUser(req))"><MkUserName :user="displayUser(req)"/></MkA>
- <p class="acct">@{{ acct(displayUser(req)) }}</p>
- </div>
- <div v-if="tab === 'list'" class="commands">
- <MkButton class="command" rounded primary @click="accept(displayUser(req))"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
- <MkButton class="command" rounded danger @click="reject(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
- </div>
- <div v-else class="commands">
- <MkButton class="command" rounded danger @click="cancel(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.cancel }}</MkButton>
- </div>
+ <MkPagination ref="paginationComponent" :pagination="pagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" draggable="false"/>
+ <div>{{ i18n.ts.noFollowRequests }}</div>
+ </div>
+ </template>
+ <template #default="{items}">
+ <div class="mk-follow-requests _gaps">
+ <div v-for="req in items" :key="req.id" class="user _panel">
+ <MkAvatar class="avatar" :user="displayUser(req)" indicator link preview/>
+ <div class="body">
+ <div class="name">
+ <MkA v-user-preview="displayUser(req).id" class="name" :to="userPage(displayUser(req))"><MkUserName :user="displayUser(req)"/></MkA>
+ <p class="acct">@{{ acct(displayUser(req)) }}</p>
+ </div>
+ <div v-if="tab === 'list'" class="commands">
+ <MkButton class="command" rounded primary @click="accept(displayUser(req))"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
+ <MkButton class="command" rounded danger @click="reject(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+ </div>
+ <div v-else class="commands">
+ <MkButton class="command" rounded danger @click="cancel(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.cancel }}</MkButton>
</div>
</div>
</div>
- </template>
- </MkPagination>
- </MkSwiper>
+ </div>
+ </template>
+ </MkPagination>
</MkSpacer>
</PageWithHeader>
</template>
@@ -52,7 +50,6 @@ import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { infoImageUrl } from '@/instance.js';
import { $i } from '@/i.js';
-import MkSwiper from '@/components/MkSwiper.vue';
const paginationComponent = useTemplateRef('paginationComponent');
diff --git a/packages/frontend/src/pages/gallery/index.vue b/packages/frontend/src/pages/gallery/index.vue
index c6ce773ab0..1bde30898e 100644
--- a/packages/frontend/src/pages/gallery/index.vue
+++ b/packages/frontend/src/pages/gallery/index.vue
@@ -4,43 +4,41 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="1400">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'explore'">
- <MkFoldableSection class="_margin">
- <template #header><i class="ti ti-clock"></i>{{ i18n.ts.recentPosts }}</template>
- <MkPagination v-slot="{items}" :pagination="recentPostsPagination" :disableAutoLoad="true">
- <div :class="$style.items">
- <MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
- </div>
- </MkPagination>
- </MkFoldableSection>
- <MkFoldableSection class="_margin">
- <template #header><i class="ti ti-comet"></i>{{ i18n.ts.popularPosts }}</template>
- <MkPagination v-slot="{items}" :pagination="popularPostsPagination" :disableAutoLoad="true">
- <div :class="$style.items">
- <MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
- </div>
- </MkPagination>
- </MkFoldableSection>
- </div>
- <div v-else-if="tab === 'liked'">
- <MkPagination v-slot="{items}" :pagination="likedPostsPagination">
+ <div v-if="tab === 'explore'">
+ <MkFoldableSection class="_margin">
+ <template #header><i class="ti ti-clock"></i>{{ i18n.ts.recentPosts }}</template>
+ <MkPagination v-slot="{items}" :pagination="recentPostsPagination" :disableAutoLoad="true">
<div :class="$style.items">
- <MkGalleryPostPreview v-for="like in items" :key="like.id" :post="like.post" class="post"/>
+ <MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
</div>
</MkPagination>
- </div>
- <div v-else-if="tab === 'my'">
- <MkA to="/gallery/new" class="_link" style="margin: 16px;"><i class="ti ti-plus"></i> {{ i18n.ts.postToGallery }}</MkA>
- <MkPagination v-slot="{items}" :pagination="myPostsPagination">
+ </MkFoldableSection>
+ <MkFoldableSection class="_margin">
+ <template #header><i class="ti ti-comet"></i>{{ i18n.ts.popularPosts }}</template>
+ <MkPagination v-slot="{items}" :pagination="popularPostsPagination" :disableAutoLoad="true">
<div :class="$style.items">
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
</div>
</MkPagination>
- </div>
- </MkSwiper>
+ </MkFoldableSection>
+ </div>
+ <div v-else-if="tab === 'liked'">
+ <MkPagination v-slot="{items}" :pagination="likedPostsPagination">
+ <div :class="$style.items">
+ <MkGalleryPostPreview v-for="like in items" :key="like.id" :post="like.post" class="post"/>
+ </div>
+ </MkPagination>
+ </div>
+ <div v-else-if="tab === 'my'">
+ <MkA to="/gallery/new" class="_link" style="margin: 16px;"><i class="ti ti-plus"></i> {{ i18n.ts.postToGallery }}</MkA>
+ <MkPagination v-slot="{items}" :pagination="myPostsPagination">
+ <div :class="$style.items">
+ <MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
+ </div>
+ </MkPagination>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -50,7 +48,6 @@ import { watch, ref, computed } from 'vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
import MkPagination from '@/components/MkPagination.vue';
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import { useRouter } from '@/router.js';
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index fde462944c..be77799eb6 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -4,129 +4,127 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer v-if="instance" :contentMax="600" :marginMin="16" :marginMax="32">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'overview'" class="_gaps_m">
- <div class="fnfelxur">
- <img :src="faviconUrl" alt="" class="icon"/>
- <span class="name">{{ instance.name || `(${i18n.ts.unknown})` }}</span>
- </div>
- <div style="display: flex; flex-direction: column; gap: 1em;">
- <MkKeyValue :copy="host" oneline>
- <template #key>Host</template>
- <template #value><span class="_monospace"><MkLink :url="`https://${host}`">{{ host }}</MkLink></span></template>
- </MkKeyValue>
- <MkKeyValue oneline>
- <template #key>{{ i18n.ts.software }}</template>
- <template #value><span class="_monospace">{{ instance.softwareName || `(${i18n.ts.unknown})` }} / {{ instance.softwareVersion || `(${i18n.ts.unknown})` }}</span></template>
- </MkKeyValue>
- <MkKeyValue oneline>
- <template #key>{{ i18n.ts.administrator }}</template>
- <template #value>{{ instance.maintainerName || `(${i18n.ts.unknown})` }} ({{ instance.maintainerEmail || `(${i18n.ts.unknown})` }})</template>
- </MkKeyValue>
- </div>
- <MkKeyValue>
- <template #key>{{ i18n.ts.description }}</template>
- <template #value>{{ instance.description }}</template>
+ <div v-if="tab === 'overview'" class="_gaps_m">
+ <div class="fnfelxur">
+ <img :src="faviconUrl" alt="" class="icon"/>
+ <span class="name">{{ instance.name || `(${i18n.ts.unknown})` }}</span>
+ </div>
+ <div style="display: flex; flex-direction: column; gap: 1em;">
+ <MkKeyValue :copy="host" oneline>
+ <template #key>Host</template>
+ <template #value><span class="_monospace"><MkLink :url="`https://${host}`">{{ host }}</MkLink></span></template>
</MkKeyValue>
+ <MkKeyValue oneline>
+ <template #key>{{ i18n.ts.software }}</template>
+ <template #value><span class="_monospace">{{ instance.softwareName || `(${i18n.ts.unknown})` }} / {{ instance.softwareVersion || `(${i18n.ts.unknown})` }}</span></template>
+ </MkKeyValue>
+ <MkKeyValue oneline>
+ <template #key>{{ i18n.ts.administrator }}</template>
+ <template #value>{{ instance.maintainerName || `(${i18n.ts.unknown})` }} ({{ instance.maintainerEmail || `(${i18n.ts.unknown})` }})</template>
+ </MkKeyValue>
+ </div>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.description }}</template>
+ <template #value>{{ instance.description }}</template>
+ </MkKeyValue>
- <FormSection v-if="iAmModerator">
- <template #label>Moderation</template>
- <div class="_gaps_s">
- <MkKeyValue>
- <template #key>
- {{ i18n.ts._delivery.status }}
- </template>
- <template #value>
- {{ i18n.ts._delivery._type[suspensionState] }}
- </template>
- </MkKeyValue>
- <MkButton v-if="suspensionState === 'none'" :disabled="!instance" danger @click="stopDelivery">{{ i18n.ts._delivery.stop }}</MkButton>
- <MkButton v-if="suspensionState !== 'none'" :disabled="!instance" @click="resumeDelivery">{{ i18n.ts._delivery.resume }}</MkButton>
- <MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
- <MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
- <MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
- <MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
- <MkTextarea v-model="moderationNote" manualSave>
- <template #label>{{ i18n.ts.moderationNote }}</template>
- <template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
- </MkTextarea>
- </div>
- </FormSection>
-
- <FormSection>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.registeredAt }}</template>
- <template #value><MkTime mode="detail" :time="instance.firstRetrievedAt"/></template>
+ <FormSection v-if="iAmModerator">
+ <template #label>Moderation</template>
+ <div class="_gaps_s">
+ <MkKeyValue>
+ <template #key>
+ {{ i18n.ts._delivery.status }}
+ </template>
+ <template #value>
+ {{ i18n.ts._delivery._type[suspensionState] }}
+ </template>
</MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.updatedAt }}</template>
- <template #value><MkTime mode="detail" :time="instance.infoUpdatedAt"/></template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.latestRequestReceivedAt }}</template>
- <template #value><MkTime v-if="instance.latestRequestReceivedAt" :time="instance.latestRequestReceivedAt"/><span v-else>N/A</span></template>
- </MkKeyValue>
- </FormSection>
+ <MkButton v-if="suspensionState === 'none'" :disabled="!instance" danger @click="stopDelivery">{{ i18n.ts._delivery.stop }}</MkButton>
+ <MkButton v-if="suspensionState !== 'none'" :disabled="!instance" @click="resumeDelivery">{{ i18n.ts._delivery.resume }}</MkButton>
+ <MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
+ <MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
+ <MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
+ <MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
+ <MkTextarea v-model="moderationNote" manualSave>
+ <template #label>{{ i18n.ts.moderationNote }}</template>
+ <template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
+ </MkTextarea>
+ </div>
+ </FormSection>
- <FormSection>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>Following (Pub)</template>
- <template #value>{{ number(instance.followingCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>Followers (Sub)</template>
- <template #value>{{ number(instance.followersCount) }}</template>
- </MkKeyValue>
- </FormSection>
+ <FormSection>
+ <MkKeyValue oneline style="margin: 1em 0;">
+ <template #key>{{ i18n.ts.registeredAt }}</template>
+ <template #value><MkTime mode="detail" :time="instance.firstRetrievedAt"/></template>
+ </MkKeyValue>
+ <MkKeyValue oneline style="margin: 1em 0;">
+ <template #key>{{ i18n.ts.updatedAt }}</template>
+ <template #value><MkTime mode="detail" :time="instance.infoUpdatedAt"/></template>
+ </MkKeyValue>
+ <MkKeyValue oneline style="margin: 1em 0;">
+ <template #key>{{ i18n.ts.latestRequestReceivedAt }}</template>
+ <template #value><MkTime v-if="instance.latestRequestReceivedAt" :time="instance.latestRequestReceivedAt"/><span v-else>N/A</span></template>
+ </MkKeyValue>
+ </FormSection>
- <FormSection>
- <template #label>Well-known resources</template>
- <FormLink :to="`https://${host}/.well-known/host-meta`" external style="margin-bottom: 8px;">host-meta</FormLink>
- <FormLink :to="`https://${host}/.well-known/host-meta.json`" external style="margin-bottom: 8px;">host-meta.json</FormLink>
- <FormLink :to="`https://${host}/.well-known/nodeinfo`" external style="margin-bottom: 8px;">nodeinfo</FormLink>
- <FormLink :to="`https://${host}/robots.txt`" external style="margin-bottom: 8px;">robots.txt</FormLink>
- <FormLink :to="`https://${host}/manifest.json`" external style="margin-bottom: 8px;">manifest.json</FormLink>
- </FormSection>
- </div>
- <div v-else-if="tab === 'chart'" class="_gaps_m">
- <div class="cmhjzshl">
- <div class="selects">
- <MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;">
- <option value="instance-requests">{{ i18n.ts._instanceCharts.requests }}</option>
- <option value="instance-users">{{ i18n.ts._instanceCharts.users }}</option>
- <option value="instance-users-total">{{ i18n.ts._instanceCharts.usersTotal }}</option>
- <option value="instance-notes">{{ i18n.ts._instanceCharts.notes }}</option>
- <option value="instance-notes-total">{{ i18n.ts._instanceCharts.notesTotal }}</option>
- <option value="instance-ff">{{ i18n.ts._instanceCharts.ff }}</option>
- <option value="instance-ff-total">{{ i18n.ts._instanceCharts.ffTotal }}</option>
- <option value="instance-drive-usage">{{ i18n.ts._instanceCharts.cacheSize }}</option>
- <option value="instance-drive-usage-total">{{ i18n.ts._instanceCharts.cacheSizeTotal }}</option>
- <option value="instance-drive-files">{{ i18n.ts._instanceCharts.files }}</option>
- <option value="instance-drive-files-total">{{ i18n.ts._instanceCharts.filesTotal }}</option>
- </MkSelect>
- </div>
- <div class="charts">
- <div class="label">{{ i18n.tsx.recentNHours({ n: 90 }) }}</div>
- <MkChart class="chart" :src="chartSrc" span="hour" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
- <div class="label">{{ i18n.tsx.recentNDays({ n: 90 }) }}</div>
- <MkChart class="chart" :src="chartSrc" span="day" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
- </div>
+ <FormSection>
+ <MkKeyValue oneline style="margin: 1em 0;">
+ <template #key>Following (Pub)</template>
+ <template #value>{{ number(instance.followingCount) }}</template>
+ </MkKeyValue>
+ <MkKeyValue oneline style="margin: 1em 0;">
+ <template #key>Followers (Sub)</template>
+ <template #value>{{ number(instance.followersCount) }}</template>
+ </MkKeyValue>
+ </FormSection>
+
+ <FormSection>
+ <template #label>Well-known resources</template>
+ <FormLink :to="`https://${host}/.well-known/host-meta`" external style="margin-bottom: 8px;">host-meta</FormLink>
+ <FormLink :to="`https://${host}/.well-known/host-meta.json`" external style="margin-bottom: 8px;">host-meta.json</FormLink>
+ <FormLink :to="`https://${host}/.well-known/nodeinfo`" external style="margin-bottom: 8px;">nodeinfo</FormLink>
+ <FormLink :to="`https://${host}/robots.txt`" external style="margin-bottom: 8px;">robots.txt</FormLink>
+ <FormLink :to="`https://${host}/manifest.json`" external style="margin-bottom: 8px;">manifest.json</FormLink>
+ </FormSection>
+ </div>
+ <div v-else-if="tab === 'chart'" class="_gaps_m">
+ <div class="cmhjzshl">
+ <div class="selects">
+ <MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;">
+ <option value="instance-requests">{{ i18n.ts._instanceCharts.requests }}</option>
+ <option value="instance-users">{{ i18n.ts._instanceCharts.users }}</option>
+ <option value="instance-users-total">{{ i18n.ts._instanceCharts.usersTotal }}</option>
+ <option value="instance-notes">{{ i18n.ts._instanceCharts.notes }}</option>
+ <option value="instance-notes-total">{{ i18n.ts._instanceCharts.notesTotal }}</option>
+ <option value="instance-ff">{{ i18n.ts._instanceCharts.ff }}</option>
+ <option value="instance-ff-total">{{ i18n.ts._instanceCharts.ffTotal }}</option>
+ <option value="instance-drive-usage">{{ i18n.ts._instanceCharts.cacheSize }}</option>
+ <option value="instance-drive-usage-total">{{ i18n.ts._instanceCharts.cacheSizeTotal }}</option>
+ <option value="instance-drive-files">{{ i18n.ts._instanceCharts.files }}</option>
+ <option value="instance-drive-files-total">{{ i18n.ts._instanceCharts.filesTotal }}</option>
+ </MkSelect>
+ </div>
+ <div class="charts">
+ <div class="label">{{ i18n.tsx.recentNHours({ n: 90 }) }}</div>
+ <MkChart class="chart" :src="chartSrc" span="hour" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
+ <div class="label">{{ i18n.tsx.recentNDays({ n: 90 }) }}</div>
+ <MkChart class="chart" :src="chartSrc" span="day" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
</div>
</div>
- <div v-else-if="tab === 'users'" class="_gaps_m">
- <MkPagination v-slot="{items}" :pagination="usersPagination" style="display: grid; grid-template-columns: repeat(auto-fill,minmax(270px,1fr)); grid-gap: 12px;">
- <MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/admin/user/${user.id}`">
- <MkUserCardMini :user="user"/>
- </MkA>
- </MkPagination>
- </div>
- <div v-else-if="tab === 'raw'" class="_gaps_m">
- <MkObjectView tall :value="instance">
- </MkObjectView>
- </div>
- </MkSwiper>
+ </div>
+ <div v-else-if="tab === 'users'" class="_gaps_m">
+ <MkPagination v-slot="{items}" :pagination="usersPagination" style="display: grid; grid-template-columns: repeat(auto-fill,minmax(270px,1fr)); grid-gap: 12px;">
+ <MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/admin/user/${user.id}`">
+ <MkUserCardMini :user="user"/>
+ </MkA>
+ </MkPagination>
+ </div>
+ <div v-else-if="tab === 'raw'" class="_gaps_m">
+ <MkObjectView tall :value="instance">
+ </MkObjectView>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -153,7 +151,6 @@ import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import MkUserCardMini from '@/components/MkUserCardMini.vue';
import MkPagination from '@/components/MkPagination.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { getProxiedImageUrlNullable } from '@/utility/media-proxy.js';
import { dateString } from '@/filters/date.js';
import MkTextarea from '@/components/MkTextarea.vue';
diff --git a/packages/frontend/src/pages/my-clips/index.vue b/packages/frontend/src/pages/my-clips/index.vue
index 5b9b3af90b..624ce3ac3f 100644
--- a/packages/frontend/src/pages/my-clips/index.vue
+++ b/packages/frontend/src/pages/my-clips/index.vue
@@ -4,20 +4,18 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="700">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'my'" class="_gaps">
- <MkButton primary rounded class="add" @click="create"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
+ <div v-if="tab === 'my'" class="_gaps">
+ <MkButton primary rounded class="add" @click="create"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
- <MkPagination v-slot="{ items }" ref="pagingComponent" :pagination="pagination" class="_gaps">
- <MkClipPreview v-for="item in items" :key="item.id" :clip="item" :noUserInfo="true"/>
- </MkPagination>
- </div>
- <div v-else-if="tab === 'favorites'" class="_gaps">
- <MkClipPreview v-for="item in favorites" :key="item.id" :clip="item"/>
- </div>
- </MkSwiper>
+ <MkPagination v-slot="{ items }" ref="pagingComponent" :pagination="pagination" class="_gaps">
+ <MkClipPreview v-for="item in items" :key="item.id" :clip="item" :noUserInfo="true"/>
+ </MkPagination>
+ </div>
+ <div v-else-if="tab === 'favorites'" class="_gaps">
+ <MkClipPreview v-for="item in favorites" :key="item.id" :clip="item"/>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -33,7 +31,6 @@ import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { clipsCache } from '@/cache.js';
-import MkSwiper from '@/components/MkSwiper.vue';
const pagination = {
endpoint: 'clips/list' as const,
diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue
index 8524f30595..bf21ac5a08 100644
--- a/packages/frontend/src/pages/notifications.vue
+++ b/packages/frontend/src/pages/notifications.vue
@@ -4,19 +4,17 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="800">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'all'">
- <XNotifications :class="$style.notifications" :excludeTypes="excludeTypes"/>
- </div>
- <div v-else-if="tab === 'mentions'">
- <MkNotes :pagination="mentionsPagination"/>
- </div>
- <div v-else-if="tab === 'directNotes'">
- <MkNotes :pagination="directNotesPagination"/>
- </div>
- </MkSwiper>
+ <div v-if="tab === 'all'">
+ <XNotifications :class="$style.notifications" :excludeTypes="excludeTypes"/>
+ </div>
+ <div v-else-if="tab === 'mentions'">
+ <MkNotes :pagination="mentionsPagination"/>
+ </div>
+ <div v-else-if="tab === 'directNotes'">
+ <MkNotes :pagination="directNotesPagination"/>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -26,7 +24,6 @@ import { computed, ref } from 'vue';
import { notificationTypes } from '@@/js/const.js';
import XNotifications from '@/components/MkNotifications.vue';
import MkNotes from '@/components/MkNotes.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
diff --git a/packages/frontend/src/pages/pages.vue b/packages/frontend/src/pages/pages.vue
index d412bad616..c727238a55 100644
--- a/packages/frontend/src/pages/pages.vue
+++ b/packages/frontend/src/pages/pages.vue
@@ -4,34 +4,32 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkSpacer :contentMax="700">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <div v-if="tab === 'featured'">
- <MkPagination v-slot="{items}" :pagination="featuredPagesPagination">
- <div class="_gaps">
- <MkPagePreview v-for="page in items" :key="page.id" :page="page"/>
- </div>
- </MkPagination>
- </div>
+ <div v-if="tab === 'featured'">
+ <MkPagination v-slot="{items}" :pagination="featuredPagesPagination">
+ <div class="_gaps">
+ <MkPagePreview v-for="page in items" :key="page.id" :page="page"/>
+ </div>
+ </MkPagination>
+ </div>
- <div v-else-if="tab === 'my'" class="_gaps">
- <MkButton class="new" @click="create()"><i class="ti ti-plus"></i></MkButton>
- <MkPagination v-slot="{items}" :pagination="myPagesPagination">
- <div class="_gaps">
- <MkPagePreview v-for="page in items" :key="page.id" :page="page"/>
- </div>
- </MkPagination>
- </div>
+ <div v-else-if="tab === 'my'" class="_gaps">
+ <MkButton class="new" @click="create()"><i class="ti ti-plus"></i></MkButton>
+ <MkPagination v-slot="{items}" :pagination="myPagesPagination">
+ <div class="_gaps">
+ <MkPagePreview v-for="page in items" :key="page.id" :page="page"/>
+ </div>
+ </MkPagination>
+ </div>
- <div v-else-if="tab === 'liked'">
- <MkPagination v-slot="{items}" :pagination="likedPagesPagination">
- <div class="_gaps">
- <MkPagePreview v-for="like in items" :key="like.page.id" :page="like.page"/>
- </div>
- </MkPagination>
- </div>
- </MkSwiper>
+ <div v-else-if="tab === 'liked'">
+ <MkPagination v-slot="{items}" :pagination="likedPagesPagination">
+ <div class="_gaps">
+ <MkPagePreview v-for="like in items" :key="like.page.id" :page="like.page"/>
+ </div>
+ </MkPagination>
+ </div>
</MkSpacer>
</PageWithHeader>
</template>
@@ -41,7 +39,6 @@ import { computed, ref } from 'vue';
import MkPagePreview from '@/components/MkPagePreview.vue';
import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { useRouter } from '@/router.js';
diff --git a/packages/frontend/src/pages/search.vue b/packages/frontend/src/pages/search.vue
index 814ddf3cb9..00e2b195d2 100644
--- a/packages/frontend/src/pages/search.vue
+++ b/packages/frontend/src/pages/search.vue
@@ -4,21 +4,19 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <MkSpacer v-if="tab === 'note'" :contentMax="800">
- <div v-if="notesSearchAvailable || ignoreNotesSearchAvailable">
- <XNote v-bind="props"/>
- </div>
- <div v-else>
- <MkInfo warn>{{ i18n.ts.notesSearchNotAvailable }}</MkInfo>
- </div>
- </MkSpacer>
+<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
+ <MkSpacer v-if="tab === 'note'" :contentMax="800">
+ <div v-if="notesSearchAvailable || ignoreNotesSearchAvailable">
+ <XNote v-bind="props"/>
+ </div>
+ <div v-else>
+ <MkInfo warn>{{ i18n.ts.notesSearchNotAvailable }}</MkInfo>
+ </div>
+ </MkSpacer>
- <MkSpacer v-else-if="tab === 'user'" :contentMax="800">
- <XUser v-bind="props"/>
- </MkSpacer>
- </MkSwiper>
+ <MkSpacer v-else-if="tab === 'user'" :contentMax="800">
+ <XUser v-bind="props"/>
+ </MkSpacer>
</PageWithHeader>
</template>
@@ -28,7 +26,6 @@ import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { notesSearchAvailable } from '@/utility/check-permissions.js';
import MkInfo from '@/components/MkInfo.vue';
-import MkSwiper from '@/components/MkSwiper.vue';
const props = withDefaults(defineProps<{
query?: string,
diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue
index 83c7bf45bb..2adc3925fa 100644
--- a/packages/frontend/src/pages/user/index.vue
+++ b/packages/frontend/src/pages/user/index.vue
@@ -4,24 +4,22 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<PageWithHeader v-model:tab="tab" :tabs="headerTabs" :actions="headerActions">
+<PageWithHeader v-model:tab="tab" :tabs="headerTabs" :actions="headerActions" :swipable="true">
<div v-if="user">
- <MkSwiper v-model:tab="tab" :tabs="headerTabs">
- <XHome v-if="tab === 'home'" :user="user" @unfoldFiles="() => { tab = 'files'; }"/>
- <MkSpacer v-else-if="tab === 'notes'" :contentMax="800" style="padding-top: 0">
- <XTimeline :user="user"/>
- </MkSpacer>
- <XFiles v-else-if="tab === 'files'" :user="user"/>
- <XActivity v-else-if="tab === 'activity'" :user="user"/>
- <XAchievements v-else-if="tab === 'achievements'" :user="user"/>
- <XReactions v-else-if="tab === 'reactions'" :user="user"/>
- <XClips v-else-if="tab === 'clips'" :user="user"/>
- <XLists v-else-if="tab === 'lists'" :user="user"/>
- <XPages v-else-if="tab === 'pages'" :user="user"/>
- <XFlashs v-else-if="tab === 'flashs'" :user="user"/>
- <XGallery v-else-if="tab === 'gallery'" :user="user"/>
- <XRaw v-else-if="tab === 'raw'" :user="user"/>
- </MkSwiper>
+ <XHome v-if="tab === 'home'" :user="user" @unfoldFiles="() => { tab = 'files'; }"/>
+ <MkSpacer v-else-if="tab === 'notes'" :contentMax="800" style="padding-top: 0">
+ <XTimeline :user="user"/>
+ </MkSpacer>
+ <XFiles v-else-if="tab === 'files'" :user="user"/>
+ <XActivity v-else-if="tab === 'activity'" :user="user"/>
+ <XAchievements v-else-if="tab === 'achievements'" :user="user"/>
+ <XReactions v-else-if="tab === 'reactions'" :user="user"/>
+ <XClips v-else-if="tab === 'clips'" :user="user"/>
+ <XLists v-else-if="tab === 'lists'" :user="user"/>
+ <XPages v-else-if="tab === 'pages'" :user="user"/>
+ <XFlashs v-else-if="tab === 'flashs'" :user="user"/>
+ <XGallery v-else-if="tab === 'gallery'" :user="user"/>
+ <XRaw v-else-if="tab === 'raw'" :user="user"/>
</div>
<MkError v-else-if="error" @retry="fetchUser()"/>
<MkLoading v-else/>
@@ -36,7 +34,6 @@ import { misskeyApi } from '@/utility/misskey-api.js';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import { $i } from '@/i.js';
-import MkSwiper from '@/components/MkSwiper.vue';
import { serverContext, assertServerContext } from '@/server-context.js';
const XHome = defineAsyncComponent(() => import('./home.vue'));