diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 2a7b74da..7c5c8d45 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -64,6 +64,7 @@ const PostStatusForm = {
'statusScope',
'statusContentType',
'replyTo',
+ 'quoteId',
'repliedUser',
'attentions',
'copyMessageScope',
@@ -108,12 +109,12 @@ const PostStatusForm = {
this.updateIdempotencyKey()
this.resize(this.$refs.textarea)
- if (this.replyTo) {
+ if (this.replyTo || this.quoteId) {
const textLength = this.$refs.textarea.value.length
this.$refs.textarea.setSelectionRange(textLength, textLength)
}
- if (this.replyTo || this.autoFocus) {
+ if (this.replyTo || this.quoteId || this.autoFocus) {
this.$refs.textarea.focus()
}
},
@@ -123,7 +124,7 @@ const PostStatusForm = {
const { scopeCopy } = this.$store.getters.mergedConfig
- if (this.replyTo) {
+ if (this.replyTo || this.quoteId) {
const currentUser = this.$store.state.users.currentUser
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
@@ -347,6 +348,7 @@ const PostStatusForm = {
media: newStatus.files,
store: this.$store,
inReplyToStatusId: this.replyTo,
+ quoteId: this.quoteId,
contentType: newStatus.contentType,
poll,
idempotencyKey: this.idempotencyKey
@@ -380,6 +382,7 @@ const PostStatusForm = {
media: [],
store: this.$store,
inReplyToStatusId: this.replyTo,
+ quoteId: this.quoteId,
contentType: newStatus.contentType,
poll: {},
preview: true
diff --git a/src/components/quote_button/quote_button.js b/src/components/quote_button/quote_button.js
new file mode 100644
index 00000000..227a68e2
--- /dev/null
+++ b/src/components/quote_button/quote_button.js
@@ -0,0 +1,16 @@
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faQuoteLeft } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faQuoteLeft)
+
+const QuoteButton = {
+ name: 'QuoteButton',
+ props: ['status', 'quoting'],
+ computed: {
+ loggedIn () {
+ return !!this.$store.state.users.currentUser
+ }
+ }
+}
+
+export default QuoteButton
diff --git a/src/components/quote_button/quote_button.vue b/src/components/quote_button/quote_button.vue
new file mode 100644
index 00000000..319db8b4
--- /dev/null
+++ b/src/components/quote_button/quote_button.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/status/status.js b/src/components/status/status.js
index c9c26ad5..472c28fd 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -1,4 +1,5 @@
import ReplyButton from '../reply_button/reply_button.vue'
+import QuoteButton from '../quote_button/quote_button.vue'
import FavoriteButton from '../favorite_button/favorite_button.vue'
import ReactButton from '../react_button/react_button.vue'
import RetweetButton from '../retweet_button/retweet_button.vue'
@@ -117,7 +118,8 @@ const Status = {
MentionLink,
MentionsLine,
UserPopover,
- UserLink
+ UserLink,
+ QuoteButton
},
props: [
'statusoid',
@@ -147,6 +149,8 @@ const Status = {
'controlledToggleShowingLongSubject',
'controlledReplying',
'controlledToggleReplying',
+ 'controlledQuoting',
+ 'controlledToggleQuoting',
'controlledMediaPlaying',
'controlledSetMediaPlaying',
'dive'
@@ -154,6 +158,7 @@ const Status = {
data () {
return {
uncontrolledReplying: false,
+ uncontrolledQuoting: false,
unmuted: false,
userExpanded: false,
uncontrolledMediaPlaying: [],
@@ -166,7 +171,7 @@ const Status = {
swapReacts () {
return this.mergedConfig.swapReacts
},
- ...controlledOrUncontrolledGetters(['replying', 'mediaPlaying']),
+ ...controlledOrUncontrolledGetters(['replying', 'quoting', 'mediaPlaying']),
muteWords () {
return this.mergedConfig.muteWords
},
@@ -428,6 +433,9 @@ const Status = {
toggleReplying () {
controlledOrUncontrolledToggle(this, 'replying')
},
+ toggleQuoting () {
+ controlledOrUncontrolledToggle(this, 'quoting')
+ },
gotoOriginal (id) {
if (this.inConversation) {
this.$emit('goto', id)
diff --git a/src/components/status/status.scss b/src/components/status/status.scss
index c2f816eb..fcbc9d90 100644
--- a/src/components/status/status.scss
+++ b/src/components/status/status.scss
@@ -357,6 +357,15 @@
flex: 1;
}
+ .quote-form {
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+
+ .quote-body {
+ flex: 1;
+ }
+
.favs-repeated-users {
margin-top: var(--status-margin, $status-margin);
}
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 9b33a51e..51bf05f3 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -447,6 +447,11 @@
:status="status"
@toggle="toggleReplying"
/>
+
+
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 3dafc032..5eb45394 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -822,6 +822,7 @@ const postStatus = ({
poll,
mediaIds = [],
inReplyToStatusId,
+ quoteId,
contentType,
preview,
idempotencyKey
@@ -854,6 +855,9 @@ const postStatus = ({
if (inReplyToStatusId) {
form.append('in_reply_to_id', inReplyToStatusId)
}
+ if (quoteId) {
+ form.append('quote_id', quoteId)
+ }
if (preview) {
form.append('preview', 'true')
}
diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js
index 1eb10bb6..aaef5a7a 100644
--- a/src/services/status_poster/status_poster.service.js
+++ b/src/services/status_poster/status_poster.service.js
@@ -10,6 +10,7 @@ const postStatus = ({
poll,
media = [],
inReplyToStatusId = undefined,
+ quoteId = undefined,
contentType = 'text/plain',
preview = false,
idempotencyKey = ''
@@ -24,6 +25,7 @@ const postStatus = ({
sensitive,
mediaIds,
inReplyToStatusId,
+ quoteId,
contentType,
poll,
preview,