...
 
Commits (27)
......@@ -77,6 +77,9 @@ Use custom image for NSFW'd images
### `showFeaturesPanel`
Show panel showcasing instance features/settings to logged-out visitors
### `hideSitename`
Hide instance name in header
## Indirect configuration
Some features are configured depending on how backend is configured. In general the approach is "if backend allows it there's no need to hide it, if backend doesn't allow it there's no need to show it.
......
......@@ -8,7 +8,7 @@ import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_pan
import ChatPanel from './components/chat_panel/chat_panel.vue'
import MediaModal from './components/media_modal/media_modal.vue'
import SideDrawer from './components/side_drawer/side_drawer.vue'
import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
import FloatingPostButton from './components/floating_post_button/floating_post_button.vue'
import MobileNav from './components/mobile_nav/mobile_nav.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
......@@ -27,7 +27,7 @@ export default {
ChatPanel,
MediaModal,
SideDrawer,
MobilePostStatusButton,
FloatingPostButton,
MobileNav,
UserReportingModal,
PostStatusModal
......@@ -90,6 +90,7 @@ export default {
},
sitename () { return this.$store.state.instance.name },
chat () { return this.$store.state.chat.channel.state === 'joined' },
hideSitename () { return this.$store.state.instance.hideSitename },
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
showInstanceSpecificPanel () {
return this.$store.state.instance.showInstanceSpecificPanel &&
......
......@@ -870,3 +870,16 @@ nav {
transform: rotate(359deg);
}
}
.new-status-notification {
position:relative;
margin-top: -1px;
font-size: 1.1em;
border-width: 1px 0 0 0;
border-style: solid;
border-color: var(--border, $fallback--border);
padding: 10px;
z-index: 1;
background-color: $fallback--fg;
background-color: var(--panel, $fallback--fg);
}
......@@ -31,6 +31,7 @@
</div>
<div class="item">
<router-link
v-if="!hideSitename"
class="site-name"
:to="{ name: 'root' }"
active-class="home"
......@@ -117,7 +118,7 @@
:floating="true"
class="floating-chat mobile-hidden"
/>
<MobilePostStatusButton />
<FloatingPostButton v-if="currentUser && isMobileLayout" />
<UserReportingModal />
<PostStatusModal />
<portal-target name="modal" />
......
......@@ -108,6 +108,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
copyInstanceOption('alwaysShowSubjectInput')
copyInstanceOption('noAttachmentLinks')
copyInstanceOption('showFeaturesPanel')
copyInstanceOption('hideSitename')
return store.dispatch('setTheme', config['theme'])
}
......
import { debounce } from 'lodash'
import 'javascript-detect-element-resize'
const MobilePostStatusButton = {
// NOTE: We use the hard-coded boundingClientRect obj of the button at the moment
// since the button moves vertically and it makes difficult to determine the boundingClientRect
const buttonRect = {
bottom: -21, // Can get the actual bottom value by adding window.innerHeight
right: -21, // Can get the actual right value by adding window.innerWidth
height: 70,
width: 70
}
const FloatingPostButton = {
data () {
return {
hidden: false,
scrollingDown: false,
inputActive: false,
oldScrollPos: 0,
amountScrolled: 0
hoverInlineReply: false,
oldScrollPos: 0
}
},
created () {
if (this.autohideFloatingPostButton) {
this.activateFloatingPostButtonAutohide()
}
window.addEventListener('resize', this.handleOSK)
},
destroyed () {
if (this.autohideFloatingPostButton) {
this.deactivateFloatingPostButtonAutohide()
}
window.removeEventListener('resize', this.handleOSK)
},
computed: {
isLoggedIn () {
return !!this.$store.state.users.currentUser
},
isHidden () {
return this.autohideFloatingPostButton && (this.hidden || this.inputActive)
return this.autohideFloatingPostButton && (this.scrollingDown || this.inputActive || this.hoverInlineReply)
},
autohideFloatingPostButton () {
return !!this.$store.getters.mergedConfig.autohideFloatingPostButton
},
postStatusForms () {
return this.$store.state.interface.postStatusForms
}
},
watch: {
......@@ -46,10 +53,14 @@ const MobilePostStatusButton = {
activateFloatingPostButtonAutohide () {
window.addEventListener('scroll', this.handleScrollStart)
window.addEventListener('scroll', this.handleScrollEnd)
window.addEventListener('resize', this.handleResize)
window.addResizeListener(document.body, this.checkHoverInlineReply)
},
deactivateFloatingPostButtonAutohide () {
window.removeEventListener('scroll', this.handleScrollStart)
window.removeEventListener('scroll', this.handleScrollEnd)
window.removeEventListener('resize', this.handleResize)
window.removeResizeListener(document.body, this.checkHoverInlineReply)
},
openPostForm () {
this.$store.dispatch('openPostStatusModal')
......@@ -74,20 +85,36 @@ const MobilePostStatusButton = {
this.inputActive = false
}
},
checkHoverInlineReply () {
this.hoverInlineReply = this.postStatusForms.some(form => {
const rect = form.getBoundingClientRect()
return rect.bottom > window.innerHeight + buttonRect.bottom - buttonRect.height &&
rect.right > window.innerWidth + buttonRect.right - buttonRect.width &&
rect.bottom - rect.height < window.innerHeight + buttonRect.bottom &&
rect.right - rect.width < window.innerWidth + buttonRect.right
})
},
handleScrollStart: debounce(function () {
if (window.scrollY > this.oldScrollPos) {
this.hidden = true
this.scrollingDown = true
} else {
this.hidden = false
this.scrollingDown = false
}
this.oldScrollPos = window.scrollY
}, 100, { leading: true, trailing: false }),
handleScrollEnd: debounce(function () {
this.hidden = false
this.scrollingDown = false
this.oldScrollPos = window.scrollY
}, 100, { leading: false, trailing: true })
this.checkHoverInlineReply()
}, 100, { leading: false, trailing: true }),
handleResize: debounce(function () {
this.handleOSK()
this.checkHoverInlineReply()
}, 100)
}
}
export default MobilePostStatusButton
export default FloatingPostButton
<template>
<div v-if="isLoggedIn">
<button
class="new-status-button"
:class="{ 'hidden': isHidden }"
@click="openPostForm"
>
<i class="icon-edit" />
</button>
</div>
<button
class="floating-post-button"
:class="{ 'hidden': isHidden }"
@click="openPostForm"
>
<i class="icon-edit" />
</button>
</template>
<script src="./mobile_post_status_button.js"></script>
<script src="./floating_post_button.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.new-status-button {
.floating-post-button {
width: 5em;
height: 5em;
border-radius: 100%;
......@@ -46,10 +44,4 @@
}
}
@media all and (min-width: 801px) {
.new-status-button {
display: none;
}
}
</style>
......@@ -29,6 +29,7 @@ const MobileNav = {
unseenNotificationsCount () {
return this.unseenNotifications.length
},
hideSitename () { return this.$store.state.instance.hideSitename },
sitename () { return this.$store.state.instance.name }
},
methods: {
......
......@@ -17,6 +17,7 @@
<i class="button-icon icon-menu" />
</a>
<router-link
v-if="!hideSitename"
class="site-name"
:to="{ name: 'root' }"
active-class="home"
......
......@@ -48,6 +48,11 @@ const PostStatusForm = {
if (this.replyTo) {
this.$refs.textarea.focus()
}
this.$store.dispatch('addNewPostStatusForm', this)
},
beforeDestroy () {
this.$store.dispatch('removePostStatusForm', this)
},
data () {
const preset = this.$route.query.message
......@@ -374,6 +379,9 @@ const PostStatusForm = {
},
dismissScopeNotice () {
this.$store.dispatch('setOption', { name: 'hideScopeNotice', value: true })
},
getBoundingClientRect () {
return this.$refs.root.getBoundingClientRect()
}
}
}
......
......@@ -172,7 +172,7 @@
for="captcha-label"
>{{ $t('captcha') }}</label>
<template v-if="captcha.type == 'kocaptcha'">
<template v-if="['kocaptcha', 'native'].includes(captcha.type)">
<img
:src="captcha.url"
@click="setCaptcha"
......
......@@ -33,6 +33,9 @@ const SideDrawer = {
logo () {
return this.$store.state.instance.logo
},
hideSitename () {
return this.$store.state.instance.hideSitename
},
sitename () {
return this.$store.state.instance.name
},
......
......@@ -27,7 +27,7 @@
class="side-drawer-logo-wrapper"
>
<img :src="logo">
<span>{{ sitename }}</span>
<span v-if="!hideSitename">{{ sitename }}</span>
</div>
</div>
<ul>
......
......@@ -93,17 +93,4 @@
opacity: 1;
}
}
.new-status-notification {
position:relative;
margin-top: -1px;
font-size: 1.1em;
border-width: 1px 0 0 0;
border-style: solid;
border-color: var(--border, $fallback--border);
padding: 10px;
z-index: 1;
background-color: $fallback--fg;
background-color: var(--panel, $fallback--fg);
}
</style>
......@@ -27,6 +27,7 @@ const defaultState = {
scopeCopy: true,
subjectLineBehavior: 'email',
postContentType: 'text/plain',
hideSitename: false,
nsfwCensorImage: undefined,
vapidPublicKey: undefined,
noAttachmentLinks: false,
......
......@@ -12,7 +12,8 @@ const defaultState = {
window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)')
)
},
mobileLayout: false
mobileLayout: false,
postStatusForms: []
}
const interfaceMod = {
......@@ -35,6 +36,12 @@ const interfaceMod = {
},
setMobileLayout (state, value) {
state.mobileLayout = value
},
addNewPostStatusForm (state, instance) {
state.postStatusForms.push(instance)
},
removePostStatusForm (state, instance) {
del(state.postStatusForms, state.postStatusForms.indexOf(instance))
}
},
actions: {
......@@ -49,6 +56,12 @@ const interfaceMod = {
},
setMobileLayout ({ commit }, value) {
commit('setMobileLayout', value)
},
addNewPostStatusForm ({ commit }, instance) {
commit('addNewPostStatusForm', instance)
},
removePostStatusForm ({ commit }, instance) {
commit('removePostStatusForm', instance)
}
}
}
......
......@@ -22,7 +22,7 @@ const MFA_BACKUP_CODES_URL = '/api/pleroma/accounts/mfa/backup_codes'
const MFA_SETUP_OTP_URL = '/api/pleroma/accounts/mfa/setup/totp'
const MFA_CONFIRM_OTP_URL = '/api/pleroma/accounts/mfa/confirm/totp'
const MFA_DISABLE_OTP_URL = '/api/pleroma/account/mfa/totp'
const MFA_DISABLE_OTP_URL = '/api/pleroma/accounts/mfa/totp'
const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials'
const MASTODON_REGISTRATION_URL = '/api/v1/accounts'
......
......@@ -4103,6 +4103,11 @@ istanbul@0.4.5, istanbul@^0.4.0:
which "^1.1.1"
wordwrap "^1.0.0"
javascript-detect-element-resize@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/javascript-detect-element-resize/-/javascript-detect-element-resize-0.5.3.tgz#1a71cd51dfe565907f299012fe73a294104025de"
integrity sha1-GnHNUd/lZZB/KZAS/nOilBBAJd4=
js-base64@^2.1.9:
version "2.5.0"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.0.tgz#42255ba183ab67ce59a0dee640afdc00ab5ae93e"
......