diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2020-10-17 20:12:00 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-17 20:12:00 +0900 |
| commit | 7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a (patch) | |
| tree | 2263a06acec7fa21882366bae26d1a983ce21135 /src/client/pages/timeline.vue | |
| parent | CW の input でも投稿ショートカットが動作するように (#6690) (diff) | |
| download | misskey-7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a.tar.gz misskey-7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a.tar.bz2 misskey-7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a.zip | |
Migrate to Vue3 (#6587)
* Update reaction.vue
* fix bug
* wip
* wip
* wjio
* wip
* Revert "wip"
This reverts commit e427f2160adf4e8a4147006e25a89854edab0033.
* wip
* wip
* wip
* Update init.ts
* Update drive-window.vue
* wip
* wip
* Use PascalCase for components
* Use PascalCase for components
* update dep
* wip
* wip
* wip
* Update init.ts
* wip
* Update paging.ts
* Update test.vue
* watch deep
* wip
* lint
* wip
* wip
* wip
* wip
* wiop
* wip
* Update webpack.config.ts
* alllow null poll
* wip
* wip
* wip
* wiop
* UI redesign & refactor (#6714)
* wip
* wip
* wip
* wip
* wip
* Update drive.vue
* Update word-mute.vue
* wip
* wip
* wip
* clean up
* wip
* Update default.vue
* wip
* Update notes.vue
* Update mfm.ts
* Update index.home.vue
* Update post-form.vue
* Update post-form-attaches.vue
* wip
* Update post-form.vue
* Update sidebar.vue
* wip
* wip
* Update index.vue
* wip
* Update default.vue
* Update index.vue
* Update index.vue
* wip
* Update post-form-attaches.vue
* Update note.vue
* wip
* clean up
* Update notes.vue
* wip
* wip
* Update ja-JP.yml
* wip
* wip
* Update index.vue
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* Update default.vue
* wip
* Update _dark.json5
* wip
* wip
* wip
* clean up
* wip
* wip
* Update index.vue
* Update test.vue
* wip
* wip
* fix
* wip
* wip
* wip
* wip
* clena yop
* wip
* wip
* Update store.ts
* Update messaging-room.vue
* Update default.widgets.vue
* fix
* wip
* wip
* Update modal.vue
* wip
* Update os.ts
* Update os.ts
* Update deck.vue
* Update init.ts
* wip
* Update ja-JP.yml
* v-sizeは単にwindowのresizeを監視するだけで良いかもしれない
* Update modal.vue
* wip
* Update tooltip.ts
* wip
* wip
* wip
* wip
* wip
* Update image-viewer.vue
* wip
* wip
* Update style.scss
* Update style.scss
* Update visitor.vue
* wip
* Update init.ts
* Update init.ts
* wip
* wip
* Update visitor.vue
* Update visitor.vue
* Update visitor.vue
* Update visitor.vue
* wip
* wip
* Update modal.vue
* Update header.vue
* Update menu.vue
* Update about.vue
* Update about-misskey.vue
* wip
* wip
* Update visitor.vue
* Update tooltip.ts
* wip
* Update drive.vue
* wip
* Update style.scss
* Update header.vue
* wip
* wip
* Update users.user.vue
* Update announcements.vue
* wip
* wip
* wip
* Update emojis.vue
* wip
* Update emojis.vue
* Update style.scss
* Update users.vue
* wip
* Update style.scss
* wip
* Update welcome.entrance.vue
* Update radio.vue
* Update size.ts
* Update emoji-edit-dialog.vue
* wip
* Update emojis.vue
* wip
* Update emojis.vue
* Update emojis.vue
* Update emojis.vue
* wip
* wip
* wip
* wip
* Update file-dialog.vue
* wip
* wip
* Update token-generate-window.vue
* Update notification-setting-window.vue
* wip
* wip
* Update _error_.vue
* Update ja-JP.yml
* wip
* wip
* Update store.ts
* Update emojis.vue
* Update emojis.vue
* Update emojis.vue
* Update announcements.vue
* Update store.ts
* wip
* Update page-editor.vue
* wip
* wip
* Update modal.vue
* wip
* Update select-file.ts
* Update timeline.vue
* Update emojis.vue
* Update os.ts
* wip
* Update user-select.vue
* Update mfm.ts
* Update get-file-info.ts
* Update drive.vue
* Update init.ts
* Update mfm.ts
* wip
* wip
* Update window.vue
* Update note.vue
* wip
* wip
* Update user-info.vue
* wip
* wip
* wip
* wip
* wip
* Update header.vue
* Update header.vue
* wip
* Update explore.vue
* wip
* wip
* wip
* Update webpack.config.ts
* wip
* wip
* wip
* wip
* wip
* wip
* Update autocomplete.ts
* wip
* wip
* wip
* Update toast.vue
* wip
* Update post-form-dialog.vue
* wip
* wip
* wip
* wip
* wip
* Update users.vue
* wip
* Update explore.vue
* wip
* wip
* wip
* Update package.json
* wip
* Update icon-dialog.vue
* wip
* wip
* Update user-preview.ts
* wip
* wip
* wip
* wip
* wip
* Update instance.vue
* Update user-name.vue
* Update federation.vue
* Update instance.vue
* wip
* wip
* Update tag.vue
* wip
* wip
* wip
* wip
* wip
* Update instance.vue
* wip
* Update os.ts
* Update os.ts
* wip
* wip
* wip
* Update router.ts
* wip
* Update init.ts
* Update note.vue
* Update messages.vue
* wip
* wip
* wip
* wip
* wip
* google
* wip
* wip
* wip
* wip
* Update theme-editor.vue
* wip
* wip
* Update room.vue
* Update channel-editor.vue
* wip
* Update window.vue
* Update window.vue
* wip
* Update window.vue
* Update window.vue
* wip
* Update menu.vue
* wip
* wip
* wip
* wip
* Update messaging-room.vue
* wip
* Update post-form.vue
* Update default.widgets.vue
* Update window.vue
* wip
Diffstat (limited to 'src/client/pages/timeline.vue')
| -rw-r--r-- | src/client/pages/timeline.vue | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/client/pages/timeline.vue b/src/client/pages/timeline.vue new file mode 100644 index 0000000000..a15d57e37e --- /dev/null +++ b/src/client/pages/timeline.vue @@ -0,0 +1,239 @@ +<template> +<div class="mk-home" v-hotkey.global="keymap"> + <div class="new" v-if="queue > 0" :style="{ width: width + 'px' }"><button class="_buttonPrimary" @click="top()">{{ $t('newNoteRecived') }}</button></div> + + <div class="_section"> + <XTutorial v-if="$store.state.settings.tutorial != -1" class="tutorial _content _vMargin"/> + <XPostForm v-if="$store.state.device.showFixedPostForm" class="post-form _panel _content _vMargin" fixed/> + <XTimeline ref="tl" + class="_content _vMargin" + :key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src" + :src="src" + :list="list ? list.id : null" + :antenna="antenna ? antenna.id : null" + :channel="channel ? channel.id : null" + :sound="true" + @before="before()" + @after="after()" + @queue="queueUpdated" + /> + </div> +</div> +</template> + +<script lang="ts"> +import { defineComponent, defineAsyncComponent, computed } from 'vue'; +import { faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faListUl, faSatellite, faSatelliteDish, faCircle, faEllipsisH, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; +import { faComments } from '@fortawesome/free-regular-svg-icons'; +import Progress from '@/scripts/loading'; +import XTimeline from '@/components/timeline.vue'; +import XPostForm from '@/components/post-form.vue'; +import { scroll } from '@/scripts/scroll'; +import * as os from '@/os'; + +export default defineComponent({ + name: 'timeline', + + components: { + XTimeline, + XTutorial: defineAsyncComponent(() => import('./timeline.tutorial.vue')), + XPostForm, + }, + + data() { + return { + src: 'home', + list: null, + antenna: null, + channel: null, + menuOpened: false, + queue: 0, + width: 0, + INFO: { + header: [{ + id: 'home', + title: null, + tooltip: this.$t('_timelines.home'), + icon: faHome, + onClick: () => { this.src = 'home'; this.saveSrc(); }, + selected: computed(() => this.src === 'home') + }, { + id: 'local', + title: null, + tooltip: this.$t('_timelines.local'), + icon: faComments, + onClick: () => { this.src = 'local'; this.saveSrc(); }, + selected: computed(() => this.src === 'local') + }, { + id: 'social', + title: null, + tooltip: this.$t('_timelines.social'), + icon: faShareAlt, + onClick: () => { this.src = 'social'; this.saveSrc(); }, + selected: computed(() => this.src === 'social') + }, { + id: 'global', + title: null, + tooltip: this.$t('_timelines.global'), + icon: faGlobe, + onClick: () => { this.src = 'global'; this.saveSrc(); }, + selected: computed(() => this.src === 'global') + }, { + id: 'other', + title: null, + icon: faEllipsisH, + onClick: this.choose, + indicate: computed(() => this.$store.state.i.hasUnreadAntenna || this.$store.state.i.hasUnreadChannel) + }], + action: { + icon: faPencilAlt, + handler: () => os.post() + } + }, + faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faSatelliteDish, faCircle + }; + }, + + computed: { + keymap(): any { + return { + 't': this.focus + }; + }, + + meta() { + return this.$store.state.instance.meta; + }, + }, + + watch: { + src() { + 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() { + this.src = this.$store.state.deviceUser.tl.src; + if (this.src === 'list') { + this.list = this.$store.state.deviceUser.tl.arg; + } else if (this.src === 'antenna') { + this.antenna = this.$store.state.deviceUser.tl.arg; + } else if (this.src === 'channel') { + this.channel = this.$store.state.deviceUser.tl.arg; + } + }, + + mounted() { + this.width = this.$el.offsetWidth; + }, + + methods: { + before() { + Progress.start(); + }, + + after() { + Progress.done(); + }, + + queueUpdated(q) { + if (this.$el.offsetWidth !== 0) this.width = this.$el.offsetWidth; + this.queue = q; + }, + + top() { + scroll(this.$el, 0); + }, + + async choose(ev) { + if (this.meta == null) return; + const [antennas, lists, channels] = await Promise.all([ + os.api('antennas/list'), + os.api('users/lists/list'), + os.api('channels/followed'), + ]); + const antennaItems = antennas.map(antenna => ({ + text: antenna.name, + icon: faSatellite, + indicate: antenna.hasUnreadNote, + action: () => { + this.antenna = antenna; + this.src = 'antenna'; + this.saveSrc(); + } + })); + const listItems = lists.map(list => ({ + text: list.name, + icon: faListUl, + action: () => { + this.list = list; + this.src = 'list'; + this.saveSrc(); + } + })); + const channelItems = channels.map(channel => ({ + text: channel.name, + icon: faSatelliteDish, + indicate: channel.hasUnreadNote, + action: () => { + // NOTE: チャンネルタイムラインをこのコンポーネントで表示するようにすると投稿フォームはどうするかなどの問題が生じるのでとりあえずページ遷移で + //this.channel = channel; + //this.src = 'channel'; + //this.saveSrc(); + this.$router.push(`/channels/${channel.id}`); + } + })); + os.modalMenu([...antennaItems, listItems.length > 0 ? null : undefined, ...listItems, channelItems.length > 0 ? null : undefined, ...channelItems], ev.currentTarget || ev.target); + }, + + saveSrc() { + this.$store.commit('deviceUser/setTl', { + src: this.src, + arg: + this.src === 'list' ? this.list : + this.src === 'antenna' ? this.antenna : + this.channel + }); + }, + + focus() { + (this.$refs.tl as any).focus(); + } + } +}); +</script> + +<style lang="scss" scoped> +.mk-home { + > .new { + position: fixed; + z-index: 1000; + + > button { + display: block; + margin: var(--margin) auto 0 auto; + padding: 8px 16px; + border-radius: 32px; + } + } + + > ._section { + + } +} +</style> |