mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-18 17:53:42 -05:00
web/roomlist: add option to hide invite avatars
This commit is contained in:
parent
86843d61f6
commit
ef05bc71f9
7 changed files with 46 additions and 15 deletions
|
@ -78,11 +78,16 @@ function getFallbackCharacter(from: unknown, idx: number): string {
|
|||
return Array.from(from.slice(0, (idx + 1) * 2))[idx]?.toUpperCase().toWellFormed() ?? ""
|
||||
}
|
||||
|
||||
export const getAvatarURL = (userID: UserID, content?: UserProfile | null, thumbnail = false): string | undefined => {
|
||||
export const getAvatarURL = (
|
||||
userID: UserID,
|
||||
content?: UserProfile | null,
|
||||
thumbnail = false,
|
||||
forceFallback = false,
|
||||
): string | undefined => {
|
||||
const fallbackCharacter = getFallbackCharacter(content?.displayname, 0) || getFallbackCharacter(userID, 1)
|
||||
const backgroundColor = getUserColor(userID)
|
||||
const [server, mediaID] = parseMXC(content?.avatar_file?.url ?? content?.avatar_url)
|
||||
if (!mediaID) {
|
||||
if (!mediaID || forceFallback) {
|
||||
return makeFallbackAvatar(backgroundColor, fallbackCharacter)
|
||||
}
|
||||
const encrypted = !!content?.avatar_file
|
||||
|
@ -91,8 +96,12 @@ export const getAvatarURL = (userID: UserID, content?: UserProfile | null, thumb
|
|||
return thumbnail ? `${url}&thumbnail=avatar` : url
|
||||
}
|
||||
|
||||
export const getAvatarThumbnailURL = (userID: UserID, content?: UserProfile | null): string | undefined => {
|
||||
return getAvatarURL(userID, content, true)
|
||||
export const getAvatarThumbnailURL = (
|
||||
userID: UserID,
|
||||
content?: UserProfile | null,
|
||||
forceFallback = false,
|
||||
): string | undefined => {
|
||||
return getAvatarURL(userID, content, true, forceFallback)
|
||||
}
|
||||
|
||||
interface RoomForAvatarURL {
|
||||
|
@ -104,14 +113,21 @@ interface RoomForAvatarURL {
|
|||
}
|
||||
|
||||
export const getRoomAvatarURL = (
|
||||
room: RoomForAvatarURL, avatarOverride?: ContentURI, thumbnail = false,
|
||||
room: RoomForAvatarURL,
|
||||
avatarOverride?: ContentURI,
|
||||
thumbnail = false,
|
||||
forceFallback = false,
|
||||
): string | undefined => {
|
||||
return getAvatarURL(room.dm_user_id ?? room.room_id, {
|
||||
displayname: room.name,
|
||||
avatar_url: avatarOverride ?? room.avatar ?? room.avatar_url,
|
||||
}, thumbnail)
|
||||
}, thumbnail, forceFallback)
|
||||
}
|
||||
|
||||
export const getRoomAvatarThumbnailURL = (room: RoomForAvatarURL, avatarOverride?: ContentURI): string | undefined => {
|
||||
return getRoomAvatarURL(room, avatarOverride, true)
|
||||
export const getRoomAvatarThumbnailURL = (
|
||||
room: RoomForAvatarURL,
|
||||
avatarOverride?: ContentURI,
|
||||
forceFallback = false,
|
||||
): string | undefined => {
|
||||
return getRoomAvatarURL(room, avatarOverride, true, forceFallback)
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ export class InvitedRoomStore implements RoomListEntry, RoomSummary {
|
|||
readonly invited_by?: UserID
|
||||
readonly inviter_profile?: MemberEventContent
|
||||
readonly is_direct: boolean
|
||||
readonly is_invite = true
|
||||
|
||||
constructor(public readonly meta: DBInvitedRoom, parent: StateStore) {
|
||||
this.room_id = meta.room_id
|
||||
|
|
|
@ -55,6 +55,7 @@ export interface RoomListEntry {
|
|||
unread_notifications: number
|
||||
unread_highlights: number
|
||||
marked_unread: boolean
|
||||
is_invite?: boolean
|
||||
}
|
||||
|
||||
export interface GCSettings {
|
||||
|
|
|
@ -65,6 +65,12 @@ export const preferences = {
|
|||
allowedContexts: anyContext,
|
||||
defaultValue: true,
|
||||
}),
|
||||
show_invite_avatars: new Preference<boolean>({
|
||||
displayName: "Show avatars in invites",
|
||||
description: "If disabled, the avatar of the room or invitee will not be shown in the invite view.",
|
||||
allowedContexts: anyGlobalContext,
|
||||
defaultValue: true,
|
||||
}),
|
||||
code_block_line_wrap: new Preference<boolean>({
|
||||
displayName: "Code block line wrap",
|
||||
description: "Whether to wrap long lines in code blocks instead of scrolling horizontally.",
|
||||
|
|
|
@ -29,6 +29,7 @@ export interface RoomListEntryProps {
|
|||
room: RoomListEntry
|
||||
isActive: boolean
|
||||
hidden: boolean
|
||||
hideAvatar?: boolean
|
||||
}
|
||||
|
||||
function getPreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent | null): [string, JSX.Element | null] {
|
||||
|
@ -57,7 +58,7 @@ function getPreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent | null):
|
|||
return ["", null]
|
||||
}
|
||||
|
||||
function renderEntry(room: RoomListEntry) {
|
||||
function renderEntry(room: RoomListEntry, hideAvatar: boolean | undefined) {
|
||||
const [previewText, croppedPreviewText] = getPreviewText(room.preview_event, room.preview_sender)
|
||||
|
||||
return <>
|
||||
|
@ -65,7 +66,7 @@ function renderEntry(room: RoomListEntry) {
|
|||
<img
|
||||
loading="lazy"
|
||||
className="avatar room-avatar"
|
||||
src={getRoomAvatarThumbnailURL(room)}
|
||||
src={getRoomAvatarThumbnailURL(room, undefined, hideAvatar)}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
|
@ -77,7 +78,7 @@ function renderEntry(room: RoomListEntry) {
|
|||
</>
|
||||
}
|
||||
|
||||
const Entry = ({ room, isActive, hidden }: RoomListEntryProps) => {
|
||||
const Entry = ({ room, isActive, hidden, hideAvatar }: RoomListEntryProps) => {
|
||||
const [isVisible, divRef] = useContentVisibility<HTMLDivElement>()
|
||||
const openModal = use(ModalContext)
|
||||
const mainScreen = use(MainScreenContext)
|
||||
|
@ -105,7 +106,7 @@ const Entry = ({ room, isActive, hidden }: RoomListEntryProps) => {
|
|||
onContextMenu={onContextMenu}
|
||||
data-room-id={room.room_id}
|
||||
>
|
||||
{isVisible ? renderEntry(room) : null}
|
||||
{isVisible ? renderEntry(room, hideAvatar) : null}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import React, { use, useCallback, useRef, useState } from "react"
|
||||
import { RoomListFilter, Space as SpaceStore, SpaceUnreadCounts } from "@/api/statestore"
|
||||
import { RoomListFilter, Space as SpaceStore, SpaceUnreadCounts, usePreference } from "@/api/statestore"
|
||||
import type { RoomID } from "@/api/types"
|
||||
import { useEventAsState } from "@/util/eventdispatcher.ts"
|
||||
import reverseMap from "@/util/reversemap.ts"
|
||||
|
@ -103,6 +103,7 @@ const RoomList = ({ activeRoomID, space }: RoomListProps) => {
|
|||
}
|
||||
}
|
||||
|
||||
const showInviteAvatars = usePreference(client.store, null, "show_invite_avatars")
|
||||
const roomListFilter = client.store.roomListFilterFunc
|
||||
return <div className="room-list-wrapper">
|
||||
<div className="room-search-wrapper">
|
||||
|
@ -145,6 +146,7 @@ const RoomList = ({ activeRoomID, space }: RoomListProps) => {
|
|||
isActive={room.room_id === activeRoomID}
|
||||
hidden={roomListFilter ? !roomListFilter(room) : false}
|
||||
room={room}
|
||||
hideAvatar={room.is_invite && !showInviteAvatars}
|
||||
/>,
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import { use, useEffect, useState } from "react"
|
||||
import { ScaleLoader } from "react-spinners"
|
||||
import { getAvatarThumbnailURL, getAvatarURL, getRoomAvatarURL } from "@/api/media.ts"
|
||||
import { usePreference } from "@/api/statestore/hooks.ts"
|
||||
import { InvitedRoomStore } from "@/api/statestore/invitedroom.ts"
|
||||
import { RoomID, RoomSummary } from "@/api/types"
|
||||
import { getDisplayname, getServerName } from "@/util/validation.ts"
|
||||
|
@ -84,13 +85,15 @@ const RoomPreview = ({ roomID, via, alias, invite }: RoomPreviewProps) => {
|
|||
const name = summary?.name ?? summary?.canonical_alias ?? invite?.name ?? invite?.canonical_alias ?? alias ?? roomID
|
||||
const memberCount = summary?.num_joined_members || null
|
||||
const topic = summary?.topic ?? invite?.topic ?? ""
|
||||
const showInviteAvatars = usePreference(client.store, null, "show_invite_avatars")
|
||||
const noAvatarPreview = invite && !showInviteAvatars
|
||||
return <div className="room-view preview">
|
||||
<div className="preview-inner">
|
||||
{invite?.invited_by && !invite.dm_user_id ? <div className="inviter-info">
|
||||
<img
|
||||
className="small avatar"
|
||||
onClick={use(LightboxContext)}
|
||||
src={getAvatarThumbnailURL(invite.invited_by, invite.inviter_profile)}
|
||||
src={getAvatarThumbnailURL(invite.invited_by, invite.inviter_profile, noAvatarPreview)}
|
||||
data-full-src={getAvatarURL(invite.invited_by, invite.inviter_profile)}
|
||||
alt=""
|
||||
/>
|
||||
|
@ -102,7 +105,8 @@ const RoomPreview = ({ roomID, via, alias, invite }: RoomPreviewProps) => {
|
|||
<h2 className="room-name">{name}</h2>
|
||||
<img
|
||||
// this is a big avatar (120px), use full resolution
|
||||
src={getRoomAvatarURL(invite ?? summary ?? { room_id: roomID })}
|
||||
src={getRoomAvatarURL(invite ?? summary ?? { room_id: roomID }, undefined, false, noAvatarPreview)}
|
||||
data-full-src={getRoomAvatarURL(invite ?? summary ?? { room_id: roomID })}
|
||||
className="large avatar"
|
||||
onClick={use(LightboxContext)}
|
||||
alt=""
|
||||
|
|
Loading…
Add table
Reference in a new issue