diff options
author | Louis <6653109+artonge@users.noreply.github.com> | 2023-01-24 13:41:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-24 13:41:30 +0100 |
commit | c973a1663f26c2faa46e9e37e4e5984a702a31f3 (patch) | |
tree | 7c39ba7cef10bbafbeafa1fe698c1cedba84b787 | |
parent | db4bb9255ea7cf907fb663de2ba4b0adfd81b862 (diff) | |
parent | cef7d9b42995285d448a890e7944827330d3593f (diff) |
Merge pull request #1588 from nextcloud/artonge/fix/posting_attachments
Fix posting attachments
-rw-r--r-- | lib/Controller/LocalController.php | 6 | ||||
-rw-r--r-- | src/components/Composer/Composer.vue | 326 | ||||
-rw-r--r-- | src/components/PostAttachment.vue | 43 | ||||
-rw-r--r-- | src/components/TimelineEntry.vue | 14 | ||||
-rw-r--r-- | src/components/TimelinePost.vue | 8 |
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; |