UI improvements

This commit is contained in:
Henry Jameson 2026-08-14 18:54:18 +03:00
commit bcfe1de1b2
16 changed files with 94 additions and 40 deletions

View file

@ -7,7 +7,7 @@
class="avatars-item"
>
<UserAvatar
:user="user"
:user-id="user.id"
class="avatar-small"
/>
</router-link>

View file

@ -5,7 +5,7 @@
>
<div class="chat-list-item-left">
<UserAvatar
:user="chat.account"
:user-id="chat.account.id"
height="48px"
width="48px"
/>

View file

@ -83,7 +83,7 @@
<UserAvatar
v-if="author"
:compact="true"
:user="author"
:user-id="author.id"
/>
</UserPopover>
<div

View file

@ -10,7 +10,7 @@
>
<UserAvatar
class="titlebar-avatar"
:user="user"
:user-id="user.id"
/>
</UserPopover>
<RichContent

View file

@ -6,6 +6,11 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useUsersStore } from 'src/stores/users.js'
import { useStreamingStore } from 'src/stores/streaming.js'
import {
WSConnectionStatus,
} from 'src/api/websocket.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -20,6 +25,8 @@ import {
faSignOutAlt,
faTachometerAlt,
faUserPlus,
faPlug,
faPlugCircleXmark
} from '@fortawesome/free-solid-svg-icons'
library.add(
@ -34,6 +41,8 @@ library.add(
faTachometerAlt,
faCog,
faInfoCircle,
faPlug,
faPlugCircleXmark
)
export default {
@ -93,9 +102,23 @@ export default {
hideSitename: (store) => store.instanceIdentity.hideSitename,
}),
...mapState(useUsersStore, ['currentUser']),
...mapState(useStreamingStore, {
streamingConnected: (store) => store.state === WSConnectionStatus.JOINED
}),
...mapState(useMergedConfigStore, ['mergedConfig']),
shouldConfirmLogout() {
return useMergedConfigStore().mergedConfig.modalOnLogout
return this.mergedConfig.modalOnLogout
},
streamingEnabled() {
return this.mergedConfig.useStreamingApi
},
streamingTooltip() {
if (this.streamingConnected) {
return this.$t('timeline.socket_reconnected')
} else {
return this.$t('timeline.socket_disconnected')
}
}
},
methods: {
scrollToTop() {

View file

@ -15,6 +15,25 @@
>
{{ sitename }}
</router-link>
<div
class="nav-icon"
v-if="streamingEnabled"
:title="streamingTooltip"
>
<FAIcon
v-if="streamingConnected"
fixed-width
class="fa-scale-110 fa-old-padding"
icon="plug"
/>
<FAIcon
v-else
fixed-width
class="fa-scale-110 fa-old-padding"
icon="plug-circle-xmark"
/>
</div>
</div>
<router-link
class="logo"

View file

@ -31,7 +31,7 @@
<UserAvatar
v-if="shouldShowAvatar"
class="mention-avatar"
:user="user"
:user-id="user.id"
/><span
class="shortName"
>@<span

View file

@ -57,7 +57,7 @@
<UserAvatar
class="post-avatar"
:compact="true"
:user="notification.from_profile"
:user-id="notification.from_profile.id"
/>
</UserPopover>
</a>

View file

@ -223,9 +223,6 @@ const Status = {
botStatus() {
return this.status.user.actor_type === 'Service'
},
showActorTypeIndicator() {
return !this.hideBotIndication
},
sensitiveStatus() {
return this.status.nsfw
},

View file

@ -55,8 +55,7 @@
<UserAvatar
v-if="retweet"
class="left-side repeater-avatar"
:show-actor-type-indicator="showActorTypeIndicator"
:user="statusoid.user"
:user-id="statusoid.user.id"
/>
<div class="right-side faint">
<bdi
@ -114,15 +113,14 @@
>
<UserAvatar
class="post-avatar"
:show-actor-type-indicator="showActorTypeIndicator"
:compact="compact"
:user="status?.user"
:user-id="status?.user.id"
/>
</UserPopover>
</a>
<UserAvatar
v-else
:user="status?.user"
:user-id="status?.user.id"
class="post-avatar"
:compact="compact"
:title="$t('status.unknown_user_info')"
@ -529,7 +527,6 @@
<UserAvatar
class="post-avatar"
:compact="compact"
:show-actor-type-indicator="showActorTypeIndicator"
/>
</div>
<div class="right-side">

View file

@ -1,5 +1,7 @@
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useUsersStore } from 'src/stores/users.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faPeopleGroup, faRobot } from '@fortawesome/free-solid-svg-icons'
@ -8,10 +10,10 @@ library.add(faRobot, faPeopleGroup)
const UserAvatar = {
props: {
// User object to show avatar of
user: {
// UserID of a user to show avatar of
userId: {
required: true,
type: Object,
type: String,
},
// Use less space and use alternative roundness
compact: {
@ -19,12 +21,6 @@ const UserAvatar = {
type: Boolean,
default: false,
},
// Show small icon indicating if account is a bot or group
showActorTypeIndicator: {
required: false,
type: Boolean,
default: false,
},
// Override avatar image URL, useful for profile editing
url: {
required: false,
@ -39,7 +35,14 @@ const UserAvatar = {
betterShadow: useInterfaceStore().browserSupport.cssFilter,
}
},
components: {},
computed: {
user() {
return useUsersStore().findUser(this.userId)
},
showActorTypeIndicator() {
return useMergedConfigStore().mergedConfig.hideBotIndication
},
},
methods: {
imgSrc(src) {
return !src || this.showPlaceholder ? this.defaultAvatar : src

View file

@ -23,7 +23,7 @@
class="user-info-avatar -link"
@click="zoomAvatar"
>
<UserAvatar :user="user" />
<UserAvatar :user-id="user.id" />
<div class="user-info-avatar -link -overlay">
<FAIcon
class="fa-scale-110 fa-old-padding"
@ -38,7 +38,7 @@
@click="changeAvatar"
>
<UserAvatar
:user="user"
:user-id="user.id"
:url="avatarImgSrc"
/>
<div class="user-info-avatar -link -overlay">
@ -51,7 +51,7 @@
<UserAvatar
v-else-if="typeof avatarAction === 'function'"
class="user-info-avatar"
:user="user"
:user-id="user.id"
@click="avatarAction"
/>
<router-link
@ -59,7 +59,7 @@
class="user-info-avatar"
:to="userProfileLink(user)"
>
<UserAvatar :user="user" />
<UserAvatar :user-id="user.id" />
</router-link>
<div class="user-summary">
<div class="top-line">

View file

@ -17,7 +17,7 @@
class="user-list-row"
>
<UserAvatar
:user="user"
:user-id="user.id"
class="avatar-small"
:compact="true"
/>

View file

@ -1633,6 +1633,8 @@
"no_more_statuses": "No more statuses",
"no_statuses": "No statuses",
"socket_reconnected": "Realtime connection established",
"socket_disconnected": "Realtime connection unavaialable",
"socket_closed": "Realtime connection closed",
"socket_broke": "Realtime connection lost: CloseEvent code {0}",
"quick_view_settings": "Quick view settings",
"quick_filter_settings": "Quick filter settings",
@ -1730,6 +1732,7 @@
"more_actions": "More actions on this status",
"loading": "Loading...",
"load_error": "Unable to load status: {error}",
"interact_error": "Error interacting with status: {error}",
"admin_change_scope": "Change visibility",
"mark_as_sensitive": "Sensitive",
"mark_as_non-sensitive": "Non-sensitive"

View file

@ -95,14 +95,26 @@ export const useInterfaceStore = defineStore('interface', {
}
},
onStreamDisconnect(closeEvent) {
// TODO better explanation/localization
const { code } = closeEvent
this.pushGlobalNotice({
level: 'error',
messageKey: 'timeline.socket_broke',
messageArgs: [code],
timeout: 5000,
})
const intendedCodes = new Set([
1000, // Normal (intended) closure
1001, // Going away
])
const { code } = closeEvent.original
if (intendedCodes.has(code)) {
this.pushGlobalNotice({
level: 'success',
messageKey: 'timeline.socket_closed',
messageArgs: [code],
timeout: 5000,
})
} else {
this.pushGlobalNotice({
level: 'error',
messageKey: 'timeline.socket_broke',
messageArgs: [code],
timeout: 5000,
})
}
},
setTemporaryChanges({ confirm, revert }) {
this.temporaryChangesCountdown = 10

View file

@ -338,7 +338,7 @@ export const useStatusesStore = defineStore('statuses', {
useInterfaceStore().pushGlobalNotice({
level: 'error',
messageKey: 'status.react_error',
messageKey: 'status.interact_error',
messageArgs: [error],
timeout: 5000,
})