From 2c6ec37e6a796d2d7be7be58ac0e3c6c8bbd6a18 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 18 Feb 2019 05:03:26 +0000 Subject: media description support --- src/services/api/api.service.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/services/api/api.service.js') diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index dfffc291..cb205e3f 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -617,7 +617,8 @@ const postStatus = ({ poll, mediaIds = [], inReplyToStatusId, - contentType + contentType, + mediaDescriptions }) => { const form = new FormData() const pollOptions = poll.options || [] @@ -644,6 +645,7 @@ const postStatus = ({ form.append('poll[options][]', option) }) } + form.append('descriptions', JSON.stringify(mediaDescriptions)) if (inReplyToStatusId) { form.append('in_reply_to_id', inReplyToStatusId) } -- cgit v1.2.3-70-g09d2 From 223fabfe90512122ee9d51c22deb01241ba931cd Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Sun, 28 Jun 2020 12:16:41 +0300 Subject: add rich text preview --- .../post_status_form/post_status_form.js | 52 +++++++++- .../post_status_form/post_status_form.vue | 113 +++++++++++++++++++-- src/i18n/en.json | 5 +- src/services/api/api.service.js | 14 ++- .../status_poster/status_poster.service.js | 19 +++- 5 files changed, 180 insertions(+), 23 deletions(-) (limited to 'src/services/api/api.service.js') diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 9027566f..3f7e36a6 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -3,6 +3,7 @@ import MediaUpload from '../media_upload/media_upload.vue' import ScopeSelector from '../scope_selector/scope_selector.vue' import EmojiInput from '../emoji_input/emoji_input.vue' import PollForm from '../poll/poll_form.vue' +import StatusContent from '../status_content/status_content.vue' import fileTypeService from '../../services/file_type/file_type.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { reject, map, uniqBy } from 'lodash' @@ -38,7 +39,8 @@ const PostStatusForm = { EmojiInput, PollForm, ScopeSelector, - Checkbox + Checkbox, + StatusContent }, mounted () { this.resize(this.$refs.textarea) @@ -84,7 +86,9 @@ const PostStatusForm = { caret: 0, pollFormVisible: false, showDropIcon: 'hide', - dropStopTimeout: null + dropStopTimeout: null, + preview: null, + previewLoading: false } }, computed: { @@ -163,8 +167,20 @@ const PostStatusForm = { this.newStatus.poll && this.newStatus.poll.error }, + showPreview () { + return !!this.preview || this.previewLoading + }, ...mapGetters(['mergedConfig']) }, + watch: { + 'newStatus.contentType': function (newType) { + if (newType === 'text/plain') { + this.closePreview() + } else if (this.preview) { + this.previewStatus(this.newStatus) + } + } + }, methods: { postStatus (newStatus) { if (this.posting) { return } @@ -218,6 +234,38 @@ const PostStatusForm = { this.posting = false }) }, + previewStatus (newStatus) { + this.previewLoading = true + statusPoster.postStatus({ + status: newStatus.status, + spoilerText: newStatus.spoilerText || null, + visibility: newStatus.visibility, + sensitive: newStatus.nsfw, + media: newStatus.files, + store: this.$store, + inReplyToStatusId: this.replyTo, + contentType: newStatus.contentType, + poll: {}, + preview: true + }).then((data) => { + // Don't apply preview if not loading, because it means + // user has closed the preview manually. + if (!this.previewLoading) return + if (!data.error) { + this.preview = data + } else { + this.preview = { error: data.error } + } + }).catch((error) => { + this.preview = { error } + }).finally(() => { + this.previewLoading = false + }) + }, + closePreview () { + this.preview = null + this.previewLoading = false + }, addMediaFile (fileInfo) { this.newStatus.files.push(fileInfo) }, diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index e3d8d087..9931f5ca 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -16,6 +16,58 @@ @drop.stop="fileDrop" />
+ + {{ $t('status.preview') }} + +
+ + + {{ $t('status.status_preview') }} + + + + {{ $t('status.preview_update') }} + + + + + +
+ {{ $t('general.loading') }} +
+
+ {{ preview.error }} +
+ +
{ const form = new FormData() const pollOptions = poll.options || [] @@ -647,6 +648,9 @@ const postStatus = ({ if (inReplyToStatusId) { form.append('in_reply_to_id', inReplyToStatusId) } + if (preview) { + form.append('preview', 'true') + } return fetch(MASTODON_POST_STATUS_URL, { body: form, @@ -654,13 +658,7 @@ const postStatus = ({ headers: authHeaders(credentials) }) .then((response) => { - if (response.ok) { - return response.json() - } else { - return { - error: response - } - } + return response.json() }) .then((data) => data.error ? data : parseStatus(data)) } diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js index 9e904d3a..86fc5601 100644 --- a/src/services/status_poster/status_poster.service.js +++ b/src/services/status_poster/status_poster.service.js @@ -1,7 +1,18 @@ import { map } from 'lodash' import apiService from '../api/api.service.js' -const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => { +const postStatus = ({ + store, + status, + spoilerText, + visibility, + sensitive, + poll, + media = [], + inReplyToStatusId = undefined, + contentType = 'text/plain', + preview = false +}) => { const mediaIds = map(media, 'id') return apiService.postStatus({ @@ -13,9 +24,11 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, m mediaIds, inReplyToStatusId, contentType, - poll }) + poll, + preview + }) .then((data) => { - if (!data.error) { + if (!data.error && !preview) { store.dispatch('addNewStatuses', { statuses: [data], timeline: 'friends', -- cgit v1.2.3-70-g09d2 From de291e2e33f1d9e04b27ed30ba3b012d73178e63 Mon Sep 17 00:00:00 2001 From: Eugenij Date: Fri, 3 Jul 2020 19:45:49 +0000 Subject: Add bookmarks Co-authored-by: jared --- CHANGELOG.md | 1 + package.json | 1 + src/boot/routes.js | 2 + .../bookmark_timeline/bookmark_timeline.js | 17 +++++++++ .../bookmark_timeline/bookmark_timeline.vue | 9 +++++ src/components/extra_buttons/extra_buttons.js | 10 +++++ src/components/extra_buttons/extra_buttons.vue | 16 ++++++++ src/components/nav_panel/nav_panel.vue | 5 +++ src/components/side_drawer/side_drawer.vue | 8 ++++ src/components/timeline/timeline.js | 2 +- src/i18n/en.json | 6 ++- src/i18n/ru.json | 7 +++- src/modules/statuses.js | 43 ++++++++++++++++++---- src/services/api/api.service.js | 34 +++++++++++++++-- .../entity_normalizer/entity_normalizer.service.js | 16 ++++++++ .../notifications_fetcher.service.js | 2 +- .../timeline_fetcher/timeline_fetcher.service.js | 17 +++++---- static/fontello.json | 12 ++++++ .../entity_normalizer/entity_normalizer.spec.js | 22 ++++++++++- yarn.lock | 7 ++++ 20 files changed, 213 insertions(+), 24 deletions(-) create mode 100644 src/components/bookmark_timeline/bookmark_timeline.js create mode 100644 src/components/bookmark_timeline/bookmark_timeline.vue mode change 100755 => 100644 static/fontello.json (limited to 'src/services/api/api.service.js') diff --git a/CHANGELOG.md b/CHANGELOG.md index d978d362..2595af1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -99,6 +99,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Ability to change user's email - About page - Added remote user redirect +- Bookmarks ### Changed - changed the way fading effects for user profile/long statuses works, now uses css-mask instead of gradient background hacks which weren't exactly compatible with semi-transparent themes ### Fixed diff --git a/package.json b/package.json index c0665f6e..96231171 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "cropperjs": "^1.4.3", "diff": "^3.0.1", "escape-html": "^1.0.3", + "parse-link-header": "^1.0.1", "localforage": "^1.5.0", "phoenix": "^1.3.0", "portal-vue": "^2.1.4", diff --git a/src/boot/routes.js b/src/boot/routes.js index d98a3b50..f63d8adf 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -2,6 +2,7 @@ import PublicTimeline from 'components/public_timeline/public_timeline.vue' import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue' import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue' import TagTimeline from 'components/tag_timeline/tag_timeline.vue' +import BookmarkTimeline from 'components/bookmark_timeline/bookmark_timeline.vue' import ConversationPage from 'components/conversation-page/conversation-page.vue' import Interactions from 'components/interactions/interactions.vue' import DMs from 'components/dm_timeline/dm_timeline.vue' @@ -40,6 +41,7 @@ export default (store) => { { name: 'public-timeline', path: '/main/public', component: PublicTimeline }, { name: 'friends', path: '/main/friends', component: FriendsTimeline, beforeEnter: validateAuthenticatedRoute }, { name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline }, + { name: 'bookmarks', path: '/bookmarks', component: BookmarkTimeline }, { name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } }, { name: 'remote-user-profile-acct', path: '/remote-users/(@?):username([^/@]+)@:hostname([^/@]+)', diff --git a/src/components/bookmark_timeline/bookmark_timeline.js b/src/components/bookmark_timeline/bookmark_timeline.js new file mode 100644 index 00000000..64b69e5d --- /dev/null +++ b/src/components/bookmark_timeline/bookmark_timeline.js @@ -0,0 +1,17 @@ +import Timeline from '../timeline/timeline.vue' + +const Bookmarks = { + computed: { + timeline () { + return this.$store.state.statuses.timelines.bookmarks + } + }, + components: { + Timeline + }, + destroyed () { + this.$store.commit('clearTimeline', { timeline: 'bookmarks' }) + } +} + +export default Bookmarks diff --git a/src/components/bookmark_timeline/bookmark_timeline.vue b/src/components/bookmark_timeline/bookmark_timeline.vue new file mode 100644 index 00000000..8da6884b --- /dev/null +++ b/src/components/bookmark_timeline/bookmark_timeline.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/components/extra_buttons/extra_buttons.js b/src/components/extra_buttons/extra_buttons.js index e4b19d01..5e0c36bb 100644 --- a/src/components/extra_buttons/extra_buttons.js +++ b/src/components/extra_buttons/extra_buttons.js @@ -34,6 +34,16 @@ const ExtraButtons = { navigator.clipboard.writeText(this.statusLink) .then(() => this.$emit('onSuccess')) .catch(err => this.$emit('onError', err.error.error)) + }, + bookmarkStatus () { + this.$store.dispatch('bookmark', { id: this.status.id }) + .then(() => this.$emit('onSuccess')) + .catch(err => this.$emit('onError', err.error.error)) + }, + unbookmarkStatus () { + this.$store.dispatch('unbookmark', { id: this.status.id }) + .then(() => this.$emit('onSuccess')) + .catch(err => this.$emit('onError', err.error.error)) } }, computed: { diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue index 68db6fd8..7a4e8642 100644 --- a/src/components/extra_buttons/extra_buttons.vue +++ b/src/components/extra_buttons/extra_buttons.vue @@ -40,6 +40,22 @@ > {{ $t("status.unpin") }} + +
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index c4d7fb53..067acbe9 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -645,8 +645,7 @@ const postStatus = ({ poll, mediaIds = [], inReplyToStatusId, - contentType, - mediaDescriptions + contentType }) => { const form = new FormData() const pollOptions = poll.options || [] @@ -673,7 +672,6 @@ const postStatus = ({ form.append('poll[options][]', option) }) } - form.append('descriptions', JSON.stringify(mediaDescriptions)) if (inReplyToStatusId) { form.append('in_reply_to_id', inReplyToStatusId) } @@ -712,6 +710,17 @@ const uploadMedia = ({ formData, credentials }) => { .then((data) => parseAttachment(data)) } +const setMediaDescription = ({ id, description, credentials }) => { + return promisedRequest({ + url: `${MASTODON_MEDIA_UPLOAD_URL}/${id}`, + method: 'PUT', + headers: authHeaders(credentials), + payload: { + description + } + }).then((data) => parseAttachment(data)) +} + const importBlocks = ({ file, credentials }) => { const formData = new FormData() formData.append('list', file) @@ -1181,6 +1190,7 @@ const apiService = { postStatus, deleteStatus, uploadMedia, + setMediaDescription, fetchMutes, muteUser, unmuteUser, diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js index 090ff673..7f5f501c 100644 --- a/src/services/status_poster/status_poster.service.js +++ b/src/services/status_poster/status_poster.service.js @@ -1,7 +1,7 @@ import { map } from 'lodash' import apiService from '../api/api.service.js' -const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain', mediaDescriptions = {} }) => { +const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => { const mediaIds = map(media, 'id') return apiService.postStatus({ @@ -13,8 +13,8 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, m mediaIds, inReplyToStatusId, contentType, - poll, - mediaDescriptions }) + poll + }) .then((data) => { if (!data.error) { store.dispatch('addNewStatuses', { @@ -39,9 +39,16 @@ const uploadMedia = ({ store, formData }) => { return apiService.uploadMedia({ credentials, formData }) } +const setMediaDescription = ({ store, id, description }) => { + const credentials = store.state.users.currentUser.credentials + + return apiService.setMediaDescription({ credentials, id, description }) +} + const statusPosterService = { postStatus, - uploadMedia + uploadMedia, + setMediaDescription } export default statusPosterService -- cgit v1.2.3-70-g09d2