forked from FoundKeyGang/FoundKey
client: consolidate about & notifications pages
Reviewed-on: FoundKeyGang/FoundKey#104 Changelog: Changed
This commit is contained in:
commit
039f6db40a
15 changed files with 213 additions and 300 deletions
|
@ -847,6 +847,7 @@ typeToConfirm: "Please enter {x} to confirm"
|
|||
deleteAccount: "Delete account"
|
||||
numberOfPageCache: "Number of cached pages"
|
||||
numberOfPageCacheDescription: "Increasing this number will improve convenience for users but cause more server load as well as more memory to be used."
|
||||
document: "Document"
|
||||
file: "File"
|
||||
unclip: "Unclip"
|
||||
confirmToUnclipAlreadyClippedNote: "This note is already part of the \"{name}\" clip. Do you want to remove it from this clip instead?"
|
||||
|
|
|
@ -854,6 +854,7 @@ typeToConfirm: "この操作を行うには {x} と入力してください"
|
|||
deleteAccount: "アカウント削除"
|
||||
numberOfPageCache: "ページキャッシュ数"
|
||||
numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。"
|
||||
document: "ドキュメント"
|
||||
|
||||
_emailUnavailable:
|
||||
used: "既に使用されています"
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
</template>
|
||||
</div>
|
||||
<div class="sub">
|
||||
<a v-click-anime href="https://misskey-hub.net/help.html" target="_blank" @click.passive="close()">
|
||||
<button v-click-anime class="_button" @click="help">
|
||||
<i class="fas fa-question-circle icon"></i>
|
||||
<div class="text">{{ i18n.ts.help }}</div>
|
||||
</a>
|
||||
</button>
|
||||
<MkA v-click-anime to="/about" @click.passive="close()">
|
||||
<i class="fas fa-info-circle icon"></i>
|
||||
<div class="text">{{ i18n.t('aboutX', { x: instanceName }) }}</div>
|
||||
<div class="text">{{ i18n.ts.instanceInfo }}</div>
|
||||
</MkA>
|
||||
<MkA v-click-anime to="/about-misskey" @click.passive="close()">
|
||||
<img src="/static-assets/favicon.png" class="icon"/>
|
||||
|
@ -40,6 +40,7 @@ import { instanceName } from '@/config';
|
|||
import { defaultStore } from '@/store';
|
||||
import { i18n } from '@/i18n';
|
||||
import { deviceKind } from '@/scripts/device-kind';
|
||||
import * as os from '@/os';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
src?: HTMLElement;
|
||||
|
@ -72,6 +73,28 @@ const items = Object.keys(menuDef).filter(k => !menu.includes(k)).map(k => menuD
|
|||
function close() {
|
||||
modal.close();
|
||||
}
|
||||
|
||||
function help(ev: MouseEvent) {
|
||||
os.popupMenu([{
|
||||
type: 'link',
|
||||
to: '/mfm-cheat-sheet',
|
||||
text: i18n.ts._mfm.cheatSheet,
|
||||
icon: 'fas fa-code',
|
||||
}, {
|
||||
type: 'link',
|
||||
to: '/scratchpad',
|
||||
text: i18n.ts.scratchpad,
|
||||
icon: 'fas fa-terminal',
|
||||
}, null, {
|
||||
text: i18n.ts.document,
|
||||
icon: 'fas fa-question-circle',
|
||||
action: () => {
|
||||
window.open('https://misskey-hub.net/help.html', '_blank');
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
|
||||
close();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -112,14 +112,14 @@ export const menuDef = reactive({
|
|||
icon: 'fas fa-at',
|
||||
show: computed(() => $i != null),
|
||||
indicated: computed(() => $i != null && $i.hasUnreadMentions),
|
||||
to: '/my/mentions',
|
||||
to: '/my/notifications#mentions',
|
||||
},
|
||||
messages: {
|
||||
title: 'directNotes',
|
||||
icon: 'fas fa-envelope',
|
||||
show: computed(() => $i != null),
|
||||
indicated: computed(() => $i != null && $i.hasUnreadSpecifiedNotes),
|
||||
to: '/my/messages',
|
||||
to: '/my/notifications#directNotes',
|
||||
},
|
||||
favorites: {
|
||||
title: 'favorites',
|
||||
|
@ -151,17 +151,12 @@ export const menuDef = reactive({
|
|||
federation: {
|
||||
title: 'federation',
|
||||
icon: 'fas fa-globe',
|
||||
to: '/federation',
|
||||
to: '/about#federation',
|
||||
},
|
||||
emojis: {
|
||||
title: 'emojis',
|
||||
icon: 'fas fa-laugh',
|
||||
to: '/emojis',
|
||||
},
|
||||
scratchpad: {
|
||||
title: 'scratchpad',
|
||||
icon: 'fas fa-terminal',
|
||||
to: '/scratchpad',
|
||||
to: '/about#emojis',
|
||||
},
|
||||
ui: {
|
||||
title: 'switchUi',
|
||||
|
|
106
packages/client/src/pages/about.federation.vue
Normal file
106
packages/client/src/pages/about.federation.vue
Normal file
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div class="taeiyria">
|
||||
<div class="query">
|
||||
<MkInput v-model="host" :debounce="true" class="">
|
||||
<template #prefix><i class="fas fa-search"></i></template>
|
||||
<template #label>{{ $ts.host }}</template>
|
||||
</MkInput>
|
||||
<FormSplit style="margin-top: var(--margin);">
|
||||
<MkSelect v-model="state">
|
||||
<template #label>{{ $ts.state }}</template>
|
||||
<option value="all">{{ $ts.all }}</option>
|
||||
<option value="federating">{{ $ts.federating }}</option>
|
||||
<option value="subscribing">{{ $ts.subscribing }}</option>
|
||||
<option value="publishing">{{ $ts.publishing }}</option>
|
||||
<option value="suspended">{{ $ts.suspended }}</option>
|
||||
<option value="blocked">{{ $ts.blocked }}</option>
|
||||
<option value="notResponding">{{ $ts.notResponding }}</option>
|
||||
</MkSelect>
|
||||
<MkSelect v-model="sort">
|
||||
<template #label>{{ $ts.sort }}</template>
|
||||
<option value="+pubSub">{{ $ts.pubSub }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-pubSub">{{ $ts.pubSub }} ({{ $ts.ascendingOrder }})</option>
|
||||
<option value="+notes">{{ $ts.notes }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-notes">{{ $ts.notes }} ({{ $ts.ascendingOrder }})</option>
|
||||
<option value="+users">{{ $ts.users }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-users">{{ $ts.users }} ({{ $ts.ascendingOrder }})</option>
|
||||
<option value="+following">{{ $ts.following }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-following">{{ $ts.following }} ({{ $ts.ascendingOrder }})</option>
|
||||
<option value="+followers">{{ $ts.followers }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-followers">{{ $ts.followers }} ({{ $ts.ascendingOrder }})</option>
|
||||
<option value="+caughtAt">{{ $ts.registeredAt }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-caughtAt">{{ $ts.registeredAt }} ({{ $ts.ascendingOrder }})</option>
|
||||
<option value="+lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.descendingOrder }})</option>
|
||||
<option value="-lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.ascendingOrder }})</option>
|
||||
</MkSelect>
|
||||
</FormSplit>
|
||||
</div>
|
||||
|
||||
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
|
||||
<div class="dqokceoi">
|
||||
<MkA v-for="instance in items" :key="instance.id" v-tooltip.mfm="`Last communicated: ${new Date(instance.lastCommunicatedAt).toLocaleString()}\nStatus: ${getStatus(instance)}`" class="instance" :to="`/instance-info/${instance.host}`">
|
||||
<MkInstanceCardMini :instance="instance"/>
|
||||
</MkA>
|
||||
</div>
|
||||
</MkPagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import MkButton from '@/components/ui/button.vue';
|
||||
import MkInput from '@/components/form/input.vue';
|
||||
import MkSelect from '@/components/form/select.vue';
|
||||
import MkPagination from '@/components/ui/pagination.vue';
|
||||
import MkInstanceCardMini from '@/components/instance-card-mini.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import * as os from '@/os';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
let host = $ref('');
|
||||
let state = $ref('federating');
|
||||
let sort = $ref('+pubSub');
|
||||
const pagination = {
|
||||
endpoint: 'federation/instances' as const,
|
||||
limit: 10,
|
||||
offsetMode: true,
|
||||
params: computed(() => ({
|
||||
sort: sort,
|
||||
host: host !== '' ? host : null,
|
||||
...(
|
||||
state === 'federating' ? { federating: true } :
|
||||
state === 'subscribing' ? { subscribing: true } :
|
||||
state === 'publishing' ? { publishing: true } :
|
||||
state === 'suspended' ? { suspended: true } :
|
||||
state === 'blocked' ? { blocked: true } :
|
||||
state === 'notResponding' ? { notResponding: true } :
|
||||
{}),
|
||||
})),
|
||||
};
|
||||
|
||||
function getStatus(instance) {
|
||||
if (instance.isSuspended) return 'Suspended';
|
||||
if (instance.isBlocked) return 'Blocked';
|
||||
if (instance.isNotResponding) return 'Error';
|
||||
return 'Alive';
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.taeiyria {
|
||||
> .query {
|
||||
background: var(--bg);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.dqokceoi {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
|
||||
grid-gap: 12px;
|
||||
|
||||
> .instance:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -73,7 +73,7 @@
|
|||
<MkSpacer v-else-if="tab === 'federation'" :content-max="1000" :margin-min="20">
|
||||
<XFederation/>
|
||||
</MkSpacer>
|
||||
<MkSpacer v-else-if="tab === 'charts'" :content-max="1000" :margin-min="20">
|
||||
<MkSpacer v-else-if="tab === 'charts'" :content-max="1200" :margin-min="20">
|
||||
<MkInstanceStats :chart-limit="500" :detailed="true"/>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
|
@ -81,6 +81,8 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import XEmojis from './about.emojis.vue';
|
||||
import XFederation from './about.federation.vue';
|
||||
import { version, host } from '@/config';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
|
@ -93,6 +95,23 @@ import number from '@/filters/number';
|
|||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
const headerTabs = $computed(() => [{
|
||||
key: 'overview',
|
||||
title: i18n.ts.overview,
|
||||
}, {
|
||||
key: 'emojis',
|
||||
title: i18n.ts.customEmojis,
|
||||
icon: 'fas fa-laugh',
|
||||
}, {
|
||||
key: 'federation',
|
||||
title: i18n.ts.federation,
|
||||
icon: 'fas fa-globe',
|
||||
}, {
|
||||
key: 'charts',
|
||||
title: i18n.ts.charts,
|
||||
icon: 'fas fa-chart-simple',
|
||||
}]);
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
initialTab?: string;
|
||||
}>(), {
|
||||
|
@ -100,7 +119,7 @@ const props = withDefaults(defineProps<{
|
|||
});
|
||||
|
||||
let stats = $ref(null);
|
||||
let tab = $ref(props.initialTab);
|
||||
let tab = $ref(headerTabs.some(({ key }) => key === props.initialTab) ? props.initialTab : 'overview');
|
||||
|
||||
const initStats = () => os.api('stats', {
|
||||
}).then((res) => {
|
||||
|
@ -109,15 +128,6 @@ const initStats = () => os.api('stats', {
|
|||
|
||||
const headerActions = $computed(() => []);
|
||||
|
||||
const headerTabs = $computed(() => [{
|
||||
key: 'overview',
|
||||
title: i18n.ts.overview,
|
||||
}, {
|
||||
key: 'charts',
|
||||
title: i18n.ts.charts,
|
||||
icon: 'fas fa-chart-bar',
|
||||
}]);
|
||||
|
||||
definePageMetadata(computed(() => ({
|
||||
title: i18n.ts.instanceInfo,
|
||||
icon: 'fas fa-info-circle',
|
||||
|
|
|
@ -185,12 +185,10 @@ const menuDef = $computed(() => [{
|
|||
}]);
|
||||
|
||||
const component = $computed(() => {
|
||||
if (props.initialPage == null) return null;
|
||||
switch (props.initialPage) {
|
||||
case 'overview': return defineAsyncComponent(() => import('./overview.vue'));
|
||||
case 'users': return defineAsyncComponent(() => import('./users.vue'));
|
||||
case 'emojis': return defineAsyncComponent(() => import('./emojis.vue'));
|
||||
case 'federation': return defineAsyncComponent(() => import('../federation.vue'));
|
||||
case 'queue': return defineAsyncComponent(() => import('./queue.vue'));
|
||||
case 'files': return defineAsyncComponent(() => import('./files.vue'));
|
||||
case 'announcements': return defineAsyncComponent(() => import('./announcements.vue'));
|
||||
|
@ -204,6 +202,7 @@ const component = $computed(() => {
|
|||
case 'integrations': return defineAsyncComponent(() => import('./integrations.vue'));
|
||||
case 'instance-block': return defineAsyncComponent(() => import('./instance-block.vue'));
|
||||
case 'proxy-account': return defineAsyncComponent(() => import('./proxy-account.vue'));
|
||||
default: return null;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<div :class="$style.root">
|
||||
<XCategory/>
|
||||
</div>
|
||||
</MkStickyContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import XCategory from './emojis.category.vue';
|
||||
import * as os from '@/os';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
function menu(ev) {
|
||||
os.popupMenu([{
|
||||
icon: 'fas fa-download',
|
||||
text: i18n.ts.export,
|
||||
action: async () => {
|
||||
os.api('export-custom-emojis', {
|
||||
})
|
||||
.then(() => {
|
||||
os.alert({
|
||||
type: 'info',
|
||||
text: i18n.ts.exportRequested,
|
||||
});
|
||||
}).catch((err) => {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: err.message,
|
||||
});
|
||||
});
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
const headerActions = $computed(() => [{
|
||||
icon: 'fas fa-ellipsis-h',
|
||||
handler: menu,
|
||||
}]);
|
||||
|
||||
const headerTabs = $computed(() => []);
|
||||
|
||||
definePageMetadata({
|
||||
title: i18n.ts.customEmojis,
|
||||
icon: 'fas fa-laugh',
|
||||
bg: 'var(--bg)',
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
|
@ -1,122 +0,0 @@
|
|||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="1000">
|
||||
<div class="taeiyria">
|
||||
<div class="query">
|
||||
<MkInput v-model="host" :debounce="true" class="">
|
||||
<template #prefix><i class="fas fa-search"></i></template>
|
||||
<template #label>{{ i18n.ts.host }}</template>
|
||||
</MkInput>
|
||||
<FormSplit style="margin-top: var(--margin);">
|
||||
<MkSelect v-model="state">
|
||||
<template #label>{{ i18n.ts.state }}</template>
|
||||
<option value="all">{{ i18n.ts.all }}</option>
|
||||
<option value="federating">{{ i18n.ts.federating }}</option>
|
||||
<option value="subscribing">{{ i18n.ts.subscribing }}</option>
|
||||
<option value="publishing">{{ i18n.ts.publishing }}</option>
|
||||
<option value="suspended">{{ i18n.ts.suspended }}</option>
|
||||
<option value="blocked">{{ i18n.ts.blocked }}</option>
|
||||
<option value="notResponding">{{ i18n.ts.notResponding }}</option>
|
||||
</MkSelect>
|
||||
<MkSelect v-model="sort">
|
||||
<template #label>{{ i18n.ts.sort }}</template>
|
||||
<option value="+pubSub">{{ i18n.ts.pubSub }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-pubSub">{{ i18n.ts.pubSub }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+notes">{{ i18n.ts.notes }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-notes">{{ i18n.ts.notes }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+users">{{ i18n.ts.users }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-users">{{ i18n.ts.users }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+following">{{ i18n.ts.following }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-following">{{ i18n.ts.following }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+followers">{{ i18n.ts.followers }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-followers">{{ i18n.ts.followers }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+caughtAt">{{ i18n.ts.registeredAt }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-caughtAt">{{ i18n.ts.registeredAt }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+lastCommunicatedAt">{{ i18n.ts.lastCommunication }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-lastCommunicatedAt">{{ i18n.ts.lastCommunication }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
</MkSelect>
|
||||
</FormSplit>
|
||||
</div>
|
||||
|
||||
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
|
||||
<div class="dqokceoi">
|
||||
<MkA v-for="instance in items" :key="instance.id" v-tooltip.mfm="`Last communicated: ${new Date(instance.lastCommunicatedAt).toLocaleString()}\nStatus: ${getStatus(instance)}`" class="instance" :to="`/instance-info/${instance.host}`">
|
||||
<MkInstanceCardMini :instance="instance"/>
|
||||
</MkA>
|
||||
</div>
|
||||
</MkPagination>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import MkButton from '@/components/ui/button.vue';
|
||||
import MkInput from '@/components/form/input.vue';
|
||||
import MkSelect from '@/components/form/select.vue';
|
||||
import MkPagination from '@/components/ui/pagination.vue';
|
||||
import MkInstanceCardMini from '@/components/instance-card-mini.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import * as os from '@/os';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
let host = $ref('');
|
||||
let state = $ref('federating');
|
||||
let sort = $ref('+pubSub');
|
||||
const pagination = {
|
||||
endpoint: 'federation/instances' as const,
|
||||
limit: 10,
|
||||
offsetMode: true,
|
||||
params: computed(() => ({
|
||||
sort,
|
||||
host: host !== '' ? host : null,
|
||||
...(
|
||||
state === 'federating' ? { federating: true } :
|
||||
state === 'subscribing' ? { subscribing: true } :
|
||||
state === 'publishing' ? { publishing: true } :
|
||||
state === 'suspended' ? { suspended: true } :
|
||||
state === 'blocked' ? { blocked: true } :
|
||||
state === 'notResponding' ? { notResponding: true } :
|
||||
{}),
|
||||
})),
|
||||
};
|
||||
|
||||
function getStatus(instance) {
|
||||
if (instance.isSuspended) return 'Suspended';
|
||||
if (instance.isBlocked) return 'Blocked';
|
||||
if (instance.isNotResponding) return 'Error';
|
||||
return 'Alive';
|
||||
}
|
||||
|
||||
const headerActions = $computed(() => []);
|
||||
|
||||
const headerTabs = $computed(() => []);
|
||||
|
||||
definePageMetadata({
|
||||
title: i18n.ts.federation,
|
||||
icon: 'fas fa-globe',
|
||||
bg: 'var(--bg)',
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.taeiyria {
|
||||
> .query {
|
||||
background: var(--bg);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.dqokceoi {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
|
||||
grid-gap: 12px;
|
||||
|
||||
> .instance:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,29 +0,0 @@
|
|||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="800">
|
||||
<XNotes :pagination="pagination"/>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import XNotes from '@/components/notes.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
const pagination = {
|
||||
endpoint: 'notes/mentions' as const,
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
const headerActions = $computed(() => []);
|
||||
|
||||
const headerTabs = $computed(() => []);
|
||||
|
||||
definePageMetadata({
|
||||
title: i18n.ts.mentions,
|
||||
icon: 'fas fa-at',
|
||||
bg: 'var(--bg)',
|
||||
});
|
||||
</script>
|
|
@ -1,32 +0,0 @@
|
|||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="800">
|
||||
<XNotes :pagination="pagination"/>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import XNotes from '@/components/notes.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
const pagination = {
|
||||
endpoint: 'notes/mentions' as const,
|
||||
limit: 10,
|
||||
params: {
|
||||
visibility: 'specified',
|
||||
},
|
||||
};
|
||||
|
||||
const headerActions = $computed(() => []);
|
||||
|
||||
const headerTabs = $computed(() => []);
|
||||
|
||||
definePageMetadata({
|
||||
title: i18n.ts.directNotes,
|
||||
icon: 'fas fa-envelope',
|
||||
bg: 'var(--bg)',
|
||||
});
|
||||
</script>
|
|
@ -2,8 +2,14 @@
|
|||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="800">
|
||||
<div class="clupoqwt">
|
||||
<XNotifications class="notifications" :include-types="includeTypes" :unread-only="tab === 'unread'"/>
|
||||
<div v-if="tab === 'mentions'">
|
||||
<XNotes :pagination="mentionsPagination"/>
|
||||
</div>
|
||||
<div v-else-if="tab === 'directNotes'">
|
||||
<XNotes :pagination="directNotesPagination"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<XNotifications class="notifications" :include-types="includeTypes" :unread-only="unreadOnly"/>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
|
@ -13,14 +19,51 @@
|
|||
import { computed } from 'vue';
|
||||
import { notificationTypes } from 'foundkey-js';
|
||||
import XNotifications from '@/components/notifications.vue';
|
||||
import XNotes from '@/components/notes.vue';
|
||||
import * as os from '@/os';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
let tab = $ref('all');
|
||||
let includeTypes = $ref<string[] | null>(null);
|
||||
const headerTabs = $computed(() => [{
|
||||
key: 'all',
|
||||
title: i18n.ts.all,
|
||||
}, {
|
||||
key: 'unread',
|
||||
title: i18n.ts.unread,
|
||||
}, {
|
||||
key: 'mentions',
|
||||
title: i18n.ts.mentions,
|
||||
icon: 'fas fa-at',
|
||||
}, {
|
||||
key: 'directNotes',
|
||||
title: i18n.ts.directNotes,
|
||||
icon: 'fas fa-envelope',
|
||||
}]);
|
||||
|
||||
function setFilter(ev) {
|
||||
const props = withDefaults(defineProps<{
|
||||
initialTab?: string;
|
||||
}>(), {
|
||||
initialTab: 'all',
|
||||
});
|
||||
|
||||
let tab = $ref(headerTabs.some(({ key }) => key === props.initialTab) ? props.initialTab : 'all');
|
||||
let includeTypes = $ref<string[] | null>(null);
|
||||
let unreadOnly = $computed(() => tab === 'unread');
|
||||
|
||||
const mentionsPagination = {
|
||||
endpoint: 'notes/mentions' as const,
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
const directNotesPagination = {
|
||||
endpoint: 'notes/mentions' as const,
|
||||
limit: 10,
|
||||
params: {
|
||||
visibility: 'specified',
|
||||
},
|
||||
};
|
||||
|
||||
function setFilter(ev: Event): void {
|
||||
const typeItems = notificationTypes.map(t => ({
|
||||
text: i18n.t(`_notification._types.${t}`),
|
||||
active: includeTypes && includeTypes.includes(t),
|
||||
|
@ -38,34 +81,21 @@ function setFilter(ev) {
|
|||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
const headerActions = $computed(() => [{
|
||||
const headerActions = $computed(() => tab === 'all' ? [{
|
||||
text: i18n.ts.filter,
|
||||
icon: 'fas fa-filter',
|
||||
highlighted: includeTypes != null,
|
||||
handler: setFilter,
|
||||
}, {
|
||||
},{
|
||||
text: i18n.ts.markAllAsRead,
|
||||
icon: 'fas fa-check',
|
||||
handler: () => {
|
||||
os.apiWithDialog('notifications/mark-all-as-read');
|
||||
},
|
||||
}]);
|
||||
|
||||
const headerTabs = $computed(() => [{
|
||||
key: 'all',
|
||||
title: i18n.ts.all,
|
||||
}, {
|
||||
key: 'unread',
|
||||
title: i18n.ts.unread,
|
||||
}]);
|
||||
}] : []);
|
||||
|
||||
definePageMetadata(computed(() => ({
|
||||
title: i18n.ts.notifications,
|
||||
icon: 'fas fa-bell',
|
||||
})));
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.clupoqwt {
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<MkContainer>
|
||||
<template #header><i class="fas fa-chart-bar" style="margin-right: 0.5em;"></i>{{ $ts.activity }}</template>
|
||||
<template #header><i class="fas fa-chart-simple" style="margin-right: 0.5em;"></i>{{ $ts.activity }}</template>
|
||||
<template #func>
|
||||
<button class="_button" @click="showMenu">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
|
|
|
@ -70,12 +70,6 @@ export const routes = [{
|
|||
}, {
|
||||
path: '/explore',
|
||||
component: page(() => import('./pages/explore.vue')),
|
||||
}, {
|
||||
path: '/federation',
|
||||
component: page(() => import('./pages/federation.vue')),
|
||||
}, {
|
||||
path: '/emojis',
|
||||
component: page(() => import('./pages/emojis.vue')),
|
||||
}, {
|
||||
path: '/search',
|
||||
component: page(() => import('./pages/search.vue')),
|
||||
|
@ -167,17 +161,12 @@ export const routes = [{
|
|||
}, {
|
||||
path: '/my/notifications',
|
||||
component: page(() => import('./pages/notifications.vue')),
|
||||
hash: 'initialTab',
|
||||
loginRequired: true,
|
||||
}, {
|
||||
path: '/my/favorites',
|
||||
component: page(() => import('./pages/favorites.vue')),
|
||||
loginRequired: true,
|
||||
}, {
|
||||
path: '/my/messages',
|
||||
component: page(() => import('./pages/messages.vue')),
|
||||
}, {
|
||||
path: '/my/mentions',
|
||||
component: page(() => import('./pages/mentions.vue')),
|
||||
}, {
|
||||
name: 'messaging',
|
||||
path: '/my/messaging',
|
||||
|
|
Loading…
Reference in a new issue