自前ルーティング (#6759)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip
This commit is contained in:
		@@ -4,7 +4,7 @@
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<ul>
 | 
			
		||||
				<li v-for="doc in docs" :key="doc.path">
 | 
			
		||||
					<router-link :to="`/docs/${doc.path}`">{{ doc.title }}</router-link>
 | 
			
		||||
					<MkA :to="`/docs/${doc.path}`">{{ doc.title }}</MkA>
 | 
			
		||||
				</li>
 | 
			
		||||
			</ul>
 | 
			
		||||
		</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -38,8 +38,8 @@
 | 
			
		||||
			<template #header><Fa :icon="faHashtag" fixed-width style="margin-right: 0.5em;"/>{{ $t('popularTags') }}</template>
 | 
			
		||||
 | 
			
		||||
			<div class="vxjfqztj">
 | 
			
		||||
				<router-link v-for="tag in tagsLocal" :to="`/explore/tags/${tag.tag}`" :key="'local:' + tag.tag" class="local">{{ tag.tag }}</router-link>
 | 
			
		||||
				<router-link v-for="tag in tagsRemote" :to="`/explore/tags/${tag.tag}`" :key="'remote:' + tag.tag">{{ tag.tag }}</router-link>
 | 
			
		||||
				<MkA v-for="tag in tagsLocal" :to="`/explore/tags/${tag.tag}`" :key="'local:' + tag.tag" class="local">{{ tag.tag }}</MkA>
 | 
			
		||||
				<MkA v-for="tag in tagsRemote" :to="`/explore/tags/${tag.tag}`" :key="'remote:' + tag.tag">{{ tag.tag }}</MkA>
 | 
			
		||||
			</div>
 | 
			
		||||
		</MkFolder>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
				<MkAvatar class="avatar" :user="req.follower"/>
 | 
			
		||||
				<div class="body">
 | 
			
		||||
					<div class="name">
 | 
			
		||||
						<router-link class="name" :to="userPage(req.follower)" v-user-preview="req.follower.id"><MkUserName :user="req.follower"/></router-link>
 | 
			
		||||
						<MkA class="name" :to="userPage(req.follower)" v-user-preview="req.follower.id"><MkUserName :user="req.follower"/></MkA>
 | 
			
		||||
						<p class="acct">@{{ acct(req.follower) }}</p>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="description" v-if="req.follower.description" :title="req.follower.description">
 | 
			
		||||
 
 | 
			
		||||
@@ -4,13 +4,12 @@
 | 
			
		||||
		<MkButton @click="start" primary class="start"><Fa :icon="faPlus"/> {{ $t('startMessaging') }}</MkButton>
 | 
			
		||||
 | 
			
		||||
		<div class="history" v-if="messages.length > 0">
 | 
			
		||||
			<router-link v-for="(message, i) in messages"
 | 
			
		||||
			<MkA v-for="(message, i) in messages"
 | 
			
		||||
				class="message _panel"
 | 
			
		||||
				:class="{ isMe: isMe(message), isRead: message.groupId ? message.reads.includes($store.state.i.id) : message.isRead }"
 | 
			
		||||
				:to="message.groupId ? `/my/messaging/group/${message.groupId}` : `/my/messaging/${getAcct(isMe(message) ? message.recipient : message.user)}`"
 | 
			
		||||
				:data-index="i"
 | 
			
		||||
				:key="message.id"
 | 
			
		||||
				@click.prevent="go(message)"
 | 
			
		||||
			>
 | 
			
		||||
				<div>
 | 
			
		||||
					<MkAvatar class="avatar" :user="message.groupId ? message.user : isMe(message) ? message.recipient : message.user"/>
 | 
			
		||||
@@ -27,7 +26,7 @@
 | 
			
		||||
						<p class="text"><span class="me" v-if="isMe(message)">{{ $t('you') }}:</span>{{ message.text }}</p>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</router-link>
 | 
			
		||||
			</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="_fullinfo" v-if="!fetching && messages.length == 0">
 | 
			
		||||
			<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
 | 
			
		||||
@@ -90,18 +89,6 @@ export default defineComponent({
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	methods: {
 | 
			
		||||
		go(message) {
 | 
			
		||||
			const url = message.groupId ? `/my/messaging/group/${message.groupId}` : `/my/messaging/${getAcct(this.isMe(message) ? message.recipient : message.user)}`;
 | 
			
		||||
			if (this.navHook) {
 | 
			
		||||
				this.navHook(url, defineAsyncComponent(() => import('@/pages/messaging/messaging-room.vue')), {
 | 
			
		||||
					userAcct: message.groupId ? null : getAcct(this.isMe(message) ? message.recipient : message.user),
 | 
			
		||||
					groupId: message.groupId
 | 
			
		||||
				});
 | 
			
		||||
			} else {
 | 
			
		||||
				this.$router.push(url);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		getAcct,
 | 
			
		||||
 | 
			
		||||
		isMe(message) {
 | 
			
		||||
 
 | 
			
		||||
@@ -317,7 +317,7 @@ const Component = defineComponent({
 | 
			
		||||
				text: this.$t('openInWindow'),
 | 
			
		||||
				icon: faWindowMaximize,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					os.pageWindow(url, Component, this.$props);
 | 
			
		||||
					os.pageWindow(url);
 | 
			
		||||
					this.$router.back();
 | 
			
		||||
				},
 | 
			
		||||
			}, this.inWindow ? undefined : {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
 | 
			
		||||
			<MkPagination :pagination="ownedPagination" #default="{items}" ref="owned">
 | 
			
		||||
				<div class="_card" v-for="group in items" :key="group.id">
 | 
			
		||||
					<div class="_title"><router-link :to="`/my/groups/${ group.id }`" class="_link">{{ group.name }}</router-link></div>
 | 
			
		||||
					<div class="_title"><MkA :to="`/my/groups/${ group.id }`" class="_link">{{ group.name }}</MkA></div>
 | 
			
		||||
					<div class="_content"><MkAvatars :user-ids="group.userIds"/></div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</MkPagination>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 | 
			
		||||
	<MkPagination :pagination="pagination" #default="{items}" class="lists _content" ref="list">
 | 
			
		||||
		<div class="list _panel" v-for="(list, i) in items" :key="list.id">
 | 
			
		||||
			<router-link :to="`/my/lists/${ list.id }`">{{ list.name }}</router-link>
 | 
			
		||||
			<MkA :to="`/my/lists/${ list.id }`">{{ list.name }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
	</MkPagination>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,12 @@ export default defineComponent({
 | 
			
		||||
		MkRemoteCaution,
 | 
			
		||||
		MkButton,
 | 
			
		||||
	},
 | 
			
		||||
	props: {
 | 
			
		||||
		noteId: {
 | 
			
		||||
			type: String,
 | 
			
		||||
			required: true
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			INFO: computed(() => this.note ? {
 | 
			
		||||
@@ -77,7 +83,7 @@ export default defineComponent({
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		$route: 'fetch'
 | 
			
		||||
		noteId: 'fetch'
 | 
			
		||||
	},
 | 
			
		||||
	created() {
 | 
			
		||||
		this.fetch();
 | 
			
		||||
@@ -86,7 +92,7 @@ export default defineComponent({
 | 
			
		||||
		fetch() {
 | 
			
		||||
			Progress.start();
 | 
			
		||||
			os.api('notes/show', {
 | 
			
		||||
				noteId: this.$route.params.note
 | 
			
		||||
				noteId: this.noteId
 | 
			
		||||
			}).then(note => {
 | 
			
		||||
				Promise.all([
 | 
			
		||||
					os.api('users/notes', {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
			</header>
 | 
			
		||||
 | 
			
		||||
			<section>
 | 
			
		||||
				<router-link class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><Fa :icon="faExternalLinkSquareAlt"/> {{ $t('_pages.viewPage') }}</router-link>
 | 
			
		||||
				<MkA class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><Fa :icon="faExternalLinkSquareAlt"/> {{ $t('_pages.viewPage') }}</MkA>
 | 
			
		||||
 | 
			
		||||
				<MkInput v-model:value="title">
 | 
			
		||||
					<span>{{ $t('_pages.title') }}</span>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,9 @@
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="_section links">
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<router-link :to="`./${page.name}/view-source`" class="link">{{ $t('_pages.viewSource') }}</router-link>
 | 
			
		||||
			<MkA :to="`./${page.name}/view-source`" class="link">{{ $t('_pages.viewSource') }}</MkA>
 | 
			
		||||
			<template v-if="$store.getters.isSignedIn && $store.state.i.id === page.userId">
 | 
			
		||||
				<router-link :to="`/my/pages/edit/${page.id}`" class="link">{{ $t('_pages.editThisPage') }}</router-link>
 | 
			
		||||
				<MkA :to="`/my/pages/edit/${page.id}`" class="link">{{ $t('_pages.editThisPage') }}</MkA>
 | 
			
		||||
				<button v-if="$store.state.i.pinnedPageId === page.id" @click="pin(false)" class="link _textButton">{{ $t('unpin') }}</button>
 | 
			
		||||
				<button v-else @click="pin(true)" class="link _textButton">{{ $t('pin') }}</button>
 | 
			
		||||
			</template>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,10 @@
 | 
			
		||||
<div class="_section">
 | 
			
		||||
	<section class="_card _vMargin">
 | 
			
		||||
		<div class="_title"><Fa :icon="faCog"/> {{ $t('general') }}</div>
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<div>{{ $t('defaultNavigationBehaviour') }}</div>
 | 
			
		||||
			<MkSwitch v-model:value="defaultSideView">{{ $t('openInSideView') }}</MkSwitch>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<div>{{ $t('whenServerDisconnected') }}</div>
 | 
			
		||||
			<MkRadio v-model="serverDisconnectedBehavior" value="reload">{{ $t('_serverDisconnectedBehavior.reload') }}</MkRadio>
 | 
			
		||||
@@ -51,6 +55,10 @@
 | 
			
		||||
 | 
			
		||||
	<section class="_card _vMargin">
 | 
			
		||||
		<div class="_title"><Fa :icon="faColumns"/> {{ $t('deck') }}</div>
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<div>{{ $t('defaultNavigationBehaviour') }}</div>
 | 
			
		||||
			<MkSwitch v-model:value="deckNavWindow">{{ $t('openInWindow') }}</MkSwitch>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<MkSwitch v-model:value="deckAlwaysShowMainColumn">
 | 
			
		||||
				{{ $t('_deck.alwaysShowMainColumn') }}
 | 
			
		||||
@@ -146,6 +154,16 @@ export default defineComponent({
 | 
			
		||||
			set(value) { this.$store.commit('device/set', { key: 'showFixedPostForm', value }); }
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		defaultSideView: {
 | 
			
		||||
			get() { return this.$store.state.device.defaultSideView; },
 | 
			
		||||
			set(value) { this.$store.commit('device/set', { key: 'defaultSideView', value }); }
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		deckNavWindow: {
 | 
			
		||||
			get() { return this.$store.state.device.deckNavWindow; },
 | 
			
		||||
			set(value) { this.$store.commit('device/set', { key: 'deckNavWindow', value }); }
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		chatOpenBehavior: {
 | 
			
		||||
			get() { return this.$store.state.device.chatOpenBehavior; },
 | 
			
		||||
			set(value) { this.$store.commit('device/set', { key: 'chatOpenBehavior', value }); }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,52 +1,57 @@
 | 
			
		||||
<template>
 | 
			
		||||
<div class="vvcocwet" :class="{ wide: !narrow }" ref="el">
 | 
			
		||||
	<div class="nav" v-if="!narrow || $route.name === 'settings'">
 | 
			
		||||
	<div class="nav" v-if="!narrow || page == null">
 | 
			
		||||
		<div class="menu">
 | 
			
		||||
			<div class="label">{{ $t('basicSettings') }}</div>
 | 
			
		||||
			<router-link class="item" replace to="/settings/profile"><Fa :icon="faUser" fixed-width class="icon"/>{{ $t('profile') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/privacy"><Fa :icon="faLockOpen" fixed-width class="icon"/>{{ $t('privacy') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/reaction"><Fa :icon="faLaugh" fixed-width class="icon"/>{{ $t('reaction') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/notifications"><Fa :icon="faBell" fixed-width class="icon"/>{{ $t('notifications') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/integration"><Fa :icon="faShareAlt" fixed-width class="icon"/>{{ $t('integration') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/security"><Fa :icon="faLock" fixed-width class="icon"/>{{ $t('security') }}</router-link>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'profile' }" replace to="/settings/profile"><Fa :icon="faUser" fixed-width class="icon"/>{{ $t('profile') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'privacy' }" replace to="/settings/privacy"><Fa :icon="faLockOpen" fixed-width class="icon"/>{{ $t('privacy') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'reaction' }" replace to="/settings/reaction"><Fa :icon="faLaugh" fixed-width class="icon"/>{{ $t('reaction') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'notifications' }" replace to="/settings/notifications"><Fa :icon="faBell" fixed-width class="icon"/>{{ $t('notifications') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'integration' }" replace to="/settings/integration"><Fa :icon="faShareAlt" fixed-width class="icon"/>{{ $t('integration') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'security' }" replace to="/settings/security"><Fa :icon="faLock" fixed-width class="icon"/>{{ $t('security') }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="menu">
 | 
			
		||||
			<div class="label">{{ $t('clientSettings') }}</div>
 | 
			
		||||
			<router-link class="item" replace to="/settings/general"><Fa :icon="faCogs" fixed-width class="icon"/>{{ $t('general') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/theme"><Fa :icon="faPalette" fixed-width class="icon"/>{{ $t('theme') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/sidebar"><Fa :icon="faListUl" fixed-width class="icon"/>{{ $t('sidebar') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/sounds"><Fa :icon="faMusic" fixed-width class="icon"/>{{ $t('sounds') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/plugins"><Fa :icon="faPlug" fixed-width class="icon"/>{{ $t('plugins') }}</router-link>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'general' }" replace to="/settings/general"><Fa :icon="faCogs" fixed-width class="icon"/>{{ $t('general') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'theme' }" replace to="/settings/theme"><Fa :icon="faPalette" fixed-width class="icon"/>{{ $t('theme') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'sidebar' }" replace to="/settings/sidebar"><Fa :icon="faListUl" fixed-width class="icon"/>{{ $t('sidebar') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'sounds' }" replace to="/settings/sounds"><Fa :icon="faMusic" fixed-width class="icon"/>{{ $t('sounds') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'plugins' }" replace to="/settings/plugins"><Fa :icon="faPlug" fixed-width class="icon"/>{{ $t('plugins') }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="menu">
 | 
			
		||||
			<div class="label">{{ $t('otherSettings') }}</div>
 | 
			
		||||
			<router-link class="item" replace to="/settings/mute-block"><Fa :icon="faBan" fixed-width class="icon"/>{{ $t('muteAndBlock') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/word-mute"><Fa :icon="faCommentSlash" fixed-width class="icon"/>{{ $t('wordMute') }}</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/api"><Fa :icon="faKey" fixed-width class="icon"/>API</router-link>
 | 
			
		||||
			<router-link class="item" replace to="/settings/other"><Fa :icon="faEllipsisH" fixed-width class="icon"/>{{ $t('other') }}</router-link>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'mute-block' }" replace to="/settings/mute-block"><Fa :icon="faBan" fixed-width class="icon"/>{{ $t('muteAndBlock') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'word-mute' }" replace to="/settings/word-mute"><Fa :icon="faCommentSlash" fixed-width class="icon"/>{{ $t('wordMute') }}</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'api' }" replace to="/settings/api"><Fa :icon="faKey" fixed-width class="icon"/>API</MkA>
 | 
			
		||||
			<MkA class="item" :class="{ active: page === 'other' }" replace to="/settings/other"><Fa :icon="faEllipsisH" fixed-width class="icon"/>{{ $t('other') }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="menu">
 | 
			
		||||
			<button class="_button item" @click="logout">{{ $t('logout') }}</button>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="main">
 | 
			
		||||
		<router-view v-slot="{ Component }">
 | 
			
		||||
			<transition :name="($store.state.device.animation && !narrow) ? 'view-slide' : ''" appear mode="out-in">
 | 
			
		||||
				<component :is="Component" @info="onInfo"/>
 | 
			
		||||
			</transition>
 | 
			
		||||
		</router-view>
 | 
			
		||||
		<transition :name="($store.state.device.animation && !narrow) ? 'view-slide' : ''" appear mode="out-in">
 | 
			
		||||
			<component :is="component" @info="onInfo"/>
 | 
			
		||||
		</transition>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent, onMounted, ref } from 'vue';
 | 
			
		||||
import { computed, defineAsyncComponent, defineComponent, onMounted, ref } from 'vue';
 | 
			
		||||
import { faCog, faPalette, faPlug, faUser, faListUl, faLock, faCommentSlash, faMusic, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey } from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
import { faLaugh, faBell } from '@fortawesome/free-regular-svg-icons';
 | 
			
		||||
import { store } from '@/store';
 | 
			
		||||
import { i18n } from '@/i18n';
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
	props: {
 | 
			
		||||
		page: {
 | 
			
		||||
			type: String,
 | 
			
		||||
			required: false
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	setup(props, context) {
 | 
			
		||||
		const INFO = ref({
 | 
			
		||||
			header: [{
 | 
			
		||||
@@ -60,6 +65,27 @@ export default defineComponent({
 | 
			
		||||
		const onInfo = (viewInfo) => {
 | 
			
		||||
			INFO.value = viewInfo;
 | 
			
		||||
		};
 | 
			
		||||
		const component = computed(() => {
 | 
			
		||||
			switch (props.page) {
 | 
			
		||||
				case 'profile': return defineAsyncComponent(() => import('./profile.vue'));
 | 
			
		||||
				case 'privacy': return defineAsyncComponent(() => import('./privacy.vue'));
 | 
			
		||||
				case 'reaction': return defineAsyncComponent(() => import('./reaction.vue'));
 | 
			
		||||
				case 'notifications': return defineAsyncComponent(() => import('./notifications.vue'));
 | 
			
		||||
				case 'mute-block': return defineAsyncComponent(() => import('./mute-block.vue'));
 | 
			
		||||
				case 'word-mute': return defineAsyncComponent(() => import('./word-mute.vue'));
 | 
			
		||||
				case 'integration': return defineAsyncComponent(() => import('./integration.vue'));
 | 
			
		||||
				case 'security': return defineAsyncComponent(() => import('./security.vue'));
 | 
			
		||||
				case 'api': return defineAsyncComponent(() => import('./api.vue'));
 | 
			
		||||
				case 'other': return defineAsyncComponent(() => import('./other.vue'));
 | 
			
		||||
				case 'general': return defineAsyncComponent(() => import('./general.vue'));
 | 
			
		||||
				case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
 | 
			
		||||
				case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
 | 
			
		||||
				case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
 | 
			
		||||
				case 'plugins': return defineAsyncComponent(() => import('./plugins.vue'));
 | 
			
		||||
				case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
 | 
			
		||||
				default: return null;
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		onMounted(() => {
 | 
			
		||||
			narrow.value = el.value.offsetWidth < 650;
 | 
			
		||||
@@ -71,6 +97,7 @@ export default defineComponent({
 | 
			
		||||
			view,
 | 
			
		||||
			el,
 | 
			
		||||
			onInfo,
 | 
			
		||||
			component,
 | 
			
		||||
			logout: () => {
 | 
			
		||||
				store.dispatch('logout');
 | 
			
		||||
				location.href = '/';
 | 
			
		||||
@@ -121,7 +148,7 @@ export default defineComponent({
 | 
			
		||||
					//border-top: solid 1px var(--divider);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				&.router-link-active {
 | 
			
		||||
				&.active {
 | 
			
		||||
					color: var(--accent);
 | 
			
		||||
					padding-left: 42px;
 | 
			
		||||
				}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@
 | 
			
		||||
			<template #empty><MkInfo>{{ $t('noUsers') }}</MkInfo></template>
 | 
			
		||||
			<template #default="{items}">
 | 
			
		||||
				<div class="user" v-for="mute in items" :key="mute.id">
 | 
			
		||||
					<router-link class="name" :to="userPage(mute.mutee)">
 | 
			
		||||
					<MkA class="name" :to="userPage(mute.mutee)">
 | 
			
		||||
						<MkAcct :user="mute.mutee"/>
 | 
			
		||||
					</router-link>
 | 
			
		||||
					</MkA>
 | 
			
		||||
				</div>
 | 
			
		||||
			</template>
 | 
			
		||||
		</MkPagination>
 | 
			
		||||
@@ -18,9 +18,9 @@
 | 
			
		||||
			<template #empty><MkInfo>{{ $t('noUsers') }}</MkInfo></template>
 | 
			
		||||
			<template #default="{items}">
 | 
			
		||||
				<div class="user" v-for="block in items" :key="block.id">
 | 
			
		||||
					<router-link class="name" :to="userPage(block.blockee)">
 | 
			
		||||
					<MkA class="name" :to="userPage(block.blockee)">
 | 
			
		||||
						<MkAcct :user="block.blockee"/>
 | 
			
		||||
					</router-link>
 | 
			
		||||
					</MkA>
 | 
			
		||||
				</div>
 | 
			
		||||
			</template>
 | 
			
		||||
		</MkPagination>
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
					<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
 | 
			
		||||
				</optgroup>
 | 
			
		||||
			</MkSelect>
 | 
			
		||||
			<a href="https://assets.msky.cafe/theme/list" rel="noopener" target="_blank" class="_link">{{ $t('_theme.explore') }}</a>・<router-link to="/theme-editor" class="_link">{{ $t('_theme.make') }}</router-link>
 | 
			
		||||
			<a href="https://assets.msky.cafe/theme/list" rel="noopener" target="_blank" class="_link">{{ $t('_theme.explore') }}</a>・<MkA to="/theme-editor" class="_link">{{ $t('_theme.make') }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="_content">
 | 
			
		||||
			<MkButton primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</MkButton>
 | 
			
		||||
 
 | 
			
		||||
@@ -15,11 +15,18 @@ export default defineComponent({
 | 
			
		||||
		XNotes
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	props: {
 | 
			
		||||
		tag: {
 | 
			
		||||
			type: String,
 | 
			
		||||
			required: true
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			INFO: {
 | 
			
		||||
				header: [{
 | 
			
		||||
					title: this.$route.params.tag,
 | 
			
		||||
					title: this.tag,
 | 
			
		||||
					icon: faHashtag
 | 
			
		||||
				}],
 | 
			
		||||
			},
 | 
			
		||||
@@ -27,7 +34,7 @@ export default defineComponent({
 | 
			
		||||
				endpoint: 'notes/search-by-tag',
 | 
			
		||||
				limit: 10,
 | 
			
		||||
				params: () => ({
 | 
			
		||||
					tag: this.$route.params.tag,
 | 
			
		||||
					tag: this.tag,
 | 
			
		||||
				})
 | 
			
		||||
			},
 | 
			
		||||
			faHashtag
 | 
			
		||||
@@ -35,7 +42,7 @@ export default defineComponent({
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	watch: {
 | 
			
		||||
		$route() {
 | 
			
		||||
		tag() {
 | 
			
		||||
			(this.$refs.notes as any).reload();
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 
 | 
			
		||||
@@ -229,7 +229,7 @@ export default defineComponent({
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		messagingWindowOpen() {
 | 
			
		||||
			os.pageWindow('/my/messaging', defineAsyncComponent(() => import('@/pages/messaging/index.vue')));
 | 
			
		||||
			os.pageWindow('/my/messaging');
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		openWaitingDialog(text?) {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
	<div class="_content" v-else-if="tutorial === 1">
 | 
			
		||||
		<div>{{ $t('_tutorial.step2_1') }}</div>
 | 
			
		||||
		<div>{{ $t('_tutorial.step2_2') }}</div>
 | 
			
		||||
		<router-link class="_link" to="/settings/profile">{{ $t('editProfile') }}</router-link>
 | 
			
		||||
		<MkA class="_link" to="/settings/profile">{{ $t('editProfile') }}</MkA>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="_content" v-else-if="tutorial === 2">
 | 
			
		||||
		<div>{{ $t('_tutorial.step3_1') }}</div>
 | 
			
		||||
@@ -25,10 +25,10 @@
 | 
			
		||||
		<div>{{ $t('_tutorial.step5_1') }}</div>
 | 
			
		||||
		<i18n-t keypath="_tutorial.step5_2" tag="div">
 | 
			
		||||
			<template #featured>
 | 
			
		||||
				<router-link class="_link" to="/featured">{{ $t('featured') }}</router-link>
 | 
			
		||||
				<MkA class="_link" to="/featured">{{ $t('featured') }}</MkA>
 | 
			
		||||
			</template>
 | 
			
		||||
			<template #explore>
 | 
			
		||||
				<router-link class="_link" to="/explore">{{ $t('explore') }}</router-link>
 | 
			
		||||
				<MkA class="_link" to="/explore">{{ $t('explore') }}</MkA>
 | 
			
		||||
			</template>
 | 
			
		||||
		</i18n-t>
 | 
			
		||||
		<div>{{ $t('_tutorial.step5_3') }}</div>
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
		<div>{{ $t('_tutorial.step7_1') }}</div>
 | 
			
		||||
		<i18n-t keypath="_tutorial.step7_2" tag="div">
 | 
			
		||||
			<template #help>
 | 
			
		||||
				<router-link class="_link" to="/docs">{{ $t('help') }}</router-link>
 | 
			
		||||
				<MkA class="_link" to="/docs">{{ $t('help') }}</MkA>
 | 
			
		||||
			</template>
 | 
			
		||||
		</i18n-t>
 | 
			
		||||
		<div>{{ $t('_tutorial.step7_3') }}</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent } from 'vue';
 | 
			
		||||
import parseAcct from '../../../misc/acct/parse';
 | 
			
		||||
import MkUserInfo from '@/components/user-info.vue';
 | 
			
		||||
import MkPagination from '@/components/ui/pagination.vue';
 | 
			
		||||
import { userPage, acct } from '../../filters/user';
 | 
			
		||||
@@ -22,10 +21,14 @@ export default defineComponent({
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	props: {
 | 
			
		||||
		user: {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			required: true
 | 
			
		||||
		},
 | 
			
		||||
		type: {
 | 
			
		||||
			type: String,
 | 
			
		||||
			required: true
 | 
			
		||||
		}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	data() {
 | 
			
		||||
@@ -34,7 +37,7 @@ export default defineComponent({
 | 
			
		||||
				endpoint: () => this.type === 'following' ? 'users/following' : 'users/followers',
 | 
			
		||||
				limit: 20,
 | 
			
		||||
				params: {
 | 
			
		||||
					...parseAcct(this.$route.params.user),
 | 
			
		||||
					userId: this.user.id,
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
@@ -45,7 +48,7 @@ export default defineComponent({
 | 
			
		||||
			this.$refs.list.reload();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		'$route'() {
 | 
			
		||||
		user() {
 | 
			
		||||
			this.$refs.list.reload();
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,11 @@
 | 
			
		||||
<div class="ujigsodd">
 | 
			
		||||
	<MkLoading v-if="fetching"/>
 | 
			
		||||
	<div class="stream" v-if="!fetching && images.length > 0">
 | 
			
		||||
		<router-link v-for="(image, i) in images" :key="i"
 | 
			
		||||
		<MkA v-for="image in images"
 | 
			
		||||
			class="img"
 | 
			
		||||
			:style="`background-image: url(${thumbnail(image.file)})`"
 | 
			
		||||
			:to="notePage(image.note)"
 | 
			
		||||
		></router-link>
 | 
			
		||||
		></MkA>
 | 
			
		||||
	</div>
 | 
			
		||||
	<p class="empty" v-if="!fetching && images.length == 0">{{ $t('nothing') }}</p>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -67,24 +67,23 @@
 | 
			
		||||
				</dl>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="status">
 | 
			
		||||
				<router-link :to="userPage(user)" :class="{ active: $route.name === 'user' }">
 | 
			
		||||
				<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
 | 
			
		||||
					<b>{{ number(user.notesCount) }}</b>
 | 
			
		||||
					<span>{{ $t('notes') }}</span>
 | 
			
		||||
				</router-link>
 | 
			
		||||
				<router-link :to="userPage(user, 'following')" :class="{ active: $route.name === 'userFollowing' }">
 | 
			
		||||
				</MkA>
 | 
			
		||||
				<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
 | 
			
		||||
					<b>{{ number(user.followingCount) }}</b>
 | 
			
		||||
					<span>{{ $t('following') }}</span>
 | 
			
		||||
				</router-link>
 | 
			
		||||
				<router-link :to="userPage(user, 'followers')" :class="{ active: $route.name === 'userFollowers' }">
 | 
			
		||||
				</MkA>
 | 
			
		||||
				<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
 | 
			
		||||
					<b>{{ number(user.followersCount) }}</b>
 | 
			
		||||
					<span>{{ $t('followers') }}</span>
 | 
			
		||||
				</router-link>
 | 
			
		||||
				</MkA>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
	<router-view :user="user"></router-view>
 | 
			
		||||
	<template v-if="$route.name == 'user'">
 | 
			
		||||
	<template v-if="page === 'index'">
 | 
			
		||||
		<div class="_section">
 | 
			
		||||
			<div class="_content _vMargin" v-if="user.pinnedNotes.length > 0">
 | 
			
		||||
				<XNote v-for="note in user.pinnedNotes" class="note _vMargin" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :detail="true" :pinned="true"/>
 | 
			
		||||
@@ -106,6 +105,8 @@
 | 
			
		||||
			<XUserTimeline :user="user" class="_content"/>
 | 
			
		||||
		</div>
 | 
			
		||||
	</template>
 | 
			
		||||
	<XFollowList v-else-if="page === 'following'" type="following" :user="user"/>
 | 
			
		||||
	<XFollowList v-else-if="page === 'followers'" type="followers" :user="user"/>
 | 
			
		||||
</div>
 | 
			
		||||
<div v-else-if="error">
 | 
			
		||||
	<MkError @retry="fetch()"/>
 | 
			
		||||
@@ -128,7 +129,7 @@ import parseAcct from '../../../misc/acct/parse';
 | 
			
		||||
import { getScrollPosition } from '@/scripts/scroll';
 | 
			
		||||
import { getUserMenu } from '@/scripts/get-user-menu';
 | 
			
		||||
import number from '../../filters/number';
 | 
			
		||||
import { userPage, acct } from '../../filters/user';
 | 
			
		||||
import { userPage, acct as getAcct } from '../../filters/user';
 | 
			
		||||
import * as os from '@/os';
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
@@ -139,10 +140,23 @@ export default defineComponent({
 | 
			
		||||
		MkContainer,
 | 
			
		||||
		MkRemoteCaution,
 | 
			
		||||
		MkFolder,
 | 
			
		||||
		XFollowList: defineAsyncComponent(() => import('./follow-list.vue')),
 | 
			
		||||
		XPhotos: defineAsyncComponent(() => import('./index.photos.vue')),
 | 
			
		||||
		XActivity: defineAsyncComponent(() => import('./index.activity.vue')),
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	props: {
 | 
			
		||||
		acct: {
 | 
			
		||||
			type: String,
 | 
			
		||||
			required: true
 | 
			
		||||
		},
 | 
			
		||||
		page: {
 | 
			
		||||
			type: String,
 | 
			
		||||
			required: false,
 | 
			
		||||
			default: 'index'
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			INFO: computed(() => this.user ? {
 | 
			
		||||
@@ -176,7 +190,7 @@ export default defineComponent({
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	watch: {
 | 
			
		||||
		$route: 'fetch'
 | 
			
		||||
		acct: 'fetch'
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	created() {
 | 
			
		||||
@@ -192,10 +206,12 @@ export default defineComponent({
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	methods: {
 | 
			
		||||
		getAcct,
 | 
			
		||||
 | 
			
		||||
		fetch() {
 | 
			
		||||
			if (this.$route.params.user == null) return;
 | 
			
		||||
			if (this.acct == null) return;
 | 
			
		||||
			Progress.start();
 | 
			
		||||
			os.api('users/show', parseAcct(this.$route.params.user)).then(user => {
 | 
			
		||||
			os.api('users/show', parseAcct(this.acct)).then(user => {
 | 
			
		||||
				this.user = user;
 | 
			
		||||
			}).catch(e => {
 | 
			
		||||
				this.error = e;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user