diff options
| -rw-r--r-- | src/App.js | 23 | ||||
| -rw-r--r-- | src/App.scss | 7 | ||||
| -rw-r--r-- | src/App.vue | 2 | ||||
| -rw-r--r-- | src/components/settings/settings.js | 4 | ||||
| -rw-r--r-- | src/components/settings/settings.vue | 4 | ||||
| -rw-r--r-- | src/components/status/status.vue | 16 | ||||
| -rw-r--r-- | src/components/timeline/timeline.js | 24 | ||||
| -rw-r--r-- | src/i18n/messages.js | 2 | ||||
| -rw-r--r-- | src/modules/config.js | 1 | ||||
| -rw-r--r-- | src/modules/statuses.js | 8 |
10 files changed, 84 insertions, 7 deletions
@@ -23,6 +23,18 @@ export default { style () { return { 'background-image': `url(${this.background})` } }, sitename () { return this.$store.state.config.name } }, + created () { + // this is to detect user zooming mostly + window.addEventListener('resize', this.fixSidebarWidth) + }, + mounted () { + // for some reason, at least in dev mode, dom is not ready enough at this point + // in theory calling the function directly here should be enough, but it's not + setTimeout(() => { this.fixSidebarWidth() }, 500) + }, + destroyed () { + window.removeEventListener('resize', this.fixSidebarWidth) + }, methods: { activatePanel (panelName) { this.mobileActivePanel = panelName @@ -32,6 +44,17 @@ export default { }, logout () { this.$store.dispatch('logout') + }, + fixSidebarWidth () { + // firefox + let barwidth = window.innerWidth - document.body.offsetWidth + if (document.body.offsetWidth <= 0) { + // chromium + barwidth = window.innerWidth - document.body.scrollWidth + } + // adjust the sidebar size to fit the scrollbar width to keep the gap consistently sized + document.getElementById('sidebar-container').style.width = `${345 + barwidth}px` + document.getElementById('sidebar-container').style.paddingRight = `${barwidth}px` } } } diff --git a/src/App.scss b/src/App.scss index f10c3d65..c3c9013e 100644 --- a/src/App.scss +++ b/src/App.scss @@ -219,16 +219,19 @@ nav { } @media all and (min-width: 960px) { + body { + overflow-y: scroll; + } .sidebar { overflow: hidden; max-height: 100vh; - width: 350px; + width: 345px; position: fixed; margin-top: -10px; .sidebar-container { height: 96vh; - width: 362px; + width: 365px; padding-top: 10px; padding-right: 20px; overflow-x: hidden; diff --git a/src/App.vue b/src/App.vue index 8e802a02..59cfcaa6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -19,7 +19,7 @@ </div> <div class="sidebar-flexer" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar'}"> <div class="sidebar" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar' }"> - <div class="sidebar-container"> + <div class="sidebar-container" id="sidebar-container"> <user-panel></user-panel> <nav-panel></nav-panel> <notifications v-if="currentUser"></notifications> diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index b3bb8290..b88937bb 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -9,6 +9,7 @@ const settings = { hideNsfwLocal: this.$store.state.config.hideNsfw, muteWordsString: this.$store.state.config.muteWords.join('\n'), autoLoadLocal: this.$store.state.config.autoLoad, + streamingLocal: this.$store.state.config.streaming, hoverPreviewLocal: this.$store.state.config.hoverPreview } }, @@ -33,6 +34,9 @@ const settings = { autoLoadLocal (value) { this.$store.dispatch('setOption', { name: 'autoLoad', value }) }, + streamingLocal (value) { + this.$store.dispatch('setOption', { name: 'streaming', value }) + }, hoverPreviewLocal (value) { this.$store.dispatch('setOption', { name: 'hoverPreview', value }) }, diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index 5978e4ed..6a311d55 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -33,6 +33,10 @@ <label for="autoLoad">{{$t('settings.autoload')}}</label> </li> <li> + <input type="checkbox" id="streaming" v-model="streamingLocal"> + <label for="streaming">{{$t('settings.streaming')}}</label> + </li> + <li> <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal"> <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label> </li> diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 8d6dce67..84397bfa 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -14,7 +14,7 @@ </div> <post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" v-on:posted="toggleReplying" v-if="replying"/> </div> - <div class="status-el base00-background base03-border" v-else-if="!status.deleted" v-bind:class="[{ 'base01-background': isFocused }, { 'status-conversation': inConversation }]" > + <div class="status-el base00-background base03-border status-fadein" v-else-if="!status.deleted" v-bind:class="[{ 'base01-background': isFocused }, { 'status-conversation': inConversation }]" > <template v-if="muted"> <div class="media status container muted"> <small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small> @@ -232,6 +232,20 @@ } } + .status-fadein { + animation-duration: 0.5s; + animation-name: fadein; + } + + @keyframes fadein { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + .greentext { color: green; } diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 6968bc6f..613b8a34 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -11,6 +11,11 @@ const Timeline = { 'userId', 'tag' ], + data () { + return { + paused: false + } + }, computed: { timelineError () { return this.$store.state.statuses.error }, followers () { @@ -21,6 +26,9 @@ const Timeline = { }, viewing () { return this.timeline.viewing + }, + newStatusCount () { + return this.timeline.newStatusCount } }, components: { @@ -56,6 +64,7 @@ const Timeline = { methods: { showNewStatuses () { this.$store.commit('showNewStatuses', { timeline: this.timelineName }) + this.paused = false }, fetchOlderStatuses () { const store = this.$store @@ -90,6 +99,21 @@ const Timeline = { this.fetchOlderStatuses() } } + }, + watch: { + newStatusCount (count) { + if (!this.$store.state.config.streaming) { + return + } + if (count > 0) { + // only 'stream' them when you're scrolled to the top + if (window.pageYOffset < 15 && !this.paused) { + this.showNewStatuses() + } else { + this.paused = true + } + } + } } } diff --git a/src/i18n/messages.js b/src/i18n/messages.js index b9a4f756..cedb7fd7 100644 --- a/src/i18n/messages.js +++ b/src/i18n/messages.js @@ -103,6 +103,7 @@ const fi = { hide_attachments_in_convo: 'Piilota liitteet keskusteluissa', nsfw_clickthrough: 'Piilota NSFW liitteet klikkauksen taakse.', autoload: 'Lataa vanhempia viestejä automaattisesti ruudun pohjalla', + streaming: 'Näytä uudet viestit automaattisesti ollessasi ruudun huipulla', reply_link_preview: 'Keskusteluiden vastauslinkkien esikatselu' }, notifications: { @@ -186,6 +187,7 @@ const en = { hide_attachments_in_convo: 'Hide attachments in conversations', nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding', autoload: 'Enable automatic loading when scrolled to the bottom', + streaming: 'Enable automatic streaming of new posts when scrolled to the top', reply_link_preview: 'Enable reply-link preview on mouse hover' }, notifications: { diff --git a/src/modules/config.js b/src/modules/config.js index f7d6e9c8..ac17747e 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -8,6 +8,7 @@ const defaultState = { hideAttachmentsInConv: false, hideNsfw: true, autoLoad: true, + streaming: false, hoverPreview: true, muteWords: [] } diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 884ba0ef..6d4b4843 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -131,7 +131,7 @@ export const statusType = (status) => { return 'favorite' } - if (status.text.match(/deleted notice {{tag/)) { + if (status.text.match(/deleted notice {{tag/) || status.qvitter_delete_notice) { return 'deletion' } @@ -211,8 +211,10 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us sortTimeline(mentions) } - - addNotification({ type: 'mention', status, action: status }) + // Don't add notification for self-mention + if (status.user.id !== user.id) { + addNotification({ type: 'mention', status, action: status }) + } } } |
