commit: ccba92a27cc96d6db9b28d456f6fff6cb6804a52
parent: 61bb02ef0631b534e1a80a3b08f0e27c1a1c8e66
Author: Shpuld Shpludson <shp@cock.li>
Date: Wed, 25 Sep 2019 06:41:26 +0000
Merge branch '639-2' into 'develop'
Add "Mention user" button to user card
Closes #639
See merge request pleroma/pleroma-fe!955
Diffstat:
15 files changed, 273 insertions(+), 204 deletions(-)
diff --git a/src/App.js b/src/App.js
@@ -8,9 +8,10 @@ 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 MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_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'
import { windowWidth } from './services/window_utils/window_utils'
export default {
@@ -26,9 +27,10 @@ export default {
ChatPanel,
MediaModal,
SideDrawer,
- MobilePostStatusModal,
+ MobilePostStatusButton,
MobileNav,
- UserReportingModal
+ UserReportingModal,
+ PostStatusModal
},
data: () => ({
mobileActivePanel: 'timeline',
diff --git a/src/App.vue b/src/App.vue
@@ -107,8 +107,9 @@
:floating="true"
class="floating-chat mobile-hidden"
/>
- <MobilePostStatusModal />
+ <MobilePostStatusButton />
<UserReportingModal />
+ <PostStatusModal />
<portal-target name="modal" />
</div>
</template>
diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.js b/src/components/mobile_post_status_button/mobile_post_status_button.js
@@ -0,0 +1,93 @@
+import { debounce } from 'lodash'
+
+const MobilePostStatusButton = {
+ data () {
+ return {
+ hidden: false,
+ scrollingDown: false,
+ inputActive: false,
+ oldScrollPos: 0,
+ amountScrolled: 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)
+ },
+ autohideFloatingPostButton () {
+ return !!this.$store.state.config.autohideFloatingPostButton
+ }
+ },
+ watch: {
+ autohideFloatingPostButton: function (isEnabled) {
+ if (isEnabled) {
+ this.activateFloatingPostButtonAutohide()
+ } else {
+ this.deactivateFloatingPostButtonAutohide()
+ }
+ }
+ },
+ methods: {
+ activateFloatingPostButtonAutohide () {
+ window.addEventListener('scroll', this.handleScrollStart)
+ window.addEventListener('scroll', this.handleScrollEnd)
+ },
+ deactivateFloatingPostButtonAutohide () {
+ window.removeEventListener('scroll', this.handleScrollStart)
+ window.removeEventListener('scroll', this.handleScrollEnd)
+ },
+ openPostForm () {
+ this.$store.dispatch('openPostStatusModal')
+ },
+ 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
+ }
+ },
+ handleScrollStart: debounce(function () {
+ if (window.scrollY > this.oldScrollPos) {
+ this.hidden = true
+ } else {
+ this.hidden = false
+ }
+ this.oldScrollPos = window.scrollY
+ }, 100, { leading: true, trailing: false }),
+
+ handleScrollEnd: debounce(function () {
+ this.hidden = false
+ this.oldScrollPos = window.scrollY
+ }, 100, { leading: false, trailing: true })
+ }
+}
+
+export default MobilePostStatusButton
diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.vue b/src/components/mobile_post_status_button/mobile_post_status_button.vue
@@ -0,0 +1,55 @@
+<template>
+ <div v-if="isLoggedIn">
+ <button
+ class="new-status-button"
+ :class="{ 'hidden': isHidden }"
+ @click="openPostForm"
+ >
+ <i class="icon-edit" />
+ </button>
+ </div>
+</template>
+
+<script src="./mobile_post_status_button.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.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/mobile_post_status_modal/mobile_post_status_modal.js b/src/components/mobile_post_status_modal/mobile_post_status_modal.js
@@ -1,108 +0,0 @@
-import PostStatusForm from '../post_status_form/post_status_form.vue'
-import { debounce } from 'lodash'
-
-const MobilePostStatusModal = {
- components: {
- PostStatusForm
- },
- data () {
- return {
- hidden: false,
- postFormOpen: false,
- scrollingDown: false,
- inputActive: false,
- oldScrollPos: 0,
- amountScrolled: 0
- }
- },
- created () {
- if (this.autohideFloatingPostButton) {
- this.activateFloatingPostButtonAutohide()
- }
- window.addEventListener('resize', this.handleOSK)
- },
- destroyed () {
- if (this.autohideFloatingPostButton) {
- this.deactivateFloatingPostButtonAutohide()
- }
- window.removeEventListener('resize', this.handleOSK)
- },
- computed: {
- currentUser () {
- return this.$store.state.users.currentUser
- },
- isHidden () {
- return this.autohideFloatingPostButton && (this.hidden || this.inputActive)
- },
- autohideFloatingPostButton () {
- return !!this.$store.state.config.autohideFloatingPostButton
- }
- },
- watch: {
- autohideFloatingPostButton: function (isEnabled) {
- if (isEnabled) {
- this.activateFloatingPostButtonAutohide()
- } else {
- this.deactivateFloatingPostButtonAutohide()
- }
- }
- },
- methods: {
- activateFloatingPostButtonAutohide () {
- window.addEventListener('scroll', this.handleScrollStart)
- window.addEventListener('scroll', this.handleScrollEnd)
- },
- deactivateFloatingPostButtonAutohide () {
- window.removeEventListener('scroll', this.handleScrollStart)
- window.removeEventListener('scroll', this.handleScrollEnd)
- },
- 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
- }
- },
- handleScrollStart: debounce(function () {
- if (window.scrollY > this.oldScrollPos) {
- this.hidden = true
- } else {
- this.hidden = false
- }
- this.oldScrollPos = window.scrollY
- }, 100, { leading: true, trailing: false }),
-
- handleScrollEnd: debounce(function () {
- this.hidden = false
- this.oldScrollPos = window.scrollY
- }, 100, { leading: false, trailing: true })
- }
-}
-
-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
@@ -1,89 +0,0 @@
-<template>
- <div v-if="currentUser">
- <div
- v-show="postFormOpen"
- class="post-form-modal-view modal-view"
- @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 {
- align-items: flex-start;
-}
-
-.post-form-modal-panel {
- flex-shrink: 0;
- margin-top: 25%;
- margin-bottom: 2em;
- width: 100%;
- max-width: 700px;
-
- @media (orientation: landscape) {
- margin-top: 8%;
- }
-}
-
-.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/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
@@ -8,7 +8,7 @@ import fileTypeService from '../../services/file_type/file_type.service.js'
import { reject, map, uniqBy } from 'lodash'
import suggestor from '../emoji-input/suggestor.js'
-const buildMentionsString = ({ user, attentions }, currentUser) => {
+const buildMentionsString = ({ user, attentions = [] }, currentUser) => {
let allAttentions = [...attentions]
allAttentions.unshift(user)
diff --git a/src/components/post_status_modal/post_status_modal.js b/src/components/post_status_modal/post_status_modal.js
@@ -0,0 +1,32 @@
+import PostStatusForm from '../post_status_form/post_status_form.vue'
+
+const PostStatusModal = {
+ components: {
+ PostStatusForm
+ },
+ computed: {
+ isLoggedIn () {
+ return !!this.$store.state.users.currentUser
+ },
+ isOpen () {
+ return this.isLoggedIn && this.$store.state.postStatus.modalActivated
+ },
+ params () {
+ return this.$store.state.postStatus.params || {}
+ }
+ },
+ watch: {
+ isOpen (val) {
+ if (val) {
+ this.$nextTick(() => this.$el.querySelector('textarea').focus())
+ }
+ }
+ },
+ methods: {
+ closeModal () {
+ this.$store.dispatch('closePostStatusModal')
+ }
+ }
+}
+
+export default PostStatusModal
diff --git a/src/components/post_status_modal/post_status_modal.vue b/src/components/post_status_modal/post_status_modal.vue
@@ -0,0 +1,43 @@
+<template>
+ <div
+ v-if="isOpen"
+ class="post-form-modal-view modal-view"
+ @click="closeModal"
+ >
+ <div
+ class="post-form-modal-panel panel"
+ @click.stop=""
+ >
+ <div class="panel-heading">
+ {{ $t('post_status.new_status') }}
+ </div>
+ <PostStatusForm
+ class="panel-body"
+ v-bind="params"
+ @posted="closeModal"
+ />
+ </div>
+ </div>
+</template>
+
+<script src="./post_status_modal.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.post-form-modal-view {
+ align-items: flex-start;
+}
+
+.post-form-modal-panel {
+ flex-shrink: 0;
+ margin-top: 25%;
+ margin-bottom: 2em;
+ width: 100%;
+ max-width: 700px;
+
+ @media (orientation: landscape) {
+ margin-top: 8%;
+ }
+}
+</style>
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
@@ -168,6 +168,9 @@ export default {
}
this.$store.dispatch('setMedia', [attachment])
this.$store.dispatch('setCurrent', attachment)
+ },
+ mentionUser () {
+ this.$store.dispatch('openPostStatusModal', { replyTo: true, repliedUser: this.user })
}
}
}
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
@@ -190,6 +190,15 @@
<div>
<button
+ class="btn btn-default btn-block"
+ @click="mentionUser"
+ >
+ {{ $t('user_card.mention') }}
+ </button>
+ </div>
+
+ <div>
+ <button
v-if="user.muted"
class="btn btn-default btn-block pressed"
@click="unmuteUser"
diff --git a/src/components/user_panel/user_panel.vue b/src/components/user_panel/user_panel.vue
@@ -11,7 +11,7 @@
rounded="top"
/>
<div class="panel-footer">
- <post-status-form v-if="user" />
+ <post-status-form />
</div>
</div>
<auth-form
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -529,6 +529,7 @@
"follows_you": "Follows you!",
"its_you": "It's you!",
"media": "Media",
+ "mention": "Mention",
"mute": "Mute",
"muted": "Muted",
"per_day": "per day",
diff --git a/src/main.js b/src/main.js
@@ -15,6 +15,7 @@ import mediaViewerModule from './modules/media_viewer.js'
import oauthTokensModule from './modules/oauth_tokens.js'
import reportsModule from './modules/reports.js'
import pollsModule from './modules/polls.js'
+import postStatusModule from './modules/postStatus.js'
import VueI18n from 'vue-i18n'
@@ -76,7 +77,8 @@ const persistedStateOptions = {
mediaViewer: mediaViewerModule,
oauthTokens: oauthTokensModule,
reports: reportsModule,
- polls: pollsModule
+ polls: pollsModule,
+ postStatus: postStatusModule
},
plugins: [persistedState, pushNotifications],
strict: false // Socket modifies itself, let's ignore this for now.
diff --git a/src/modules/postStatus.js b/src/modules/postStatus.js
@@ -0,0 +1,25 @@
+const postStatus = {
+ state: {
+ params: null,
+ modalActivated: false
+ },
+ mutations: {
+ openPostStatusModal (state, params) {
+ state.params = params
+ state.modalActivated = true
+ },
+ closePostStatusModal (state) {
+ state.modalActivated = false
+ }
+ },
+ actions: {
+ openPostStatusModal ({ commit }, params) {
+ commit('openPostStatusModal', params)
+ },
+ closePostStatusModal ({ commit }) {
+ commit('closePostStatusModal')
+ }
+ }
+}
+
+export default postStatus