refs #4085 Show reply target message on compose

This commit is contained in:
AkiraFukushima 2023-02-08 22:22:08 +09:00
parent b0b7c1f95c
commit 285d66eddf
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
5 changed files with 141 additions and 15 deletions

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="compose"> <div class="compose">
<Quote v-if="inReplyTo" :message="inReplyTo" @close="clearReply" />
<el-form :model="form" class="compose-form"> <el-form :model="form" class="compose-form">
<el-input v-model="form.spoiler" class="spoiler" :placeholder="$t('modals.new_toot.cw')" v-if="cw" /> <el-input v-model="form.spoiler" class="spoiler" :placeholder="$t('modals.new_toot.cw')" v-if="cw" />
<el-input <el-input
@ -115,6 +116,7 @@ import { LocalServer } from '~/src/types/localServer'
import visibilityList from '~/src/constants/visibility' import visibilityList from '~/src/constants/visibility'
import { MUTATION_TYPES } from '@/store/TimelineSpace/Compose' import { MUTATION_TYPES } from '@/store/TimelineSpace/Compose'
import ReceiveDrop from './ReceiveDrop.vue' import ReceiveDrop from './ReceiveDrop.vue'
import Quote from './Compose/Quote.vue'
type Expire = { type Expire = {
label: string label: string
@ -123,7 +125,7 @@ type Expire = {
export default defineComponent({ export default defineComponent({
name: 'Compose', name: 'Compose',
components: { Picker, ReceiveDrop }, components: { Picker, ReceiveDrop, Quote },
setup() { setup() {
const route = useRoute() const route = useRoute()
const store = useStore() const store = useStore()
@ -248,7 +250,7 @@ export default defineComponent({
watch(inReplyTo, current => { watch(inReplyTo, current => {
if (current) { if (current) {
form.status = `@${current.acct} ` form.status = `@${current.account.acct} `
} }
}) })
@ -411,6 +413,10 @@ export default defineComponent({
e.preventDefault() e.preventDefault()
} }
const clearReply = () => {
store.commit(`${space}/${MUTATION_TYPES.CLEAR_REPLY_TO_ID}`)
}
return { return {
form, form,
post, post,
@ -434,7 +440,9 @@ export default defineComponent({
expiresList, expiresList,
addPollOption, addPollOption,
removePollOption, removePollOption,
droppableVisible droppableVisible,
inReplyTo,
clearReply
} }
} }
}) })

View File

@ -0,0 +1,125 @@
<template>
<div class="quote">
<div class="icon">
<FailoverImg :src="message.account.avatar" />
</div>
<div class="status">
<div class="header">
<div class="user">
<span class="display-name"><bdi v-html="username(message.account)"></bdi></span>
<span class="acct">{{ accountName(message.account) }}</span>
</div>
<div class="close">
<el-button link>
<font-awesome-icon icon="xmark" @click="close" />
</el-button>
</div>
</div>
<div class="body">
<div class="spoiler" v-html="emojiText(message.spoiler_text, message.emojis)"></div>
<div class="content" v-html="emojiText(message.content, message.emojis)"></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, PropType } from 'vue'
import { Entity } from 'megalodon'
import DisplayStyle from '~/src/constants/displayStyle'
import FailoverImg from '@/components/atoms/FailoverImg.vue'
import emojify from '@/utils/emojify'
import { useStore } from '@/store'
export default defineComponent({
name: 'Quote',
components: {
FailoverImg
},
props: {
message: {
type: Object as PropType<Entity.Status>,
required: true
}
},
emits: ['close'],
setup(_props, ctx) {
const store = useStore()
const displayNameStyle = computed(() => store.state.App.displayNameStyle)
const username = (account: Entity.Account) => {
switch (displayNameStyle.value) {
case DisplayStyle.DisplayNameAndUsername.value:
if (account.display_name !== '') {
return emojify(account.display_name, account.emojis)
} else {
return account.acct
}
case DisplayStyle.DisplayName.value:
if (account.display_name !== '') {
return emojify(account.display_name, account.emojis)
} else {
return account.acct
}
default:
return account.acct
}
}
const accountName = (account: Entity.Account) => {
switch (displayNameStyle.value) {
case DisplayStyle.DisplayNameAndUsername.value:
return `@${account.acct}`
case DisplayStyle.DisplayName.value:
default:
return ''
}
}
const emojiText = (content: string, emojis: Array<Entity.Emoji>) => {
return emojify(content, emojis)
}
const close = () => {
ctx.emit('close', null)
}
return {
username,
accountName,
emojiText,
close
}
}
})
</script>
<style lang="scss" scoped>
.quote {
display: flex;
border-radius: 4px;
overflow: hidden;
border: 1px solid var(--theme-border-color);
font-size: var(--base-font-size);
background-color: var(--theme-selected-background-color);
margin-bottom: 8px;
.icon {
img {
width: 40px;
height: 40px;
min-width: 40px;
min-height: 40px;
margin: 10px;
border-radius: 4px;
}
}
.status {
width: calc(100% - 40px);
.header {
display: flex;
justify-content: space-between;
}
}
}
</style>

View File

@ -41,7 +41,7 @@ export default defineComponent({
}) })
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.quote { .quote {
display: flex; display: flex;
border-radius: 4px; border-radius: 4px;

View File

@ -504,10 +504,7 @@ export default defineComponent({
} }
} }
const openReply = () => { const openReply = () => {
store.commit(`TimelineSpace/Compose/${COMPOSE_MUTATION.SET_REPLY_TO_ID}`, { store.commit(`TimelineSpace/Compose/${COMPOSE_MUTATION.SET_REPLY_TO_ID}`, originalMessage.value)
acct: originalMessage.value.account.acct,
id: originalMessage.value.id
})
} }
const openDetail = (message: Entity.Status | null) => { const openDetail = (message: Entity.Status | null) => {
if (message) { if (message) {

View File

@ -1,13 +1,9 @@
import { Module, MutationTree } from 'vuex' import { Module, MutationTree } from 'vuex'
import { RootState } from '@/store' import { RootState } from '@/store'
import { Entity } from 'megalodon'
export type ReplyTo = {
acct: string
id: string
}
export type ComposeState = { export type ComposeState = {
inReplyTo: ReplyTo | null inReplyTo: Entity.Status | null
} }
const state = (): ComposeState => ({ const state = (): ComposeState => ({
@ -20,7 +16,7 @@ export const MUTATION_TYPES = {
} }
const mutations: MutationTree<ComposeState> = { const mutations: MutationTree<ComposeState> = {
[MUTATION_TYPES.SET_REPLY_TO_ID]: (state, inReplyTo: ReplyTo) => { [MUTATION_TYPES.SET_REPLY_TO_ID]: (state, inReplyTo: Entity.Status) => {
state.inReplyTo = inReplyTo state.inReplyTo = inReplyTo
}, },
[MUTATION_TYPES.CLEAR_REPLY_TO_ID]: state => { [MUTATION_TYPES.CLEAR_REPLY_TO_ID]: state => {