mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
7f1b6086ae
* Add a developer flag for the search tab Introduces a globalSearchEnabled user preference (off by default) with a toggle in Developer Options, used to gate the new search experience. * Support search role tabs in the tab coordinator Migrates the NavigationTabCoordinator to SwiftUI's value-based Tab API and adds an isSearch option so a tab can adopt the iOS 26 .search role, which detaches it into the trailing search button in the tab bar. * Moves room search to a new screen Adds a new screen that filters the alternate room summary provider as you type, shows an empty state, and lists matching rooms with their matrix identifier. Supports hardware keyboard selection (arrow keys to move through results, return to open) by reaching into the system search field. * Present search in a dedicated tab Adds the search tab to the chats flow on iOS 26 when the flag is enabled, rendered as the detached .search role button. The Cmd+K shortcut now selects this tab, and the home screen's inline search is hidden while the tab is available. * Remove the old global search screen The dedicated search tab replaces the Cmd+K floating window, so the GlobalSearchScreen, its window plumbing in the WindowManager, and its presentation in the chats flow are all removed.
168 lines
4.4 KiB
Swift
168 lines
4.4 KiB
Swift
//
|
|
// Copyright 2025 Element Creations Ltd.
|
|
// Copyright 2022-2025 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
|
// Please see LICENSE files in the repository root for full details.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
|
|
enum Avatars {
|
|
enum Size {
|
|
case user(on: UserAvatarSizeOnScreen)
|
|
case room(on: RoomAvatarSizeOnScreen)
|
|
/// custom
|
|
case custom(CGFloat)
|
|
|
|
/// Value in UIKit points
|
|
var value: CGFloat {
|
|
switch self {
|
|
case .user(let screen):
|
|
return screen.value
|
|
case .room(let screen):
|
|
return screen.value
|
|
case .custom(let val):
|
|
return val
|
|
}
|
|
}
|
|
|
|
/// Value in pixels by using the scale of the main screen
|
|
@MainActor var scaledValue: CGFloat {
|
|
value * UIScreen.main.scale
|
|
}
|
|
|
|
@MainActor var scaledSize: CGSize {
|
|
CGSize(width: scaledValue, height: scaledValue)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
static func generatePlaceholderAvatarImageData(name: String, id: String, size: CGSize) -> Data? {
|
|
let image = PlaceholderAvatarImage(name: name, contentID: id)
|
|
.clipShape(Circle())
|
|
.frame(width: size.width, height: size.height)
|
|
|
|
let renderer = ImageRenderer(content: image)
|
|
|
|
// Specify the scale so the image is rendered correctly. We don't have access to the screen
|
|
// here so a hardcoded 3.0 will have to do
|
|
renderer.scale = 3.0
|
|
|
|
guard let image = renderer.uiImage else {
|
|
MXLog.info("Generating notification icon placeholder failed")
|
|
return nil
|
|
}
|
|
|
|
return image.pngData()
|
|
}
|
|
}
|
|
|
|
enum UserAvatarSizeOnScreen {
|
|
case chats
|
|
case spaces
|
|
case timeline
|
|
case settings
|
|
case roomDetails
|
|
case roomMembersList
|
|
case roomChangeRoles
|
|
case dmDetails
|
|
case startChat
|
|
case memberDetails
|
|
case inviteUsers
|
|
case readReceipt
|
|
case readReceiptSheet
|
|
case editUserDetails
|
|
case spaceHeader
|
|
case completionSuggestions
|
|
case blockedUsers
|
|
case knockingUsersBannerStack
|
|
case knockingUserBanner
|
|
case knockingUserList
|
|
case mediaPreviewDetails
|
|
case sendInviteConfirmation
|
|
case sessionVerification
|
|
case threadList
|
|
case threadSummary
|
|
case map
|
|
case classicAppAccount
|
|
|
|
var value: CGFloat {
|
|
switch self {
|
|
case .readReceipt:
|
|
16
|
|
case .spaceHeader:
|
|
20
|
|
case .threadSummary:
|
|
24
|
|
case .knockingUsersBannerStack:
|
|
28
|
|
case .chats, .spaces, .map,
|
|
.timeline, .readReceiptSheet, .completionSuggestions,
|
|
.blockedUsers, .roomMembersList, .knockingUserBanner:
|
|
32
|
|
case .startChat:
|
|
36
|
|
case .roomDetails:
|
|
44
|
|
case .inviteUsers, .knockingUserList, .sessionVerification,
|
|
.settings, .threadList, .mediaPreviewDetails:
|
|
52
|
|
case .roomChangeRoles:
|
|
56
|
|
case .sendInviteConfirmation:
|
|
64
|
|
case .dmDetails:
|
|
75
|
|
case .memberDetails, .editUserDetails, .classicAppAccount:
|
|
96
|
|
}
|
|
}
|
|
}
|
|
|
|
enum RoomAvatarSizeOnScreen {
|
|
case chats
|
|
case spaces
|
|
case spaceSettings
|
|
case spaceFilters
|
|
case authorizedSpaces
|
|
case timeline
|
|
case leaveSpace
|
|
case messageForwarding
|
|
case globalSearch
|
|
case roomSelection
|
|
case details
|
|
case editRoomDetails
|
|
case notificationSettings
|
|
case roomDirectorySearch
|
|
case joinRoom
|
|
case spaceHeader
|
|
case editSpaceDetails
|
|
case spaceAddRooms
|
|
case spaceAddRoomsSelected
|
|
case completionSuggestions
|
|
case createRoomSelectSpace
|
|
|
|
var value: CGFloat {
|
|
switch self {
|
|
case .notificationSettings:
|
|
30
|
|
case .timeline, .leaveSpace, .roomDirectorySearch,
|
|
.completionSuggestions, .authorizedSpaces, .createRoomSelectSpace,
|
|
.spaceFilters, .globalSearch:
|
|
32
|
|
case .messageForwarding, .roomSelection,
|
|
.spaceAddRooms:
|
|
36
|
|
case .chats, .spaces, .spaceSettings,
|
|
.spaceAddRoomsSelected:
|
|
52
|
|
case .joinRoom, .spaceHeader, .editSpaceDetails:
|
|
64
|
|
case .details, .editRoomDetails:
|
|
96
|
|
}
|
|
}
|
|
}
|