Merge remote-tracking branch 'upstream/develop' into shigusegubu
* upstream/develop: (32 commits) set flex-shrink and flex-basis explicitly set flex amount correctly update flex-grow calculation logic keep image natural ratio in gallery row populate gallery row height without getting width refactor using Set clean up update event name update condition move modal animation keyframes definition migrate viewClass prop to class attribute fix eslint errors fix message input not auto-focusing bug revert changes to render modal into portal use higher css specificity fix eslint warnings remove needless ref definition render modals into the “modal” portal remove needless console.log remove needless importing ...
This commit is contained in:
commit
6a5d57d2fe
24 changed files with 207 additions and 176 deletions
|
@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Ability to hide/show repeats from user
|
||||
- User profile button clutter organized into a menu
|
||||
- Emoji picker
|
||||
- Started changelog anew
|
||||
### Changed
|
||||
|
|
25
src/App.scss
25
src/App.scss
|
@ -717,31 +717,6 @@ nav {
|
|||
}
|
||||
}
|
||||
|
||||
@keyframes modal-background-fadein {
|
||||
from {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
to {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-view {
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
animation-duration: 0.2s;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
animation-name: modal-background-fadein;
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ export default (store) => {
|
|||
{ name: 'dms', path: '/users/:username/dms', component: DMs, beforeEnter: validateAuthenticatedRoute },
|
||||
{ name: 'settings', path: '/settings', component: Settings },
|
||||
{ name: 'registration', path: '/registration', component: Registration },
|
||||
{ name: 'password-reset', path: '/password-reset', component: PasswordReset },
|
||||
{ name: 'password-reset', path: '/password-reset', component: PasswordReset, props: true },
|
||||
{ name: 'registration-token', path: '/registration/:token', component: Registration },
|
||||
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests, beforeEnter: validateAuthenticatedRoute },
|
||||
{ name: 'user-settings', path: '/user-settings', component: UserSettings, beforeEnter: validateAuthenticatedRoute },
|
||||
|
|
|
@ -10,7 +10,8 @@ const Attachment = {
|
|||
'statusId',
|
||||
'size',
|
||||
'allowPlay',
|
||||
'setMedia'
|
||||
'setMedia',
|
||||
'naturalSizeLoad'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
|
@ -88,6 +89,11 @@ const Attachment = {
|
|||
} else {
|
||||
this.showHidden = !this.showHidden
|
||||
}
|
||||
},
|
||||
onImageLoad (image) {
|
||||
const width = image.naturalWidth
|
||||
const height = image.naturalHeight
|
||||
this.naturalSizeLoad && this.naturalSizeLoad({ width, height })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
:referrerpolicy="referrerpolicy"
|
||||
:mimetype="attachment.mimetype"
|
||||
:src="attachment.large_thumb_url || attachment.url"
|
||||
:image-load-handler="onImageLoad"
|
||||
/>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
||||
export default {
|
||||
props: ['user'],
|
||||
props: ['user', 'labelFollowing', 'buttonClass'],
|
||||
data () {
|
||||
return {
|
||||
inProgress: false
|
||||
|
@ -23,7 +23,7 @@ export default {
|
|||
if (this.inProgress) {
|
||||
return this.$t('user_card.follow_progress')
|
||||
} else if (this.user.following) {
|
||||
return this.$t('user_card.following')
|
||||
return this.labelFollowing || this.$t('user_card.following')
|
||||
} else if (this.user.requested) {
|
||||
return this.$t('user_card.follow_sent')
|
||||
} else {
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
||||
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
||||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
||||
import FollowButton from '../follow_button/follow_button.vue'
|
||||
|
||||
const FollowCard = {
|
||||
props: [
|
||||
'user',
|
||||
'noFollowsYou'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
inProgress: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
BasicUserCard,
|
||||
RemoteFollow
|
||||
RemoteFollow,
|
||||
FollowButton
|
||||
},
|
||||
computed: {
|
||||
isMe () {
|
||||
|
@ -23,20 +19,6 @@ const FollowCard = {
|
|||
loggedIn () {
|
||||
return this.$store.state.users.currentUser
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
followUser () {
|
||||
this.inProgress = true
|
||||
requestFollow(this.user, this.$store).then(() => {
|
||||
this.inProgress = false
|
||||
})
|
||||
},
|
||||
unfollowUser () {
|
||||
this.inProgress = true
|
||||
requestUnfollow(this.user, this.$store).then(() => {
|
||||
this.inProgress = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,36 +16,11 @@
|
|||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button
|
||||
v-if="!user.following"
|
||||
class="btn btn-default follow-card-follow-button"
|
||||
:disabled="inProgress"
|
||||
:title="user.requested ? $t('user_card.follow_again') : ''"
|
||||
@click="followUser"
|
||||
>
|
||||
<template v-if="inProgress">
|
||||
{{ $t('user_card.follow_progress') }}
|
||||
</template>
|
||||
<template v-else-if="user.requested">
|
||||
{{ $t('user_card.follow_sent') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $t('user_card.follow') }}
|
||||
</template>
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-default follow-card-follow-button pressed"
|
||||
:disabled="inProgress"
|
||||
@click="unfollowUser"
|
||||
>
|
||||
<template v-if="inProgress">
|
||||
{{ $t('user_card.follow_progress') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $t('user_card.follow_unfollow') }}
|
||||
</template>
|
||||
</button>
|
||||
<FollowButton
|
||||
:user="user"
|
||||
class="follow-card-follow-button"
|
||||
:label-following="$t('user_card.follow_unfollow')"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</basic-user-card>
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
import Attachment from '../attachment/attachment.vue'
|
||||
import { chunk, last, dropRight } from 'lodash'
|
||||
import { chunk, last, dropRight, sumBy } from 'lodash'
|
||||
|
||||
const Gallery = {
|
||||
data: () => ({
|
||||
width: 500
|
||||
}),
|
||||
props: [
|
||||
'attachments',
|
||||
'nsfw',
|
||||
'setMedia'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
sizes: {}
|
||||
}
|
||||
},
|
||||
components: { Attachment },
|
||||
mounted () {
|
||||
this.resize()
|
||||
window.addEventListener('resize', this.resize)
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
},
|
||||
computed: {
|
||||
rows () {
|
||||
if (!this.attachments) {
|
||||
|
@ -33,21 +28,24 @@ const Gallery = {
|
|||
}
|
||||
return rows
|
||||
},
|
||||
rowHeight () {
|
||||
return itemsPerRow => ({ 'height': `${(this.width / (itemsPerRow + 0.6))}px` })
|
||||
},
|
||||
useContainFit () {
|
||||
return this.$store.getters.mergedConfig.useContainFit
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resize () {
|
||||
// Quick optimization to make resizing not always trigger state change,
|
||||
// only update attachment size in 10px steps
|
||||
const width = Math.floor(this.$el.getBoundingClientRect().width / 10) * 10
|
||||
if (this.width !== width) {
|
||||
this.width = width
|
||||
}
|
||||
onNaturalSizeLoad (id, size) {
|
||||
this.$set(this.sizes, id, size)
|
||||
},
|
||||
rowStyle (itemsPerRow) {
|
||||
return { 'padding-bottom': `${(100 / (itemsPerRow + 0.6))}%` }
|
||||
},
|
||||
itemStyle (id, row) {
|
||||
const total = sumBy(row, item => this.getAspectRatio(item.id))
|
||||
return { flex: `${this.getAspectRatio(id) / total} 1 0%` }
|
||||
},
|
||||
getAspectRatio (id) {
|
||||
const size = this.sizes[id]
|
||||
return size ? size.width / size.height : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,21 @@
|
|||
v-for="(row, index) in rows"
|
||||
:key="index"
|
||||
class="gallery-row"
|
||||
:style="rowHeight(row.length)"
|
||||
:style="rowStyle(row.length)"
|
||||
:class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"
|
||||
>
|
||||
<attachment
|
||||
v-for="attachment in row"
|
||||
:key="attachment.id"
|
||||
:set-media="setMedia"
|
||||
:nsfw="nsfw"
|
||||
:attachment="attachment"
|
||||
:allow-play="false"
|
||||
/>
|
||||
<div class="gallery-row-inner">
|
||||
<attachment
|
||||
v-for="attachment in row"
|
||||
:key="attachment.id"
|
||||
:set-media="setMedia"
|
||||
:nsfw="nsfw"
|
||||
:attachment="attachment"
|
||||
:allow-play="false"
|
||||
:natural-size-load="onNaturalSizeLoad.bind(null, attachment.id)"
|
||||
:style="itemStyle(attachment.id, row)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -28,15 +32,24 @@
|
|||
@import '../../_variables.scss';
|
||||
|
||||
.gallery-row {
|
||||
height: 200px;
|
||||
position: relative;
|
||||
height: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-content: stretch;
|
||||
flex-grow: 1;
|
||||
margin-top: 0.5em;
|
||||
|
||||
.gallery-row-inner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-content: stretch;
|
||||
}
|
||||
|
||||
// FIXME: specificity problem with this and .attachments.attachment
|
||||
// we shouldn't have the need for .image here
|
||||
.attachment.image {
|
||||
|
|
|
@ -59,6 +59,8 @@ const LoginForm = {
|
|||
if (result.error) {
|
||||
if (result.error === 'mfa_required') {
|
||||
this.requireMFA({ app: app, settings: result })
|
||||
} else if (result.identifier === 'password_reset_required') {
|
||||
this.$router.push({ name: 'password-reset', params: { passwordResetRequested: true } })
|
||||
} else {
|
||||
this.error = result.error
|
||||
this.focusOnPasswordInput()
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import StillImage from '../still-image/still-image.vue'
|
||||
import VideoAttachment from '../video_attachment/video_attachment.vue'
|
||||
import Modal from '../modal/modal.vue'
|
||||
import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||
|
||||
const MediaModal = {
|
||||
components: {
|
||||
StillImage,
|
||||
VideoAttachment
|
||||
VideoAttachment,
|
||||
Modal
|
||||
},
|
||||
computed: {
|
||||
showing () {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<template>
|
||||
<div
|
||||
<Modal
|
||||
v-if="showing"
|
||||
v-body-scroll-lock="showing"
|
||||
class="modal-view media-modal-view"
|
||||
@click.prevent="hide"
|
||||
class="media-modal-view"
|
||||
@backdropClicked="hide"
|
||||
>
|
||||
<img
|
||||
v-if="type === 'image'"
|
||||
|
@ -33,21 +32,15 @@
|
|||
>
|
||||
<i class="icon-right-open arrow-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script src="./media_modal.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.media-modal-view {
|
||||
.modal-view.media-modal-view {
|
||||
z-index: 1001;
|
||||
|
||||
body:not(.scroll-locked) & {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.modal-view-button-arrow {
|
||||
opacity: 0.75;
|
||||
|
@ -114,5 +107,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
52
src/components/modal/modal.vue
Normal file
52
src/components/modal/modal.vue
Normal file
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<div
|
||||
v-show="isOpen"
|
||||
v-body-scroll-lock="isOpen"
|
||||
class="modal-view"
|
||||
@click.self="$emit('backdropClicked')"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
isOpen: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.modal-view {
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
animation-duration: 0.2s;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
animation-name: modal-background-fadein;
|
||||
|
||||
body:not(.scroll-locked) & {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes modal-background-fadein {
|
||||
from {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
to {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -25,6 +25,12 @@ const passwordReset = {
|
|||
this.$router.push({ name: 'root' })
|
||||
}
|
||||
},
|
||||
props: {
|
||||
passwordResetRequested: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dismissError () {
|
||||
this.error = null
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
>
|
||||
<div class="container">
|
||||
<div v-if="!mailerEnabled">
|
||||
<p>
|
||||
<p v-if="passwordResetRequested">
|
||||
{{ $t('password_reset.password_reset_required_but_mailer_is_disabled') }}
|
||||
</p>
|
||||
<p v-else>
|
||||
{{ $t('password_reset.password_reset_disabled') }}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -25,6 +28,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p
|
||||
v-if="passwordResetRequested"
|
||||
class="password-reset-required error"
|
||||
>
|
||||
{{ $t('password_reset.password_reset_required') }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('password_reset.instruction') }}
|
||||
</p>
|
||||
|
@ -104,6 +113,11 @@
|
|||
margin: 0.3em 0.0em 1em;
|
||||
}
|
||||
|
||||
.password-reset-required {
|
||||
background-color: var(--alertError, $fallback--alertError);
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.notice-dismissible {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||
import Modal from '../modal/modal.vue'
|
||||
import get from 'lodash/get'
|
||||
|
||||
const PostStatusModal = {
|
||||
components: {
|
||||
PostStatusForm
|
||||
PostStatusForm,
|
||||
Modal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
<template>
|
||||
<div
|
||||
<Modal
|
||||
v-if="isLoggedIn && !resettingForm"
|
||||
v-show="modalActivated"
|
||||
class="post-form-modal-view modal-view"
|
||||
@click="closeModal"
|
||||
:is-open="modalActivated"
|
||||
class="post-form-modal-view"
|
||||
@backdropClicked="closeModal"
|
||||
>
|
||||
<div
|
||||
class="post-form-modal-panel panel"
|
||||
@click.stop=""
|
||||
>
|
||||
<div class="post-form-modal-panel panel">
|
||||
<div class="panel-heading">
|
||||
{{ $t('post_status.new_status') }}
|
||||
</div>
|
||||
|
@ -18,15 +15,13 @@
|
|||
@posted="closeModal"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script src="./post_status_modal.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.post-form-modal-view {
|
||||
.modal-view.post-form-modal-view {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
|
|
@ -840,6 +840,11 @@ $status-margin: 0.75em;
|
|||
&.button-icon-active {
|
||||
color: $fallback--cBlue;
|
||||
color: var(--cBlue, $fallback--cBlue);
|
||||
}
|
||||
}
|
||||
|
||||
.button-icon.icon-reply {
|
||||
&:not(.button-icon-disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ const StillImage = {
|
|||
'src',
|
||||
'referrerpolicy',
|
||||
'mimetype',
|
||||
'imageLoadError'
|
||||
'imageLoadError',
|
||||
'imageLoadHandler'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
|
@ -17,6 +18,7 @@ const StillImage = {
|
|||
},
|
||||
methods: {
|
||||
onLoad () {
|
||||
this.imageLoadHandler && this.imageLoadHandler(this.$refs.src)
|
||||
const canvas = this.$refs.canvas
|
||||
if (!canvas) return
|
||||
const width = this.$refs.src.naturalWidth
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
import Status from '../status/status.vue'
|
||||
import List from '../list/list.vue'
|
||||
import Checkbox from '../checkbox/checkbox.vue'
|
||||
import Modal from '../modal/modal.vue'
|
||||
|
||||
const UserReportingModal = {
|
||||
components: {
|
||||
Status,
|
||||
List,
|
||||
Checkbox
|
||||
Checkbox,
|
||||
Modal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
<template>
|
||||
<div
|
||||
<Modal
|
||||
v-if="isOpen"
|
||||
class="modal-view"
|
||||
@click="closeModal"
|
||||
@backdropClicked="closeModal"
|
||||
>
|
||||
<div
|
||||
class="user-reporting-panel panel"
|
||||
@click.stop=""
|
||||
>
|
||||
<div class="user-reporting-panel panel">
|
||||
<div class="panel-heading">
|
||||
<div class="title">
|
||||
{{ $t('user_reporting.title', [user.screen_name]) }}
|
||||
|
@ -69,7 +65,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script src="./user_reporting_modal.js"></script>
|
||||
|
|
|
@ -2,42 +2,49 @@ import * as bodyScrollLock from 'body-scroll-lock'
|
|||
|
||||
let previousNavPaddingRight
|
||||
let previousAppBgWrapperRight
|
||||
const lockerEls = new Set([])
|
||||
|
||||
const disableBodyScroll = (el) => {
|
||||
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth
|
||||
bodyScrollLock.disableBodyScroll(el, {
|
||||
reserveScrollBarGap: true
|
||||
})
|
||||
lockerEls.add(el)
|
||||
setTimeout(() => {
|
||||
// If previousNavPaddingRight is already set, don't set it again.
|
||||
if (previousNavPaddingRight === undefined) {
|
||||
const navEl = document.getElementById('nav')
|
||||
previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right')
|
||||
navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||
if (lockerEls.size <= 1) {
|
||||
// If previousNavPaddingRight is already set, don't set it again.
|
||||
if (previousNavPaddingRight === undefined) {
|
||||
const navEl = document.getElementById('nav')
|
||||
previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right')
|
||||
navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||
}
|
||||
// If previousAppBgWrapeprRight is already set, don't set it again.
|
||||
if (previousAppBgWrapperRight === undefined) {
|
||||
const appBgWrapperEl = document.getElementById('app_bg_wrapper')
|
||||
previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
|
||||
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||
}
|
||||
document.body.classList.add('scroll-locked')
|
||||
}
|
||||
// If previousAppBgWrapeprRight is already set, don't set it again.
|
||||
if (previousAppBgWrapperRight === undefined) {
|
||||
const appBgWrapperEl = document.getElementById('app_bg_wrapper')
|
||||
previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
|
||||
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||
}
|
||||
document.body.classList.add('scroll-locked')
|
||||
})
|
||||
}
|
||||
|
||||
const enableBodyScroll = (el) => {
|
||||
lockerEls.delete(el)
|
||||
setTimeout(() => {
|
||||
if (previousNavPaddingRight !== undefined) {
|
||||
document.getElementById('nav').style.paddingRight = previousNavPaddingRight
|
||||
// Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
|
||||
previousNavPaddingRight = undefined
|
||||
if (lockerEls.size === 0) {
|
||||
if (previousNavPaddingRight !== undefined) {
|
||||
document.getElementById('nav').style.paddingRight = previousNavPaddingRight
|
||||
// Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
|
||||
previousNavPaddingRight = undefined
|
||||
}
|
||||
if (previousAppBgWrapperRight !== undefined) {
|
||||
document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight
|
||||
// Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again.
|
||||
previousAppBgWrapperRight = undefined
|
||||
}
|
||||
document.body.classList.remove('scroll-locked')
|
||||
}
|
||||
if (previousAppBgWrapperRight !== undefined) {
|
||||
document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight
|
||||
// Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again.
|
||||
previousAppBgWrapperRight = undefined
|
||||
}
|
||||
document.body.classList.remove('scroll-locked')
|
||||
})
|
||||
bodyScrollLock.enableBodyScroll(el)
|
||||
}
|
||||
|
|
|
@ -635,6 +635,8 @@
|
|||
"return_home": "Return to the home page",
|
||||
"not_found": "We couldn't find that email or username.",
|
||||
"too_many_requests": "You have reached the limit of attempts, try again later.",
|
||||
"password_reset_disabled": "Password reset is disabled. Please contact your instance administrator."
|
||||
"password_reset_disabled": "Password reset is disabled. Please contact your instance administrator.",
|
||||
"password_reset_required": "You must reset your password to log in.",
|
||||
"password_reset_required_but_mailer_is_disabled": "You must reset your password, but password reset is disabled. Please contact your instance administrator."
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue