commit: f397537642a6b8a4079d8d45d835ddd50f2d2b4a
parent: bb1a4e11f8d063427dbb91f6b4f5349fac2458d5
Author: Shpuld Shpludson <shp@cock.li>
Date: Mon, 11 Mar 2019 16:51:37 +0000
Merge branch 'feature/mobile-improvements-2' into 'develop'
Add floating post-status button on mobile
See merge request pleroma/pleroma-fe!628
Diffstat:
8 files changed, 203 insertions(+), 26 deletions(-)
diff --git a/src/App.js b/src/App.js
@@ -8,6 +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 MobilePostStatusModal from './components/mobile_post_status_modal/mobile_post_status_modal.vue'
import { unseenNotificationsFromStore } from './services/notification_utils/notification_utils'
export default {
@@ -22,7 +23,8 @@ export default {
WhoToFollowPanel,
ChatPanel,
MediaModal,
- SideDrawer
+ SideDrawer,
+ MobilePostStatusModal
},
data: () => ({
mobileActivePanel: 'timeline',
diff --git a/src/App.scss b/src/App.scss
@@ -671,6 +671,31 @@ nav {
border-radius: var(--inputRadius, $fallback--inputRadius);
}
+@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;
}
diff --git a/src/App.vue b/src/App.vue
@@ -50,6 +50,7 @@
<media-modal></media-modal>
</div>
<chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel>
+ <MobilePostStatusModal />
</div>
</template>
diff --git a/src/boot/routes.js b/src/boot/routes.js
@@ -13,7 +13,6 @@ import FollowRequests from 'components/follow_requests/follow_requests.vue'
import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
import UserSearch from 'components/user_search/user_search.vue'
import Notifications from 'components/notifications/notifications.vue'
-import UserPanel from 'components/user_panel/user_panel.vue'
import LoginForm from 'components/login_form/login_form.vue'
import ChatPanel from 'components/chat_panel/chat_panel.vue'
import WhoToFollow from 'components/who_to_follow/who_to_follow.vue'
@@ -43,7 +42,6 @@ export default (store) => {
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests },
{ name: 'user-settings', path: '/user-settings', component: UserSettings },
{ name: 'notifications', path: '/:username/notifications', component: Notifications },
- { name: 'new-status', path: '/:username/new-status', component: UserPanel },
{ name: 'login', path: '/login', component: LoginForm },
{ name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) },
{ name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) },
diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue
@@ -1,5 +1,5 @@
<template>
- <div class="modal-view" v-if="showing" @click.prevent="hide">
+ <div class="modal-view media-modal-view" v-if="showing" @click.prevent="hide">
<img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img>
<VideoAttachment
class="modal-image"
@@ -32,18 +32,7 @@
<style lang="scss">
@import '../../_variables.scss';
-.modal-view {
- z-index: 1000;
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- background-color: rgba(0, 0, 0, 0.5);
-
+.media-modal-view {
&:hover {
.modal-view-button-arrow {
opacity: 0.75;
diff --git a/src/components/mobile_post_status_modal/mobile_post_status_modal.js b/src/components/mobile_post_status_modal/mobile_post_status_modal.js
@@ -0,0 +1,91 @@
+import PostStatusForm from '../post_status_form/post_status_form.vue'
+import { throttle } from 'lodash'
+
+const MobilePostStatusModal = {
+ components: {
+ PostStatusForm
+ },
+ data () {
+ return {
+ hidden: false,
+ postFormOpen: false,
+ scrollingDown: false,
+ inputActive: false,
+ oldScrollPos: 0,
+ amountScrolled: 0
+ }
+ },
+ created () {
+ window.addEventListener('scroll', this.handleScroll)
+ window.addEventListener('resize', this.handleOSK)
+ },
+ destroyed () {
+ window.removeEventListener('scroll', this.handleScroll)
+ window.removeEventListener('resize', this.handleOSK)
+ },
+ computed: {
+ currentUser () {
+ return this.$store.state.users.currentUser
+ },
+ isHidden () {
+ return this.hidden || this.inputActive
+ }
+ },
+ methods: {
+ openPostForm () {
+ this.postFormOpen = true
+ this.hidden = true
+
+ const el = this.$el.querySelector('textarea')
+ this.$nextTick(function () {
+ el.focus()
+ })
+ },
+ closePostForm () {
+ this.postFormOpen = false
+ this.hidden = false
+ },
+ handleOSK () {
+ // This is a big hack: we're guessing from changed window sizes if the
+ // on-screen keyboard is active or not. This is only really important
+ // for phones in portrait mode and it's more important to show the button
+ // in normal scenarios on all phones, than it is to hide it when the
+ // keyboard is active.
+ // Guesswork based on https://www.mydevice.io/#compare-devices
+
+ // for example, iphone 4 and android phones from the same time period
+ const smallPhone = window.innerWidth < 350
+ const smallPhoneKbOpen = smallPhone && window.innerHeight < 345
+
+ const biggerPhone = !smallPhone && window.innerWidth < 450
+ const biggerPhoneKbOpen = biggerPhone && window.innerHeight < 560
+ if (smallPhoneKbOpen || biggerPhoneKbOpen) {
+ this.inputActive = true
+ } else {
+ this.inputActive = false
+ }
+ },
+ handleScroll: throttle(function () {
+ const scrollAmount = window.scrollY - this.oldScrollPos
+ const scrollingDown = scrollAmount > 0
+
+ if (scrollingDown !== this.scrollingDown) {
+ this.amountScrolled = 0
+ this.scrollingDown = scrollingDown
+ if (!scrollingDown) {
+ this.hidden = false
+ }
+ } else if (scrollingDown) {
+ this.amountScrolled += scrollAmount
+ if (this.amountScrolled > 100 && !this.hidden) {
+ this.hidden = true
+ }
+ }
+
+ this.oldScrollPos = window.scrollY
+ this.scrollingDown = scrollingDown
+ }, 100)
+ }
+}
+
+export default MobilePostStatusModal
diff --git a/src/components/mobile_post_status_modal/mobile_post_status_modal.vue b/src/components/mobile_post_status_modal/mobile_post_status_modal.vue
@@ -0,0 +1,76 @@
+<template>
+<div v-if="currentUser">
+ <div
+ class="post-form-modal-view modal-view"
+ v-show="postFormOpen"
+ @click="closePostForm"
+ >
+ <div class="post-form-modal-panel panel" @click.stop="">
+ <div class="panel-heading">{{$t('post_status.new_status')}}</div>
+ <PostStatusForm class="panel-body" @posted="closePostForm"/>
+ </div>
+ </div>
+ <button
+ class="new-status-button"
+ :class="{ 'hidden': isHidden }"
+ @click="openPostForm"
+ >
+ <i class="icon-edit" />
+ </button>
+</div>
+</template>
+
+<script src="./mobile_post_status_modal.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.post-form-modal-view {
+ max-height: 100%;
+ display: block;
+}
+
+.post-form-modal-panel {
+ flex-shrink: 0;
+ margin: 25% 0 4em 0;
+ width: 100%;
+}
+
+.new-status-button {
+ width: 5em;
+ height: 5em;
+ border-radius: 100%;
+ position: fixed;
+ bottom: 1.5em;
+ right: 1.5em;
+ // TODO: this needs its own color, it has to stand out enough and link color
+ // is not very optimal for this particular use.
+ background-color: $fallback--fg;
+ background-color: var(--btn, $fallback--fg);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3), 0px 4px 6px rgba(0, 0, 0, 0.3);
+ z-index: 10;
+
+ transition: 0.35s transform;
+ transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
+
+ &.hidden {
+ transform: translateY(150%);
+ }
+
+ i {
+ font-size: 1.5em;
+ color: $fallback--text;
+ color: var(--text, $fallback--text);
+ }
+}
+
+@media all and (min-width: 801px) {
+ .new-status-button {
+ display: none;
+ }
+}
+
+</style>
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
@@ -15,12 +15,7 @@
</div>
</div>
<ul>
- <li v-if="currentUser" @click="toggleDrawer">
- <router-link :to="{ name: 'new-status', params: { username: currentUser.screen_name } }">
- {{ $t("post_status.new_status") }}
- </router-link>
- </li>
- <li v-else @click="toggleDrawer">
+ <li v-if="!currentUser" @click="toggleDrawer">
<router-link :to="{ name: 'login' }">
{{ $t("login.login") }}
</router-link>
@@ -119,14 +114,14 @@
}
.side-drawer-container-open {
- transition-delay: 0.0s;
- transition-property: left;
+ transition: 0.35s;
+ transition-property: background-color;
+ background-color: rgba(0, 0, 0, 0.5);
}
.side-drawer-container-closed {
left: -100%;
- transition-delay: 0.5s;
- transition-property: left;
+ background-color: rgba(0, 0, 0, 0);
}
.side-drawer-click-outside {