diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/chat/chat.js | 10 | ||||
| -rw-r--r-- | src/components/conversation/conversation.js | 6 | ||||
| -rw-r--r-- | src/components/conversation/conversation.vue | 8 | ||||
| -rw-r--r-- | src/components/quick_filter_settings/quick_filter_settings.js (renamed from src/components/timeline/timeline_quick_settings.js) | 7 | ||||
| -rw-r--r-- | src/components/quick_filter_settings/quick_filter_settings.vue (renamed from src/components/timeline/timeline_quick_settings.vue) | 18 | ||||
| -rw-r--r-- | src/components/quick_view_settings/quick_view_settings.js | 69 | ||||
| -rw-r--r-- | src/components/quick_view_settings/quick_view_settings.vue | 94 | ||||
| -rw-r--r-- | src/components/timeline/timeline.js | 6 | ||||
| -rw-r--r-- | src/components/timeline/timeline.vue | 3 | ||||
| -rw-r--r-- | src/components/update_notification/update_notification.js | 66 | ||||
| -rw-r--r-- | src/components/update_notification/update_notification.scss | 107 | ||||
| -rw-r--r-- | src/components/update_notification/update_notification.vue | 100 |
12 files changed, 474 insertions, 20 deletions
diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index 5a5c37b6..79f24771 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -57,6 +57,7 @@ const Chat = { }, unmounted () { window.removeEventListener('scroll', this.handleScroll) + window.removeEventListener('resize', this.handleResize) if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false) this.$store.dispatch('clearCurrentChat') }, @@ -135,7 +136,7 @@ const Chat = { }, // "Sticks" scroll to bottom instead of top, helps with OSK resizing the viewport handleResize (opts = {}) { - const { expand = false, delayed = false } = opts + const { delayed = false } = opts if (delayed) { setTimeout(() => { @@ -146,10 +147,10 @@ const Chat = { this.$nextTick(() => { const { offsetHeight = undefined } = getScrollPosition() - const diff = this.lastScrollPosition.offsetHeight - offsetHeight - if (diff !== 0 || (!this.bottomedOut() && expand)) { + const diff = offsetHeight - this.lastScrollPosition.offsetHeight + if (diff !== 0 && !this.bottomedOut()) { this.$nextTick(() => { - window.scrollTo({ top: window.scrollY + diff }) + window.scrollBy({ top: -Math.trunc(diff) }) }) } this.lastScrollPosition = getScrollPosition() @@ -187,6 +188,7 @@ const Chat = { }, 5000) }, handleScroll: _.throttle(function () { + this.lastScrollPosition = getScrollPosition() if (!this.currentChat) { return } if (this.reachedTop()) { diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 3b540cac..712e2a2c 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -1,6 +1,8 @@ import { reduce, filter, findIndex, clone, get } from 'lodash' import Status from '../status/status.vue' import ThreadTree from '../thread_tree/thread_tree.vue' +import QuickFilterSettings from '../quick_filter_settings/quick_filter_settings.vue' +import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -343,7 +345,9 @@ const conversation = { }, components: { Status, - ThreadTree + ThreadTree, + QuickFilterSettings, + QuickViewSettings }, watch: { statusId (newVal, oldVal) { diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 1adbe250..61832566 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -17,6 +17,14 @@ > {{ $t('timeline.collapse') }} </button> + <QuickFilterSettings + v-if="!collapsable" + :conversation="true" + /> + <QuickViewSettings + v-if="!collapsable" + :conversation="true" + /> </div> <div class="conversation-body panel-body"> <div diff --git a/src/components/timeline/timeline_quick_settings.js b/src/components/quick_filter_settings/quick_filter_settings.js index 92d5ac14..e67e3a4b 100644 --- a/src/components/timeline/timeline_quick_settings.js +++ b/src/components/quick_filter_settings/quick_filter_settings.js @@ -9,7 +9,10 @@ library.add( faWrench ) -const TimelineQuickSettings = { +const QuickFilterSettings = { + props: { + conversation: Boolean + }, components: { Popover }, @@ -64,4 +67,4 @@ const TimelineQuickSettings = { } } -export default TimelineQuickSettings +export default QuickFilterSettings diff --git a/src/components/timeline/timeline_quick_settings.vue b/src/components/quick_filter_settings/quick_filter_settings.vue index 297bc72a..982238e7 100644 --- a/src/components/timeline/timeline_quick_settings.vue +++ b/src/components/quick_filter_settings/quick_filter_settings.vue @@ -1,13 +1,14 @@ <template> <Popover trigger="click" - class="TimelineQuickSettings" + class="QuickFilterSettings" :bound-to="{ x: 'container' }" > <template #content> <div class="dropdown-menu"> <div v-if="loggedIn"> <button + v-if="!conversation" class="button-default dropdown-item" @click="replyVisibilityAll = true" > @@ -17,6 +18,7 @@ />{{ $t('settings.reply_visibility_all') }} </button> <button + v-if="!conversation" class="button-default dropdown-item" @click="replyVisibilityFollowing = true" > @@ -26,6 +28,7 @@ />{{ $t('settings.reply_visibility_following_short') }} </button> <button + v-if="!conversation" class="button-default dropdown-item" @click="replyVisibilitySelf = true" > @@ -35,6 +38,7 @@ />{{ $t('settings.reply_visibility_self_short') }} </button> <div + v-if="!conversation" role="separator" class="dropdown-divider" /> @@ -70,13 +74,7 @@ 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') }} + <FAIcon icon="font" />{{ $t('settings.word_filter_and_more') }} </button> </div> </template> @@ -88,11 +86,11 @@ </Popover> </template> -<script src="./timeline_quick_settings.js"></script> +<script src="./quick_filter_settings.js"></script> <style lang="scss"> -.TimelineQuickSettings { +.QuickFilterSettings { > button { line-height: 100%; diff --git a/src/components/quick_view_settings/quick_view_settings.js b/src/components/quick_view_settings/quick_view_settings.js new file mode 100644 index 00000000..2798f37a --- /dev/null +++ b/src/components/quick_view_settings/quick_view_settings.js @@ -0,0 +1,69 @@ +import Popover from '../popover/popover.vue' +import { mapGetters } from 'vuex' +import { library } from '@fortawesome/fontawesome-svg-core' +import { faList, faFolderTree, faBars, faWrench } from '@fortawesome/free-solid-svg-icons' + +library.add( + faList, + faFolderTree, + faBars, + faWrench +) + +const QuickViewSettings = { + props: { + conversation: Boolean + }, + components: { + Popover + }, + methods: { + setConversationDisplay (visibility) { + this.$store.dispatch('setOption', { name: 'conversationDisplay', value: visibility }) + }, + openTab (tab) { + this.$store.dispatch('openSettingsModalTab', tab) + } + }, + computed: { + ...mapGetters(['mergedConfig']), + loggedIn () { + return !!this.$store.state.users.currentUser + }, + conversationDisplay: { + get () { return this.mergedConfig.conversationDisplay }, + set (newVal) { this.setConversationDisplay(newVal) } + }, + autoUpdate: { + get () { return this.mergedConfig.streaming }, + set () { + const value = !this.autoUpdate + this.$store.dispatch('setOption', { name: 'streaming', value }) + } + }, + collapseWithSubjects: { + get () { return this.mergedConfig.collapseMessageWithSubject }, + set () { + const value = !this.collapseWithSubjects + this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value }) + } + }, + showUserAvatars: { + get () { return this.mergedConfig.mentionLinkShowAvatar }, + set () { + const value = !this.showUserAvatars + console.log(value) + this.$store.dispatch('setOption', { name: 'mentionLinkShowAvatar', value }) + } + }, + muteBotStatuses: { + get () { return this.mergedConfig.muteBotStatuses }, + set () { + const value = !this.muteBotStatuses + this.$store.dispatch('setOption', { name: 'muteBotStatuses', value }) + } + } + } +} + +export default QuickViewSettings diff --git a/src/components/quick_view_settings/quick_view_settings.vue b/src/components/quick_view_settings/quick_view_settings.vue new file mode 100644 index 00000000..99b14a66 --- /dev/null +++ b/src/components/quick_view_settings/quick_view_settings.vue @@ -0,0 +1,94 @@ +<template> + <Popover + trigger="click" + class="QuickViewSettings" + :bound-to="{ x: 'container' }" + > + <template #content> + <div class="dropdown-menu"> + <button + class="button-default dropdown-item" + @click="conversationDisplay = 'tree'" + > + <span + class="menu-checkbox -radio" + :class="{ 'menu-checkbox-checked': conversationDisplay === 'tree' }" + /><FAIcon icon="folder-tree" /> {{ $t('settings.conversation_display_tree_quick') }} + </button> + <button + class="button-default dropdown-item" + @click="conversationDisplay = 'linear'" + > + <span + class="menu-checkbox -radio" + :class="{ 'menu-checkbox-checked': conversationDisplay === 'linear' }" + /><FAIcon icon="list" /> {{ $t('settings.conversation_display_linear_quick') }} + </button> + <div + role="separator" + class="dropdown-divider" + /> + <button + class="button-default dropdown-item" + @click="showUserAvatars = !showUserAvatars" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-checked': showUserAvatars }" + />{{ $t('settings.mention_link_show_avatar_quick') }} + </button> + <button + v-if="!conversation" + class="button-default dropdown-item" + @click="autoUpdate = !autoUpdate" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-checked': autoUpdate }" + />{{ $t('settings.auto_update') }} + </button> + <button + v-if="!conversation" + class="button-default dropdown-item" + @click="collapseWithSubjects = !collapseWithSubjects" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-checked': collapseWithSubjects }" + />{{ $t('settings.collapse_subject') }} + </button> + <button + class="button-default dropdown-item dropdown-item-icon" + @click="openTab('general')" + > + <FAIcon icon="wrench" />{{ $t('settings.more_settings') }} + </button> + </div> + </template> + <template #trigger> + <button class="button-unstyled"> + <FAIcon icon="bars" /> + </button> + </template> + </Popover> +</template> + +<script src="./quick_view_settings.js"></script> + +<style lang="scss"> + +.QuickViewSettings { + + > button { + line-height: 100%; + height: 100%; + width: var(--__panel-heading-height-inner); + text-align: center; + + svg { + font-size: 1.2em; + } + } +} + +</style> diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 5b6c5089..8f6cae66 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -2,7 +2,8 @@ import Status from '../status/status.vue' 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' @@ -39,7 +40,8 @@ const Timeline = { Status, Conversation, TimelineMenu, - TimelineQuickSettings + QuickFilterSettings, + QuickViewSettings }, computed: { filteredVisibleStatuses () { diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index 266c1d9a..627cafbb 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -16,7 +16,8 @@ > {{ $t('timeline.up_to_date') }} </div> - <TimelineQuickSettings v-if="!embedded" /> + <QuickFilterSettings v-if="!embedded" /> + <QuickViewSettings v-if="!embedded" /> </div> <div :class="classes.body"> <div diff --git a/src/components/update_notification/update_notification.js b/src/components/update_notification/update_notification.js new file mode 100644 index 00000000..ba008d81 --- /dev/null +++ b/src/components/update_notification/update_notification.js @@ -0,0 +1,66 @@ +import Modal from 'src/components/modal/modal.vue' +import { library } from '@fortawesome/fontawesome-svg-core' +import pleromaTan from 'src/assets/pleromatan_apology.png' +import pleromaTanFox from 'src/assets/pleromatan_apology_fox.png' + +import { + faTimes +} from '@fortawesome/free-solid-svg-icons' +library.add( + faTimes +) + +export const CURRENT_UPDATE_COUNTER = 1 + +const UpdateNotification = { + data () { + return { + pleromaTanVariant: Math.random() > 0.5 ? pleromaTan : pleromaTanFox, + showingMore: false, + contentHeight: 0 + } + }, + components: { + Modal + }, + computed: { + pleromaTanStyles () { + return { + 'shape-outside': 'url(' + this.pleromaTanVariant + ')' + } + }, + dynamicStyles () { + return { + '--____extraInfoGroupHeight': this.contentHeight + 'px' + } + }, + shouldShow () { + return !this.$store.state.instance.disableUpdateNotification && + this.$store.state.users.currentUser && + this.$store.state.serverSideStorage.flagStorage.updateCounter < CURRENT_UPDATE_COUNTER && + !this.$store.state.serverSideStorage.flagStorage.dontShowUpdateNotifs + } + }, + methods: { + toggleShow () { + this.showingMore = !this.showingMore + }, + neverShowAgain () { + this.toggleShow() + this.$store.commit('setFlag', { flag: 'updateCounter', value: CURRENT_UPDATE_COUNTER }) + this.$store.commit('setFlag', { flag: 'dontShowUpdateNotifs', value: 1 }) + this.$store.dispatch('pushServerSideStorage') + }, + dismiss () { + this.$store.commit('setFlag', { flag: 'updateCounter', value: CURRENT_UPDATE_COUNTER }) + this.$store.dispatch('pushServerSideStorage') + } + }, + mounted () { + setTimeout(() => { + this.contentHeight = this.$refs.animatedText.scrollHeight + }, 1000) + } +} + +export default UpdateNotification diff --git a/src/components/update_notification/update_notification.scss b/src/components/update_notification/update_notification.scss new file mode 100644 index 00000000..8cad1bc7 --- /dev/null +++ b/src/components/update_notification/update_notification.scss @@ -0,0 +1,107 @@ +@import 'src/_variables.scss'; +.UpdateNotification { + overflow: hidden; +} + +.UpdateNotificationModal { + --__top-fringe: 15em; // how much pleroma-tan should stick her head above + --__bottom-fringe: 80em; // just reserving as much as we can, number is mostly irrelevant + --__right-fringe: 8em; + + font-size: 15px; + position: relative; + transition: transform; + transition-timing-function: ease-in-out; + transition-duration: 500ms; + + .text { + max-width: 40em; + padding-left: 1em; + } + + @media all and (max-width: 800px) { + /* For mobile, the modal takes 100% of the available screen. + This ensures the minimized modal is always 50px above the browser bottom bar regardless of whether or not it is visible. + */ + width: 100vw; + } + + @media all and (max-height: 600px) { + display: none; + } + + .content { + overflow: hidden; + margin-top: calc(-1 * var(--__top-fringe)); + margin-bottom: calc(-1 * var(--__bottom-fringe)); + margin-right: calc(-1 * var(--__right-fringe)); + } + + .panel-body { + border-width: 0 0 1px 0; + border-style: solid; + border-color: var(--border, $fallback--border); + } + + .panel-footer { + z-index: 22; + position: relative; + border-width: 0; + grid-template-columns: auto; + } + + .pleroma-tan { + object-fit: cover; + object-position: top; + transition: position, left, right, top, bottom, max-width, max-height; + transition-timing-function: ease-in-out; + transition-duration: 500ms; + width: 25em; + float: right; + z-index: 20; + position: relative; + shape-margin: 0.5em; + filter: drop-shadow(5px 5px 10px rgba(0,0,0,0.5)); + pointer-events: none; + } + + .spacer-top { + min-height: var(--__top-fringe); + } + + .spacer-bottom { + min-height: var(--__bottom-fringe); + } + + .extra-info-group { + transition: max-height, padding, height; + transition-timing-function: ease-in-out; + transition-duration: 500ms; + max-height: calc(var(--____extraInfoGroupHeight) + 1em); // include bottom padding + mask: + linear-gradient(to top, white, transparent) bottom/100% 2px no-repeat, + linear-gradient(to top, white, white); + } + + .art-credit { + text-align: right; + } + + &.-peek { + /* Explanation: + * 100vh - 100% = Distance between modal's top+bottom boundaries and screen + * (100vh - 100%) / 2 = Distance between bottom (or top) boundary and screen + */ + transform: translateY(calc(((100vh - 100%) / 2))); + + .pleroma-tan { + float: right; + z-index: 10; + shape-image-threshold: 0.7; + } + + .extra-info-group { + max-height: 0; + } + } +} diff --git a/src/components/update_notification/update_notification.vue b/src/components/update_notification/update_notification.vue new file mode 100644 index 00000000..d0e2499c --- /dev/null +++ b/src/components/update_notification/update_notification.vue @@ -0,0 +1,100 @@ +<template> + <Modal + :is-open="!!shouldShow" + class="UpdateNotification" + :no-background="true" + > + <div + class="UpdateNotificationModal panel" + :class="{ '-peek': !showingMore }" + :style="dynamicStyles" + > + <div class="panel-heading"> + <span class="title"> + {{ $t('update.big_update_title') }} + </span> + </div> + <div class="panel-body"> + <div class="content"> + <img + class="pleroma-tan" + :src="pleromaTanVariant" + :style="pleromaTanStyles" + > + <div class="spacer-top" /> + <div class="text"> + <p> + {{ $t('update.big_update_content') }} + </p> + <div + ref="animatedText" + class="extra-info-group" + > + <i18n-t + keypath="update.update_bugs" + tag="p" + > + <template #pleromaGitlab> + <a + target="_blank" + href="https://git.pleroma.social/" + >{{ $t('update.update_bugs_gitlab') }}</a> + </template> + </i18n-t> + <i18n-t + keypath="update.update_changelog" + tag="p" + > + <template #theFullChangelog> + <a + target="_blank" + href="https://pleroma.social/announcements/" + >{{ $t('update.update_changelog_here') }}</a> + </template> + </i18n-t> + <p class="art-credit"> + <i18n-t + keypath="update.art_by" + tag="small" + > + <template #linkToArtist> + <a + target="_blank" + href="https://post.ebin.club/pipivovott" + >pipivovott</a> + </template> + </i18n-t> + </p> + </div> + </div> + <div class="spacer-bottom" /> + </div> + </div> + <div class="panel-footer"> + <button + class="button-default" + @click.prevent="neverShowAgain" + > + {{ $t("general.never_show_again") }} + </button> + <button + v-if="!showingMore" + class="button-default" + @click.prevent="toggleShow" + > + {{ $t("general.show_more") }} + </button> + <button + class="button-default" + @click.prevent="dismiss" + > + {{ $t("general.dismiss") }} + </button> + </div> + </div> + </Modal> +</template> + +<script src="./update_notification.js"></script> + +<style src="./update_notification.scss" lang="scss"></style> |
