diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/about/about.vue | 2 | ||||
| -rw-r--r-- | src/components/chat/chat.js | 54 | ||||
| -rw-r--r-- | src/components/chat/chat.scss | 17 | ||||
| -rw-r--r-- | src/components/chat/chat.vue | 6 | ||||
| -rw-r--r-- | src/components/chat_list/chat_list.vue | 2 | ||||
| -rw-r--r-- | src/components/chat_title/chat_title.vue | 2 | ||||
| -rw-r--r-- | src/components/desktop_nav/desktop_nav.scss | 2 | ||||
| -rw-r--r-- | src/components/mobile_nav/mobile_nav.js | 3 | ||||
| -rw-r--r-- | src/components/mobile_nav/mobile_nav.vue | 11 | ||||
| -rw-r--r-- | src/components/notifications/notifications.js | 15 | ||||
| -rw-r--r-- | src/components/notifications/notifications.vue | 116 | ||||
| -rw-r--r-- | src/components/password_reset/password_reset.vue | 3 | ||||
| -rw-r--r-- | src/components/registration/registration.vue | 5 | ||||
| -rw-r--r-- | src/components/settings_modal/settings_modal.scss | 12 | ||||
| -rw-r--r-- | src/components/status/status.scss | 4 | ||||
| -rw-r--r-- | src/components/timeline/timeline.js | 6 | ||||
| -rw-r--r-- | src/components/timeline/timeline.scss | 1 | ||||
| -rw-r--r-- | src/components/user_card/user_card.vue | 9 |
18 files changed, 137 insertions, 133 deletions
diff --git a/src/components/about/about.vue b/src/components/about/about.vue index 518f6184..5d5d6479 100644 --- a/src/components/about/about.vue +++ b/src/components/about/about.vue @@ -1,5 +1,5 @@ <template> - <div class="sidebar"> + <div class="column-inner"> <instance-specific-panel v-if="showInstanceSpecificPanel" /> <staff-panel /> <terms-of-service-panel /> diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index aef11712..5d2c1d09 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -6,7 +6,7 @@ import PostStatusForm from '../post_status_form/post_status_form.vue' import ChatTitle from '../chat_title/chat_title.vue' import chatService from '../../services/chat_service/chat_service.js' import { promiseInterval } from '../../services/promise_interval/promise_interval.js' -import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContainerHeight, isScrollable } from './chat_layout_utils.js' +import { getScrollPosition, getNewTopPosition, isBottomedOut, isScrollable } from './chat_layout_utils.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronDown, @@ -19,8 +19,10 @@ library.add( faChevronLeft ) +const scroller = () => document.getElementById('content') + const BOTTOMED_OUT_OFFSET = 10 -const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 150 +const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 10 const SAFE_RESIZE_TIME_OFFSET = 100 const MARK_AS_READ_DELAY = 1500 const MAX_RETRIES = 10 @@ -46,19 +48,18 @@ const Chat = { window.addEventListener('resize', this.handleLayoutChange) }, mounted () { - window.addEventListener('scroll', this.handleScroll) + scroller().addEventListener('scroll', this.handleScroll) if (typeof document.hidden !== 'undefined') { document.addEventListener('visibilitychange', this.handleVisibilityChange, false) } this.$nextTick(() => { - this.updateScrollableContainerHeight() this.handleResize() }) this.setChatLayout() }, unmounted () { - window.removeEventListener('scroll', this.handleScroll) + scroller().removeEventListener('scroll', this.handleScroll) window.removeEventListener('resize', this.handleLayoutChange) this.unsetChatLayout() if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false) @@ -132,7 +133,6 @@ const Chat = { onFilesDropped () { this.$nextTick(() => { this.handleResize() - this.updateScrollableContainerHeight() }) }, handleVisibilityChange () { @@ -154,10 +154,6 @@ const Chat = { if (html) { html.classList.add('chat-layout') } - - this.$nextTick(() => { - this.updateScrollableContainerHeight() - }) }, unsetChatLayout () { let html = document.querySelector('html') @@ -167,17 +163,9 @@ const Chat = { }, handleLayoutChange () { this.$nextTick(() => { - this.updateScrollableContainerHeight() this.scrollDown() }) }, - // Ensures the proper position of the posting form in the mobile layout (the mobile browser panel does not overlap or hide it) - updateScrollableContainerHeight () { - const header = this.$refs.header - const footer = this.$refs.footer - const inner = this.mobileLayout ? window.document.body : this.$refs.inner - this.scrollableContainerHeight = scrollableContainerHeight(inner, header, footer) + 'px' - }, // Preserves the scroll position when OSK appears or the posting form changes its height. handleResize (opts = {}) { const { expand = false, delayed = false } = opts @@ -190,17 +178,14 @@ const Chat = { } this.$nextTick(() => { - this.updateScrollableContainerHeight() - const { offsetHeight = undefined } = this.lastScrollPosition - this.lastScrollPosition = getScrollPosition(this.$refs.scrollable) + this.lastScrollPosition = getScrollPosition(scroller()) const diff = this.lastScrollPosition.offsetHeight - offsetHeight if (diff < 0 || (!this.bottomedOut() && expand)) { this.$nextTick(() => { - this.updateScrollableContainerHeight() - this.$refs.scrollable.scrollTo({ - top: this.$refs.scrollable.scrollTop - diff, + scroller().scrollTo({ + top: scroller().scrollTop - diff, left: 0 }) }) @@ -209,7 +194,7 @@ const Chat = { }, scrollDown (options = {}) { const { behavior = 'auto', forceRead = false } = options - const scrollable = this.$refs.scrollable + const scrollable = scroller() if (!scrollable) { return } this.$nextTick(() => { scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior }) @@ -228,10 +213,10 @@ const Chat = { }) }, bottomedOut (offset) { - return isBottomedOut(this.$refs.scrollable, offset) + return isBottomedOut(scroller(), offset) }, reachedTop () { - const scrollable = this.$refs.scrollable + const scrollable = scroller() return scrollable && scrollable.scrollTop <= 0 }, cullOlderCheck () { @@ -263,8 +248,8 @@ const Chat = { } }, 200), handleScrollUp (positionBeforeLoading) { - const positionAfterLoading = getScrollPosition(this.$refs.scrollable) - this.$refs.scrollable.scrollTo({ + const positionAfterLoading = getScrollPosition(scroller()) + scroller().scrollTo({ top: getNewTopPosition(positionBeforeLoading, positionAfterLoading), left: 0 }) @@ -285,22 +270,18 @@ const Chat = { chatService.clear(chatMessageService) } - const positionBeforeUpdate = getScrollPosition(this.$refs.scrollable) + const positionBeforeUpdate = getScrollPosition(scroller()) this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => { this.$nextTick(() => { if (fetchOlderMessages) { this.handleScrollUp(positionBeforeUpdate) } - if (isFirstFetch) { - this.updateScrollableContainerHeight() - } - // In vertical screens, the first batch of fetched messages may not always take the // full height of the scrollable container. // If this is the case, we want to fetch the messages until the scrollable container // is fully populated so that the user has the ability to scroll up and load the history. - if (!isScrollable(this.$refs.scrollable) && messages.length > 0) { + if (!isScrollable(scroller()) && messages.length > 0) { this.fetchChat({ maxId: this.currentChatMessageService.minId }) } }) @@ -336,9 +317,6 @@ const Chat = { this.handleResize() // When the posting form size changes because of a media attachment, we need an extra resize // to account for the potential delay in the DOM update. - setTimeout(() => { - this.updateScrollableContainerHeight() - }, SAFE_RESIZE_TIME_OFFSET) this.scrollDown({ forceRead: true }) }) }, diff --git a/src/components/chat/chat.scss b/src/components/chat/chat.scss index 3a26686c..51bb3ea6 100644 --- a/src/components/chat/chat.scss +++ b/src/components/chat/chat.scss @@ -1,19 +1,12 @@ .chat-view { display: flex; - height: calc(100vh - 60px); - width: 100%; - - .chat-title { - // prevents chat header jumping on when the user avatar loads - height: 28px; - } + height: 100%; .chat-view-inner { height: auto; width: 100%; overflow: visible; display: flex; - margin: 0.5em 0.5em 0 0.5em; } .chat-view-body { @@ -32,11 +25,9 @@ } } - .scrollable-message-list { + .message-list { padding: 0 0.8em; height: 100%; - overflow-y: scroll; - overflow-x: hidden; display: flex; flex-direction: column; } @@ -44,12 +35,14 @@ .footer { position: sticky; bottom: 0; + background-color: $fallback--bg; + background-color: var(--bg, $fallback--bg); + z-index: 10; } .chat-view-heading { align-items: center; justify-content: space-between; - top: 50px; display: flex; z-index: 2; position: sticky; diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue index 493c5d5a..3b0129fa 100644 --- a/src/components/chat/chat.vue +++ b/src/components/chat/chat.vue @@ -8,7 +8,7 @@ > <div ref="header" - class="panel-heading chat-view-heading mobile-hidden" + class="panel-heading -sticky chat-view-heading mobile-hidden" > <a class="go-back-button" @@ -27,10 +27,8 @@ </div> </div> <div - ref="scrollable" - class="scrollable-message-list" + class="message-list" :style="{ height: scrollableContainerHeight }" - @scroll="handleScroll" > <template v-if="!errorLoadingChat"> <ChatMessage diff --git a/src/components/chat_list/chat_list.vue b/src/components/chat_list/chat_list.vue index f98b7ed2..58e8d0b3 100644 --- a/src/components/chat_list/chat_list.vue +++ b/src/components/chat_list/chat_list.vue @@ -6,7 +6,7 @@ v-else class="chat-list panel panel-default" > - <div class="panel-heading"> + <div class="panel-heading -sticky"> <span class="title"> {{ $t("chats.chats") }} </span> diff --git a/src/components/chat_title/chat_title.vue b/src/components/chat_title/chat_title.vue index a92028e8..06ad129d 100644 --- a/src/components/chat_title/chat_title.vue +++ b/src/components/chat_title/chat_title.vue @@ -15,7 +15,7 @@ </router-link> <RichContent class="username" - :title="'@'+user.screen_name_ui" + :title="'@'+(user && user.screen_name_ui)" :html="htmlTitle" :emoji="user.emoji" /> diff --git a/src/components/desktop_nav/desktop_nav.scss b/src/components/desktop_nav/desktop_nav.scss index 2d468588..1e731c70 100644 --- a/src/components/desktop_nav/desktop_nav.scss +++ b/src/components/desktop_nav/desktop_nav.scss @@ -1,9 +1,7 @@ @import '../../_variables.scss'; .DesktopNav { - height: 50px; width: 100%; - position: fixed; a { color: var(--topBarLink, $fallback--link); diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js index 9e736cfb..877d52a9 100644 --- a/src/components/mobile_nav/mobile_nav.js +++ b/src/components/mobile_nav/mobile_nav.js @@ -78,7 +78,8 @@ const MobileNav = { this.$store.dispatch('logout') }, markNotificationsAsSeen () { - this.$refs.notifications.markAsSeen() + // this.$refs.notifications.markAsSeen() + this.$store.dispatch('markNotificationsAsSeen') }, onScroll ({ target: { scrollTop, clientHeight, scrollHeight } }) { if (scrollTop + clientHeight >= scrollHeight) { diff --git a/src/components/mobile_nav/mobile_nav.vue b/src/components/mobile_nav/mobile_nav.vue index 0f0ea457..6c810bba 100644 --- a/src/components/mobile_nav/mobile_nav.vue +++ b/src/components/mobile_nav/mobile_nav.vue @@ -69,12 +69,9 @@ </div> <div class="mobile-notifications" + id="mobile-notifications" @scroll="onScroll" > - <Notifications - ref="notifications" - :no-heading="true" - /> </div> </div> <SideDrawer @@ -92,12 +89,10 @@ .MobileNav { .mobile-nav { display: grid; - line-height: 50px; - height: 50px; + line-height: var(--navbar-height); grid-template-rows: 50px; grid-template-columns: 2fr auto; width: 100%; - position: fixed; box-sizing: border-box; } @@ -182,7 +177,7 @@ .mobile-notifications { margin-top: 50px; width: 100vw; - height: calc(100vh - 50px); + height: calc(100vh - var(--navbar-height)); overflow-x: hidden; overflow-y: scroll; diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index c8f1ebcb..2bb8a1d1 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -23,8 +23,6 @@ const Notifications = { NotificationFilters }, props: { - // Disables display of panel header - noHeading: Boolean, // Disables panel styles, unread mark, potentially other notification-related actions // meant for "Interactions" timeline minimalMode: Boolean, @@ -65,6 +63,19 @@ const Notifications = { loading () { return this.$store.state.statuses.notifications.loading }, + noHeading () { + const { layoutType } = this.$store.state.interface + console.log(layoutType) + return layoutType === 'mobile' + }, + teleportTarget () { + const { layoutType } = this.$store.state.interface + const map = { + wide: '#notifs-column', + mobile: '#mobile-notifications' + } + return map[layoutType] || '#notifs-sidebar' + }, notificationsToDisplay () { return this.filteredNotifications.slice(0, this.unseenCount + this.seenToDisplayCount) }, diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue index 2ce5d56f..f50d3d38 100644 --- a/src/components/notifications/notifications.vue +++ b/src/components/notifications/notifications.vue @@ -1,69 +1,71 @@ <template> - <div - :class="{ minimal: minimalMode }" - class="Notifications" - > - <div :class="mainClass"> - <div - v-if="!noHeading" - class="panel-heading" - > - <div class="title"> - {{ $t('notifications.notifications') }} - <span - v-if="unseenCount" - class="badge badge-notification unseen-count" - >{{ unseenCount }}</span> - </div> - <button - v-if="unseenCount" - class="button-default read-button" - @click.prevent="markAsSeen" - > - {{ $t('notifications.read') }} - </button> - <NotificationFilters /> - </div> - <div class="panel-body"> + <teleport :to="teleportTarget"> + <div + :class="{ minimal: minimalMode }" + class="Notifications" + > + <div :class="mainClass"> <div - v-for="notification in notificationsToDisplay" - :key="notification.id" - class="notification" - :class="{"unseen": !minimalMode && !notification.seen}" + v-if="!noHeading" + class="notifications-heading panel-heading -sticky" > - <div class="notification-overlay" /> - <notification :notification="notification" /> + <div class="title"> + {{ $t('notifications.notifications') }} + <span + v-if="unseenCount" + class="badge badge-notification unseen-count" + >{{ unseenCount }}</span> + </div> + <button + v-if="unseenCount" + class="button-default read-button" + @click.prevent="markAsSeen" + > + {{ $t('notifications.read') }} + </button> + <NotificationFilters /> </div> - </div> - <div class="panel-footer notifications-footer"> - <div - v-if="bottomedOut" - class="new-status-notification text-center faint" - > - {{ $t('notifications.no_more_notifications') }} + <div class="panel-body"> + <div + v-for="notification in notificationsToDisplay" + :key="notification.id" + class="notification" + :class="{"unseen": !minimalMode && !notification.seen}" + > + <div class="notification-overlay" /> + <notification :notification="notification" /> + </div> </div> - <button - v-else-if="!loading" - class="button-unstyled -link -fullwidth" - @click.prevent="fetchOlderNotifications()" - > - <div class="new-status-notification text-center"> - {{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }} + <div class="panel-footer notifications-footer"> + <div + v-if="bottomedOut" + class="new-status-notification text-center faint" + > + {{ $t('notifications.no_more_notifications') }} + </div> + <button + v-else-if="!loading" + class="button-unstyled -link -fullwidth" + @click.prevent="fetchOlderNotifications()" + > + <div class="new-status-notification text-center"> + {{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }} + </div> + </button> + <div + v-else + class="new-status-notification text-center" + > + <FAIcon + icon="circle-notch" + spin + size="lg" + /> </div> - </button> - <div - v-else - class="new-status-notification text-center" - > - <FAIcon - icon="circle-notch" - spin - size="lg" - /> </div> </div> </div> - </div> + </teleport> </template> <script src="./notifications.js"></script> diff --git a/src/components/password_reset/password_reset.vue b/src/components/password_reset/password_reset.vue index 3ffa5425..e0579568 100644 --- a/src/components/password_reset/password_reset.vue +++ b/src/components/password_reset/password_reset.vue @@ -91,6 +91,9 @@ flex-direction: column; margin-top: 0.6em; max-width: 18rem; + > * { + min-width: 0; + } } .form-group { diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index 3d409109..1e735c69 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -271,7 +271,10 @@ $validations-cRed: #f04124; .container { display: flex; flex-direction: row; - //margin-bottom: 1em; + + > * { + min-width: 0; + } } .terms-of-service { diff --git a/src/components/settings_modal/settings_modal.scss b/src/components/settings_modal/settings_modal.scss index 2f7649a9..f3738a8c 100644 --- a/src/components/settings_modal/settings_modal.scss +++ b/src/components/settings_modal/settings_modal.scss @@ -2,6 +2,18 @@ .settings-modal { overflow: hidden; + .setting-list, + .option-list { + list-style-type: none; + padding-left: 2em; + li { + margin-bottom: 0.5em; + } + .suboptions { + margin-top: 0.3em + } + } + &.peek { .settings-modal-panel { /* Explanation: diff --git a/src/components/status/status.scss b/src/components/status/status.scss index 5ed43e0d..e38e2a53 100644 --- a/src/components/status/status.scss +++ b/src/components/status/status.scss @@ -42,6 +42,10 @@ display: flex; padding: var(--status-margin, $status-margin); + > * { + min-width: 0; + } + &.-repeat { padding-top: 0; } diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 8ec5d1e5..9056319b 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -64,7 +64,7 @@ const Timeline = { if (this.blockingClicks) rootClasses = rootClasses.concat(['-blocked', '_misclick-prevention']) return { root: rootClasses, - header: ['timeline-heading'].concat(!this.embedded ? ['panel-heading'] : []), + header: ['timeline-heading'].concat(!this.embedded ? ['panel-heading', '-sticky'] : []), body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : []), footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : []) } @@ -89,7 +89,7 @@ const Timeline = { const credentials = store.state.users.currentUser.credentials const showImmediately = this.timeline.visibleStatuses.length === 0 - window.addEventListener('scroll', this.handleScroll) + document.getElementById('content').addEventListener('scroll', this.handleScroll) if (store.state.api.fetchers[this.timelineName]) { return false } @@ -111,7 +111,7 @@ const Timeline = { setTimeout(this.determineVisibleStatuses, 250) }, unmounted () { - window.removeEventListener('scroll', this.handleScroll) + document.getElementById('content').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 }) diff --git a/src/components/timeline/timeline.scss b/src/components/timeline/timeline.scss index 2c5a67e2..c10375d4 100644 --- a/src/components/timeline/timeline.scss +++ b/src/components/timeline/timeline.scss @@ -13,7 +13,6 @@ max-width: 100%; flex-wrap: nowrap; align-items: center; - position: relative; .loadmore-button { flex-shrink: 0; diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 14b4643a..43a660e1 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -8,7 +8,7 @@ :style="style" class="background-image" /> - <div class="panel-heading"> + <div class="panel-heading -flexible-height"> <div class="user-info"> <div class="container"> <a @@ -289,6 +289,7 @@ .user-card { position: relative; + z-index: 1; &:hover { --_still-image-img-visibility: visible; @@ -331,6 +332,7 @@ border-top-left-radius: calc(var(--panelRadius) - 1px); border-top-right-radius: calc(var(--panelRadius) - 1px); background-color: var(--profileBg); + z-index: -2; &.hide-bio { mask-size: 100% 40px; @@ -385,11 +387,16 @@ padding: 0 26px; .container { + min-width: 0; padding: 16px 0 6px; display: flex; align-items: flex-start; max-height: 56px; + > * { + min-width: 0; + } + .Avatar { --_avatarShadowBox: var(--avatarShadow); --_avatarShadowFilter: var(--avatarShadowFilter); |
