summaryrefslogtreecommitdiff
path: root/src/client/components/sidebar.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/components/sidebar.vue')
-rw-r--r--src/client/components/sidebar.vue272
1 files changed, 124 insertions, 148 deletions
diff --git a/src/client/components/sidebar.vue b/src/client/components/sidebar.vue
index 77e9af27e5..7548b136ea 100644
--- a/src/client/components/sidebar.vue
+++ b/src/client/components/sidebar.vue
@@ -4,7 +4,7 @@
<div class="nav-back _modalBg"
v-if="showing"
@click="showing = false"
- @touchstart="showing = false"
+ @touchstart.passive="showing = false"
></div>
</transition>
@@ -12,31 +12,31 @@
<nav class="nav" :class="{ iconOnly, hidden }" v-show="showing">
<div>
<button class="item _button account" @click="openAccountMenu" v-if="$store.getters.isSignedIn">
- <mk-avatar :user="$store.state.i" class="avatar"/><mk-acct class="text" :user="$store.state.i"/>
+ <MkAvatar :user="$store.state.i" class="avatar"/><MkAcct class="text" :user="$store.state.i"/>
</button>
<button class="item _button index active" @click="top()" v-if="$route.name === 'index'">
- <fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
+ <Fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</button>
<router-link class="item index" active-class="active" to="/" exact v-else>
- <fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
+ <Fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</router-link>
<template v-for="item in menu">
<div v-if="item === '-'" class="divider"></div>
- <component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'router-link' : 'button'" class="item _button" :class="item" active-class="active" @click="() => { if (menuDef[item].action) menuDef[item].action() }" :to="menuDef[item].to">
- <fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $t(menuDef[item].title) }}</span>
- <i v-if="menuDef[item].indicated"><fa :icon="faCircle"/></i>
+ <component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'router-link' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to">
+ <Fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $t(menuDef[item].title) }}</span>
+ <i v-if="menuDef[item].indicated"><Fa :icon="faCircle"/></i>
</component>
</template>
<div class="divider"></div>
<button class="item _button" :class="{ active: $route.path === '/instance' || $route.path.startsWith('/instance/') }" v-if="$store.getters.isSignedIn && ($store.state.i.isAdmin || $store.state.i.isModerator)" @click="oepnInstanceMenu">
- <fa :icon="faServer" fixed-width/><span class="text">{{ $t('instance') }}</span>
+ <Fa :icon="faServer" fixed-width/><span class="text">{{ $t('instance') }}</span>
</button>
<button class="item _button" @click="more">
- <fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $t('more') }}</span>
- <i v-if="otherNavItemIndicated"><fa :icon="faCircle"/></i>
+ <Fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $t('more') }}</span>
+ <i v-if="otherNavItemIndicated"><Fa :icon="faCircle"/></i>
</button>
- <router-link class="item" active-class="active" to="/preferences">
- <fa :icon="faCog" fixed-width/><span class="text">{{ $t('settings') }}</span>
+ <router-link class="item" active-class="active" to="/settings">
+ <Fa :icon="faCog" fixed-width/><span class="text">{{ $t('settings') }}</span>
</router-link>
</div>
</nav>
@@ -45,13 +45,15 @@
</template>
<script lang="ts">
-import Vue from 'vue';
-import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram } from '@fortawesome/free-solid-svg-icons';
+import { defineComponent } from 'vue';
+import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram, faStream } from '@fortawesome/free-solid-svg-icons';
import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
-import { host, instanceName } from '../config';
-import { search } from '../scripts/search';
+import { host, instanceName } from '@/config';
+import { search } from '@/scripts/search';
+import * as os from '@/os';
+import { sidebarDef } from '@/sidebar';
-export default Vue.extend({
+export default defineComponent({
data() {
return {
host: host,
@@ -59,9 +61,7 @@ export default Vue.extend({
searching: false,
accounts: [],
connection: null,
- menuDef: this.$store.getters.nav({
- search: this.search
- }),
+ menuDef: sidebarDef,
iconOnly: false,
hidden: false,
faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram
@@ -127,7 +127,7 @@ export default Vue.extend({
search() {
if (this.searching) return;
- this.$root.dialog({
+ os.dialog({
title: this.$t('search'),
input: true
}).then(async ({ canceled, result: query }) => {
@@ -141,7 +141,7 @@ export default Vue.extend({
},
async openAccountMenu(ev) {
- const accounts = (await this.$root.api('users/show', { userIds: this.$store.state.device.accounts.map(x => x.id) })).filter(x => x.id !== this.$store.state.i.id);
+ const accounts = (await os.api('users/show', { userIds: this.$store.state.device.accounts.map(x => x.id) })).filter(x => x.id !== this.$store.state.i.id);
const accountItems = accounts.map(account => ({
type: 'user',
@@ -149,96 +149,80 @@ export default Vue.extend({
action: () => { this.switchAccount(account); }
}));
- this.$root.menu({
- items: [...[{
- type: 'link',
- text: this.$t('profile'),
- to: `/@${ this.$store.state.i.username }`,
- avatar: this.$store.state.i,
- }, {
- type: 'link',
- text: this.$t('accountSettings'),
- to: '/my/settings',
- icon: faCog,
- }, null, ...accountItems, {
- icon: faPlus,
- text: this.$t('addAcount'),
- action: () => {
- this.$root.menu({
- items: [{
- text: this.$t('existingAcount'),
- action: () => { this.addAcount(); },
- }, {
- text: this.$t('createAccount'),
- action: () => { this.createAccount(); },
- }],
- align: 'left',
- fixed: true,
- width: 240,
- source: ev.currentTarget || ev.target,
- });
- },
- }]],
- align: 'left',
- fixed: true,
- width: 240,
- source: ev.currentTarget || ev.target,
+ os.modalMenu([...[{
+ type: 'link',
+ text: this.$t('profile'),
+ to: `/@${ this.$store.state.i.username }`,
+ avatar: this.$store.state.i,
+ }, null, ...accountItems, {
+ icon: faPlus,
+ text: this.$t('addAcount'),
+ action: () => {
+ os.modalMenu([{
+ text: this.$t('existingAcount'),
+ action: () => { this.addAcount(); },
+ }, {
+ text: this.$t('createAccount'),
+ action: () => { this.createAccount(); },
+ }], ev.currentTarget || ev.target);
+ },
+ }]], ev.currentTarget || ev.target, {
+ align: 'left'
});
},
oepnInstanceMenu(ev) {
- this.$root.menu({
- items: [{
- type: 'link',
- text: this.$t('dashboard'),
- to: '/instance',
- icon: faTachometerAlt,
- }, null, {
- type: 'link',
- text: this.$t('settings'),
- to: '/instance/settings',
- icon: faCog,
- }, {
- type: 'link',
- text: this.$t('customEmojis'),
- to: '/instance/emojis',
- icon: faLaugh,
- }, {
- type: 'link',
- text: this.$t('users'),
- to: '/instance/users',
- icon: faUsers,
- }, {
- type: 'link',
- text: this.$t('files'),
- to: '/instance/files',
- icon: faCloud,
- }, {
- type: 'link',
- text: this.$t('jobQueue'),
- to: '/instance/queue',
- icon: faExchangeAlt,
- }, {
- type: 'link',
- text: this.$t('federation'),
- to: '/instance/federation',
- icon: faGlobe,
- }, {
- type: 'link',
- text: this.$t('relays'),
- to: '/instance/relays',
- icon: faProjectDiagram,
- }, {
- type: 'link',
- text: this.$t('announcements'),
- to: '/instance/announcements',
- icon: faBroadcastTower,
- }],
- align: 'left',
- fixed: true,
- width: 200,
- source: ev.currentTarget || ev.target,
- });
+ os.modalMenu([{
+ type: 'link',
+ text: this.$t('dashboard'),
+ to: '/instance',
+ icon: faTachometerAlt,
+ }, null, this.$store.state.i.isAdmin ? {
+ type: 'link',
+ text: this.$t('settings'),
+ to: '/instance/settings',
+ icon: faCog,
+ } : undefined, {
+ type: 'link',
+ text: this.$t('customEmojis'),
+ to: '/instance/emojis',
+ icon: faLaugh,
+ }, {
+ type: 'link',
+ text: this.$t('users'),
+ to: '/instance/users',
+ icon: faUsers,
+ }, {
+ type: 'link',
+ text: this.$t('files'),
+ to: '/instance/files',
+ icon: faCloud,
+ }, {
+ type: 'link',
+ text: this.$t('jobQueue'),
+ to: '/instance/queue',
+ icon: faExchangeAlt,
+ }, {
+ type: 'link',
+ text: this.$t('federation'),
+ to: '/instance/federation',
+ icon: faGlobe,
+ }, {
+ type: 'link',
+ text: this.$t('relays'),
+ to: '/instance/relays',
+ icon: faProjectDiagram,
+ }, {
+ type: 'link',
+ text: this.$t('announcements'),
+ to: '/instance/announcements',
+ icon: faBroadcastTower,
+ }, {
+ type: 'link',
+ text: this.$t('logs'),
+ to: '/instance/logs',
+ icon: faStream,
+ }], ev.currentTarget || ev.target);
},
more(ev) {
@@ -250,45 +234,40 @@ export default Vue.extend({
action: def.action,
indicate: def.indicated,
}));
- this.$root.menu({
- items: [...items, null, {
- type: 'link',
- text: this.$t('help'),
- to: '/docs',
- icon: faQuestionCircle,
- }, {
- type: 'link',
- text: this.$t('aboutX', { x: instanceName || host }),
- to: '/about',
- icon: faInfoCircle,
- }, {
- type: 'link',
- text: this.$t('aboutMisskey'),
- to: '/about-misskey',
- icon: faInfoCircle,
- }],
- align: 'left',
- fixed: true,
- width: 200,
- source: ev.currentTarget || ev.target,
- });
+ os.modalMenu([...items, null, {
+ type: 'link',
+ text: this.$t('help'),
+ to: '/docs',
+ icon: faQuestionCircle,
+ }, {
+ type: 'link',
+ text: this.$t('aboutX', { x: instanceName || host }),
+ to: '/about',
+ icon: faInfoCircle,
+ }, {
+ type: 'link',
+ text: this.$t('aboutMisskey'),
+ to: '/about-misskey',
+ icon: faInfoCircle,
+ }], ev.currentTarget || ev.target);
},
async addAcount() {
- this.$root.new(await import('./signin-dialog.vue').then(m => m.default)).$once('login', res => {
- this.$store.dispatch('addAcount', res);
- this.$root.dialog({
- type: 'success',
- iconOnly: true, autoClose: true
- });
- });
+ os.popup(await import('./signin-dialog.vue'), {}, {
+ done: res => {
+ this.$store.dispatch('addAcount', res);
+ os.success();
+ },
+ }, 'closed');
},
async createAccount() {
- this.$root.new(await import('./signup-dialog.vue').then(m => m.default)).$once('signup', res => {
- this.$store.dispatch('addAcount', res);
- this.switchAccountWithToken(res.i);
- });
+ os.popup(await import('./signup-dialog.vue'), {}, {
+ done: res => {
+ this.$store.dispatch('addAcount', res);
+ this.switchAccountWithToken(res.i);
+ },
+ }, 'closed');
},
async switchAccount(account: any) {
@@ -297,12 +276,9 @@ export default Vue.extend({
},
switchAccountWithToken(token: string) {
- this.$root.dialog({
- type: 'waiting',
- iconOnly: true
- });
+ os.waiting();
- this.$root.api('i', {}, token).then((i: any) => {
+ os.api('i', {}, token).then((i: any) => {
this.$store.dispatch('switchAccount', {
...i,
token: token
@@ -324,7 +300,7 @@ export default Vue.extend({
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
-.nav-enter,
+.nav-enter-from,
.nav-leave-active {
opacity: 0;
transform: translateX(-240px);
@@ -335,7 +311,7 @@ export default Vue.extend({
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
-.nav-back-enter,
+.nav-back-enter-from,
.nav-back-leave-active {
opacity: 0;
}