diff options
Diffstat (limited to 'src/components/timeline')
| -rw-r--r-- | src/components/timeline/timeline.js | 35 | ||||
| -rw-r--r-- | src/components/timeline/timeline.scss | 31 | ||||
| -rw-r--r-- | src/components/timeline/timeline.vue | 91 | ||||
| -rw-r--r-- | src/components/timeline/timeline_quick_settings.js | 67 | ||||
| -rw-r--r-- | src/components/timeline/timeline_quick_settings.vue | 109 |
5 files changed, 136 insertions, 197 deletions
diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index c575e876..b7414610 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -1,15 +1,21 @@ import Status from '../status/status.vue' +import { mapState } from 'vuex' import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js' import Conversation from '../conversation/conversation.vue' import TimelineMenu from '../timeline_menu/timeline_menu.vue' -import TimelineQuickSettings from './timeline_quick_settings.vue' +import QuickFilterSettings from '../quick_filter_settings/quick_filter_settings.vue' +import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue' import { debounce, throttle, keyBy } from 'lodash' import { library } from '@fortawesome/fontawesome-svg-core' -import { faCircleNotch, faCog } from '@fortawesome/free-solid-svg-icons' +import { faCircleNotch, faCirclePlus, faCog, faMinus, faArrowUp, faCheck } from '@fortawesome/free-solid-svg-icons' library.add( faCircleNotch, - faCog + faCog, + faMinus, + faArrowUp, + faCirclePlus, + faCheck ) const Timeline = { @@ -18,6 +24,7 @@ const Timeline = { 'timelineName', 'title', 'userId', + 'listId', 'tag', 'embedded', 'count', @@ -27,6 +34,7 @@ const Timeline = { ], data () { return { + showScrollTop: false, paused: false, unfocused: false, bottomedOut: false, @@ -38,7 +46,8 @@ const Timeline = { Status, Conversation, TimelineMenu, - TimelineQuickSettings + QuickFilterSettings, + QuickViewSettings }, computed: { filteredVisibleStatuses () { @@ -60,6 +69,13 @@ const Timeline = { return `${this.$t('timeline.show_new')} (${this.newStatusCount})` } }, + mobileLoadButtonString () { + if (this.timeline.flushMarker !== 0) { + return '+' + } else { + return this.newStatusCount > 99 ? '∞' : this.newStatusCount + } + }, classes () { let rootClasses = !this.embedded ? ['panel', 'panel-default'] : ['-nonpanel'] if (this.blockingClicks) rootClasses = rootClasses.concat(['-blocked', '_misclick-prevention']) @@ -84,7 +100,10 @@ const Timeline = { }, virtualScrollingEnabled () { return this.$store.getters.mergedConfig.virtualScrolling - } + }, + ...mapState({ + mobileLayout: state => state.interface.layoutType === 'mobile' + }) }, created () { const store = this.$store @@ -101,6 +120,7 @@ const Timeline = { timeline: this.timelineName, showImmediately, userId: this.userId, + listId: this.listId, tag: this.tag }) }, @@ -119,6 +139,9 @@ const Timeline = { this.$store.commit('setLoading', { timeline: this.timelineName, value: false }) }, methods: { + scrollToTop () { + window.scrollTo({ top: this.$el.offsetTop }) + }, stopBlockingClicks: debounce(function () { this.blockingClicks = false }, 1000), @@ -156,6 +179,7 @@ const Timeline = { older: true, showImmediately: true, userId: this.userId, + listId: this.listId, tag: this.tag }).then(({ statuses }) => { if (statuses && statuses.length === 0) { @@ -217,6 +241,7 @@ const Timeline = { } }, handleScroll: throttle(function (e) { + this.showScrollTop = this.$el.offsetTop < window.scrollY this.determineVisibleStatuses() this.scrollLoad(e) }, 200), diff --git a/src/components/timeline/timeline.scss b/src/components/timeline/timeline.scss index 9e009fd3..c6fb1ca7 100644 --- a/src/components/timeline/timeline.scss +++ b/src/components/timeline/timeline.scss @@ -1,8 +1,35 @@ @import '../../_variables.scss'; .Timeline { - .loadmore-text { - opacity: 1; + .alert-dot { + border-radius: 100%; + height: 8px; + width: 8px; + position: absolute; + left: calc(50% - 4px); + top: calc(50% - 4px); + margin-left: 6px; + margin-top: -6px; + background-color: var(--badgeNeutral); + } + + .alert-badge { + font-size: 0.75em; + line-height: 1; + text-align: right; + border-radius: var(--tooltipRadius); + position: absolute; + left: calc(50% - 0.5em); + top: calc(50% - 0.4em); + padding: 0.2em; + margin-left: 0.7em; + margin-top: -1em; + background-color: var(--badgeNeutral); + color: var(--badgeNeutralText); + } + + .loadmore-button { + position: relative; } &.-blocked { diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index f65881b6..877a0cc0 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -1,31 +1,90 @@ <template> <div :class="['Timeline', classes.root]"> <div :class="classes.header"> - <TimelineMenu v-if="!embedded" /> - <button - v-if="showLoadButton" - class="button-default loadmore-button" - @click.prevent="showNewStatuses" - > - {{ loadButtonString }} - </button> + <TimelineMenu + v-if="!embedded" + :timeline-name="timelineName" + /> <div - v-else-if="!embedded" - class="loadmore-text faint" - @click.prevent + class="rightside-button" + v-if="showScrollTop && !embedded" > - {{ $t('timeline.up_to_date') }} + <button + class="button-unstyled scroll-to-top-button" + type="button" + :title="$t('general.scroll_to_top')" + @click="scrollToTop" + > + <FALayers class="fa-scale-110 fa-old-padding-layer"> + <FAIcon icon="arrow-up" /> + <FAIcon + icon="minus" + transform="up-7" + /> + </FALayers> + </button> </div> - <TimelineQuickSettings v-if="!embedded" /> + <template v-if="mobileLayout && !embedded"> + <div + class="rightside-button" + v-if="showLoadButton" + > + <button + class="button-unstyled loadmore-button" + :title="loadButtonString" + @click.prevent="showNewStatuses" + > + <FAIcon + fixed-width + icon="circle-plus" + /> + <div class="alert-badge"> + {{ mobileLoadButtonString }} + </div> + </button> + </div> + <div + v-else-if="!embedded" + class="loadmore-text faint veryfaint rightside-icon" + :title="$t('timeline.up_to_date')" + :aria-disabled="true" + @click.prevent + > + <FAIcon + fixed-width + icon="check" + /> + </div> + </template> + <template v-else> + <button + v-if="showLoadButton" + class="button-default loadmore-button" + @click.prevent="showNewStatuses" + > + {{ loadButtonString }} + </button> + <div + v-else-if="!embedded" + class="loadmore-text faint" + @click.prevent + > + {{ $t('timeline.up_to_date') }} + </div> + </template> + <QuickFilterSettings v-if="!embedded" class="rightside-button"/> + <QuickViewSettings v-if="!embedded" class="rightside-button"/> </div> <div :class="classes.body"> <div ref="timeline" class="timeline" + role="feed" > <conversation v-for="statusId in filteredPinnedStatusIds" :key="statusId + '-pinned'" + role="listitem" class="status-fadein" :status-id="statusId" :collapsable="true" @@ -36,6 +95,7 @@ <conversation v-for="status in filteredVisibleStatuses" :key="status.id" + role="listitem" class="status-fadein" :status-id="status.id" :collapsable="true" @@ -46,7 +106,10 @@ </div> </div> <div :class="classes.footer"> - <teleport :to="footerSlipgate" :disabled="!embedded || !footerSlipgate"> + <teleport + :to="footerSlipgate" + :disabled="!embedded || !footerSlipgate" + > <div v-if="count===0" class="new-status-notification text-center faint" diff --git a/src/components/timeline/timeline_quick_settings.js b/src/components/timeline/timeline_quick_settings.js deleted file mode 100644 index 92d5ac14..00000000 --- a/src/components/timeline/timeline_quick_settings.js +++ /dev/null @@ -1,67 +0,0 @@ -import Popover from '../popover/popover.vue' -import { mapGetters } from 'vuex' -import { library } from '@fortawesome/fontawesome-svg-core' -import { faFilter, faFont, faWrench } from '@fortawesome/free-solid-svg-icons' - -library.add( - faFilter, - faFont, - faWrench -) - -const TimelineQuickSettings = { - components: { - Popover - }, - methods: { - setReplyVisibility (visibility) { - this.$store.dispatch('setOption', { name: 'replyVisibility', value: visibility }) - this.$store.dispatch('queueFlushAll') - }, - openTab (tab) { - this.$store.dispatch('openSettingsModalTab', tab) - } - }, - computed: { - ...mapGetters(['mergedConfig']), - loggedIn () { - return !!this.$store.state.users.currentUser - }, - replyVisibilitySelf: { - get () { return this.mergedConfig.replyVisibility === 'self' }, - set () { this.setReplyVisibility('self') } - }, - replyVisibilityFollowing: { - get () { return this.mergedConfig.replyVisibility === 'following' }, - set () { this.setReplyVisibility('following') } - }, - replyVisibilityAll: { - get () { return this.mergedConfig.replyVisibility === 'all' }, - set () { this.setReplyVisibility('all') } - }, - hideMedia: { - get () { return this.mergedConfig.hideAttachments || this.mergedConfig.hideAttachmentsInConv }, - set () { - const value = !this.hideMedia - this.$store.dispatch('setOption', { name: 'hideAttachments', value }) - this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value }) - } - }, - hideMutedPosts: { - get () { return this.mergedConfig.hideFilteredStatuses }, - set () { - const value = !this.hideMutedPosts - this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value }) - } - }, - muteBotStatuses: { - get () { return this.mergedConfig.muteBotStatuses }, - set () { - const value = !this.muteBotStatuses - this.$store.dispatch('setOption', { name: 'muteBotStatuses', value }) - } - } - } -} - -export default TimelineQuickSettings diff --git a/src/components/timeline/timeline_quick_settings.vue b/src/components/timeline/timeline_quick_settings.vue deleted file mode 100644 index 98fab926..00000000 --- a/src/components/timeline/timeline_quick_settings.vue +++ /dev/null @@ -1,109 +0,0 @@ -<template> - <Popover - trigger="click" - class="TimelineQuickSettings" - :bound-to="{ x: 'container' }" - > - <template v-slot:content> - <div class="dropdown-menu"> - <div v-if="loggedIn"> - <button - class="button-default dropdown-item" - @click="replyVisibilityAll = true" - > - <span - class="menu-checkbox -radio" - :class="{ 'menu-checkbox-checked': replyVisibilityAll }" - />{{ $t('settings.reply_visibility_all') }} - </button> - <button - class="button-default dropdown-item" - @click="replyVisibilityFollowing = true" - > - <span - class="menu-checkbox -radio" - :class="{ 'menu-checkbox-checked': replyVisibilityFollowing }" - />{{ $t('settings.reply_visibility_following_short') }} - </button> - <button - class="button-default dropdown-item" - @click="replyVisibilitySelf = true" - > - <span - class="menu-checkbox -radio" - :class="{ 'menu-checkbox-checked': replyVisibilitySelf }" - />{{ $t('settings.reply_visibility_self_short') }} - </button> - <div - role="separator" - class="dropdown-divider" - /> - </div> - <button - class="button-default dropdown-item" - @click="muteBotStatuses = !muteBotStatuses" - > - <span - class="menu-checkbox" - :class="{ 'menu-checkbox-checked': muteBotStatuses }" - />{{ $t('settings.mute_bot_posts') }} - </button> - <button - class="button-default dropdown-item" - @click="hideMedia = !hideMedia" - > - <span - class="menu-checkbox" - :class="{ 'menu-checkbox-checked': hideMedia }" - />{{ $t('settings.hide_media_previews') }} - </button> - <button - class="button-default dropdown-item" - @click="hideMutedPosts = !hideMutedPosts" - > - <span - class="menu-checkbox" - :class="{ 'menu-checkbox-checked': hideMutedPosts }" - />{{ $t('settings.hide_all_muted_posts') }} - </button> - <button - class="button-default dropdown-item dropdown-item-icon" - @click="openTab('filtering')" - > - <FAIcon icon="font" />{{ $t('settings.word_filter') }} - </button> - <button - class="button-default dropdown-item dropdown-item-icon" - @click="openTab('general')" - > - <FAIcon icon="wrench" />{{ $t('settings.more_settings') }} - </button> - </div> - </template> - <template v-slot:trigger> - <button class="button-unstyled"> - <FAIcon icon="filter" /> - </button> - </template> - </Popover> -</template> - -<script src="./timeline_quick_settings.js"></script> - -<style lang="scss"> - -.TimelineQuickSettings { - - > button { - line-height: 100%; - height: 100%; - width: var(--__panel-heading-height-inner); - text-align: center; - - svg { - font-size: 1.2em; - } - } -} - -</style> |
