Merge branch 'chat-refactor' into shigusegubu-themes3
This commit is contained in:
commit
08f5d1d584
9 changed files with 110 additions and 20 deletions
|
|
@ -14,6 +14,7 @@ import StatusPopover from 'src/components/status_popover/status_popover.vue'
|
||||||
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
|
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
|
||||||
import UserPopover from 'src/components/user_popover/user_popover.vue'
|
import UserPopover from 'src/components/user_popover/user_popover.vue'
|
||||||
import Timeago from 'src/components/timeago/timeago.vue'
|
import Timeago from 'src/components/timeago/timeago.vue'
|
||||||
|
import EmojiReactions from 'src/components/emoji_reactions/emoji_reactions.vue'
|
||||||
|
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
import { useInterfaceStore } from 'src/stores/interface'
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
@ -25,9 +26,11 @@ import {
|
||||||
faEllipsisH,
|
faEllipsisH,
|
||||||
faTimes,
|
faTimes,
|
||||||
faReply,
|
faReply,
|
||||||
|
faRetweet,
|
||||||
|
faStar,
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
library.add(faTimes, faEllipsisH, faCircleNotch, faReply)
|
library.add(faTimes, faEllipsisH, faCircleNotch, faReply, faStar, faRetweet)
|
||||||
|
|
||||||
const ChatMessage = {
|
const ChatMessage = {
|
||||||
name: 'ChatMessage',
|
name: 'ChatMessage',
|
||||||
|
|
@ -52,6 +55,7 @@ const ChatMessage = {
|
||||||
Gallery,
|
Gallery,
|
||||||
LinkPreview,
|
LinkPreview,
|
||||||
ChatMessageDate,
|
ChatMessageDate,
|
||||||
|
EmojiReactions,
|
||||||
UserPopover,
|
UserPopover,
|
||||||
StatusPopover,
|
StatusPopover,
|
||||||
MentionLink,
|
MentionLink,
|
||||||
|
|
@ -153,6 +157,11 @@ const ChatMessage = {
|
||||||
menuOpened: false,
|
menuOpened: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
focused: function (value) {
|
||||||
|
this.scrollIfFocused(value)
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onHover(bool) {
|
onHover(bool) {
|
||||||
this.$emit('hover', {
|
this.$emit('hover', {
|
||||||
|
|
@ -188,6 +197,22 @@ const ChatMessage = {
|
||||||
this.hovered = false
|
this.hovered = false
|
||||||
this.menuOpened = false
|
this.menuOpened = false
|
||||||
},
|
},
|
||||||
|
scrollIfFocused(focused) {
|
||||||
|
if (this.$el.getBoundingClientRect == null) return
|
||||||
|
if (focused) {
|
||||||
|
const rect = this.$el.getBoundingClientRect()
|
||||||
|
if (rect.top < 100) {
|
||||||
|
// Post is above screen, match its top to screen top
|
||||||
|
window.scrollBy(0, rect.top - 100)
|
||||||
|
} else if (rect.height >= window.innerHeight - 50) {
|
||||||
|
// Post we want to see is taller than screen so match its top to screen top
|
||||||
|
window.scrollBy(0, rect.top - 100)
|
||||||
|
} else if (rect.bottom > window.innerHeight - 50) {
|
||||||
|
// Post is below screen, match its bottom to screen bottom
|
||||||
|
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attachments {
|
||||||
|
min-width: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-message-toolbar {
|
.chat-message-toolbar {
|
||||||
transition: opacity 0.1s;
|
transition: opacity 0.1s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
@ -126,20 +130,26 @@
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.end-spacer {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: calc(2.2rem + 0.5rem + 2rem);
|
||||||
|
}
|
||||||
|
|
||||||
.reply-indicator {
|
.reply-indicator {
|
||||||
display: flex;
|
display: flex;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
place-content: center;
|
place-content: center;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
|
width: 1em;
|
||||||
margin: var(--roundness) 0;
|
margin: var(--roundness) 0;
|
||||||
background: var(--border);
|
background: var(--border);
|
||||||
border-radius: var(--roundness);
|
border-radius: var(--roundness);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
}
|
|
||||||
|
|
||||||
.end-spacer {
|
+ .end-spacer {
|
||||||
flex: 1 1 0;
|
// Compensate for reply indicator
|
||||||
min-width: calc(2.2em + 0.5em + 2em);
|
min-width: calc(2.2rem + 0.5rem + 2rem - (1rem + (1px + 0.25rem) * 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.-incoming {
|
&.-incoming {
|
||||||
|
|
|
||||||
|
|
@ -44,22 +44,24 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #user>
|
<template #user>
|
||||||
<!-- v-if is there because status might not be loaded yet -->
|
|
||||||
<StatusBody
|
|
||||||
v-if="customReplyTo && customReplyTo.text.trim().length > 0"
|
|
||||||
class="reply-body faint"
|
|
||||||
:status="customReplyTo"
|
|
||||||
collapse
|
|
||||||
single-line
|
|
||||||
/>
|
|
||||||
<MentionLink
|
<MentionLink
|
||||||
v-else-if="customReplyTo"
|
|
||||||
class="reply-body"
|
class="reply-body"
|
||||||
:content="replyToName"
|
:content="replyToName"
|
||||||
:url="replyProfileLink"
|
:url="replyProfileLink"
|
||||||
:user-id="message.in_reply_to_user_id"
|
:user-id="message.in_reply_to_user_id"
|
||||||
:user-screen-name="message.in_reply_to_screen_name"
|
:user-screen-name="message.in_reply_to_screen_name"
|
||||||
/>
|
/>
|
||||||
|
<!-- v-if is there because status might not be loaded yet -->
|
||||||
|
<template v-if="customReplyTo && customReplyTo.text.trim().length > 0">
|
||||||
|
:
|
||||||
|
<StatusBody
|
||||||
|
class="reply-body faint"
|
||||||
|
:status="customReplyTo"
|
||||||
|
collapse
|
||||||
|
single-line
|
||||||
|
ignore-subject
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
<div
|
<div
|
||||||
|
|
@ -143,9 +145,28 @@
|
||||||
:full-content="true"
|
:full-content="true"
|
||||||
>
|
>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
<EmojiReactions :status="message" />
|
||||||
<span
|
<span
|
||||||
class="created-at"
|
class="created-at"
|
||||||
>
|
>
|
||||||
|
<span
|
||||||
|
v-if="message.favorited"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
class="fa-scale-110"
|
||||||
|
icon="star"
|
||||||
|
fixed-width
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="message.repeated"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
class="fa-scale-110"
|
||||||
|
icon="retweet"
|
||||||
|
fixed-width
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="message.visibility"
|
v-if="message.visibility"
|
||||||
class="visibility-icon"
|
class="visibility-icon"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import PostStatusForm from 'src/components/post_status_form/post_status_form.vue
|
||||||
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
|
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
|
||||||
import QuickViewSettings from 'src/components/quick_view_settings/quick_view_settings.vue'
|
import QuickViewSettings from 'src/components/quick_view_settings/quick_view_settings.vue'
|
||||||
import ThreadTree from 'src/components/thread_tree/thread_tree.vue'
|
import ThreadTree from 'src/components/thread_tree/thread_tree.vue'
|
||||||
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
|
|
||||||
import { useInterfaceStore } from 'src/stores/interface'
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
@ -426,6 +427,7 @@ const conversation = {
|
||||||
QuickViewSettings,
|
QuickViewSettings,
|
||||||
ChatMessageList,
|
ChatMessageList,
|
||||||
PostStatusForm,
|
PostStatusForm,
|
||||||
|
RichContent,
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
statusId(newVal, oldVal) {
|
statusId(newVal, oldVal) {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,13 @@
|
||||||
class="panel-heading conversation-heading -sticky"
|
class="panel-heading conversation-heading -sticky"
|
||||||
>
|
>
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
|
<RichContent
|
||||||
|
v-if="conversation[0]?.summary"
|
||||||
|
:html="conversation[0].summary"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
{{ $t('timeline.conversation') }}
|
{{ $t('timeline.conversation') }}
|
||||||
|
</template>
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
v-if="collapsable"
|
v-if="collapsable"
|
||||||
|
|
|
||||||
|
|
@ -540,10 +540,9 @@ const Status = {
|
||||||
toggleThreadDisplay() {
|
toggleThreadDisplay() {
|
||||||
this.controlledToggleThreadDisplay()
|
this.controlledToggleThreadDisplay()
|
||||||
},
|
},
|
||||||
scrollIfFocused(focusedId) {
|
scrollIfFocused(focused) {
|
||||||
if (this.$el.getBoundingClientRect == null) return
|
if (this.$el.getBoundingClientRect == null) return
|
||||||
const id = focusedId
|
if (focused) {
|
||||||
if (this.status.id === id) {
|
|
||||||
const rect = this.$el.getBoundingClientRect()
|
const rect = this.$el.getBoundingClientRect()
|
||||||
if (rect.top < 100) {
|
if (rect.top < 100) {
|
||||||
// Post is above screen, match its top to screen top
|
// Post is above screen, match its top to screen top
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
|
@ -15,6 +16,9 @@ library.add(faFile, faMusic, faImage, faLink, faPollH)
|
||||||
|
|
||||||
const StatusBody = {
|
const StatusBody = {
|
||||||
name: 'StatusBody',
|
name: 'StatusBody',
|
||||||
|
components: {
|
||||||
|
RichContent,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
status: {
|
status: {
|
||||||
// Main thing
|
// Main thing
|
||||||
|
|
@ -44,6 +48,12 @@ const StatusBody = {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
ignoreSubject: {
|
||||||
|
// Pretend subject line doesn't exist. Useful for chat messages
|
||||||
|
// to indicate what post reply belongs to
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -76,7 +86,7 @@ const StatusBody = {
|
||||||
return this.status.summary.length > 240
|
return this.status.summary.length > 240
|
||||||
},
|
},
|
||||||
hasSubject() {
|
hasSubject() {
|
||||||
return !!this.status.summary
|
return !!this.status.summary && !this.ignoreSubject
|
||||||
},
|
},
|
||||||
// When a status has a subject and is also tall, we should only have one show more/less
|
// When a status has a subject and is also tall, we should only have one show more/less
|
||||||
// button. If the default is to collapse statuses with subjects, we just treat it like
|
// button. If the default is to collapse statuses with subjects, we just treat it like
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.-single-line {
|
||||||
|
.summary-wrapper {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-wrapper {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& .tall-status-hider,
|
& .tall-status-hider,
|
||||||
& .tall-subject-hider,
|
& .tall-subject-hider,
|
||||||
& .status-unhider,
|
& .status-unhider,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="StatusBody"
|
class="StatusBody"
|
||||||
:class="{ '-compact': compact }"
|
:class="{ '-compact': compact, '-single-line': singleLine }"
|
||||||
>
|
>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div
|
<div
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="text-wrapper"
|
class="text-wrapper"
|
||||||
:class="{'-tall-status': hideTallStatus, '-hidden': shouldHide, '-expanded': showingMore}"
|
:class="{'-tall-status': hideTallStatus, '-hidden': shouldHide, '-expanded': showingMore }"
|
||||||
>
|
>
|
||||||
<RichContent
|
<RichContent
|
||||||
v-if="!(singleLine && hasSubject) && !shouldHide"
|
v-if="!(singleLine && hasSubject) && !shouldHide"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue