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:
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -106,6 +106,8 @@ struct HomeScreenViewState: BindableState {
|
||||
return rooms
|
||||
}
|
||||
|
||||
var hideInviteAvatars = false
|
||||
|
||||
var bindings = HomeScreenViewStateBindings()
|
||||
|
||||
var placeholderRooms: [HomeScreenRoom] {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user