Add quotes #59
10 changed files with 147 additions and 7 deletions
|
@ -5,7 +5,7 @@ library.add(faQuoteLeft)
|
|||
|
||||
const QuoteButton = {
|
||||
name: 'QuoteButton',
|
||||
props: ['status', 'quoting'],
|
||||
props: ['status', 'quoting', 'visibility'],
|
||||
computed: {
|
||||
loggedIn () {
|
||||
return !!this.$store.state.users.currentUser
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<div class="QuoteButton">
|
||||
<div
|
||||
v-if="loggedIn"
|
||||
class="QuoteButton"
|
||||
>
|
||||
<button
|
||||
v-if="loggedIn"
|
||||
v-if="visibility === 'public' || visibility === 'unlisted'"
|
||||
class="button-unstyled interactive"
|
||||
:class="{'-active': quoting}"
|
||||
:title="$t('tool_tip.quote')"
|
||||
|
@ -12,11 +15,11 @@
|
|||
icon="quote-left"
|
||||
/>
|
||||
</button>
|
||||
<span v-else>
|
||||
<span v-else-if="loggedIn">
|
||||
<FAIcon
|
||||
icon="quot-left"
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
:title="$t('tool_tip.quote')"
|
||||
icon="lock"
|
||||
:title="$t('timeline.no_quote_hint')"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
|
24
src/components/quote_card/quote_card.js
Normal file
24
src/components/quote_card/quote_card.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { mapGetters } from 'vuex'
|
||||
import QuoteCardContent from '../quote_card_content/quote_card_content.vue'
|
||||
|
||||
const QuoteCard = {
|
||||
name: 'QuoteCard',
|
||||
props: [
|
||||
'status'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
imageLoaded: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'mergedConfig'
|
||||
])
|
||||
},
|
||||
components: {
|
||||
QuoteCardContent
|
||||
}
|
||||
}
|
||||
|
||||
export default QuoteCard
|
76
src/components/quote_card/quote_card.vue
Normal file
76
src/components/quote_card/quote_card.vue
Normal file
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div>
|
||||
<a
|
||||
class="quote-card"
|
||||
:href="status.url"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<QuoteCardContent
|
||||
:status="status"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./quote_card"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.quote-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
margin-top: 0.5em;
|
||||
|
||||
.card-image {
|
||||
flex-shrink: 0;
|
||||
width: 120px;
|
||||
max-width: 25%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: $fallback--attachmentRadius;
|
||||
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
max-height: 100%;
|
||||
margin: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card-host {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.card-description {
|
||||
margin: 0.5em 0 0 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-word;
|
||||
line-height: 1.2em;
|
||||
// cap description at 3 lines, the 1px is to clean up some stray pixels
|
||||
// TODO: fancier fade-out at the bottom to show off that it's too long?
|
||||
max-height: calc(1.2em * 3 - 1px);
|
||||
}
|
||||
|
||||
.nsfw-alert {
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
color: $fallback--text;
|
||||
color: var(--text, $fallback--text);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: $fallback--attachmentRadius;
|
||||
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
}
|
||||
</style>
|
22
src/components/quote_card_content/quote_card_content.vue
Normal file
22
src/components/quote_card_content/quote_card_content.vue
Normal file
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<Status
|
||||
v-if="status"
|
||||
:is-preview="true"
|
||||
:statusoid="status"
|
||||
:compact="true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'QuoteCardContent',
|
||||
components: {
|
||||
Status: defineAsyncComponent(() => import('../status/status.vue'))
|
||||
},
|
||||
props: [
|
||||
'status'
|
||||
]
|
||||
}
|
||||
</script>
|
|
@ -431,6 +431,7 @@
|
|||
@toggle="toggleReplying"
|
||||
/>
|
||||
<quote-button
|
||||
:visibility="status.visibility"
|
||||
:quoting="quoting"
|
||||
:status="status"
|
||||
@toggle="toggleQuoting"
|
||||
|
|
|
@ -3,6 +3,7 @@ import Poll from '../poll/poll.vue'
|
|||
import Gallery from '../gallery/gallery.vue'
|
||||
import StatusBody from 'src/components/status_body/status_body.vue'
|
||||
import LinkPreview from '../link-preview/link-preview.vue'
|
||||
import QuoteCard from '../quote_card/quote_card.vue'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
|
@ -109,7 +110,8 @@ const StatusContent = {
|
|||
Poll,
|
||||
Gallery,
|
||||
LinkPreview,
|
||||
StatusBody
|
||||
StatusBody,
|
||||
QuoteCard
|
||||
},
|
||||
methods: {
|
||||
toggleShowingTall () {
|
||||
|
|
|
@ -51,6 +51,14 @@
|
|||
:nsfw="nsfwClickthrough"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="status.quote"
|
||||
class="quote"
|
||||
>
|
||||
<QuoteCard
|
||||
:status="status.quote"
|
||||
/>
|
||||
</div>
|
||||
</StatusBody>
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
|
|
|
@ -782,6 +782,7 @@
|
|||
"error": "Error fetching timeline: {0}",
|
||||
"load_older": "Load older statuses",
|
||||
"no_retweet_hint": "Post is marked as followers-only or direct and cannot be repeated",
|
||||
"no_quote_hint": "Post is marked as followers-only or direct and cannot be quoted",
|
||||
"repeated": "repeated",
|
||||
"show_new": "Show new",
|
||||
"reload": "Reload",
|
||||
|
|
|
@ -347,6 +347,9 @@ export const parseStatus = (data) => {
|
|||
output.visibility = data.visibility
|
||||
output.card = data.card
|
||||
output.created_at = new Date(data.created_at)
|
||||
if (data.quote) {
|
||||
output.quote = parseStatus(data.quote)
|
||||
}
|
||||
|
||||
// Converting to string, the right way.
|
||||
output.in_reply_to_status_id = output.in_reply_to_status_id
|
||||
|
|
Loading…
Reference in a new issue