summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis <6653109+artonge@users.noreply.github.com>2023-01-24 13:41:30 +0100
committerGitHub <noreply@github.com>2023-01-24 13:41:30 +0100
commitc973a1663f26c2faa46e9e37e4e5984a702a31f3 (patch)
tree7c39ba7cef10bbafbeafa1fe698c1cedba84b787
parentdb4bb9255ea7cf907fb663de2ba4b0adfd81b862 (diff)
parentcef7d9b42995285d448a890e7944827330d3593f (diff)
Merge pull request #1588 from nextcloud/artonge/fix/posting_attachments
Fix posting attachments
-rw-r--r--lib/Controller/LocalController.php6
-rw-r--r--src/components/Composer/Composer.vue326
-rw-r--r--src/components/PostAttachment.vue43
-rw-r--r--src/components/TimelineEntry.vue14
-rw-r--r--src/components/TimelinePost.vue8
5 files changed, 212 insertions, 185 deletions
diff --git a/lib/Controller/LocalController.php b/lib/Controller/LocalController.php
index 5548f1f7..b75e237f 100644
--- a/lib/Controller/LocalController.php
+++ b/lib/Controller/LocalController.php
@@ -124,14 +124,10 @@ class LocalController extends Controller {
*
* @NoAdminRequired
*/
- public function postCreate(string $content = '', $to = null, string $type = null, ?string $replyTo = null, $attachments = null, ?string $hashtags = null): DataResponse {
+ public function postCreate(string $content = '', array $to = [], string $type = null, ?string $replyTo = null, $attachments = null, array $hashtags = []): DataResponse {
$content = $content ?: '';
- $to = is_string($to) ? [$to] : $to;
- $to = $to ?? [];
$replyTo = $replyTo ?? '';
$type = $type ?? Stream::TYPE_PUBLIC;
- $hashtags = $hashtags === '' ? [] : $hashtags;
- $hashtags = $hashtags ?? [];
$attachments = $attachments ?? [];
try {
diff --git a/src/components/Composer/Composer.vue b/src/components/Composer/Composer.vue
index 9ef2c37a..62d4f6ca 100644
--- a/src/components/Composer/Composer.vue
+++ b/src/components/Composer/Composer.vue
@@ -25,7 +25,6 @@
<div class="new-post" data-id="">
<input id="file-upload"
ref="fileUploadInput"
- multiple
type="file"
tabindex="-1"
aria-hidden="true"
@@ -83,6 +82,7 @@
<div class="options">
<NcButton v-tooltip="t('social', 'Add attachment')"
type="tertiary"
+ :disabled="previewUrls.length >= 1"
:aria-label="t('social', 'Add attachment')"
@click.prevent="clickImportInput">
<template #icon>
@@ -402,11 +402,12 @@ export default {
this.$refs.fileUploadInput.click()
},
handleFileChange(event) {
- const previewUrl = URL.createObjectURL(event.target.files[0])
- this.previewUrls.push({
- description: '',
- url: previewUrl,
- result: event.target.files[0],
+ event.target.files.forEach((file) => {
+ this.previewUrls.push({
+ description: '',
+ url: URL.createObjectURL(file),
+ result: file,
+ })
})
},
removeAttachment(idx) {
@@ -421,7 +422,6 @@ export default {
}
this.post += this.$twemoji.parse(emoji) + ' '
this.$refs.composerInput.innerHTML += this.$twemoji.parse(emoji) + ' '
- this.$refs.emojiPicker.hide()
},
togglePopoverMenu() {
this.menuOpened = !this.menuOpened
@@ -476,14 +476,12 @@ export default {
const formData = new FormData()
formData.append('content', content)
- formData.append('to', to)
- formData.append('hashtags', hashtags)
+ to.forEach(to => formData.append('to[]', to))
+ hashtags.forEach(hashtag => formData.append('hashtags[]', hashtag))
formData.append('type', this.type)
- for (const preview of this.previewUrls) {
- // TODO send the summary and other props too
- formData.append('attachments', preview.result)
- formData.append('attachmentDescriptions', preview.description)
- }
+ this.previewUrls.forEach(preview => formData.append('attachments[]', preview.result))
+ this.previewUrls.forEach(preview => formData.append('attachmentDescriptions[]', preview.description))
+
if (this.replyTo) {
formData.append('replyTo', this.replyTo.id)
}
@@ -556,122 +554,146 @@ export default {
</script>
<style scoped lang="scss">
- .new-post {
- padding: 10px;
- background-color: var(--color-main-background);
- position: sticky;
- z-index: 100;
- margin-bottom: 10px;
- top: 0;
-
- &-form {
- flex-grow: 1;
- position: relative;
- top: -10px;
- margin-left: 39px;
- &__emoji-picker {
- z-index: 1;
- }
+.new-post {
+ padding: 10px;
+ background-color: var(--color-main-background);
+ position: sticky;
+ z-index: 100;
+ margin-bottom: 10px;
+ top: 0;
+
+ &-form {
+ flex-grow: 1;
+ position: relative;
+ top: -10px;
+ margin-left: 39px;
+ &__emoji-picker {
+ z-index: 1;
}
}
+}
- .new-post-author {
- padding: 5px;
- display: flex;
- flex-wrap: wrap;
-
- .post-author {
- padding: 6px;
+.new-post-author {
+ padding: 5px;
+ display: flex;
+ flex-wrap: wrap;
- .post-author-name {
- font-weight: bold;
- }
+ .post-author {
+ padding: 6px;
- .post-author-id {
- opacity: .7;
- }
+ .post-author-name {
+ font-weight: bold;
}
- }
- .reply-to {
- background-image: url(../../../img/reply.svg);
- background-position: 8px 12px;
- background-repeat: no-repeat;
- margin-left: 39px;
- margin-bottom: 20px;
- overflow: hidden;
- background-color: var(--color-background-hover);
- border-radius: var(--border-radius-large);
- padding: 5px;
- padding-left: 30px;
-
- .reply-info {
- display: flex;
- align-items: center;
- }
- .close-button {
- margin-left: auto;
+ .post-author-id {
opacity: .7;
- min-width: 30px;
- min-height: 30px;
- height: 30px;
- width: 30px !important;
}
}
+}
- .message {
- width: 100%;
- padding-right: 44px;
- min-height: 70px;
- min-width: 2px;
- display: block;
+.reply-to {
+ background-image: url(../../../img/reply.svg);
+ background-position: 8px 12px;
+ background-repeat: no-repeat;
+ margin-left: 39px;
+ margin-bottom: 20px;
+ overflow: hidden;
+ background-color: var(--color-background-hover);
+ border-radius: var(--border-radius-large);
+ padding: 5px;
+ padding-left: 30px;
+
+ .reply-info {
+ display: flex;
+ align-items: center;
}
-
- [contenteditable=true]:empty:before {
- content: attr(placeholder);
- display: block; /* For Firefox */
- opacity: .5;
+ .close-button {
+ margin-left: auto;
+ opacity: .7;
+ min-width: 30px;
+ min-height: 30px;
+ height: 30px;
+ width: 30px !important;
}
+}
- input[type=submit].inline {
- width: 44px;
- height: 44px;
- margin: 0;
- padding: 13px;
- background-color: transparent;
- border: none;
- opacity: 0.3;
- position: absolute;
- bottom: 0;
- right: 0;
- }
+.message {
+ width: 100%;
+ padding-right: 44px;
+ min-height: 70px;
+ min-width: 2px;
+ display: block;
- .options {
- display: flex;
- align-items: flex-end;
- width: 100%;
- margin-top: 0.5rem;
- }
+ :deep(.mention) {
+ color: var(--color-primary-element);
+ background-color: var(--color-background-dark);
+ border-radius: 5px;
+ padding-top: 1px;
+ padding-left: 2px;
+ padding-bottom: 1px;
+ padding-right: 5px;
- .emptySpace {
- flex-grow:1;
+ img {
+ width: 16px;
+ border-radius: 50%;
+ overflow: hidden;
+ margin-right: 3px;
+ vertical-align: middle;
+ margin-top: -1px;
+ }
}
+}
- .popovermenu-parent {
- position: relative;
- }
- .popovermenu {
- top: 55px;
- }
+[contenteditable=true]:empty:before {
+ content: attr(placeholder);
+ display: block; /* For Firefox */
+ opacity: .5;
+}
- .attachment-picker-wrapper {
- position: absolute;
- right: 0;
- top: 2;
- }
+input[type=submit].inline {
+ width: 44px;
+ height: 44px;
+ margin: 0;
+ padding: 13px;
+ background-color: transparent;
+ border: none;
+ opacity: 0.3;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+}
+
+.options {
+ display: flex;
+ align-items: flex-end;
+ width: 100%;
+ margin-top: 0.5rem;
+}
+
+.emptySpace {
+ flex-grow:1;
+}
- /* Tribute-specific styles TODO: properly scope component css */
- .tribute-container {
+.popovermenu-parent {
+ position: relative;
+}
+.popovermenu {
+ top: 55px;
+}
+
+.attachment-picker-wrapper {
+ position: absolute;
+ right: 0;
+ top: 2;
+}
+
+.hashtag {
+ text-decoration: underline;
+}
+</style>
+<style lang="scss">
+/* Tribute-specific styles TODO: properly scope component css */
+.tribute-container {
position: absolute;
top: 0;
left: 0;
@@ -694,43 +716,42 @@ export default {
border-radius: 4px;
background-clip: padding-box;
overflow: hidden;
- }
- li {
- color: var(--color-text);
- padding: 5px 10px;
- cursor: pointer;
- font-size: 14px;
- display: flex;
+ li {
+ color: var(--color-text);
+ padding: 5px 10px;
+ cursor: pointer;
+ font-size: 14px;
+ display: flex;
- span {
- display: block;
- }
+ span {
+ display: block;
+ }
- &.highlight,
- &:hover {
- background: var(--color-primary);
- color: var(--color-primary-text);
- }
+ &.highlight,
+ &:hover {
+ background: var(--color-primary);
+ color: var(--color-primary-text);
+ }
- img {
- width: 32px;
- height: 32px;
- border-radius: 50%;
- overflow: hidden;
- margin-right: 10px;
- margin-left: -3px;
- margin-top: 3px;
- }
+ img {
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ overflow: hidden;
+ margin-right: 10px;
+ margin-left: -3px;
+ margin-top: 3px;
+ }
- span {
- font-weight: bold;
- }
+ span {
+ font-weight: bold;
+ }
- &.no-match {
- cursor: default;
+ &.no-match {
+ cursor: default;
+ }
}
-
}
.menu-highlighted {
@@ -750,28 +771,5 @@ export default {
color: var(--color-primary-text) !important;
opacity: .6;
}
- }
-
- .message .mention {
- color: var(--color-primary-element);
- background-color: var(--color-background-dark);
- border-radius: 5px;
- padding-top: 1px;
- padding-left: 2px;
- padding-bottom: 1px;
- padding-right: 5px;
-
- img {
- width: 16px;
- border-radius: 50%;
- overflow: hidden;
- margin-right: 3px;
- vertical-align: middle;
- margin-top: -1px;
- }
- }
-
- .hashtag {
- text-decoration: underline;
- }
+}
</style>
diff --git a/src/components/PostAttachment.vue b/src/components/PostAttachment.vue
index 6a7644c3..0e1f06d0 100644
--- a/src/components/PostAttachment.vue
+++ b/src/components/PostAttachment.vue
@@ -1,9 +1,15 @@
<template>
- <masonry>
- <div v-for="(item, index) in attachments" :key="index">
- <img :src="imageUrl(item)" @click="showModal(index)">
+ <div class="post-attachments">
+ <div v-for="(item, index) in attachments"
+ :key="index"
+ class="post-attachment"
+ @click="showModal(index)">
+ <img v-if="item.mimeType.startsWith('image/')" :src="imageUrl(item)">
+ <div v-else>
+ {{ item }}
+ </div>
</div>
- <NcModal v-show="modal"
+ <NcModal v-if="modal"
:has-previous="current > 0"
:has-next="current < (attachments.length - 1)"
size="full"
@@ -14,11 +20,10 @@
<canvas ref="modalCanvas" />
</div>
</NcModal>
- </masonry>
+ </div>
</template>
<script>
-
import serverData from '../mixins/serverData.js'
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import { generateUrl } from '@nextcloud/router'
@@ -101,3 +106,29 @@ export default {
},
}
</script>
+<style lang="scss" scoped>
+.post-attachments {
+ margin-top: 12px;
+ width: 100%;
+ display: flex;
+ gap: 12px;
+ overflow-x: scroll;
+
+ .post-attachment {
+ height: 100px;
+ object-fit: cover;
+ border-radius: var(--border-radius-large);
+ overflow: hidden;
+ flex-shrink: 0;
+
+ > * {
+ cursor: pointer;
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+ }
+}
+</style>
diff --git a/src/components/TimelineEntry.vue b/src/components/TimelineEntry.vue
index 2ce2baec..04941109 100644
--- a/src/components/TimelineEntry.vue
+++ b/src/components/TimelineEntry.vue
@@ -27,8 +27,8 @@
<UserEntry v-if="item.type === 'SocialAppNotification' && item.details.actor" :key="item.details.actor.id" :item="item.details.actor" />
<template v-else>
<div class="wrapper">
- <TimelineAvatar :item="entryContent" />
- <TimelinePost class="message"
+ <TimelineAvatar class="entry__avatar" :item="entryContent" />
+ <TimelinePost class="entry__content"
:item="entryContent"
:parent-announce="isBoost" />
</div>
@@ -130,9 +130,19 @@ export default {
display: flex;
margin: auto;
padding: 0;
+
&:focus {
background-color: rgba(47, 47, 47, 0.068);
}
+
+ .entry__avatar {
+ flex-shrink: 0;
+ }
+
+ .entry__content {
+ flex-grow: 1;
+ width: 0;
+ }
}
.notification-header {
diff --git a/src/components/TimelinePost.vue b/src/components/TimelinePost.vue
index 05809747..9c3b095d 100644
--- a/src/components/TimelinePost.vue
+++ b/src/components/TimelinePost.vue
@@ -220,7 +220,6 @@ export default {
font-size: 15px;
line-height: 1.6em;
position: relative;
- width: 100%;
::v-deep a.widget-default {
text-decoration: none !important;
@@ -276,13 +275,6 @@ export default {
}
}
- span {
- /* opacity: 0.5; */
- }
- .entry-content {
- display: flex;
- }
-
.post-header {
display: flex;
flex-direction: row;