hide invite avatars when such flag is on

This affects:
- Invited room preview inviter avatar
- Invited room preview room avatar
- Invited room cell inviter avatar in the room list
- Invited room cell room avatar in the room list
- Push notification for an invite
This commit is contained in:
Mauro Romito
2025-03-19 16:04:08 +01:00
committed by Mauro
parent b91d1ea19e
commit 208e7de3ee
13 changed files with 54 additions and 28 deletions

View File

@@ -12,6 +12,7 @@ import SwiftUI
protocol CommonSettingsProtocol {
var logLevel: LogLevel { get }
var enableOnlySignedDeviceIsolationMode: Bool { get }
var hideInviteAvatars: Bool { get }
var hideTimelineMedia: Bool { get }
var eventCacheEnabled: Bool { get }
}
@@ -40,6 +41,7 @@ final class AppSettings {
case appAppearance
case sharePresence
case hideUnreadMessagesBadge
case hideInviteAvatars
case hideTimelineMedia
case elementCallBaseURLOverride
@@ -307,6 +309,9 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.enableOnlySignedDeviceIsolationMode, defaultValue: false, storageType: .userDefaults(store))
var enableOnlySignedDeviceIsolationMode
@UserPreference(key: UserDefaultsKeys.hideInviteAvatars, defaultValue: false, storageType: .userDefaults(store))
var hideInviteAvatars
@UserPreference(key: UserDefaultsKeys.hideTimelineMedia, defaultValue: false, storageType: .userDefaults(store))
var hideTimelineMedia

View File

@@ -101,32 +101,24 @@ extension UNMutableNotificationContent {
func addSenderIcon(using mediaProvider: MediaProviderProtocol?,
senderID: String,
senderName: String,
icon: NotificationIcon) async throws -> UNMutableNotificationContent {
// We display the placeholder only if...
var needsPlaceholder = false
icon: NotificationIcon,
forcePlaceholder: Bool = false) async throws -> UNMutableNotificationContent {
var fetchedImage: INImage?
let image: INImage
if let mediaSource = icon.mediaSource {
if !forcePlaceholder, let mediaSource = icon.mediaSource {
switch await mediaProvider?.loadThumbnailForSource(source: mediaSource, size: .init(width: 100, height: 100)) {
case .success(let data):
fetchedImage = INImage(imageData: data)
case .failure(let error):
MXLog.error("Couldn't add sender icon: \(error)")
// ...The provider failed to fetch
needsPlaceholder = true
case .none:
break
}
} else {
// ...There is no media
needsPlaceholder = true
}
if let fetchedImage {
image = fetchedImage
} else if needsPlaceholder,
let data = await getPlaceholderAvatarImageData(name: icon.groupInfo?.name ?? senderName,
} else if let data = await getPlaceholderAvatarImageData(name: icon.groupInfo?.name ?? senderName,
id: icon.groupInfo?.id ?? senderID) {
image = INImage(imageData: data)
} else {

View File

@@ -38,12 +38,13 @@ struct RoomInviterDetails: Equatable {
struct RoomInviterLabel: View {
let inviter: RoomInviterDetails
var shouldHideAvatar = false
let mediaProvider: MediaProviderProtocol?
var body: some View {
HStack(alignment: .firstTextBaseline, spacing: 8) {
LoadableAvatarImage(url: inviter.avatarURL,
LoadableAvatarImage(url: shouldHideAvatar ? nil : inviter.avatarURL,
name: inviter.displayName,
contentID: inviter.id,
avatarSize: .custom(16),

View File

@@ -106,6 +106,8 @@ struct HomeScreenViewState: BindableState {
return rooms
}
var hideInviteAvatars = false
var bindings = HomeScreenViewStateBindings()
var placeholderRooms: [HomeScreenRoom] {

View File

@@ -101,6 +101,10 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
}
.store(in: &cancellables)
appSettings.$hideInviteAvatars
.weakAssign(to: \.state.hideInviteAvatars, on: self)
.store(in: &cancellables)
let isSearchFieldFocused = context.$viewState.map(\.bindings.isSearchFieldFocused)
let searchQuery = context.$viewState.map(\.bindings.searchQuery)
let activeFilters = context.$viewState.map(\.bindings.filtersState.activeFilters)

View File

@@ -16,10 +16,14 @@ struct HomeScreenInviteCell: View {
let room: HomeScreenRoom
let context: HomeScreenViewModel.Context
private var avatar: RoomAvatar {
context.viewState.hideInviteAvatars ? .room(id: room.id, name: room.name, avatarURL: nil) : room.avatar
}
var body: some View {
HStack(alignment: .top, spacing: 16) {
if dynamicTypeSize < .accessibility3 {
RoomAvatarImage(avatar: room.avatar,
RoomAvatarImage(avatar: avatar,
avatarSize: .custom(52),
mediaProvider: context.mediaProvider)
.dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1)
@@ -71,7 +75,9 @@ struct HomeScreenInviteCell: View {
private var inviterView: some View {
if let inviter = room.inviter,
!room.isDirect {
RoomInviterLabel(inviter: inviter, mediaProvider: context.mediaProvider)
RoomInviterLabel(inviter: inviter,
shouldHideAvatar: context.viewState.hideInviteAvatars,
mediaProvider: context.mediaProvider)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textSecondary)
}

View File

@@ -23,6 +23,15 @@ enum JoinRoomScreenMode: Equatable {
case knocked
case banned(sender: String?, reason: String?)
case forbidden
var isInvite: Bool {
switch self {
case .invited:
true
default:
false
}
}
}
struct JoinRoomScreenRoomDetails {
@@ -41,9 +50,15 @@ struct JoinRoomScreenViewState: BindableState {
var roomDetails: JoinRoomScreenRoomDetails?
var mode: JoinRoomScreenMode = .loading
var hideInviteAvatars = false
var bindings = JoinRoomScreenViewStateBindings()
var shouldHideAvatars: Bool {
hideInviteAvatars && mode.isInvite
}
var title: String {
if isDMInvite, let inviter = roomDetails?.inviter {
return inviter.displayName ?? inviter.id
@@ -68,9 +83,9 @@ struct JoinRoomScreenViewState: BindableState {
var avatar: RoomAvatar? {
if isDMInvite, let inviter = roomDetails?.inviter {
return .room(id: roomID, name: inviter.displayName, avatarURL: inviter.avatarURL)
} else if let avatar = roomDetails?.avatar {
return avatar
return .room(id: roomID, name: inviter.displayName, avatarURL: hideInviteAvatars ? nil : inviter.avatarURL)
} else if let roomDetails, let avatar = roomDetails.avatar {
return shouldHideAvatars ? .room(id: roomID, name: roomDetails.name, avatarURL: nil) : avatar
} else if let name = roomDetails?.name {
return .room(id: roomID, name: name, avatarURL: nil)
} else {

View File

@@ -41,6 +41,10 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
super.init(initialViewState: JoinRoomScreenViewState(roomID: roomID), mediaProvider: mediaProvider)
appSettings.$hideInviteAvatars
.weakAssign(to: \.state.hideInviteAvatars, on: self)
.store(in: &cancellables)
context.$viewState.map(\.mode)
.removeDuplicates()
.sink { mode in

View File

@@ -58,7 +58,9 @@ struct JoinRoomScreen: View {
private var defaultView: some View {
VStack(spacing: 16) {
if let inviter = context.viewState.roomDetails?.inviter {
RoomInviterLabel(inviter: inviter, mediaProvider: context.mediaProvider)
RoomInviterLabel(inviter: inviter,
shouldHideAvatar: context.viewState.hideInviteAvatars,
mediaProvider: context.mediaProvider)
.multilineTextAlignment(.center)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textSecondary)

View File

@@ -34,7 +34,8 @@ protocol AdvancedSettingsProtocol: AnyObject {
var viewSourceEnabled: Bool { get set }
var appAppearance: AppAppearance { get set }
var sharePresence: Bool { get set }
var hideTimelineMedia: Bool { get set }
var hideInviteAvatars: Bool { get set }
var optimizeMediaUploads: Bool { get set }
}

View File

@@ -40,7 +40,6 @@ protocol DeveloperOptionsProtocol: AnyObject {
var publicSearchEnabled: Bool { get set }
var hideUnreadMessagesBadge: Bool { get set }
var fuzzyRoomListSearchEnabled: Bool { get set }
var hideTimelineMedia: Bool { get set }
var enableOnlySignedDeviceIsolationMode: Bool { get set }
var elementCallBaseURLOverride: URL? { get set }
var knockingEnabled: Bool { get set }

View File

@@ -46,12 +46,6 @@ struct DeveloperOptionsScreen: View {
}
}
Section("Room") {
Toggle(isOn: $context.hideTimelineMedia) {
Text("Hide image & video previews")
}
}
Section("Join rules") {
Toggle(isOn: $context.knockingEnabled) {
Text("Knocking")

View File

@@ -93,7 +93,8 @@ struct NotificationContentBuilder {
notification = try await notification.addSenderIcon(using: mediaProvider,
senderID: notificationItem.senderID,
senderName: notificationItem.senderDisplayName ?? notificationItem.roomDisplayName,
icon: icon(for: notificationItem))
icon: icon(for: notificationItem),
forcePlaceholder: settings.hideInviteAvatars)
notification.body = body
return notification