summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Sulzer <jonas@violoncello.ch>2020-09-02 16:26:20 +0200
committerRobin Appelman <robin@icewind.nl>2020-10-12 17:53:36 +0200
commitb3574eb2742701d1c25f6fa591bd43e14acd32c3 (patch)
tree0007a799611e628e382f476321577e83bf323b6d
parentb56732b343cf3934b012dfa7db1dd2188b7de198 (diff)
👌 IMPROVE: composerimp/composer-improvements
- button in appnavigation to create post -> open modal - composer in timeline not sticky - reply opens composer in modal - use vuex to store composer reply and modal open state Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
-rw-r--r--src/App.vue30
-rw-r--r--src/components/Composer.vue19
-rw-r--r--src/components/TimelinePost.vue3
-rw-r--r--src/store/composer.js51
-rw-r--r--src/store/index.js2
5 files changed, 91 insertions, 14 deletions
diff --git a/src/App.vue b/src/App.vue
index 78ac28d1..db008de4 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,10 +1,21 @@
<template>
<Content v-if="!serverData.setup" app-name="social" :class="{public: serverData.public}">
<AppNavigation v-if="!serverData.public">
+ <AppNavigationNew
+ :text="t('social', 'New post')"
+ :disabled="false"
+ button-id="new-socialpost-button"
+ button-class="icon-add"
+ @click="showNewPostModal" />
<AppNavigationItem v-for="item in menu.items" :key="item.key" :to="item.to"
:title="item.title" :icon="item.icon" :exact="true" />
</AppNavigation>
<AppContent>
+ <Modal v-if="newPostModal" @close="closeNewPostModal">
+ <div class="composer-in-modal">
+ <Composer />
+ </div>
+ </Modal>
<div v-if="serverData.isAdmin && !serverData.checks.success" class="setup social__wrapper">
<h3 v-if="!serverData.checks.checks.wellknown">
{{ t('social', '.well-known/webfinger isn\'t properly set up!') }}
@@ -85,6 +96,10 @@
text-decoration: underline;
}
+ .composer-in-modal {
+ width: 600px;
+ max-width: 100%;
+ }
</style>
<script>
@@ -92,8 +107,11 @@ import Content from '@nextcloud/vue/dist/Components/Content'
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation'
import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
+import AppNavigationNew from '@nextcloud/vue/dist/Components/AppNavigationNew'
+import Modal from '@nextcloud/vue/dist/Components/Modal'
import axios from '@nextcloud/axios'
+import Composer from './components/Composer.vue'
import Search from './components/Search.vue'
import currentuserMixin from './mixins/currentUserMixin'
import { loadState } from '@nextcloud/initial-state'
@@ -106,6 +124,9 @@ export default {
AppContent,
AppNavigation,
AppNavigationItem,
+ AppNavigationNew,
+ Modal,
+ Composer,
Search
},
mixins: [currentuserMixin],
@@ -118,6 +139,9 @@ export default {
}
},
computed: {
+ newPostModal() {
+ return this.$store.getters.getComposerModalState
+ },
timeline: function() {
return this.$store.getters.getTimeline
},
@@ -242,6 +266,12 @@ export default {
if (data.source === 'timeline.direct' && timeline === 'direct') {
this.$store.dispatch('addToTimeline', [data.payload])
}
+ },
+ showNewPostModal() {
+ this.$store.commit('openComposerModal')
+ },
+ closeNewPostModal() {
+ this.$store.commit('closeComposerModal')
}
}
}
diff --git a/src/components/Composer.vue b/src/components/Composer.vue
index f14a93a3..8bd0a7ad 100644
--- a/src/components/Composer.vue
+++ b/src/components/Composer.vue
@@ -36,10 +36,10 @@
</div>
<div v-if="replyTo" class="reply-to">
<p>
- <span>In reply to</span>
+ <span>{{ t('social', 'In reply to') }}</span>
<actor-avatar :actor="replyTo.actor_info" :size="16" />
<strong>{{ replyTo.actor_info.account }}</strong>
- <a class="icon-close" @click="replyTo=null" />
+ <a class="icon-close" @click="$store.commit('removeComposerReply')" />
</p>
<div class="reply-to-preview">
{{ replyTo.content }}
@@ -111,10 +111,6 @@
.new-post {
padding: 10px;
background-color: var(--color-main-background);
- position: sticky;
- top: 47px;
- z-index: 100;
- margin-bottom: 10px;
}
.new-post-author {
@@ -422,7 +418,6 @@ export default {
postAttachments: [], // The toot's attachments
canType: true,
search: '',
- replyTo: null,
tributeOptions: {
spaceSelectsMatch: true,
collection: [
@@ -517,6 +512,9 @@ export default {
}
},
computed: {
+ replyTo() {
+ return this.$store.getters.getReply
+ },
currentVisibilityIconClass() {
return this.visibilityIconClass(this.type)
},
@@ -607,11 +605,6 @@ export default {
]
}
},
- mounted() {
- this.$root.$on('composer-reply', (data) => {
- this.replyTo = data
- })
- },
methods: {
AddAttachment() {
// TODO: handle (or prevent) mulitple files
@@ -815,7 +808,7 @@ export default {
this.loading = true
this.$store.dispatch('post', postData).then((response) => {
this.loading = false
- this.replyTo = null
+ this.$store.commit('removeComposerReply')
this.post = ''
this.$refs.composerInput.innerText = this.post
this.postAttachments = []
diff --git a/src/components/TimelinePost.vue b/src/components/TimelinePost.vue
index d3ff2318..19a6a99c 100644
--- a/src/components/TimelinePost.vue
+++ b/src/components/TimelinePost.vue
@@ -144,7 +144,8 @@ export default {
return actorInfo.name !== '' ? actorInfo.name : actorInfo.preferredUsername
},
reply() {
- this.$root.$emit('composer-reply', this.item)
+ this.$store.commit('setComposerReply', this.item)
+ this.$store.commit('openComposerModal')
},
boost() {
let params = {
diff --git a/src/store/composer.js b/src/store/composer.js
new file mode 100644
index 00000000..67f65e8e
--- /dev/null
+++ b/src/store/composer.js
@@ -0,0 +1,51 @@
+/*
+ * @copyright Copyright (c) 2030 Jonas Sulzer <jonas@violoncello.ch>
+ *
+ * @author Jonas Sulzer <jonas@violoncello.ch>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+const state = {
+ openInModal: false,
+ reply: null
+}
+const mutations = {
+ openComposerModal(state) {
+ state.openInModal = true
+ },
+ closeComposerModal(state) {
+ state.openInModal = false
+ },
+ setComposerReply(state, data) {
+ state.reply = data
+ },
+ removeComposerReply(state) {
+ state.reply = null
+ }
+}
+const getters = {
+ getComposerModalState(state) {
+ return state.openInModal
+ },
+ getReply(state) {
+ return state.reply
+ }
+}
+const actions = {}
+
+export default { state, mutations, getters, actions }
diff --git a/src/store/index.js b/src/store/index.js
index 4076bff7..716de29d 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -24,6 +24,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
import timeline from './timeline'
+import composer from './composer'
import account from './account'
import settings from './settings'
@@ -34,6 +35,7 @@ const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
modules: {
timeline,
+ composer,
account,
settings
},