Fix errors in Vue3

This commit is contained in:
AkiraFukushima 2022-04-19 21:05:32 +09:00
parent 95242cf758
commit 218cb96c3a
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
24 changed files with 724 additions and 1807 deletions

View File

@ -4,12 +4,8 @@
<el-header>
<el-row>
<el-col :span="24" class="close">
<el-button
type="text"
:icon="ElIconClose"
@click="close"
class="close-button"
>
<el-button type="text" @click="close" class="close-button">
<font-awesome-icon icon="x-mark"></font-awesome-icon>
</el-button>
</el-col>
</el-row>
@ -37,12 +33,7 @@
<el-input></el-input>
</el-form-item>
<el-form-item class="submit">
<el-button
type="primary"
@click="authorizeSubmit"
v-loading="submitting"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
<el-button type="primary" @click="authorizeSubmit" v-loading="submitting" element-loading-background="rgba(0, 0, 0, 0.8)">
{{ $t('authorize.submit') }}
</el-button>
</el-form-item>
@ -53,27 +44,25 @@
</template>
<script>
import { Close as ElIconClose } from '@element-plus/icons'
export default {
data() {
return {
authorizeForm: {
code: null,
code: null
},
submitting: false,
ElIconClose,
submitting: false
}
},
name: 'authorize',
props: {
url: {
type: String,
default: '',
default: ''
},
sns: {
type: String,
default: 'mastodon',
},
default: 'mastodon'
}
},
mounted() {
console.log(this.url)
@ -84,32 +73,32 @@ export default {
this.$store
.dispatch('Authorize/submit', {
code: this.authorizeForm.code,
sns: this.sns,
sns: this.sns
})
.finally(() => {
this.submitting = false
})
.then((id) => {
.then(id => {
this.$router.push({ path: `/${id}/home` })
})
.catch((err) => {
.catch(err => {
if (err.name === 'DuplicateRecordError') {
this.$message({
message: this.$t('message.authorize_duplicate_error'),
type: 'error',
type: 'error'
})
} else {
this.$message({
message: this.$t('message.authorize_error'),
type: 'error',
type: 'error'
})
}
})
},
close() {
return this.$router.push({ path: '/', query: { redirect: 'home' } })
},
},
}
}
}
</script>

View File

@ -18,13 +18,13 @@
v-bind:key="account._id"
role="menuitem"
>
<el-icon v-if="account.avatar === undefined || account.avatar === null || account.avatar === ''"><el-icon-menu /></el-icon>
<font-awesome-icon icon="circle-user" v-if="account.avatar === undefined || account.avatar === null || account.avatar === ''" />
<FailoverImg v-else :src="account.avatar" class="avatar" :title="account.username + '@' + account.domain" />
<FailoverImg :src="`${account.baseURL}/favicon.ico`" :failoverSrc="`${account.baseURL}/favicon.png`" class="instance-icon" />
<span slot="title">{{ account.domain }}</span>
</el-menu-item>
<el-menu-item index="/login" :title="$t('global_header.add_new_account')" role="menuitem">
<el-icon><el-icon-plus /></el-icon>
<font-awesome-icon icon="plus" />
<span slot="new">New</span>
</el-menu-item>
</el-menu>
@ -35,16 +35,13 @@
</template>
<script>
import { Menu as ElIconMenu, Plus as ElIconPlus } from '@element-plus/icons'
import { mapState } from 'vuex'
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
import { StreamingError } from '~/src/errors/streamingError'
export default {
components: {
FailoverImg,
ElIconMenu,
ElIconPlus
FailoverImg
},
name: 'global-header',
computed: {

View File

@ -3,7 +3,9 @@
<el-header>
<el-row>
<el-col :span="24" class="close">
<el-button type="text" :icon="ElIconClose" @click="close" class="close-button"> </el-button>
<el-button type="text" @click="close" class="close-button">
<font-awesome-icon icon="xmark" />
</el-button>
</el-col>
</el-row>
</el-header>
@ -15,16 +17,10 @@
</template>
<script>
import { Close as ElIconClose } from '@element-plus/icons'
import LoginForm from './Login/LoginForm'
import { mapState } from 'vuex'
export default {
data() {
return {
ElIconClose
}
},
name: 'login',
components: { LoginForm },
computed: {

View File

@ -6,13 +6,9 @@
<h1>{{ $t('preferences.title') }}</h1>
</el-col>
<el-col :span="1">
<el-button
type="text"
:icon="ElIconClose"
@click="close"
class="close-button"
role="button"
></el-button>
<el-button type="text" @click="close" class="close-button" role="button">
<font-awesome-icon icon="xmark" />
</el-button>
</el-col>
</el-row>
</el-header>
@ -60,21 +56,15 @@
</template>
<script>
import { Close as ElIconClose } from '@element-plus/icons'
import { mapState } from 'vuex'
export default {
data() {
return {
ElIconClose,
}
},
name: 'preferences',
computed: {
...mapState({
primaryColor: (state) => state.App.theme.primary_color,
backgroundColor: (state) => state.App.theme.background_color,
}),
primaryColor: state => state.App.theme.primary_color,
backgroundColor: state => state.App.theme.background_color
})
},
methods: {
close() {
@ -82,8 +72,8 @@ export default {
},
activeRoute() {
return this.$route.path
},
},
}
}
}
</script>

View File

@ -17,7 +17,7 @@
<el-table-column :label="$t('preferences.account.association')">
<template #default="scope">
<el-button @click.prevent="removeAccount(scope.$index, accounts)" type="text" class="action">
<el-icon><el-icon-close /></el-icon>
<font-awesome-icon icon="xmark" />
{{ $t('preferences.account.remove_association') }}
</el-button>
</template>
@ -25,20 +25,14 @@
<el-table-column :label="$t('preferences.account.order')" width="60">
<template #default="scope">
<div class="allow-up">
<el-button
class="arrow-up action"
type="text"
:icon="ElIconArrowUp"
@click.prevent="forward(scope.$index, accounts)"
></el-button>
<el-button class="arrow-up action" type="text" @click.prevent="forward(scope.$index, accounts)">
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
<div class="allow-down">
<el-button
class="arrow-down action"
type="text"
:icon="ElIconArrowDown"
@click.prevent="backward(scope.$index, accounts)"
></el-button>
<el-button class="arrow-down action" type="text" @click.prevent="backward(scope.$index, accounts)">
<font-awesome-icon icon="arrow-down" />
</el-button>
</div>
</template>
</el-table-column>
@ -59,21 +53,15 @@
</template>
<script>
import { Close as ElIconClose, ArrowUp as ElIconArrowUp, ArrowDown as ElIconArrowDown } from '@element-plus/icons'
import { mapState } from 'vuex'
export default {
data() {
return {
openRemoveDialog: false,
deletePopoverVisible: false,
ElIconArrowUp,
ElIconArrowDown
deletePopoverVisible: false
}
},
components: {
ElIconClose
},
name: 'account',
computed: {
...mapState({

View File

@ -6,13 +6,9 @@
<h1>{{ $t('settings.title') }}</h1>
</el-col>
<el-col :span="1">
<el-button
type="text"
:icon="ElIconClose"
@click="close"
class="close-button"
role="button"
></el-button>
<el-button type="text" @click="close" class="close-button" role="button">
<font-awesome-icon icon="xmark" />
</el-button>
</el-col>
</el-row>
</el-header>
@ -48,21 +44,15 @@
</template>
<script>
import { Close as ElIconClose } from '@element-plus/icons'
import { mapState } from 'vuex'
export default {
data() {
return {
ElIconClose,
}
},
name: 'Settings',
computed: {
...mapState({
primaryColor: (state) => state.App.theme.primary_color,
backgroundColor: (state) => state.App.theme.background_color,
}),
primaryColor: state => state.App.theme.primary_color,
backgroundColor: state => state.App.theme.background_color
})
},
created() {
this.$store.commit('Settings/changeAccountID', this.id())
@ -77,8 +67,8 @@ export default {
},
activeRoute() {
return this.$route.path
},
},
}
}
}
</script>

View File

@ -1,28 +1,9 @@
<template>
<div
id="bookmarks"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="bookmarks"
:min-item-size="60"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="bookmarks" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="bookmarks" :min-item-size="60" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri === focusedId"
@ -38,18 +19,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import Toot from '@/components/organisms/Toot'
import reloadable from '~/src/renderer/components/mixins/reloadable'
@ -59,8 +37,7 @@ export default {
data() {
return {
heading: true,
focusedId: null,
ElIconArrowUp,
focusedId: null
}
},
name: 'bookmarks',
@ -68,25 +45,25 @@ export default {
mixins: [reloadable],
computed: {
...mapState('TimelineSpace', {
account: (state) => state.account,
account: state => state.account
}),
...mapState('App', {
backgroundColor: (state) => state.theme.background_color,
backgroundColor: state => state.theme.background_color
}),
...mapState('TimelineSpace/HeaderMenu', {
startReload: (state) => state.reload,
startReload: state => state.reload
}),
...mapState('TimelineSpace/Contents/SideBar', {
openSideBar: (state) => state.openSideBar,
openSideBar: state => state.openSideBar
}),
...mapState('TimelineSpace/Contents/Bookmarks', {
bookmarks: (state) => state.bookmarks,
lazyLoading: (state) => state.lazyLoading,
bookmarks: state => state.bookmarks,
lazyLoading: state => state.lazyLoading
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
return !this.focusedId && !this.modalOpened
},
}
},
created() {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
@ -95,7 +72,7 @@ export default {
.catch(() => {
this.$message({
message: this.$t('message.bookmark_fetch_error'),
type: 'error',
type: 'error'
})
})
.finally(() => {
@ -103,9 +80,7 @@ export default {
})
},
mounted() {
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
const previousFocusedId = this.focusedId
@ -120,13 +95,8 @@ export default {
},
destroyed() {
this.$store.commit('TimelineSpace/Contents/Bookmarks/updateBookmarks', [])
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -144,7 +114,7 @@ export default {
} else if (newState === null && !this.heading) {
this.heading = true
}
},
}
},
methods: {
updateToot(message) {
@ -155,21 +125,15 @@ export default {
},
onScroll(event) {
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/Bookmarks/lazyFetchBookmarks',
this.bookmarks[this.bookmarks.length - 1]
)
.catch(() => {
this.$message({
message: this.$t('message.bookmark_fetch_error'),
type: 'error',
})
this.$store.dispatch('TimelineSpace/Contents/Bookmarks/lazyFetchBookmarks', this.bookmarks[this.bookmarks.length - 1]).catch(() => {
this.$message({
message: this.$t('message.bookmark_fetch_error'),
type: 'error'
})
})
}
// for upper
if (event.target.scrollTop > 10 && this.heading) {
@ -182,14 +146,12 @@ export default {
this.$store.commit('TimelineSpace/changeLoading', true)
try {
const account = await this.reloadable()
await this.$store
.dispatch('TimelineSpace/Contents/Bookmarks/fetchBookmarks', account)
.catch(() => {
this.$message({
message: this.$t('message.bookmark_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Bookmarks/fetchBookmarks', account).catch(() => {
this.$message({
message: this.$t('message.bookmark_fetch_error'),
type: 'error'
})
})
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
@ -199,9 +161,7 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.bookmarks.findIndex(
(toot) => this.focusedId === toot.uri
)
const currentIndex = this.bookmarks.findIndex(toot => this.focusedId === toot.uri)
if (currentIndex === -1) {
this.focusedId = this.bookmarks[0].uri
} else if (currentIndex < this.bookmarks.length) {
@ -209,9 +169,7 @@ export default {
}
},
focusPrev() {
const currentIndex = this.bookmarks.findIndex(
(toot) => this.focusedId === toot.uri
)
const currentIndex = this.bookmarks.findIndex(toot => this.focusedId === toot.uri)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
@ -230,8 +188,8 @@ export default {
this.focusedId = this.bookmarks[0].uri
break
}
},
},
}
}
}
</script>

View File

@ -1,28 +1,9 @@
<template>
<div
id="directmessages"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="timeline"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="directmessages" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri + item.id === focusedId"
@ -40,18 +21,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Toot from '~/src/renderer/components/organisms/Toot'
@ -66,8 +44,7 @@ export default {
scrollPosition: null,
observer: null,
scrollTime: null,
resizeTime: null,
ElIconArrowUp,
resizeTime: null
}
},
name: 'directmessages',
@ -75,17 +52,16 @@ export default {
mixins: [reloadable],
computed: {
...mapState('TimelineSpace/Contents/DirectMessages', {
timeline: (state) => state.timeline,
lazyLoading: (state) => state.lazyLoading,
heading: (state) => state.heading,
scrolling: (state) => state.scrolling,
timeline: state => state.timeline,
lazyLoading: state => state.lazyLoading,
heading: state => state.heading,
scrolling: state => state.scrolling
}),
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: (state) => state.App.theme.background_color,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
unreadNotification: (state) =>
state.TimelineSpace.timelineSetting.unreadNotification,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: state => state.App.theme.background_color,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
unreadNotification: state => state.TimelineSpace.timelineSetting.unreadNotification
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
@ -96,23 +72,16 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1
},
}
},
async mounted() {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline',
false
)
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
this.$store.commit('TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline', false)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
if (!this.unreadNotification.direct) {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
await this.initialize().finally((_) => {
await this.initialize().finally(_ => {
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
})
}
@ -130,31 +99,18 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling
) {
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
if (
this.$store.state.TimelineSpace.SideMenu.unreadDirectMessagesTimeline &&
this.heading
) {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline',
false
)
if (this.$store.state.TimelineSpace.SideMenu.unreadDirectMessagesTimeline && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline', false)
}
if (this.scrollPosition) {
this.scrollPosition.prepare()
@ -169,21 +125,13 @@ export default {
this.observer.disconnect()
},
destroyed() {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/DirectMessages/archiveTimeline')
if (!this.unreadNotification.direct) {
this.$store.commit('TimelineSpace/Contents/DirectMessages/clearTimeline')
}
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -197,28 +145,20 @@ export default {
},
focusedId: function (newState, _oldState) {
if (newState && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', false)
} else if (newState === null && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', true)
}
},
}
},
methods: {
async initialize() {
await this.$store
.dispatch('TimelineSpace/Contents/DirectMessages/fetchTimeline')
.catch((_) => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/DirectMessages/fetchTimeline').catch(_ => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error'
})
})
await this.$store.dispatch('TimelineSpace/bindDirectMessagesStreaming')
this.$store.dispatch('TimelineSpace/startDirectMessagesStreaming')
},
@ -228,82 +168,54 @@ export default {
}
this.scrollTime = moment()
if (!this.scrolling) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', true)
}
// for lazyLoading
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/DirectMessages/lazyFetchTimeline',
this.timeline[this.timeline.length - 1]
)
.then((statuses) => {
.dispatch('TimelineSpace/Contents/DirectMessages/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', false)
} else if (event.target.scrollTop <= 10 && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', true)
}
setTimeout(() => {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', false)
}
}, 150)
},
updateToot(message) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/updateToot',
message
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/updateToot', message)
},
deleteToot(message) {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/deleteToot',
message.id
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/deleteToot', message.id)
},
async reload() {
this.$store.commit('TimelineSpace/changeLoading', true)
@ -318,27 +230,19 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id
} else if (currentIndex < this.timeline.length) {
this.focusedId =
this.timeline[currentIndex + 1].uri +
this.timeline[currentIndex + 1].id
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
}
},
focusPrev() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
this.focusedId =
this.timeline[currentIndex - 1].uri +
this.timeline[currentIndex - 1].id
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
}
},
focusToot(message) {
@ -355,18 +259,12 @@ export default {
}
},
sizeChanged() {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/DirectMessages/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,28 +1,9 @@
<template>
<div
id="favourites"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="favourites"
:min-item-size="60"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="favourites" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="favourites" :min-item-size="60" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri === focusedId"
@ -39,18 +20,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import Toot from '~/src/renderer/components/organisms/Toot'
import reloadable from '~/src/renderer/components/mixins/reloadable'
@ -60,8 +38,7 @@ export default {
data() {
return {
heading: true,
focusedId: null,
ElIconArrowUp,
focusedId: null
}
},
name: 'favourites',
@ -69,30 +46,26 @@ export default {
mixins: [reloadable],
computed: {
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: (state) => state.App.theme.background_color,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
account: (state) => state.TimelineSpace.account,
favourites: (state) => state.TimelineSpace.Contents.Favourites.favourites,
lazyLoading: (state) =>
state.TimelineSpace.Contents.Favourites.lazyLoading,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: state => state.App.theme.background_color,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
account: state => state.TimelineSpace.account,
favourites: state => state.TimelineSpace.Contents.Favourites.favourites,
lazyLoading: state => state.TimelineSpace.Contents.Favourites.lazyLoading
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
return !this.focusedId && !this.modalOpened
},
}
},
created() {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
this.$store
.dispatch(
'TimelineSpace/Contents/Favourites/fetchFavourites',
this.account
)
.dispatch('TimelineSpace/Contents/Favourites/fetchFavourites', this.account)
.catch(() => {
this.$message({
message: this.$t('message.favourite_fetch_error'),
type: 'error',
type: 'error'
})
})
.finally(() => {
@ -100,9 +73,7 @@ export default {
})
},
mounted() {
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
const previousFocusedId = this.focusedId
@ -117,13 +88,8 @@ export default {
},
destroyed() {
this.$store.commit('TimelineSpace/Contents/Favourites/updateFavourites', [])
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -141,36 +107,26 @@ export default {
} else if (newState === null && !this.heading) {
this.heading = true
}
},
}
},
methods: {
updateToot(message) {
this.$store.commit(
'TimelineSpace/Contents/Favourites/updateToot',
message
)
this.$store.commit('TimelineSpace/Contents/Favourites/updateToot', message)
},
deleteToot(message) {
this.$store.commit(
'TimelineSpace/Contents/Favourites/deleteToot',
message
)
this.$store.commit('TimelineSpace/Contents/Favourites/deleteToot', message)
},
onScroll(event) {
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/Favourites/lazyFetchFavourites',
this.favourites[this.favourites.length - 1]
)
.dispatch('TimelineSpace/Contents/Favourites/lazyFetchFavourites', this.favourites[this.favourites.length - 1])
.catch(() => {
this.$message({
message: this.$t('message.favourite_fetch_error'),
type: 'error',
type: 'error'
})
})
}
@ -185,17 +141,12 @@ export default {
this.$store.commit('TimelineSpace/changeLoading', true)
try {
const account = await this.reloadable()
await this.$store
.dispatch(
'TimelineSpace/Contents/Favourites/fetchFavourites',
account
)
.catch(() => {
this.$message({
message: this.$t('message.favourite_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Favourites/fetchFavourites', account).catch(() => {
this.$message({
message: this.$t('message.favourite_fetch_error'),
type: 'error'
})
})
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
@ -205,9 +156,7 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.favourites.findIndex(
(toot) => this.focusedId === toot.uri
)
const currentIndex = this.favourites.findIndex(toot => this.focusedId === toot.uri)
if (currentIndex === -1) {
this.focusedId = this.favourites[0].uri
} else if (currentIndex < this.favourites.length) {
@ -215,9 +164,7 @@ export default {
}
},
focusPrev() {
const currentIndex = this.favourites.findIndex(
(toot) => this.focusedId === toot.uri
)
const currentIndex = this.favourites.findIndex(toot => this.focusedId === toot.uri)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
@ -236,8 +183,8 @@ export default {
this.focusedId = this.favourites[0].uri
break
}
},
},
}
}
}
</script>

View File

@ -1,29 +1,9 @@
<template>
<div
name="tag"
class="tag-timeline"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="timeline"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div name="tag" class="tag-timeline" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri + item.id === focusedId"
@ -41,18 +21,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Toot from '~/src/renderer/components/organisms/Toot'
@ -67,8 +44,7 @@ export default {
scrollPosition: null,
observer: null,
scrollTime: null,
resizeTime: null,
ElIconArrowUp,
resizeTime: null
}
},
name: 'tag',
@ -77,14 +53,13 @@ export default {
props: ['tag'],
computed: {
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: (state) => state.App.theme.background_color,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
timeline: (state) => state.TimelineSpace.Contents.Hashtag.Tag.timeline,
lazyLoading: (state) =>
state.TimelineSpace.Contents.Hashtag.Tag.lazyLoading,
heading: (state) => state.TimelineSpace.Contents.Hashtag.Tag.heading,
scrolling: (state) => state.TimelineSpace.Contents.Hashtag.Tag.scrolling,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: state => state.App.theme.background_color,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
timeline: state => state.TimelineSpace.Contents.Hashtag.Tag.timeline,
lazyLoading: state => state.TimelineSpace.Contents.Hashtag.Tag.lazyLoading,
heading: state => state.TimelineSpace.Contents.Hashtag.Tag.heading,
scrolling: state => state.TimelineSpace.Contents.Hashtag.Tag.scrolling
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
@ -95,20 +70,16 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1
},
}
},
mounted() {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
this.load(this.tag).finally(() => {
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
})
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
@ -123,20 +94,13 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling
) {
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
@ -161,17 +125,11 @@ export default {
},
focusedId: function (newState, _oldState) {
if (newState && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false)
} else if (newState === null && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
}
},
}
},
beforeDestroy() {
this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/stopStreaming')
@ -181,38 +139,26 @@ export default {
},
methods: {
async load(tag) {
await this.$store
.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag)
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag).catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error'
})
this.$store
.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag)
.catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error',
})
})
this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag).catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error'
})
})
return true
},
reset() {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/archiveTimeline')
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/clearTimeline')
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -220,10 +166,7 @@ export default {
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/updateToot', toot)
},
deleteToot(toot) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/deleteToot',
toot.id
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/deleteToot', toot.id)
},
onScroll(event) {
if (moment().diff(this.resizeTime) < 500) {
@ -231,67 +174,48 @@ export default {
}
this.scrollTime = moment()
if (!this.scrolling) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', true)
}
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch('TimelineSpace/Contents/Hashtag/Tag/lazyFetchTimeline', {
tag: this.tag,
status: this.timeline[this.timeline.length - 1],
status: this.timeline[this.timeline.length - 1]
})
.then((statuses) => {
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false)
} else if (event.target.scrollTop <= 10 && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
}
setTimeout(() => {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', false)
}
}, 150)
},
@ -300,25 +224,19 @@ export default {
this.$store.commit('TimelineSpace/changeLoading', true)
try {
await this.reloadable()
await this.$store.dispatch(
'TimelineSpace/Contents/Hashtag/Tag/stopStreaming'
)
await this.$store
.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag)
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/stopStreaming')
await this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag).catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error'
})
this.$store
.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag)
.catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error',
})
})
this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag).catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error'
})
})
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
@ -328,27 +246,19 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id
} else if (currentIndex < this.timeline.length) {
this.focusedId =
this.timeline[currentIndex + 1].uri +
this.timeline[currentIndex + 1].id
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
}
},
focusPrev() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
this.focusedId =
this.timeline[currentIndex - 1].uri +
this.timeline[currentIndex - 1].id
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
}
},
focusToot(message) {
@ -365,18 +275,12 @@ export default {
}
},
sizeChanged() {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,45 +1,15 @@
<template>
<div
id="home"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="filteredTimeline"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="home" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="filteredTimeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<template v-if="item.id === 'loading-card'">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.id]"
:data-index="index"
:watchData="true"
>
<StatusLoading
:since_id="item.since_id"
:max_id="item.max_id"
:loading="loadingMore"
@load_since="fetchTimelineSince"
/>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.id]" :data-index="index" :watchData="true">
<StatusLoading :since_id="item.since_id" :max_id="item.max_id" :loading="loadingMore" @load_since="fetchTimelineSince" />
</DynamicScrollerItem>
</template>
<template v-else>
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri + item.id === focusedId"
@ -59,18 +29,15 @@
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Toot from '~/src/renderer/components/organisms/Toot'
@ -87,8 +54,7 @@ export default {
observer: null,
scrollTime: null,
resizeTime: null,
loadingMore: false,
ElIconArrowUp,
loadingMore: false
}
},
name: 'home',
@ -96,17 +62,17 @@ export default {
mixins: [reloadable],
computed: {
...mapState('TimelineSpace/Contents/Home', {
timeline: (state) => state.timeline,
lazyLoading: (state) => state.lazyLoading,
heading: (state) => state.heading,
showReblogs: (state) => state.showReblogs,
showReplies: (state) => state.showReplies,
scrolling: (state) => state.scrolling,
timeline: state => state.timeline,
lazyLoading: state => state.lazyLoading,
heading: state => state.heading,
showReblogs: state => state.showReblogs,
showReplies: state => state.showReplies,
scrolling: state => state.scrolling
}),
...mapState({
backgroundColor: (state) => state.App.theme.background_color,
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
backgroundColor: state => state.App.theme.background_color,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
startReload: state => state.TimelineSpace.HeaderMenu.reload
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
...mapGetters('TimelineSpace/Contents/Home', ['filters']),
@ -118,13 +84,11 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1
},
filteredTimeline() {
return this.timeline.filter((toot) => {
return this.timeline.filter(toot => {
if (toot.in_reply_to_id) {
return this.showReplies
} else if (toot.reblog) {
@ -133,13 +97,11 @@ export default {
return true
}
})
},
}
},
mounted() {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false)
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
const previousFocusedId = this.focusedId
@ -157,32 +119,18 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.loadingMore ||
(this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling)
) {
if (this.loadingMore || (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling)) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
if (
this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline &&
this.heading
) {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadHomeTimeline',
false
)
if (this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false)
}
if (this.scrollPosition) {
this.scrollPosition.prepare()
@ -195,13 +143,8 @@ export default {
destroyed() {
this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Home/archiveTimeline')
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -224,7 +167,7 @@ export default {
if (this.heading && newState.length > 0) {
this.$store.dispatch('TimelineSpace/Contents/Home/saveMarker')
}
},
}
},
methods: {
onScroll(event) {
@ -238,36 +181,26 @@ export default {
// for lazyLoading
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/Home/lazyFetchTimeline',
this.timeline[this.timeline.length - 1]
)
.then((statuses) => {
.dispatch('TimelineSpace/Contents/Home/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Home/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Home/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
@ -282,10 +215,7 @@ export default {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Home/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', false)
}
}, 150)
},
@ -297,13 +227,11 @@ export default {
},
fetchTimelineSince(since_id) {
this.loadingMore = true
this.$store
.dispatch('TimelineSpace/Contents/Home/fetchTimelineSince', since_id)
.finally(() => {
setTimeout(() => {
this.loadingMore = false
}, 500)
})
this.$store.dispatch('TimelineSpace/Contents/Home/fetchTimelineSince', since_id).finally(() => {
setTimeout(() => {
this.loadingMore = false
}, 500)
})
},
async reload() {
this.$store.commit('TimelineSpace/changeLoading', true)
@ -318,27 +246,19 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id
} else if (currentIndex < this.timeline.length) {
this.focusedId =
this.timeline[currentIndex + 1].uri +
this.timeline[currentIndex + 1].id
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
}
},
focusPrev() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
this.focusedId =
this.timeline[currentIndex - 1].uri +
this.timeline[currentIndex - 1].id
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
}
},
focusToot(message) {
@ -359,8 +279,8 @@ export default {
setTimeout(() => {
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,29 +1,9 @@
<template>
<div
name="list"
class="list-timeline"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="timeline"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div name="list" class="list-timeline" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri + item.id === focusedId"
@ -41,18 +21,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Toot from '~/src/renderer/components/organisms/Toot'
@ -67,8 +44,7 @@ export default {
scrollPosition: null,
observer: null,
scrollTime: null,
resizeTime: null,
ElIconArrowUp,
resizeTime: null
}
},
name: 'list',
@ -77,14 +53,13 @@ export default {
mixins: [reloadable],
computed: {
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: (state) => state.App.theme.background_color,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
timeline: (state) => state.TimelineSpace.Contents.Lists.Show.timeline,
lazyLoading: (state) =>
state.TimelineSpace.Contents.Lists.Show.lazyLoading,
heading: (state) => state.TimelineSpace.Contents.Lists.Show.heading,
scrolling: (state) => state.TimelineSpace.Contents.Lists.Show.scrolling,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: state => state.App.theme.background_color,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
timeline: state => state.TimelineSpace.Contents.Lists.Show.timeline,
lazyLoading: state => state.TimelineSpace.Contents.Lists.Show.lazyLoading,
heading: state => state.TimelineSpace.Contents.Lists.Show.heading,
scrolling: state => state.TimelineSpace.Contents.Lists.Show.scrolling
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
@ -95,11 +70,9 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1
},
}
},
created() {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
@ -108,9 +81,7 @@ export default {
})
},
mounted() {
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
const previousFocusedId = this.focusedId
@ -124,20 +95,13 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling
) {
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
@ -161,17 +125,11 @@ export default {
},
focusedId: function (newState, _oldState) {
if (newState && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', false)
} else if (newState === null && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', true)
}
},
}
},
beforeDestroy() {
this.$store.dispatch('TimelineSpace/Contents/Lists/Show/stopStreaming')
@ -181,56 +139,35 @@ export default {
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Lists/Show/archiveTimeline')
this.$store.commit('TimelineSpace/Contents/Lists/Show/clearTimeline')
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
methods: {
async load() {
await this.$store.dispatch(
'TimelineSpace/Contents/Lists/Show/stopStreaming'
)
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/stopStreaming')
try {
await this.$store.dispatch(
'TimelineSpace/Contents/Lists/Show/fetchTimeline',
this.list_id
)
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/fetchTimeline', this.list_id)
} catch (err) {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
}
this.$store
.dispatch(
'TimelineSpace/Contents/Lists/Show/startStreaming',
this.list_id
)
.catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error',
})
this.$store.dispatch('TimelineSpace/Contents/Lists/Show/startStreaming', this.list_id).catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error'
})
})
return 'started'
},
updateToot(message) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/updateToot',
message
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/updateToot', message)
},
deleteToot(message) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/deleteToot',
message.id
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/deleteToot', message.id)
},
onScroll(event) {
if (moment().diff(this.resizeTime) < 500) {
@ -238,67 +175,48 @@ export default {
}
this.scrollTime = moment()
if (!this.scrolling) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', true)
}
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch('TimelineSpace/Contents/Lists/Show/lazyFetchTimeline', {
list_id: this.list_id,
status: this.timeline[this.timeline.length - 1],
status: this.timeline[this.timeline.length - 1]
})
.then((statuses) => {
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', false)
} else if (event.target.scrollTop <= 10 && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', true)
}
setTimeout(() => {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', false)
}
}, 150)
},
@ -306,31 +224,19 @@ export default {
this.$store.commit('TimelineSpace/changeLoading', true)
try {
await this.reloadable()
await this.$store.dispatch(
'TimelineSpace/Contents/Lists/Show/stopStreaming'
)
await this.$store
.dispatch(
'TimelineSpace/Contents/Lists/Show/fetchTimeline',
this.list_id
)
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/stopStreaming')
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/fetchTimeline', this.list_id).catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error'
})
this.$store
.dispatch(
'TimelineSpace/Contents/Lists/Show/startStreaming',
this.list_id
)
.catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error',
})
})
this.$store.dispatch('TimelineSpace/Contents/Lists/Show/startStreaming', this.list_id).catch(() => {
this.$message({
message: this.$t('message.start_streaming_error'),
type: 'error'
})
})
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
@ -340,27 +246,19 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id
} else if (currentIndex < this.timeline.length) {
this.focusedId =
this.timeline[currentIndex + 1].uri +
this.timeline[currentIndex + 1].id
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
}
},
focusPrev() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
this.focusedId =
this.timeline[currentIndex - 1].uri +
this.timeline[currentIndex - 1].id
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
}
},
focusToot(message) {
@ -377,18 +275,12 @@ export default {
}
},
sizeChanged() {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Lists/Show/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,28 +1,9 @@
<template>
<div
id="local"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="timeline"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="local" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri + item.id === focusedId"
@ -40,18 +21,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Toot from '~/src/renderer/components/organisms/Toot'
@ -66,8 +44,7 @@ export default {
scrollPosition: null,
observer: null,
scrollTime: null,
resizeTime: null,
ElIconArrowUp,
resizeTime: null
}
},
name: 'local',
@ -75,16 +52,16 @@ export default {
mixins: [reloadable],
computed: {
...mapState('TimelineSpace/Contents/Local', {
timeline: (state) => state.timeline,
lazyLoading: (state) => state.lazyLoading,
heading: (state) => state.heading,
scrolling: (state) => state.scrolling,
timeline: state => state.timeline,
lazyLoading: state => state.lazyLoading,
heading: state => state.heading,
scrolling: state => state.scrolling
}),
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: (state) => state.App.theme.background_color,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
unreadNotification: (state) => state.TimelineSpace.unreadNotification,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: state => state.App.theme.background_color,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
unreadNotification: state => state.TimelineSpace.unreadNotification
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
@ -95,23 +72,16 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1
},
}
},
async mounted() {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadLocalTimeline',
false
)
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
this.$store.commit('TimelineSpace/SideMenu/changeUnreadLocalTimeline', false)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
if (!this.unreadNotification.local) {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
await this.initialize().finally((_) => {
await this.initialize().finally(_ => {
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
})
}
@ -129,31 +99,18 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling
) {
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
if (
this.$store.state.TimelineSpace.SideMenu.unreadLocalTimeline &&
this.heading
) {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadLocalTimeline',
false
)
if (this.$store.state.TimelineSpace.SideMenu.unreadLocalTimeline && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadLocalTimeline', false)
}
if (this.scrollPosition) {
this.scrollPosition.prepare()
@ -173,13 +130,8 @@ export default {
if (!this.unreadNotification.local) {
this.$store.commit('TimelineSpace/Contents/Local/clearTimeline')
}
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -197,18 +149,16 @@ export default {
} else if (newState === null && !this.heading) {
this.$store.commit('TimelineSpace/Contents/Local/changeHeading', true)
}
},
}
},
methods: {
async initialize() {
await this.$store
.dispatch('TimelineSpace/Contents/Local/fetchLocalTimeline')
.catch((_) => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Local/fetchLocalTimeline').catch(_ => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error'
})
})
await this.$store.dispatch('TimelineSpace/bindLocalStreaming')
this.$store.dispatch('TimelineSpace/startLocalStreaming')
},
@ -228,36 +178,26 @@ export default {
}
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/Local/lazyFetchTimeline',
this.timeline[this.timeline.length - 1]
)
.then((statuses) => {
.dispatch('TimelineSpace/Contents/Local/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Local/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Local/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
@ -271,10 +211,7 @@ export default {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Local/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', false)
}
}, 150)
},
@ -291,27 +228,19 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id
} else if (currentIndex < this.timeline.length) {
this.focusedId =
this.timeline[currentIndex + 1].uri +
this.timeline[currentIndex + 1].id
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
}
},
focusPrev() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
this.focusedId =
this.timeline[currentIndex - 1].uri +
this.timeline[currentIndex - 1].id
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
}
},
focusToot(message) {
@ -330,13 +259,10 @@ export default {
sizeChanged() {
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Local/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,45 +1,15 @@
<template>
<div
id="mentions"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="mentions"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="mentions" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="mentions" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<template v-if="item.id === 'loading-card'">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.id]"
:data-index="index"
:watchData="true"
>
<StatusLoading
:since_id="item.since_id"
:max_id="item.max_id"
:loading="loadingMore"
@load_since="fetchMentionsSince"
/>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.id]" :data-index="index" :watchData="true">
<StatusLoading :since_id="item.since_id" :max_id="item.max_id" :loading="loadingMore" @load_since="fetchMentionsSince" />
</DynamicScrollerItem>
</template>
<template v-else>
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.url]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.url]" :data-index="index" :watchData="true">
<notification
:message="item"
:focused="item.id === focusedId"
@ -57,18 +27,15 @@
</template>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Notification from '~/src/renderer/components/organisms/Notification'
@ -85,8 +52,7 @@ export default {
observer: null,
scrollTime: null,
resizeTime: null,
loadingMore: false,
ElIconArrowUp,
loadingMore: false
}
},
name: 'mentions',
@ -94,18 +60,18 @@ export default {
mixins: [reloadable],
computed: {
...mapState('App', {
backgroundColor: (state) => state.theme.background_color,
backgroundColor: state => state.theme.background_color
}),
...mapState('TimelineSpace/HeaderMenu', {
startReload: (state) => state.reload,
startReload: state => state.reload
}),
...mapState('TimelineSpace/Contents/SideBar', {
openSideBar: (state) => state.openSideBar,
openSideBar: state => state.openSideBar
}),
...mapState('TimelineSpace/Contents/Mentions', {
lazyLoading: (state) => state.lazyLoading,
heading: (state) => state.heading,
scrolling: (state) => state.scrolling,
lazyLoading: state => state.lazyLoading,
heading: state => state.heading,
scrolling: state => state.scrolling
}),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
...mapGetters('TimelineSpace/Contents/Mentions', ['mentions']),
@ -117,17 +83,13 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.mentions.findIndex(
(toot) => this.focusedId === toot.id
)
const currentIndex = this.mentions.findIndex(toot => this.focusedId === toot.id)
return currentIndex === -1
},
}
},
mounted() {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadMentions', false)
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
const previousFocusedId = this.focusedId
@ -145,28 +107,17 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.loadingMore ||
(this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling)
) {
if (this.loadingMore || (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling)) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
if (
this.$store.state.TimelineSpace.SideMenu.unreadMentions &&
this.heading
) {
if (this.$store.state.TimelineSpace.SideMenu.unreadMentions && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadMentions', false)
}
if (this.scrollPosition) {
@ -180,13 +131,8 @@ export default {
destroyed() {
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Mentions/archiveMentions')
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -200,22 +146,16 @@ export default {
},
focusedId: function (newState, _oldState) {
if (newState && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', false)
} else if (newState === null && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', true)
}
},
mentions: function (newState, _oldState) {
if (this.heading && newState.length > 0) {
this.$store.dispatch('TimelineSpace/Contents/Mentions/saveMarker')
}
},
}
},
methods: {
onScroll(event) {
@ -224,58 +164,39 @@ export default {
}
this.scrollTime = moment()
if (!this.scrolling) {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', true)
}
// for lazyLoading
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/Mentions/lazyFetchMentions',
this.mentions[this.mentions.length - 1]
)
.then((statuses) => {
.dispatch('TimelineSpace/Contents/Mentions/lazyFetchMentions', this.mentions[this.mentions.length - 1])
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', false)
} else if (event.target.scrollTop <= 10 && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', true)
this.$store.dispatch('TimelineSpace/Contents/Mentions/saveMarker')
}
@ -283,25 +204,17 @@ export default {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', false)
}
}, 150)
},
fetchMentionsSince(since_id) {
this.loadingMore = true
this.$store
.dispatch(
'TimelineSpace/Contents/Mentions/fetchMentionsSince',
since_id
)
.finally(() => {
setTimeout(() => {
this.loadingMore = false
}, 500)
})
this.$store.dispatch('TimelineSpace/Contents/Mentions/fetchMentionsSince', since_id).finally(() => {
setTimeout(() => {
this.loadingMore = false
}, 500)
})
},
async reload() {
this.$store.commit('TimelineSpace/changeLoading', true)
@ -319,9 +232,7 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.mentions.findIndex(
(toot) => this.focusedId === toot.id
)
const currentIndex = this.mentions.findIndex(toot => this.focusedId === toot.id)
if (currentIndex === -1) {
this.focusedId = this.mentions[0].id
} else if (currentIndex < this.mentions.length) {
@ -329,9 +240,7 @@ export default {
}
},
focusPrev() {
const currentIndex = this.mentions.findIndex(
(toot) => this.focusedId === toot.id
)
const currentIndex = this.mentions.findIndex(toot => this.focusedId === toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
@ -352,18 +261,12 @@ export default {
}
},
sizeChanged() {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Mentions/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,45 +1,15 @@
<template>
<div
id="notifications"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="handledNotifications"
:min-item-size="20"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="notifications" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="handledNotifications" :min-item-size="20" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<template v-if="item.id === 'loading-card'">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.id]"
:data-index="index"
:watchData="true"
>
<StatusLoading
:since_id="item.since_id"
:max_id="item.max_id"
:loading="loadingMore"
@load_since="fetchNotificationsSince"
/>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.id]" :data-index="index" :watchData="true">
<StatusLoading :since_id="item.since_id" :max_id="item.max_id" :loading="loadingMore" @load_since="fetchNotificationsSince" />
</DynamicScrollerItem>
</template>
<template v-else>
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.url]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.url]" :data-index="index" :watchData="true">
<notification
:message="item"
:focused="item.id === focusedId"
@ -56,18 +26,15 @@
</template>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Notification from '~/src/renderer/components/organisms/Notification'
@ -84,8 +51,7 @@ export default {
observer: null,
scrollTime: null,
resizeTime: null,
loadingMore: false,
ElIconArrowUp,
loadingMore: false
}
},
name: 'notifications',
@ -93,20 +59,17 @@ export default {
mixins: [reloadable],
computed: {
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
backgroundColor: (state) => state.App.theme.background_color,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
backgroundColor: state => state.App.theme.background_color
}),
...mapState('TimelineSpace/Contents/Notifications', {
notifications: (state) => state.notifications,
lazyLoading: (state) => state.lazyLoading,
heading: (state) => state.heading,
scrolling: (state) => state.scrolling,
notifications: state => state.notifications,
lazyLoading: state => state.lazyLoading,
heading: state => state.heading,
scrolling: state => state.scrolling
}),
...mapGetters('TimelineSpace/Contents/Notifications', [
'handledNotifications',
'filters',
]),
...mapGetters('TimelineSpace/Contents/Notifications', ['handledNotifications', 'filters']),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () {
if (this.modalOpened) {
@ -116,21 +79,14 @@ export default {
return true
}
// Sometimes notifications are deleted, so perhaps focused notification don't exist.
const currentIndex = this.handledNotifications.findIndex(
(notification) => this.focusedId === notification.id
)
const currentIndex = this.handledNotifications.findIndex(notification => this.focusedId === notification.id)
return currentIndex === -1
},
}
},
mounted() {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadNotifications',
false
)
this.$store.commit('TimelineSpace/SideMenu/changeUnreadNotifications', false)
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
@ -149,32 +105,18 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.loadingMore ||
(this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling)
) {
if (this.loadingMore || (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling)) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
if (
this.$store.state.TimelineSpace.SideMenu.unreadNotifications &&
this.heading
) {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadNotifications',
false
)
if (this.$store.state.TimelineSpace.SideMenu.unreadNotifications && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadNotifications', false)
}
if (this.scrollPosition) {
this.scrollPosition.prepare()
@ -185,20 +127,10 @@ export default {
this.observer.disconnect()
},
destroyed() {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeHeading',
true
)
this.$store.commit(
'TimelineSpace/Contents/Notifications/archiveNotifications'
)
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Notifications/archiveNotifications')
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -212,15 +144,9 @@ export default {
},
focusedId: function (newState, _oldState) {
if (newState >= 0 && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', false)
} else if (newState === null && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', true)
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
}
},
@ -228,7 +154,7 @@ export default {
if (this.heading && newState.length > 0) {
this.$store.dispatch('TimelineSpace/Contents/Notifications/saveMarker')
}
},
}
},
methods: {
onScroll(event) {
@ -237,15 +163,11 @@ export default {
}
this.scrollTime = moment()
if (!this.scrolling) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', true)
}
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
@ -253,41 +175,29 @@ export default {
'TimelineSpace/Contents/Notifications/lazyFetchNotifications',
this.handledNotifications[this.handledNotifications.length - 1]
)
.then((statuses) => {
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.notification_fetch_error'),
type: 'error',
type: 'error'
})
})
}
if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeHeading',
false
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', false)
} else if (event.target.scrollTop <= 10 && !this.heading) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeHeading',
true
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', true)
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
this.$store.dispatch('TimelineSpace/Contents/Notifications/saveMarker')
}
@ -296,25 +206,17 @@ export default {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Notifications/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', false)
}
}, 150)
},
fetchNotificationsSince(since_id) {
this.loadingMore = true
this.$store
.dispatch(
'TimelineSpace/Contents/Notifications/fetchNotificationsSince',
since_id
)
.finally(() => {
setTimeout(() => {
this.loadingMore = false
}, 500)
})
this.$store.dispatch('TimelineSpace/Contents/Notifications/fetchNotificationsSince', since_id).finally(() => {
setTimeout(() => {
this.loadingMore = false
}, 500)
})
},
async reload() {
this.$store.commit('TimelineSpace/changeLoading', true)
@ -326,19 +228,14 @@ export default {
}
},
updateToot(message) {
this.$store.commit(
'TimelineSpace/Contents/Notifications/updateToot',
message
)
this.$store.commit('TimelineSpace/Contents/Notifications/updateToot', message)
},
upper() {
this.$refs.scroller.scrollToItem(0)
this.focusedId = null
},
focusNext() {
const currentIndex = this.handledNotifications.findIndex(
(notification) => this.focusedId === notification.id
)
const currentIndex = this.handledNotifications.findIndex(notification => this.focusedId === notification.id)
if (currentIndex === -1) {
this.focusedId = this.handledNotifications[0].id
} else if (currentIndex < this.handledNotifications.length) {
@ -346,9 +243,7 @@ export default {
}
},
focusPrev() {
const currentIndex = this.handledNotifications.findIndex(
(notification) => this.focusedId === notification.id
)
const currentIndex = this.handledNotifications.findIndex(notification => this.focusedId === notification.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
@ -367,8 +262,8 @@ export default {
this.focusedId = this.handledNotifications[0].id
break
}
},
},
}
}
}
</script>

View File

@ -1,28 +1,9 @@
<template>
<div
id="public"
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
@shortkey="handleKey"
>
<div
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
@shortkey="reload()"
></div>
<DynamicScroller
:items="timeline"
:min-item-size="86"
id="scroller"
class="scroller"
ref="scroller"
>
<div id="public" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.uri]"
:data-index="index"
:watchData="true"
>
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot
:message="item"
:focused="item.uri + item.id === focusedId"
@ -40,18 +21,15 @@
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
v-show="!heading"
>
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" @click="upper" circle>
<font-awesome-icon icon="arrow-up" />
</el-button>
</div>
</div>
</template>
<script>
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
import { mapState, mapGetters } from 'vuex'
import moment from 'moment'
import Toot from '~/src/renderer/components/organisms/Toot'
@ -66,8 +44,7 @@ export default {
scrollPosition: null,
observer: null,
scrollTime: null,
resizeTime: null,
ElIconArrowUp,
resizeTime: null
}
},
name: 'public',
@ -75,17 +52,16 @@ export default {
mixins: [reloadable],
computed: {
...mapState('TimelineSpace/Contents/Public', {
timeline: (state) => state.timeline,
lazyLoading: (state) => state.lazyLoading,
heading: (state) => state.heading,
scrolling: (state) => state.scrolling,
timeline: state => state.timeline,
lazyLoading: state => state.lazyLoading,
heading: state => state.heading,
scrolling: state => state.scrolling
}),
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: (state) => state.App.theme.background_color,
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
unreadNotification: (state) =>
state.TimelineSpace.timelineSetting.unreadNotification,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
backgroundColor: state => state.App.theme.background_color,
startReload: state => state.TimelineSpace.HeaderMenu.reload,
unreadNotification: state => state.TimelineSpace.timelineSetting.unreadNotification
}),
...mapGetters('TimelineSpace/Contents/Public', ['filters']),
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
@ -97,23 +73,16 @@ export default {
return true
}
// Sometimes toots are deleted, so perhaps focused toot don't exist.
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1
},
}
},
async mounted() {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadPublicTimeline',
false
)
document
.getElementById('scroller')
.addEventListener('scroll', this.onScroll)
this.$store.commit('TimelineSpace/SideMenu/changeUnreadPublicTimeline', false)
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
if (!this.unreadNotification.public) {
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
await this.initialize().finally((_) => {
await this.initialize().finally(_ => {
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
})
}
@ -131,31 +100,18 @@ export default {
this.scrollPosition.prepare()
this.observer = new ResizeObserver(() => {
if (
this.scrollPosition &&
!this.heading &&
!this.lazyLoading &&
!this.scrolling
) {
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
this.resizeTime = moment()
this.scrollPosition.restore()
}
})
const scrollWrapper = el.getElementsByClassName(
'vue-recycle-scroller__item-wrapper'
)[0]
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
this.observer.observe(scrollWrapper)
},
beforeUpdate() {
if (
this.$store.state.TimelineSpace.SideMenu.unreadPublicTimeline &&
this.heading
) {
this.$store.commit(
'TimelineSpace/SideMenu/changeUnreadPublicTimeline',
false
)
if (this.$store.state.TimelineSpace.SideMenu.unreadPublicTimeline && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadPublicTimeline', false)
}
if (this.scrollPosition) {
this.scrollPosition.prepare()
@ -175,13 +131,8 @@ export default {
if (!this.unreadNotification.public) {
this.$store.commit('TimelineSpace/Contents/Public/clearTimeline')
}
if (
document.getElementById('scroller') !== undefined &&
document.getElementById('scroller') !== null
) {
document
.getElementById('scroller')
.removeEventListener('scroll', this.onScroll)
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
document.getElementById('scroller').scrollTop = 0
}
},
@ -199,18 +150,16 @@ export default {
} else if (newState === null && !this.heading) {
this.$store.commit('TimelineSpace/Contents/Public/changeHeading', true)
}
},
}
},
methods: {
async initialize() {
await this.$store
.dispatch('TimelineSpace/Contents/Public/fetchPublicTimeline')
.catch((_) => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
})
await this.$store.dispatch('TimelineSpace/Contents/Public/fetchPublicTimeline').catch(_ => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error'
})
})
await this.$store.dispatch('TimelineSpace/bindPublicStreaming')
this.$store.dispatch('TimelineSpace/startPublicStreaming')
},
@ -227,43 +176,30 @@ export default {
this.scrollTime = moment()
if (!this.scrolling) {
this.$store.commit(
'TimelineSpace/Contents/Public/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', true)
}
if (
event.target.clientHeight + event.target.scrollTop >=
document.getElementById('scroller').scrollHeight - 10 &&
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
!this.lazyloading
) {
this.$store
.dispatch(
'TimelineSpace/Contents/Public/lazyFetchTimeline',
this.timeline[this.timeline.length - 1]
)
.then((statuses) => {
.dispatch('TimelineSpace/Contents/Public/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
.then(statuses => {
if (statuses === null) {
return
}
if (statuses.length > 0) {
this.$store.commit(
'TimelineSpace/Contents/Public/changeScrolling',
true
)
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Public/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', false)
}, 500)
}
})
.catch(() => {
this.$message({
message: this.$t('message.timeline_fetch_error'),
type: 'error',
type: 'error'
})
})
}
@ -278,10 +214,7 @@ export default {
const now = moment()
if (now.diff(this.scrollTime) >= 150) {
this.scrollTime = null
this.$store.commit(
'TimelineSpace/Contents/Public/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', false)
}
}, 150)
},
@ -298,27 +231,19 @@ export default {
this.focusedId = null
},
focusNext() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id
} else if (currentIndex < this.timeline.length) {
this.focusedId =
this.timeline[currentIndex + 1].uri +
this.timeline[currentIndex + 1].id
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
}
},
focusPrev() {
const currentIndex = this.timeline.findIndex(
(toot) => this.focusedId === toot.uri + toot.id
)
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) {
this.focusedId = null
} else if (currentIndex > 0) {
this.focusedId =
this.timeline[currentIndex - 1].uri +
this.timeline[currentIndex - 1].id
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
}
},
focusToot(message) {
@ -337,13 +262,10 @@ export default {
sizeChanged() {
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', true)
setTimeout(() => {
this.$store.commit(
'TimelineSpace/Contents/Public/changeScrolling',
false
)
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', false)
}, 500)
},
},
}
}
}
</script>

View File

@ -1,20 +1,12 @@
<template>
<div
class="side-bar"
v-if="openSideBar"
v-shortkey="shortcutEnabled ? { close: ['esc'] } : {}"
@shortkey="handleKey"
>
<div class="side-bar" v-if="openSideBar" v-shortkey="shortcutEnabled ? { close: ['esc'] } : {}" @shortkey="handleKey">
<div class="header">
<el-icon><el-icon-loading /></el-icon>
<el-icon><el-icon-refresh /></el-icon>
<el-icon><el-icon-close /></el-icon>
<font-awesome-icon icon="spinner" />
<font-awesome-icon icon="rotate" />
<font-awesome-icon icon="xmark" />
</div>
<div id="sidebar_scrollable">
<account-profile
v-if="component === 1"
v-on:change-loading="changeLoading"
></account-profile>
<account-profile v-if="component === 1" v-on:change-loading="changeLoading"></account-profile>
<toot-detail v-else-if="component === 2"></toot-detail>
<div
class="loading"
@ -29,11 +21,6 @@
</template>
<script>
import {
Loading as ElIconLoading,
Refresh as ElIconRefresh,
Close as ElIconClose,
} from '@element-plus/icons'
import { mapState } from 'vuex'
import TootDetail from './SideBar/TootDetail'
import AccountProfile from './SideBar/AccountProfile'
@ -41,32 +28,29 @@ import AccountProfile from './SideBar/AccountProfile'
export default {
components: {
TootDetail,
AccountProfile,
ElIconLoading,
ElIconRefresh,
ElIconClose,
AccountProfile
},
name: 'side-bar',
props: {
overlaid: {
type: Boolean,
default: false,
},
default: false
}
},
data() {
return {
loading: false,
loading: false
}
},
computed: {
...mapState({
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
component: (state) => state.TimelineSpace.Contents.SideBar.component,
backgroundColor: (state) => state.App.theme.background_color,
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
component: state => state.TimelineSpace.Contents.SideBar.component,
backgroundColor: state => state.App.theme.background_color
}),
shortcutEnabled: function () {
return !this.overlaid
},
}
},
beforeDestroy() {
this.close()
@ -87,8 +71,8 @@ export default {
this.close()
break
}
},
},
}
}
}
</script>

View File

@ -3,17 +3,19 @@
<div id="image" v-show="modalOpen" @click="close" :aria-hidden="!modalOpen" aria-modal="true" role="dialog">
<div class="image-wrapper" v-shortkey="modalOpen ? { close: ['esc'] } : {}" @shortkey="closeHandle">
<div class="image-header">
<el-button type="text" :icon="ElIconClose" @click="close" class="close-button"></el-button>
<el-button type="text" @click="close" class="close-button">
<font-awesome-icon icon="xmark" />
</el-button>
</div>
<div class="image-content" role="presentation">
<span class="button-area"
><el-button type="text" v-show="showLeft" v-shortkey="['arrowleft']" @shortkey="decrementIndex()"
><el-icon><el-icon-arrow-left /></el-icon></el-button
><el-button type="text" v-show="showLeft" v-shortkey="['arrowleft']" @shortkey="decrementIndex()">
<font-awesome-icon icon="arrow-left" /> </el-button
></span>
<Media :src="imageURL" :type="imageType"></Media>
<span class="button-area"
><el-button type="text" v-show="showRight" v-shortkey="['arrowright']" @shortkey="incrementIndex()"
><el-icon><el-icon-arrow-right /></el-icon></el-button
><el-button type="text" v-show="showRight" v-shortkey="['arrowright']" @shortkey="incrementIndex()">
<font-awesome-icon icon="arrow-right" /> </el-button
></span>
</div>
</div>
@ -22,20 +24,12 @@
</template>
<script>
import { ArrowLeft as ElIconArrowLeft, ArrowRight as ElIconArrowRight, Close as ElIconClose } from '@element-plus/icons'
import Media from './Media'
import { mapState } from 'vuex'
export default {
data() {
return {
ElIconClose
}
},
components: {
Media,
ElIconArrowLeft,
ElIconArrowRight
Media
},
name: 'image-viewer',
computed: {

View File

@ -9,13 +9,13 @@
up: ['arrowup'],
down: ['arrowdown'],
enter: ['enter'],
esc: ['esc'],
esc: ['esc']
}
: {
linux: ['ctrl', 'enter'],
mac: ['meta', 'enter'],
left: ['arrowleft'],
right: ['arrowright'],
right: ['arrowright']
}
"
@shortkey="handleKey"
@ -29,13 +29,7 @@
autofocus
>
</textarea>
<el-popover
placement="bottom-start"
width="300"
trigger="manual"
:model-value="openSuggest"
popper-class="suggest-popper"
>
<el-popover placement="bottom-start" width="300" trigger="manual" :model-value="openSuggest" popper-class="suggest-popper">
<ul class="suggest-list">
<li
v-for="(item, index) in filteredSuggestion"
@ -60,62 +54,58 @@
<font-awesome-icon :icon="['far', 'face-smile']" size="lg" />
</el-button>
<div v-if="openEmojiPicker" class="emoji-picker">
<picker
set="emojione"
:autoFocus="true"
:custom="pickerEmojis"
@select="selectEmoji"
/>
<picker set="emojione" :autoFocus="true" :custom="pickerEmojis" @select="selectEmoji" />
</div>
</div>
</div>
</template>
<script>
import 'emoji-mart-vue-fast/css/emoji-mart.css'
import { mapState, mapGetters } from 'vuex'
import { Picker } from 'emoji-mart-vue'
import { Picker } from 'emoji-mart-vue-fast/src'
import ClickOutside from 'vue-click-outside'
import suggestText from '@/utils/suggestText'
export default {
name: 'status',
directives: {
ClickOutside,
ClickOutside
},
components: {
Picker,
Picker
},
props: {
value: {
type: String,
type: String
},
opened: {
type: Boolean,
default: false,
default: false
},
fixCursorPos: {
type: Boolean,
default: false,
default: false
},
height: {
type: Number,
default: 120,
},
default: 120
}
},
data() {
return {
highlightedIndex: 0,
openEmojiPicker: false,
openEmojiPicker: false
}
},
computed: {
...mapState('TimelineSpace/Modals/NewToot/Status', {
filteredAccounts: (state) => state.filteredAccounts,
filteredHashtags: (state) => state.filteredHashtags,
openSuggest: (state) => state.openSuggest,
startIndex: (state) => state.startIndex,
matchWord: (state) => state.matchWord,
filteredSuggestion: (state) => state.filteredSuggestion,
filteredAccounts: state => state.filteredAccounts,
filteredHashtags: state => state.filteredHashtags,
openSuggest: state => state.openSuggest,
startIndex: state => state.startIndex,
matchWord: state => state.matchWord,
filteredSuggestion: state => state.filteredSuggestion
}),
...mapGetters('TimelineSpace/Modals/NewToot/Status', ['pickerEmojis']),
status: {
@ -124,8 +114,8 @@ export default {
},
set: function (value) {
this.$emit('input', value)
},
},
}
}
},
mounted() {
// When change account, the new toot modal is recreated.
@ -148,7 +138,7 @@ export default {
this.closeSuggest()
this.hideEmojiPicker()
}
},
}
},
methods: {
async startSuggest(e) {
@ -184,10 +174,7 @@ export default {
},
async suggestAccount(start, word) {
try {
await this.$store.dispatch(
'TimelineSpace/Modals/NewToot/Status/suggestAccount',
{ word: word, start: start }
)
await this.$store.dispatch('TimelineSpace/Modals/NewToot/Status/suggestAccount', { word: word, start: start })
this.$emit('suggestOpened', true)
return true
} catch (err) {
@ -197,10 +184,7 @@ export default {
},
async suggestHashtag(start, word) {
try {
await this.$store.dispatch(
'TimelineSpace/Modals/NewToot/Status/suggestHashtag',
{ word: word, start: start }
)
await this.$store.dispatch('TimelineSpace/Modals/NewToot/Status/suggestHashtag', { word: word, start: start })
this.$emit('suggestOpened', true)
return true
} catch (err) {
@ -210,10 +194,7 @@ export default {
},
suggestEmoji(start, word) {
try {
this.$store.dispatch(
'TimelineSpace/Modals/NewToot/Status/suggestEmoji',
{ word: word, start: start }
)
this.$store.dispatch('TimelineSpace/Modals/NewToot/Status/suggestEmoji', { word: word, start: start })
this.$emit('suggestOpened', true)
return true
} catch (err) {
@ -239,14 +220,10 @@ export default {
},
insertItem(item) {
if (item.code) {
const str = `${this.status.slice(0, this.startIndex - 1)}${
item.code
} ${this.status.slice(this.startIndex + this.matchWord.length)}`
const str = `${this.status.slice(0, this.startIndex - 1)}${item.code} ${this.status.slice(this.startIndex + this.matchWord.length)}`
this.status = str
} else {
const str = `${this.status.slice(0, this.startIndex - 1)}${
item.name
} ${this.status.slice(this.startIndex + this.matchWord.length)}`
const str = `${this.status.slice(0, this.startIndex - 1)}${item.name} ${this.status.slice(this.startIndex + this.matchWord.length)}`
this.status = str
}
this.closeSuggest()
@ -300,18 +277,14 @@ export default {
selectEmoji(emoji) {
const current = this.$refs.status.selectionStart
if (emoji.native) {
this.status = `${this.status.slice(0, current)}${
emoji.native
} ${this.status.slice(current)}`
this.status = `${this.status.slice(0, current)}${emoji.native} ${this.status.slice(current)}`
} else {
// Custom emoji don't have natvie code
this.status = `${this.status.slice(0, current)}${
emoji.name
} ${this.status.slice(current)}`
this.status = `${this.status.slice(0, current)}${emoji.name} ${this.status.slice(current)}`
}
this.hideEmojiPicker()
},
},
}
}
}
</script>

View File

@ -12,7 +12,7 @@
</div>
<el-dropdown trigger="click" @command="handleProfile" :title="$t('side_menu.profile')">
<span class="el-dropdown-link">
<el-icon class="el-icon--right"><el-icon-arrow-down /></el-icon>
<font-awesome-icon icon="arrow-up" class="el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="show">{{ $t('side_menu.show_profile') }}</el-dropdown-item>
@ -239,13 +239,9 @@
</template>
<script>
import { ArrowDown as ElIconArrowDown } from '@element-plus/icons'
import { mapState } from 'vuex'
export default {
components: {
ElIconArrowDown
},
name: 'side-menu',
computed: {
...mapState('TimelineSpace/SideMenu', {

View File

@ -2,7 +2,7 @@
<div class="link" @click="openLink(url)">
<el-image :src="icon" class="icon" fit="cover" lazy>
<div class="image-slot" slot="error">
<el-icon><el-icon-link /></el-icon>
<font-awesome-icon icon="link" />
</div>
</el-image>
<div class="contents">
@ -13,37 +13,33 @@
</template>
<script>
import { Link as ElIconLink } from '@element-plus/icons'
export default {
components: {
ElIconLink,
},
name: 'link-preview',
props: {
icon: {
type: String,
default: '',
default: ''
},
title: {
type: String,
default: '',
default: ''
},
description: {
type: String,
default: '',
default: ''
},
url: {
type: String,
default: null,
},
default: null
}
},
methods: {
openLink(link) {
if (link) {
return window.shell.openExternal(link)
}
},
},
}
}
}
</script>

View File

@ -15,7 +15,7 @@
open: ['o'],
profile: ['p'],
image: ['i'],
cw: ['x'],
cw: ['x']
}
: {}
"
@ -28,15 +28,8 @@
<div v-show="filtered" class="filtered">Filtered</div>
<div v-show="!filtered" class="toot">
<div class="reblogger" v-show="message.reblog && !message.quote">
<span
class="reblogger-icon"
@click="openUser(message.account)"
role="presentation"
>
<FailoverImg
:src="message.account.avatar"
:alt="`Avatar of ${message.account.username}`"
/>
<span class="reblogger-icon" @click="openUser(message.account)" role="presentation">
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
</span>
<font-awesome-icon icon="retweet" />
<span
@ -58,17 +51,11 @@
<div class="detail" v-on:dblclick="openDetail(message)">
<div class="toot-header">
<div class="user" @click="openUser(originalMessage.account)">
<span class="display-name"
><bdi v-html="username(originalMessage.account)"></bdi
></span>
<span class="display-name"><bdi v-html="username(originalMessage.account)"></bdi></span>
<span class="acct">{{ accountName(originalMessage.account) }}</span>
</div>
<div class="timestamp">
<time
:datetime="originalMessage.created_at"
:title="readableTimestamp"
@click="openDetail(message)"
>
<time :datetime="originalMessage.created_at" :title="readableTimestamp" @click="openDetail(message)">
{{ timestamp }}
</time>
</div>
@ -76,28 +63,11 @@
</div>
<div class="content-wrapper">
<div class="spoiler" v-show="spoilered">
<span
v-html="
emojiText(originalMessage.spoiler_text, originalMessage.emojis)
"
></span>
<el-button
v-if="!isShowContent"
plain
type="primary"
size="medium"
class="spoil-button"
@click="toggleSpoiler"
>
<span v-html="emojiText(originalMessage.spoiler_text, originalMessage.emojis)"></span>
<el-button v-if="!isShowContent" plain type="primary" size="medium" class="spoil-button" @click="toggleSpoiler">
{{ $t('cards.toot.show_more') }}
</el-button>
<el-button
v-else
type="primary"
size="medium"
class="spoil-button"
@click="toggleSpoiler"
>
<el-button v-else type="primary" size="medium" class="spoil-button" @click="toggleSpoiler">
{{ $t('cards.toot.hide') }}
</el-button>
</div>
@ -107,21 +77,10 @@
v-html="emojiText(originalMessage.content, originalMessage.emojis)"
@click.capture.prevent="tootClick"
></div>
<Poll
v-show="isShowContent"
v-if="poll"
:poll="poll"
@vote="vote"
@refresh="refresh"
></Poll>
<Poll v-show="isShowContent" v-if="poll" :poll="poll" @vote="vote" @refresh="refresh"></Poll>
</div>
<div class="attachments">
<el-button
v-show="sensitive && !isShowAttachments"
class="show-sensitive"
type="info"
@click="toggleCW()"
>
<el-button v-show="sensitive && !isShowAttachments" class="show-sensitive" type="info" @click="toggleCW()">
{{ $t('cards.toot.sensitive') }}
</el-button>
<div v-show="isShowAttachments">
@ -134,39 +93,16 @@
>
<font-awesome-icon icon="eye" class="hide" />
</el-button>
<div
class="media"
v-bind:key="media.preview_url"
v-for="media in mediaAttachments"
>
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments">
<FailoverImg
:src="
media.preview_url
? media.preview_url
: originalMessage.account.avatar
"
:src="media.preview_url ? media.preview_url : originalMessage.account.avatar"
@click="openImage(media.url, mediaAttachments)"
:title="media.description"
:readExif="true"
/>
<el-tag
class="media-label"
size="mini"
v-if="media.type === 'gifv'"
>GIF</el-tag
>
<el-tag
class="media-label"
size="mini"
v-else-if="media.type === 'video'"
>VIDEO</el-tag
>
<el-tag
class="media-label"
size="mini"
v-else-if="media.type === 'audio'"
>AUDIO</el-tag
>
<el-tag class="media-label" size="mini" v-if="media.type === 'gifv'">GIF</el-tag>
<el-tag class="media-label" size="mini" v-else-if="media.type === 'video'">VIDEO</el-tag>
<el-tag class="media-label" size="mini" v-else-if="media.type === 'audio'">AUDIO</el-tag>
</div>
</div>
<div class="clearfix"></div>
@ -188,33 +124,17 @@
/>
<div class="emoji-reactions">
<template v-for="reaction in originalMessage.emoji_reactions">
<el-button
v-if="reaction.me"
type="success"
size="medium"
class="reaction"
@click="removeReaction(reaction.name)"
<el-button v-if="reaction.me" type="success" size="medium" class="reaction" @click="removeReaction(reaction.name)"
>{{ reaction.name }} {{ reaction.count }}</el-button
>
<el-button
v-else
type="text"
size="medium"
class="reaction"
@click="addReaction(reaction.name)"
<el-button v-else type="text" size="medium" class="reaction" @click="addReaction(reaction.name)"
>{{ reaction.name }} {{ reaction.count }}</el-button
>
</template>
</div>
<div class="toot-footer">
<div class="tool-box">
<el-button
type="text"
@click="openReply()"
class="reply"
:title="$t('cards.toot.reply')"
:aria-label="$t('cards.toot.reply')"
>
<el-button type="text" @click="openReply()" class="reply" :title="$t('cards.toot.reply')" :aria-label="$t('cards.toot.reply')">
<font-awesome-icon icon="reply" size="sm" />
</el-button>
<el-button v-show="locked" type="text" class="locked">
@ -238,11 +158,7 @@
<el-button
type="text"
@click="changeFavourite(originalMessage)"
:class="
originalMessage.favourited
? 'favourited animated bounceIn'
: 'favourite'
"
:class="originalMessage.favourited ? 'favourited animated bounceIn' : 'favourite'"
:title="$t('cards.toot.fav')"
:aria-label="$t('cards.toot.fav')"
>
@ -261,12 +177,7 @@
>
<font-awesome-icon icon="bookmark" size="sm" />
</el-button>
<el-button
type="text"
class="quote-btn"
v-if="quoteSupported"
@click="openQuote()"
>
<el-button type="text" class="quote-btn" v-if="quoteSupported" @click="openQuote()">
<font-awesome-icon icon="quote-right" size="sm" />
</el-button>
<template v-if="sns !== 'mastodon'">
@ -295,13 +206,7 @@
</el-button>
</el-popover>
</template>
<el-button
class="pinned"
type="text"
:title="$t('cards.toot.pinned')"
:aria-label="$t('cards.toot.pinned')"
v-show="pinned"
>
<el-button class="pinned" type="text" :title="$t('cards.toot.pinned')" :aria-label="$t('cards.toot.pinned')" v-show="pinned">
<font-awesome-icon icon="thumbtack" size="sm" />
</el-button>
<el-popover
@ -314,11 +219,7 @@
@hide="hideMenu"
>
<ul class="menu-list" v-if="openToolMenu">
<li
role="button"
@click="openDetail(message)"
v-show="!detailed"
>
<li role="button" @click="openDetail(message)" v-show="!detailed">
{{ $t('cards.toot.view_toot_detail') }}
</li>
<li role="button" @click="openBrowser(originalMessage)">
@ -336,20 +237,11 @@
<li role="button" @click="reportUser()" v-if="!isMyMessage">
{{ $t('cards.toot.report') }}
</li>
<li
role="button"
class="separate"
@click="deleteToot(message)"
v-if="isMyMessage"
>
<li role="button" class="separate" @click="deleteToot(message)" v-if="isMyMessage">
{{ $t('cards.toot.delete') }}
</li>
</ul>
<el-button
slot="reference"
type="text"
:title="$t('cards.toot.detail')"
>
<el-button slot="reference" type="text" :title="$t('cards.toot.detail')">
<font-awesome-icon icon="ellipsis" size="sm" />
</el-button>
</el-popover>
@ -366,9 +258,10 @@
</template>
<script>
import 'emoji-mart-vue-fast/css/emoji-mart.css'
import moment from 'moment'
import { mapState } from 'vuex'
import { Picker } from 'emoji-mart-vue'
import { Picker } from 'emoji-mart-vue-fast/src'
import ClickOutside from 'vue-click-outside'
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
import DisplayStyle from '~/src/constants/displayStyle'
@ -385,14 +278,14 @@ import Filtered from '@/utils/filter'
export default {
name: 'toot',
directives: {
ClickOutside,
ClickOutside
},
components: {
FailoverImg,
Poll,
Picker,
LinkPreview,
Quote,
Quote
},
data() {
return {
@ -401,47 +294,47 @@ export default {
hideAllAttachments: this.$store.state.App.hideAllAttachments,
now: Date.now(),
openEmojiPicker: false,
openToolMenu: false,
openToolMenu: false
}
},
props: {
message: {
type: Object,
default: {},
default: {}
},
filters: {
type: Array,
default: [],
default: []
},
focused: {
type: Boolean,
default: false,
default: false
},
overlaid: {
type: Boolean,
default: false,
default: false
},
pinned: {
type: Boolean,
default: false,
default: false
},
detailed: {
type: Boolean,
default: false,
},
default: false
}
},
computed: {
...mapState('App', {
displayNameStyle: (state) => state.displayNameStyle,
timeFormat: (state) => state.timeFormat,
language: (state) => state.language,
displayNameStyle: state => state.displayNameStyle,
timeFormat: state => state.timeFormat,
language: state => state.language
}),
...mapState('TimelineSpace', {
sns: (state) => state.sns,
account: (state) => state.account,
sns: state => state.sns,
account: state => state.account
}),
...mapState('TimelineSpace/SideMenu', {
bookmarkSupported: (state) => state.enabledTimelines.bookmark,
bookmarkSupported: state => state.enabledTimelines.bookmark
}),
shortcutEnabled: function () {
return this.focused && !this.overlaid && !this.openEmojiPicker
@ -476,10 +369,7 @@ export default {
return null
},
isMyMessage: function () {
return (
this.$store.state.TimelineSpace.account.accountId ===
this.originalMessage.account.id
)
return this.$store.state.TimelineSpace.account.accountId === this.originalMessage.account.id
},
application: function () {
const msg = this.originalMessage
@ -498,10 +388,7 @@ export default {
return this.originalMessage.poll
},
sensitive: function () {
return (
(this.hideAllAttachments || this.originalMessage.sensitive) &&
this.mediaAttachments.length > 0
)
return (this.hideAllAttachments || this.originalMessage.sensitive) && this.mediaAttachments.length > 0
},
isShowAttachments: function () {
return !this.sensitive || this.showAttachments
@ -517,7 +404,7 @@ export default {
},
quoteSupported: function () {
return QuoteSupported(this.sns, this.account.domain)
},
}
},
mounted() {
if (this.focused) {
@ -541,7 +428,7 @@ export default {
this.$refs.status.blur()
})
}
},
}
},
methods: {
username(account) {
@ -589,34 +476,20 @@ export default {
}
const parsedAccount = findAccount(e.target, 'toot')
if (parsedAccount !== null) {
this.$store.commit(
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
true
)
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
this.$store
.dispatch(
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
{
parsedAccount: parsedAccount,
status: this.originalMessage,
}
)
.then((account) => {
this.$store.dispatch(
'TimelineSpace/Contents/SideBar/openAccountComponent'
)
this.$store.dispatch(
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
account
)
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', {
parsedAccount: parsedAccount,
status: this.originalMessage
})
.catch((err) => {
.then(account => {
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
})
.catch(err => {
console.error(err)
this.openLink(e)
this.$store.commit(
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
false
)
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
})
return parsedAccount.acct
}
@ -629,21 +502,12 @@ export default {
}
},
openReply() {
this.$store.dispatch(
'TimelineSpace/Modals/NewToot/openReply',
this.originalMessage
)
this.$store.dispatch('TimelineSpace/Modals/NewToot/openReply', this.originalMessage)
},
openDetail(message) {
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
this.$store.dispatch(
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
message
)
this.$store.commit(
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
true
)
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
this.$refs.status_menu_popper.doClose()
},
openBrowser(message) {
@ -655,17 +519,11 @@ export default {
this.$refs.status_menu_popper.doClose()
},
reportUser() {
this.$store.dispatch(
'TimelineSpace/Modals/Report/openReport',
this.originalMessage
)
this.$store.dispatch('TimelineSpace/Modals/Report/openReport', this.originalMessage)
this.$refs.status_menu_popper.doClose()
},
confirmMute() {
this.$store.dispatch(
'TimelineSpace/Modals/MuteConfirm/changeAccount',
this.originalMessage.account
)
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeAccount', this.originalMessage.account)
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeModal', true)
this.$refs.status_menu_popper.doClose()
},
@ -677,27 +535,27 @@ export default {
if (message.reblogged) {
this.$store
.dispatch('organisms/Toot/unreblog', message)
.then((data) => {
.then(data => {
this.$emit('update', data)
})
.catch((err) => {
.catch(err => {
console.error(err)
this.$message({
message: this.$t('message.unreblog_error'),
type: 'error',
type: 'error'
})
})
} else {
this.$store
.dispatch('organisms/Toot/reblog', message)
.then((data) => {
.then(data => {
this.$emit('update', data)
})
.catch((err) => {
.catch(err => {
console.error(err)
this.$message({
message: this.$t('message.reblog_error'),
type: 'error',
type: 'error'
})
})
}
@ -706,27 +564,27 @@ export default {
if (message.favourited) {
this.$store
.dispatch('organisms/Toot/removeFavourite', message)
.then((data) => {
.then(data => {
this.$emit('update', data)
})
.catch((err) => {
.catch(err => {
console.error(err)
this.$message({
message: this.$t('message.unfavourite_error'),
type: 'error',
type: 'error'
})
})
} else {
this.$store
.dispatch('organisms/Toot/addFavourite', message)
.then((data) => {
.then(data => {
this.$emit('update', data)
})
.catch((err) => {
.catch(err => {
console.error(err)
this.$message({
message: this.$t('message.favourite_error'),
type: 'error',
type: 'error'
})
})
}
@ -735,65 +593,57 @@ export default {
if (message.bookmarked) {
this.$store
.dispatch('organisms/Toot/removeBookmark', message)
.then((data) => {
.then(data => {
this.$emit('update', data)
})
.catch((err) => {
.catch(err => {
console.error(err)
this.$message({
message: this.$t('message.unbookmark_error'),
type: 'error',
type: 'error'
})
})
} else {
this.$store
.dispatch('organisms/Toot/addBookmark', message)
.then((data) => {
.then(data => {
this.$emit('update', data)
})
.catch((err) => {
.catch(err => {
console.error(err)
this.$message({
message: this.$t('message.bookmark_error'),
type: 'error',
type: 'error'
})
})
}
},
openImage(url, rawMediaList) {
const mediaList = rawMediaList.map((media) => {
const mediaList = rawMediaList.map(media => {
return media.url
})
const currentIndex = mediaList.indexOf(url)
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/openModal', {
currentIndex: currentIndex,
mediaList: rawMediaList,
mediaList: rawMediaList
})
},
openUser(account) {
console.log(account)
this.$store.dispatch(
'TimelineSpace/Contents/SideBar/openAccountComponent'
)
this.$store.dispatch(
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
account
)
this.$store.commit(
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
true
)
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
},
deleteToot(message) {
this.$store
.dispatch('organisms/Toot/deleteToot', message)
.then((message) => {
.then(message => {
this.$emit('delete', message)
})
.catch(() => {
this.$message({
message: this.$t('message.delete_error'),
type: 'error',
type: 'error'
})
})
},
@ -846,24 +696,24 @@ export default {
async vote(choices) {
const res = await this.$store.dispatch('organisms/Toot/vote', {
id: this.poll.id,
choices: choices,
choices: choices
})
const status = Object.assign({}, this.originalMessage, {
poll: res,
poll: res
})
this.$emit('update', status)
},
async refresh(id) {
const res = await this.$store.dispatch('organisms/Toot/refresh', id)
const status = Object.assign({}, this.originalMessage, {
poll: res,
poll: res
})
this.$emit('update', status)
},
async selectEmoji(emoji) {
const status = await this.$store.dispatch('organisms/Toot/sendReaction', {
status_id: this.originalMessage.id,
native: emoji.native,
native: emoji.native
})
this.$emit('update', status)
this.$refs.status_emoji_picker.doClose()
@ -871,25 +721,19 @@ export default {
async addReaction(native) {
const status = await this.$store.dispatch('organisms/Toot/sendReaction', {
status_id: this.originalMessage.id,
native: native,
native: native
})
this.$emit('update', status)
},
async removeReaction(native) {
const status = await this.$store.dispatch(
'organisms/Toot/deleteReaction',
{
status_id: this.originalMessage.id,
native: native,
}
)
const status = await this.$store.dispatch('organisms/Toot/deleteReaction', {
status_id: this.originalMessage.id,
native: native
})
this.$emit('update', status)
},
openQuote() {
this.$store.dispatch(
'TimelineSpace/Modals/NewToot/openQuote',
this.originalMessage
)
this.$store.dispatch('TimelineSpace/Modals/NewToot/openQuote', this.originalMessage)
},
openPicker() {
this.openEmojiPicker = true
@ -910,8 +754,8 @@ export default {
toggleCW() {
this.showAttachments = !this.showAttachments
this.$emit('sizeChanged', true)
},
},
}
}
}
</script>

View File

@ -47,7 +47,14 @@ import {
faChevronLeft,
faEllipsisVertical,
faCircleXmark,
faMagnifyingGlass
faMagnifyingGlass,
faCircleUser,
faArrowUp,
faArrowDown,
faArrowLeft,
faArrowRight,
faSpinner,
faLink
} from '@fortawesome/free-solid-svg-icons'
import {
faFaceSmile as farFaceSmile,
@ -120,7 +127,14 @@ library.add(
farTrashCan,
farBell,
faChevronLeft,
faEllipsisVertical
faEllipsisVertical,
faCircleUser,
faArrowUp,
faArrowDown,
faArrowLeft,
faArrowRight,
faSpinner,
faLink
)
const app = createApp(App)

View File

@ -1,4 +1,4 @@
import { createRouter } from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import Login from '@/components/Login.vue'
import Authorize from '@/components/Authorize.vue'
@ -215,7 +215,8 @@ const routes = [
]
const router = createRouter({
routes
history: createWebHistory(),
routes: routes
})
export default router