biome format --write
This commit is contained in:
parent
8372348148
commit
9262e803ec
415 changed files with 54076 additions and 17419 deletions
|
|
@ -8,17 +8,17 @@ import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue'
|
|||
import ScrollTopButton from '../scroll_top_button/scroll_top_button.vue'
|
||||
import { debounce, throttle, keyBy } from 'lodash'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { faCircleNotch, faCirclePlus, faCog, faMinus, faArrowUp, faCheck } from '@fortawesome/free-solid-svg-icons'
|
||||
import { useInterfaceStore } from 'src/stores/interface'
|
||||
|
||||
library.add(
|
||||
import {
|
||||
faCircleNotch,
|
||||
faCirclePlus,
|
||||
faCog,
|
||||
faMinus,
|
||||
faArrowUp,
|
||||
faCirclePlus,
|
||||
faCheck
|
||||
)
|
||||
faCheck,
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { useInterfaceStore } from 'src/stores/interface'
|
||||
|
||||
library.add(faCircleNotch, faCog, faMinus, faArrowUp, faCirclePlus, faCheck)
|
||||
|
||||
const Timeline = {
|
||||
props: [
|
||||
|
|
@ -34,16 +34,16 @@ const Timeline = {
|
|||
'count',
|
||||
'pinnedStatusIds',
|
||||
'inProfile',
|
||||
'footerSlipgate' // reference to an element where we should put our footer
|
||||
'footerSlipgate', // reference to an element where we should put our footer
|
||||
],
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
showScrollTop: false,
|
||||
paused: false,
|
||||
unfocused: false,
|
||||
bottomedOut: false,
|
||||
virtualScrollIndex: 0,
|
||||
blockingClicks: false
|
||||
blockingClicks: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
|
@ -52,72 +52,91 @@ const Timeline = {
|
|||
Conversation,
|
||||
TimelineMenu,
|
||||
QuickFilterSettings,
|
||||
QuickViewSettings
|
||||
QuickViewSettings,
|
||||
},
|
||||
computed: {
|
||||
filteredVisibleStatuses () {
|
||||
return this.timeline.visibleStatuses.filter(status => this.timelineName !== 'user' || (status.id >= this.timeline.minId && status.id <= this.timeline.maxId))
|
||||
filteredVisibleStatuses() {
|
||||
return this.timeline.visibleStatuses.filter(
|
||||
(status) =>
|
||||
this.timelineName !== 'user' ||
|
||||
(status.id >= this.timeline.minId &&
|
||||
status.id <= this.timeline.maxId),
|
||||
)
|
||||
},
|
||||
filteredPinnedStatusIds () {
|
||||
return (this.pinnedStatusIds || []).filter(statusId => this.timeline.statusesObject[statusId])
|
||||
filteredPinnedStatusIds() {
|
||||
return (this.pinnedStatusIds || []).filter(
|
||||
(statusId) => this.timeline.statusesObject[statusId],
|
||||
)
|
||||
},
|
||||
newStatusCount () {
|
||||
newStatusCount() {
|
||||
return this.timeline.newStatusCount
|
||||
},
|
||||
showLoadButton () {
|
||||
showLoadButton() {
|
||||
return this.timeline.newStatusCount > 0 || this.timeline.flushMarker !== 0
|
||||
},
|
||||
loadButtonString () {
|
||||
loadButtonString() {
|
||||
if (this.timeline.flushMarker !== 0) {
|
||||
return this.$t('timeline.reload')
|
||||
} else {
|
||||
return `${this.$t('timeline.show_new')} (${this.newStatusCount})`
|
||||
}
|
||||
},
|
||||
mobileLoadButtonString () {
|
||||
mobileLoadButtonString() {
|
||||
if (this.timeline.flushMarker !== 0) {
|
||||
return '+'
|
||||
} else {
|
||||
return this.newStatusCount > 99 ? '∞' : this.newStatusCount
|
||||
}
|
||||
},
|
||||
classes () {
|
||||
let rootClasses = !this.embedded ? ['panel', 'panel-default'] : ['-embedded']
|
||||
if (this.blockingClicks) rootClasses = rootClasses.concat(['-blocked', '_misclick-prevention'])
|
||||
classes() {
|
||||
let rootClasses = !this.embedded
|
||||
? ['panel', 'panel-default']
|
||||
: ['-embedded']
|
||||
if (this.blockingClicks)
|
||||
rootClasses = rootClasses.concat(['-blocked', '_misclick-prevention'])
|
||||
return {
|
||||
root: rootClasses,
|
||||
header: ['timeline-heading'].concat(!this.embedded ? ['panel-heading', '-sticky'] : ['panel-body']),
|
||||
body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : ['panel-body']),
|
||||
footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : ['panel-body'])
|
||||
header: ['timeline-heading'].concat(
|
||||
!this.embedded ? ['panel-heading', '-sticky'] : ['panel-body'],
|
||||
),
|
||||
body: ['timeline-body'].concat(
|
||||
!this.embedded ? ['panel-body'] : ['panel-body'],
|
||||
),
|
||||
footer: ['timeline-footer'].concat(
|
||||
!this.embedded ? ['panel-footer'] : ['panel-body'],
|
||||
),
|
||||
}
|
||||
},
|
||||
// id map of statuses which need to be hidden in the main list due to pinning logic
|
||||
pinnedStatusIdsObject () {
|
||||
pinnedStatusIdsObject() {
|
||||
return keyBy(this.pinnedStatusIds)
|
||||
},
|
||||
statusesToDisplay () {
|
||||
statusesToDisplay() {
|
||||
const amount = this.timeline.visibleStatuses.length
|
||||
const statusesPerSide = Math.ceil(Math.max(3, window.innerHeight / 80))
|
||||
const nonPinnedIndex = this.virtualScrollIndex - this.filteredPinnedStatusIds.length
|
||||
const nonPinnedIndex =
|
||||
this.virtualScrollIndex - this.filteredPinnedStatusIds.length
|
||||
const min = Math.max(0, nonPinnedIndex - statusesPerSide)
|
||||
const max = Math.min(amount, nonPinnedIndex + statusesPerSide)
|
||||
return this.timeline.visibleStatuses.slice(min, max).map(_ => _.id)
|
||||
return this.timeline.visibleStatuses.slice(min, max).map((_) => _.id)
|
||||
},
|
||||
virtualScrollingEnabled () {
|
||||
virtualScrollingEnabled() {
|
||||
return this.$store.getters.mergedConfig.virtualScrolling
|
||||
},
|
||||
...mapState(useInterfaceStore, {
|
||||
mobileLayout: store => store.layoutType === 'mobile'
|
||||
})
|
||||
mobileLayout: (store) => store.layoutType === 'mobile',
|
||||
}),
|
||||
},
|
||||
created () {
|
||||
created() {
|
||||
const store = this.$store
|
||||
const credentials = store.state.users.currentUser.credentials
|
||||
const showImmediately = this.timeline.visibleStatuses.length === 0
|
||||
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
|
||||
if (store.state.api.fetchers[this.timelineName]) { return false }
|
||||
if (store.state.api.fetchers[this.timelineName]) {
|
||||
return false
|
||||
}
|
||||
|
||||
timelineFetcher.fetchAndUpdate({
|
||||
store,
|
||||
|
|
@ -128,41 +147,56 @@ const Timeline = {
|
|||
listId: this.listId,
|
||||
statusId: this.statusId,
|
||||
bookmarkFolderId: this.bookmarkFolderId,
|
||||
tag: this.tag
|
||||
tag: this.tag,
|
||||
})
|
||||
},
|
||||
mounted () {
|
||||
mounted() {
|
||||
if (typeof document.hidden !== 'undefined') {
|
||||
document.addEventListener('visibilitychange', this.handleVisibilityChange, false)
|
||||
document.addEventListener(
|
||||
'visibilitychange',
|
||||
this.handleVisibilityChange,
|
||||
false,
|
||||
)
|
||||
this.unfocused = document.hidden
|
||||
}
|
||||
window.addEventListener('keydown', this.handleShortKey)
|
||||
setTimeout(this.determineVisibleStatuses, 250)
|
||||
},
|
||||
unmounted () {
|
||||
unmounted() {
|
||||
window.removeEventListener('scroll', this.handleScroll)
|
||||
window.removeEventListener('keydown', this.handleShortKey)
|
||||
if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
|
||||
this.$store.commit('setLoading', { timeline: this.timelineName, value: false })
|
||||
if (typeof document.hidden !== 'undefined')
|
||||
document.removeEventListener(
|
||||
'visibilitychange',
|
||||
this.handleVisibilityChange,
|
||||
false,
|
||||
)
|
||||
this.$store.commit('setLoading', {
|
||||
timeline: this.timelineName,
|
||||
value: false,
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
stopBlockingClicks: debounce(function () {
|
||||
this.blockingClicks = false
|
||||
}, 1000),
|
||||
blockClicksTemporarily () {
|
||||
blockClicksTemporarily() {
|
||||
if (!this.blockingClicks) {
|
||||
this.blockingClicks = true
|
||||
}
|
||||
this.stopBlockingClicks()
|
||||
},
|
||||
handleShortKey (e) {
|
||||
handleShortKey(e) {
|
||||
// Ignore when input fields are focused
|
||||
if (['textarea', 'input'].includes(e.target.tagName.toLowerCase())) return
|
||||
if (e.key === '.') this.showNewStatuses()
|
||||
},
|
||||
showNewStatuses () {
|
||||
showNewStatuses() {
|
||||
if (this.timeline.flushMarker !== 0) {
|
||||
this.$store.commit('clearTimeline', { timeline: this.timelineName, excludeUserId: true })
|
||||
this.$store.commit('clearTimeline', {
|
||||
timeline: this.timelineName,
|
||||
excludeUserId: true,
|
||||
})
|
||||
this.$store.commit('queueFlush', { timeline: this.timelineName, id: 0 })
|
||||
if (this.timelineName === 'user') {
|
||||
this.$store.dispatch('fetchPinnedStatuses', this.userId)
|
||||
|
|
@ -175,41 +209,54 @@ const Timeline = {
|
|||
}
|
||||
window.scrollTo({ top: 0 })
|
||||
},
|
||||
fetchOlderStatuses: throttle(function () {
|
||||
const store = this.$store
|
||||
const credentials = store.state.users.currentUser.credentials
|
||||
store.commit('setLoading', { timeline: this.timelineName, value: true })
|
||||
timelineFetcher.fetchAndUpdate({
|
||||
store,
|
||||
credentials,
|
||||
timeline: this.timelineName,
|
||||
older: true,
|
||||
showImmediately: true,
|
||||
userId: this.userId,
|
||||
listId: this.listId,
|
||||
statusId: this.statusId,
|
||||
bookmarkFolderId: this.bookmarkFolderId,
|
||||
tag: this.tag
|
||||
}).then(({ statuses }) => {
|
||||
if (statuses && statuses.length === 0) {
|
||||
this.bottomedOut = true
|
||||
}
|
||||
}).finally(() =>
|
||||
store.commit('setLoading', { timeline: this.timelineName, value: false })
|
||||
)
|
||||
}, 1000, this),
|
||||
determineVisibleStatuses () {
|
||||
fetchOlderStatuses: throttle(
|
||||
function () {
|
||||
const store = this.$store
|
||||
const credentials = store.state.users.currentUser.credentials
|
||||
store.commit('setLoading', { timeline: this.timelineName, value: true })
|
||||
timelineFetcher
|
||||
.fetchAndUpdate({
|
||||
store,
|
||||
credentials,
|
||||
timeline: this.timelineName,
|
||||
older: true,
|
||||
showImmediately: true,
|
||||
userId: this.userId,
|
||||
listId: this.listId,
|
||||
statusId: this.statusId,
|
||||
bookmarkFolderId: this.bookmarkFolderId,
|
||||
tag: this.tag,
|
||||
})
|
||||
.then(({ statuses }) => {
|
||||
if (statuses && statuses.length === 0) {
|
||||
this.bottomedOut = true
|
||||
}
|
||||
})
|
||||
.finally(() =>
|
||||
store.commit('setLoading', {
|
||||
timeline: this.timelineName,
|
||||
value: false,
|
||||
}),
|
||||
)
|
||||
},
|
||||
1000,
|
||||
this,
|
||||
),
|
||||
determineVisibleStatuses() {
|
||||
if (!this.$refs.timeline) return
|
||||
if (!this.virtualScrollingEnabled) return
|
||||
|
||||
const statuses = this.$refs.timeline.children
|
||||
const cappedScrollIndex = Math.max(0, Math.min(this.virtualScrollIndex, statuses.length - 1))
|
||||
const cappedScrollIndex = Math.max(
|
||||
0,
|
||||
Math.min(this.virtualScrollIndex, statuses.length - 1),
|
||||
)
|
||||
|
||||
if (statuses.length === 0) return
|
||||
|
||||
const height = Math.max(document.body.offsetHeight, window.pageYOffset)
|
||||
|
||||
const centerOfScreen = window.pageYOffset + (window.innerHeight * 0.5)
|
||||
const centerOfScreen = window.pageYOffset + window.innerHeight * 0.5
|
||||
|
||||
// Start from approximating the index of some visible status by using the
|
||||
// the center of the screen on the timeline.
|
||||
|
|
@ -219,7 +266,8 @@ const Timeline = {
|
|||
// if we have a previous scroll index that can be used, test if it's
|
||||
// closer than the previous approximation, use it if so
|
||||
|
||||
const virtualScrollIndexY = statuses[cappedScrollIndex].getBoundingClientRect().y
|
||||
const virtualScrollIndexY =
|
||||
statuses[cappedScrollIndex].getBoundingClientRect().y
|
||||
if (Math.abs(err) > virtualScrollIndexY) {
|
||||
approxIndex = cappedScrollIndex
|
||||
err = virtualScrollIndexY
|
||||
|
|
@ -240,12 +288,14 @@ const Timeline = {
|
|||
// statuses will be nearby statuses before and after it
|
||||
this.virtualScrollIndex = approxIndex
|
||||
},
|
||||
scrollLoad () {
|
||||
scrollLoad() {
|
||||
const bodyBRect = document.body.getBoundingClientRect()
|
||||
const height = Math.max(bodyBRect.height, -(bodyBRect.y))
|
||||
if (this.timeline.loading === false &&
|
||||
this.$el.offsetHeight > 0 &&
|
||||
(window.innerHeight + window.pageYOffset) >= (height - 750)) {
|
||||
const height = Math.max(bodyBRect.height, -bodyBRect.y)
|
||||
if (
|
||||
this.timeline.loading === false &&
|
||||
this.$el.offsetHeight > 0 &&
|
||||
window.innerHeight + window.pageYOffset >= height - 750
|
||||
) {
|
||||
this.fetchOlderStatuses()
|
||||
}
|
||||
},
|
||||
|
|
@ -253,12 +303,12 @@ const Timeline = {
|
|||
this.determineVisibleStatuses()
|
||||
this.scrollLoad(e)
|
||||
}, 200),
|
||||
handleVisibilityChange () {
|
||||
handleVisibilityChange() {
|
||||
this.unfocused = document.hidden
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
newStatusCount (count) {
|
||||
newStatusCount(count) {
|
||||
if (!this.$store.getters.mergedConfig.streaming) {
|
||||
return
|
||||
}
|
||||
|
|
@ -266,17 +316,18 @@ const Timeline = {
|
|||
// only 'stream' them when you're scrolled to the top
|
||||
const doc = document.documentElement
|
||||
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
|
||||
if (top < 15 &&
|
||||
!this.paused &&
|
||||
!(this.unfocused && this.$store.getters.mergedConfig.pauseOnUnfocused)
|
||||
if (
|
||||
top < 15 &&
|
||||
!this.paused &&
|
||||
!(this.unfocused && this.$store.getters.mergedConfig.pauseOnUnfocused)
|
||||
) {
|
||||
this.showNewStatuses()
|
||||
} else {
|
||||
this.paused = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default Timeline
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue