mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-13 13:37:31 -07:00
enhance(client): リスト、アンテナタイムラインを個別ページとして分割
This commit is contained in:
parent
ce949edb59
commit
1d051438c5
9 changed files with 348 additions and 70 deletions
|
@ -8,13 +8,14 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## 12.x.x (unreleased)
|
## 12.x.x (unreleased)
|
||||||
- ActivityPub: deliverキューのメモリ使用量を削減
|
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
- ActivityPub: リモートユーザーのDeleteアクティビティに対応
|
- ActivityPub: リモートユーザーのDeleteアクティビティに対応
|
||||||
- ActivityPub: add resolver check for blocked instance
|
- ActivityPub: add resolver check for blocked instance
|
||||||
|
- ActivityPub: deliverキューのメモリ使用量を削減
|
||||||
- アカウントが凍結された場合に、凍結された旨を表示してからログアウトするように
|
- アカウントが凍結された場合に、凍結された旨を表示してからログアウトするように
|
||||||
- 凍結されたアカウントにログインしようとしたときに、凍結されている旨を表示するように
|
- 凍結されたアカウントにログインしようとしたときに、凍結されている旨を表示するように
|
||||||
|
- リスト、アンテナタイムラインを個別ページとして分割
|
||||||
- UIの改善
|
- UIの改善
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref } from 'vue';
|
import { defineComponent, ref, unref } from 'vue';
|
||||||
import { focusPrev, focusNext } from '@client/scripts/focus';
|
import { focusPrev, focusNext } from '@client/scripts/focus';
|
||||||
import contains from '@client/scripts/contains';
|
import contains from '@client/scripts/contains';
|
||||||
|
|
||||||
|
@ -79,21 +79,26 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
watch: {
|
||||||
const items = ref(this.items.filter(item => item !== undefined));
|
items: {
|
||||||
|
handler() {
|
||||||
|
const items = ref(unref(this.items).filter(item => item !== undefined));
|
||||||
|
|
||||||
for (let i = 0; i < items.value.length; i++) {
|
for (let i = 0; i < items.value.length; i++) {
|
||||||
const item = items.value[i];
|
const item = items.value[i];
|
||||||
|
|
||||||
if (item && item.then) { // if item is Promise
|
if (item && item.then) { // if item is Promise
|
||||||
items.value[i] = { type: 'pending' };
|
items.value[i] = { type: 'pending' };
|
||||||
item.then(actualItem => {
|
item.then(actualItem => {
|
||||||
items.value[i] = actualItem;
|
items.value[i] = actualItem;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._items = items;
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
|
|
||||||
this._items = items;
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.viaKeyboard) {
|
if (this.viaKeyboard) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { computed } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { search } from '@client/scripts/search';
|
import { search } from '@client/scripts/search';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import { i18n } from '@client/i18n';
|
import { i18n } from '@client/i18n';
|
||||||
import { $i } from './account';
|
import { $i } from './account';
|
||||||
import { unisonReload } from '@client/scripts/unison-reload';
|
import { unisonReload } from '@client/scripts/unison-reload';
|
||||||
|
import { router } from './router';
|
||||||
|
|
||||||
export const menuDef = {
|
export const menuDef = {
|
||||||
notifications: {
|
notifications: {
|
||||||
|
@ -58,7 +59,26 @@ export const menuDef = {
|
||||||
title: 'lists',
|
title: 'lists',
|
||||||
icon: 'fas fa-list-ul',
|
icon: 'fas fa-list-ul',
|
||||||
show: computed(() => $i != null),
|
show: computed(() => $i != null),
|
||||||
to: '/my/lists',
|
active: computed(() => router.currentRoute.value.path.startsWith('/timeline/list/') || router.currentRoute.value.path === '/my/lists' || router.currentRoute.value.path.startsWith('/my/lists/')),
|
||||||
|
action: (ev) => {
|
||||||
|
const items = ref([{
|
||||||
|
type: 'pending'
|
||||||
|
}]);
|
||||||
|
os.api('users/lists/list').then(lists => {
|
||||||
|
const _items = [...lists.map(list => ({
|
||||||
|
type: 'link',
|
||||||
|
text: list.name,
|
||||||
|
to: `/timeline/list/${list.id}`
|
||||||
|
})), null, {
|
||||||
|
type: 'link',
|
||||||
|
to: '/my/lists',
|
||||||
|
text: i18n.locale.manageLists,
|
||||||
|
icon: 'fas fa-cog',
|
||||||
|
}];
|
||||||
|
items.value = _items;
|
||||||
|
});
|
||||||
|
os.popupMenu(items, ev.currentTarget || ev.target);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
groups: {
|
groups: {
|
||||||
title: 'groups',
|
title: 'groups',
|
||||||
|
|
|
@ -372,7 +372,7 @@ export async function openEmojiPicker(src?: HTMLElement, opts, initialTextarea:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function popupMenu(items: any[], src?: HTMLElement, options?: { align?: string; viaKeyboard?: boolean }) {
|
export function popupMenu(items: any[] | Ref<any[]>, src?: HTMLElement, options?: { align?: string; viaKeyboard?: boolean }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let dispose;
|
let dispose;
|
||||||
popup(import('@client/components/ui/popup-menu.vue'), {
|
popup(import('@client/components/ui/popup-menu.vue'), {
|
||||||
|
|
147
src/client/pages/antenna-timeline.vue
Normal file
147
src/client/pages/antenna-timeline.vue
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
<template>
|
||||||
|
<div class="tqmomfks" v-hotkey.global="keymap" v-size="{ min: [800] }">
|
||||||
|
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
|
||||||
|
<div class="tl _block">
|
||||||
|
<XTimeline ref="tl" class="tl"
|
||||||
|
:key="antennaId"
|
||||||
|
src="antenna"
|
||||||
|
:antenna="antennaId"
|
||||||
|
:sound="true"
|
||||||
|
@before="before()"
|
||||||
|
@after="after()"
|
||||||
|
@queue="queueUpdated"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, defineAsyncComponent, computed } from 'vue';
|
||||||
|
import Progress from '@client/scripts/loading';
|
||||||
|
import XTimeline from '@client/components/timeline.vue';
|
||||||
|
import { scroll } from '@client/scripts/scroll';
|
||||||
|
import * as os from '@client/os';
|
||||||
|
import * as symbols from '@client/symbols';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
XTimeline,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
antennaId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
antenna: null,
|
||||||
|
queue: 0,
|
||||||
|
[symbols.PAGE_INFO]: computed(() => this.antenna ? {
|
||||||
|
title: this.antenna.name,
|
||||||
|
icon: 'fas fa-satellite',
|
||||||
|
bg: 'var(--bg)',
|
||||||
|
actions: [{
|
||||||
|
icon: 'fas fa-calendar-alt',
|
||||||
|
text: this.$ts.jumpToSpecifiedDate,
|
||||||
|
handler: this.timetravel
|
||||||
|
}, {
|
||||||
|
icon: 'fas fa-cog',
|
||||||
|
text: this.$ts.settings,
|
||||||
|
handler: this.settings
|
||||||
|
}],
|
||||||
|
} : null),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
keymap(): any {
|
||||||
|
return {
|
||||||
|
't': this.focus
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
antennaId: {
|
||||||
|
async handler() {
|
||||||
|
this.antenna = await os.api('antennas/show', {
|
||||||
|
antennaId: this.antennaId
|
||||||
|
});
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
before() {
|
||||||
|
Progress.start();
|
||||||
|
},
|
||||||
|
|
||||||
|
after() {
|
||||||
|
Progress.done();
|
||||||
|
},
|
||||||
|
|
||||||
|
queueUpdated(q) {
|
||||||
|
this.queue = q;
|
||||||
|
},
|
||||||
|
|
||||||
|
top() {
|
||||||
|
scroll(this.$el, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
async timetravel() {
|
||||||
|
const { canceled, result: date } = await os.dialog({
|
||||||
|
title: this.$ts.date,
|
||||||
|
input: {
|
||||||
|
type: 'date'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
this.$refs.tl.timetravel(new Date(date));
|
||||||
|
},
|
||||||
|
|
||||||
|
settings() {
|
||||||
|
this.$router.push(`/my/antennas/${this.antennaId}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
(this.$refs.tl as any).focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tqmomfks {
|
||||||
|
padding: var(--margin);
|
||||||
|
|
||||||
|
> .new {
|
||||||
|
position: sticky;
|
||||||
|
top: calc(var(--stickyTop, 0px) + 16px);
|
||||||
|
z-index: 1000;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> button {
|
||||||
|
display: block;
|
||||||
|
margin: var(--margin) auto 0 auto;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tl {
|
||||||
|
background: var(--bg);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.min-width_800px {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -6,11 +6,8 @@
|
||||||
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
|
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
|
||||||
<div class="tl _block">
|
<div class="tl _block">
|
||||||
<XTimeline ref="tl" class="tl"
|
<XTimeline ref="tl" class="tl"
|
||||||
:key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src"
|
:key="src"
|
||||||
:src="src"
|
:src="src"
|
||||||
:list="list ? list.id : null"
|
|
||||||
:antenna="antenna ? antenna.id : null"
|
|
||||||
:channel="channel ? channel.id : null"
|
|
||||||
:sound="true"
|
:sound="true"
|
||||||
@before="before()"
|
@before="before()"
|
||||||
@after="after()"
|
@after="after()"
|
||||||
|
@ -41,10 +38,6 @@ export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
src: 'home',
|
src: 'home',
|
||||||
list: null,
|
|
||||||
antenna: null,
|
|
||||||
channel: null,
|
|
||||||
menuOpened: false,
|
|
||||||
queue: 0,
|
queue: 0,
|
||||||
[symbols.PAGE_INFO]: computed(() => ({
|
[symbols.PAGE_INFO]: computed(() => ({
|
||||||
title: this.$ts.timeline,
|
title: this.$ts.timeline,
|
||||||
|
@ -116,32 +109,10 @@ export default defineComponent({
|
||||||
src() {
|
src() {
|
||||||
this.showNav = false;
|
this.showNav = false;
|
||||||
},
|
},
|
||||||
list(x) {
|
|
||||||
this.showNav = false;
|
|
||||||
if (x != null) this.antenna = null;
|
|
||||||
if (x != null) this.channel = null;
|
|
||||||
},
|
|
||||||
antenna(x) {
|
|
||||||
this.showNav = false;
|
|
||||||
if (x != null) this.list = null;
|
|
||||||
if (x != null) this.channel = null;
|
|
||||||
},
|
|
||||||
channel(x) {
|
|
||||||
this.showNav = false;
|
|
||||||
if (x != null) this.antenna = null;
|
|
||||||
if (x != null) this.list = null;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.src = this.$store.state.tl.src;
|
this.src = this.$store.state.tl.src;
|
||||||
if (this.src === 'list') {
|
|
||||||
this.list = this.$store.state.tl.arg;
|
|
||||||
} else if (this.src === 'antenna') {
|
|
||||||
this.antenna = this.$store.state.tl.arg;
|
|
||||||
} else if (this.src === 'channel') {
|
|
||||||
this.channel = this.$store.state.tl.arg;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -164,12 +135,9 @@ export default defineComponent({
|
||||||
async chooseList(ev) {
|
async chooseList(ev) {
|
||||||
const lists = await os.api('users/lists/list');
|
const lists = await os.api('users/lists/list');
|
||||||
const items = lists.map(list => ({
|
const items = lists.map(list => ({
|
||||||
|
type: 'link',
|
||||||
text: list.name,
|
text: list.name,
|
||||||
action: () => {
|
to: `/timeline/list/${list.id}`
|
||||||
this.list = list;
|
|
||||||
this.src = 'list';
|
|
||||||
this.saveSrc();
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
os.popupMenu(items, ev.currentTarget || ev.target);
|
os.popupMenu(items, ev.currentTarget || ev.target);
|
||||||
},
|
},
|
||||||
|
@ -177,13 +145,10 @@ export default defineComponent({
|
||||||
async chooseAntenna(ev) {
|
async chooseAntenna(ev) {
|
||||||
const antennas = await os.api('antennas/list');
|
const antennas = await os.api('antennas/list');
|
||||||
const items = antennas.map(antenna => ({
|
const items = antennas.map(antenna => ({
|
||||||
|
type: 'link',
|
||||||
text: antenna.name,
|
text: antenna.name,
|
||||||
indicate: antenna.hasUnreadNote,
|
indicate: antenna.hasUnreadNote,
|
||||||
action: () => {
|
to: `/timeline/antenna/${antenna.id}`
|
||||||
this.antenna = antenna;
|
|
||||||
this.src = 'antenna';
|
|
||||||
this.saveSrc();
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
os.popupMenu(items, ev.currentTarget || ev.target);
|
os.popupMenu(items, ev.currentTarget || ev.target);
|
||||||
},
|
},
|
||||||
|
@ -191,15 +156,10 @@ export default defineComponent({
|
||||||
async chooseChannel(ev) {
|
async chooseChannel(ev) {
|
||||||
const channels = await os.api('channels/followed');
|
const channels = await os.api('channels/followed');
|
||||||
const items = channels.map(channel => ({
|
const items = channels.map(channel => ({
|
||||||
|
type: 'link',
|
||||||
text: channel.name,
|
text: channel.name,
|
||||||
indicate: channel.hasUnreadNote,
|
indicate: channel.hasUnreadNote,
|
||||||
action: () => {
|
to: `/channels/${channel.id}`
|
||||||
// NOTE: チャンネルタイムラインをこのコンポーネントで表示するようにすると投稿フォームはどうするかなどの問題が生じるのでとりあえずページ遷移で
|
|
||||||
//this.channel = channel;
|
|
||||||
//this.src = 'channel';
|
|
||||||
//this.saveSrc();
|
|
||||||
this.$router.push(`/channels/${channel.id}`);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
os.popupMenu(items, ev.currentTarget || ev.target);
|
os.popupMenu(items, ev.currentTarget || ev.target);
|
||||||
},
|
},
|
||||||
|
@ -207,10 +167,6 @@ export default defineComponent({
|
||||||
saveSrc() {
|
saveSrc() {
|
||||||
this.$store.set('tl', {
|
this.$store.set('tl', {
|
||||||
src: this.src,
|
src: this.src,
|
||||||
arg:
|
|
||||||
this.src === 'list' ? this.list :
|
|
||||||
this.src === 'antenna' ? this.antenna :
|
|
||||||
this.channel
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
147
src/client/pages/user-list-timeline.vue
Normal file
147
src/client/pages/user-list-timeline.vue
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
<template>
|
||||||
|
<div class="eqqrhokj" v-hotkey.global="keymap" v-size="{ min: [800] }">
|
||||||
|
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
|
||||||
|
<div class="tl _block">
|
||||||
|
<XTimeline ref="tl" class="tl"
|
||||||
|
:key="listId"
|
||||||
|
src="list"
|
||||||
|
:list="listId"
|
||||||
|
:sound="true"
|
||||||
|
@before="before()"
|
||||||
|
@after="after()"
|
||||||
|
@queue="queueUpdated"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, defineAsyncComponent, computed } from 'vue';
|
||||||
|
import Progress from '@client/scripts/loading';
|
||||||
|
import XTimeline from '@client/components/timeline.vue';
|
||||||
|
import { scroll } from '@client/scripts/scroll';
|
||||||
|
import * as os from '@client/os';
|
||||||
|
import * as symbols from '@client/symbols';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
XTimeline,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
listId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: null,
|
||||||
|
queue: 0,
|
||||||
|
[symbols.PAGE_INFO]: computed(() => this.list ? {
|
||||||
|
title: this.list.name,
|
||||||
|
icon: 'fas fa-list-ul',
|
||||||
|
bg: 'var(--bg)',
|
||||||
|
actions: [{
|
||||||
|
icon: 'fas fa-calendar-alt',
|
||||||
|
text: this.$ts.jumpToSpecifiedDate,
|
||||||
|
handler: this.timetravel
|
||||||
|
}, {
|
||||||
|
icon: 'fas fa-cog',
|
||||||
|
text: this.$ts.settings,
|
||||||
|
handler: this.settings
|
||||||
|
}],
|
||||||
|
} : null),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
keymap(): any {
|
||||||
|
return {
|
||||||
|
't': this.focus
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
listId: {
|
||||||
|
async handler() {
|
||||||
|
this.list = await os.api('users/lists/show', {
|
||||||
|
listId: this.listId
|
||||||
|
});
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
before() {
|
||||||
|
Progress.start();
|
||||||
|
},
|
||||||
|
|
||||||
|
after() {
|
||||||
|
Progress.done();
|
||||||
|
},
|
||||||
|
|
||||||
|
queueUpdated(q) {
|
||||||
|
this.queue = q;
|
||||||
|
},
|
||||||
|
|
||||||
|
top() {
|
||||||
|
scroll(this.$el, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
settings() {
|
||||||
|
this.$router.push(`/my/lists/${this.listId}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
async timetravel() {
|
||||||
|
const { canceled, result: date } = await os.dialog({
|
||||||
|
title: this.$ts.date,
|
||||||
|
input: {
|
||||||
|
type: 'date'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
this.$refs.tl.timetravel(new Date(date));
|
||||||
|
},
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
(this.$refs.tl as any).focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.eqqrhokj {
|
||||||
|
padding: var(--margin);
|
||||||
|
|
||||||
|
> .new {
|
||||||
|
position: sticky;
|
||||||
|
top: calc(var(--stickyTop, 0px) + 16px);
|
||||||
|
z-index: 1000;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> button {
|
||||||
|
display: block;
|
||||||
|
margin: var(--margin) auto 0 auto;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tl {
|
||||||
|
background: var(--bg);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.min-width_800px {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -48,6 +48,8 @@ const defaultRoutes = [
|
||||||
{ path: '/channels/:channelId/edit', component: page('channel-editor'), props: true },
|
{ path: '/channels/:channelId/edit', component: page('channel-editor'), props: true },
|
||||||
{ path: '/channels/:channelId', component: page('channel'), props: route => ({ channelId: route.params.channelId }) },
|
{ path: '/channels/:channelId', component: page('channel'), props: route => ({ channelId: route.params.channelId }) },
|
||||||
{ path: '/clips/:clipId', component: page('clip'), props: route => ({ clipId: route.params.clipId }) },
|
{ path: '/clips/:clipId', component: page('clip'), props: route => ({ clipId: route.params.clipId }) },
|
||||||
|
{ path: '/timeline/list/:listId', component: page('user-list-timeline'), props: route => ({ listId: route.params.listId }) },
|
||||||
|
{ path: '/timeline/antenna/:antennaId', component: page('antenna-timeline'), props: route => ({ antennaId: route.params.antennaId }) },
|
||||||
{ path: '/my/notifications', component: page('notifications') },
|
{ path: '/my/notifications', component: page('notifications') },
|
||||||
{ path: '/my/favorites', component: page('favorites') },
|
{ path: '/my/favorites', component: page('favorites') },
|
||||||
{ path: '/my/messages', component: page('messages') },
|
{ path: '/my/messages', component: page('messages') },
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</MkA>
|
</MkA>
|
||||||
<template v-for="item in menu">
|
<template v-for="item in menu">
|
||||||
<div v-if="item === '-'" class="divider"></div>
|
<div v-if="item === '-'" class="divider"></div>
|
||||||
<component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to" v-click-anime>
|
<component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="[item, { active: menuDef[item].active }]" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to" v-click-anime>
|
||||||
<i class="fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span>
|
<i class="fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span>
|
||||||
<span v-if="menuDef[item].indicated" class="indicator"><i class="fas fa-circle"></i></span>
|
<span v-if="menuDef[item].indicated" class="indicator"><i class="fas fa-circle"></i></span>
|
||||||
</component>
|
</component>
|
||||||
|
|
Loading…
Reference in a new issue