mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
A couple of small tweaks. (#4569)
* Stop ignoring the safe area with the suggestions view. They weren't visible on iPad (hidden behind the sidebar) and I can't find any instance when they're shown where the safe area comes into play. * Make sure the room list deselects the cell when dismissed a room. * Use the backports pattern in more places. * Fix the annoying header on macOS. * Silence some warnings * Fix compound CI branch name.
This commit is contained in:
@@ -280,6 +280,8 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch context.toState {
|
||||
case .roomList(detailState: .room(let detailStateRoomID)):
|
||||
self?.selectedRoomSubject.send(detailStateRoomID)
|
||||
case .roomList(detailState: nil):
|
||||
self?.selectedRoomSubject.send(nil)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// Copyright 2024 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 SwiftUI
|
||||
|
||||
extension View {
|
||||
/// A convenience modifier to conditionally apply `.navigationTransition(.zoom(…))` when available.
|
||||
@ViewBuilder
|
||||
func zoomTransition(sourceID: some Hashable, in namespace: Namespace.ID) -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
navigationTransition(.zoom(sourceID: sourceID, in: namespace))
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience modifier to conditionally apply `.matchedTransitionSource(…)` when available.
|
||||
@ViewBuilder
|
||||
func zoomTransitionSource(id: some Hashable, in namespace: Namespace.ID) -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
matchedTransitionSource(id: id, in: namespace)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,68 @@
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
@ViewBuilder
|
||||
func backportTabBarMinimizeBehaviorOnScrollDown() -> some View {
|
||||
// MARK: iOS 18
|
||||
|
||||
/// Uses the old page style modal so that on iPadOS 18 the presentation detents have no effect.
|
||||
@ViewBuilder func backportPresentationSizingPage() -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
presentationSizing(.page)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience modifier to conditionally apply `.navigationTransition(.zoom(…))` when available.
|
||||
@ViewBuilder func backportNavigationTransitionZoom(sourceID: some Hashable, in namespace: Namespace.ID) -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
navigationTransition(.zoom(sourceID: sourceID, in: namespace))
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience modifier to conditionally apply `.matchedTransitionSource(…)` when available.
|
||||
@ViewBuilder func backportMatchedTransitionSource(id: some Hashable, in namespace: Namespace.ID) -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
matchedTransitionSource(id: id, in: namespace)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder func backportAccessibilityHint(_ hint: String, isEnabled: Bool) -> some View {
|
||||
if #available(iOS 18, *) {
|
||||
accessibilityHint(hint, isEnabled: isEnabled)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: iOS 26
|
||||
|
||||
@ViewBuilder func backportTabBarMinimizeBehaviorOnScrollDown() -> some View {
|
||||
if #available(iOS 26.0, *) {
|
||||
tabBarMinimizeBehavior(.onScrollDown)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder func backportScrollEdgeEffectHidden() -> some View {
|
||||
if #available(iOS 26, *) {
|
||||
scrollEdgeEffectHidden()
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ToolbarContent {
|
||||
@ToolbarContentBuilder func backportSharedBackgroundVisibility(_ visibility: Visibility) -> some ToolbarContent {
|
||||
if #available(iOS 26.0, *) {
|
||||
sharedBackgroundVisibility(visibility)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ extension TextFieldStyle where Self == ElementTextFieldStyle {
|
||||
}
|
||||
|
||||
/// The text field style used in authentication screens.
|
||||
struct ElementTextFieldStyle: TextFieldStyle {
|
||||
struct ElementTextFieldStyle: @MainActor TextFieldStyle {
|
||||
enum State {
|
||||
case success
|
||||
case error
|
||||
|
||||
@@ -18,8 +18,9 @@ struct RoomHeaderView: View {
|
||||
let mediaProvider: MediaProviderProtocol?
|
||||
|
||||
var body: some View {
|
||||
if ProcessInfo.isRunningAccessibilityTests {
|
||||
// Accessibility tests scale up the dynamic size in real time which may break the view
|
||||
if ProcessInfo.isRunningAccessibilityTests || ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
// Accessibility tests scale up the dynamic size in real time which may break the view.
|
||||
// macOS really doesn't like the greedy size and does weird things to it.
|
||||
content
|
||||
} else {
|
||||
content
|
||||
|
||||
@@ -22,14 +22,7 @@ struct HomeScreen: View {
|
||||
actions: leaveRoomAlertActions,
|
||||
message: leaveRoomAlertMessage)
|
||||
.navigationTitle(L10n.screenRoomlistMainSpaceTitle)
|
||||
.toolbar {
|
||||
if #available(iOS 26, *) {
|
||||
toolbar
|
||||
.sharedBackgroundVisibility(.hidden)
|
||||
} else {
|
||||
toolbar
|
||||
}
|
||||
}
|
||||
.toolbar { toolbar }
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.track(screen: .Home)
|
||||
.bloom()
|
||||
@@ -43,10 +36,12 @@ struct HomeScreen: View {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
settingsButton
|
||||
}
|
||||
.backportSharedBackgroundVisibility(.hidden)
|
||||
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
newRoomButton
|
||||
}
|
||||
.backportSharedBackgroundVisibility(.hidden)
|
||||
}
|
||||
|
||||
private var settingsButton: some View {
|
||||
|
||||
+5
-9
@@ -47,15 +47,11 @@ struct MediaEventsTimelineScreen: View {
|
||||
if context.viewState.shouldShowEmptyState {
|
||||
emptyState
|
||||
} else {
|
||||
if #available(iOS 26, *) {
|
||||
scrollView
|
||||
// Remove the glass effect of iOS 26+
|
||||
// A flipped table view will always trigger it
|
||||
// since the nav bar thinks is always at the bottom.
|
||||
.scrollEdgeEffectHidden()
|
||||
} else {
|
||||
scrollView
|
||||
}
|
||||
scrollView
|
||||
// Remove the glass effect of iOS 26+
|
||||
// A flipped table view will always trigger it
|
||||
// since the nav bar thinks is always at the bottom.
|
||||
.backportScrollEdgeEffectHidden()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -99,7 +99,6 @@ private struct BackgroundView<Content: View>: View {
|
||||
.clipShape(RoundedCornerShape(radius: shadowRadius, corners: [.topLeft, .topRight]))
|
||||
.shadow(color: .black.opacity(0.20), radius: 20.0, x: 0.0, y: 3.0)
|
||||
.mask(Rectangle().padding(.init(top: -(shadowRadius * 2), leading: 0.0, bottom: 0.0, trailing: 0.0)))
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,14 +20,7 @@ struct SpaceListScreen: View {
|
||||
}
|
||||
.navigationTitle(L10n.screenSpaceListTitle)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
if #available(iOS 26, *) {
|
||||
toolbar
|
||||
.sharedBackgroundVisibility(.hidden)
|
||||
} else {
|
||||
toolbar
|
||||
}
|
||||
}
|
||||
.toolbar { toolbar }
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.bloom()
|
||||
}
|
||||
@@ -90,11 +83,13 @@ struct SpaceListScreen: View {
|
||||
}
|
||||
.accessibilityLabel(L10n.commonSettings)
|
||||
}
|
||||
.backportSharedBackgroundVisibility(.hidden)
|
||||
|
||||
ToolbarItem(placement: .principal) {
|
||||
// Hides the navigationTitle (which is set for the navigation stack label).
|
||||
Text("").accessibilityHidden(true)
|
||||
}
|
||||
.backportSharedBackgroundVisibility(.hidden)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ struct TimelineItemMenu: View {
|
||||
}
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.timelineItemActionMenu)
|
||||
.presentationPage()
|
||||
.backportPresentationSizingPage()
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationBackground(Color.compound.bgCanvasDefault)
|
||||
.presentationDragIndicator(.visible)
|
||||
@@ -251,17 +251,6 @@ private extension EncryptionAuthenticity {
|
||||
}
|
||||
}
|
||||
|
||||
private extension View {
|
||||
/// Uses the old page style modal so that on iPadOS 18 the presentation detents have no effect.
|
||||
@ViewBuilder func presentationPage() -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
presentationSizing(.page)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
@@ -92,13 +92,9 @@ struct PollView: View {
|
||||
|
||||
private var optionsView: some View {
|
||||
ForEach(poll.options, id: \.id) { option in
|
||||
if #available(iOS 18, *) {
|
||||
pollOption(option: option)
|
||||
.accessibilityHint(L10n.a11yPollsWillRemoveSelection,
|
||||
isEnabled: isRemovePreviousSelectionHintEnabled(option: option))
|
||||
} else {
|
||||
pollOption(option: option)
|
||||
}
|
||||
pollOption(option: option)
|
||||
.backportAccessibilityHint(L10n.a11yPollsWillRemoveSelection,
|
||||
isEnabled: isRemovePreviousSelectionHintEnabled(option: option))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ struct RoomEventStringBuilder {
|
||||
default: L10n.commonWaitingForDecryptionKey
|
||||
}
|
||||
return prefix(errorMessage, with: displayName, isOutgoing: isOutgoing)
|
||||
case .other(eventType: let eventType):
|
||||
case .other:
|
||||
return nil // We shouldn't receive these without asking for custom event types.
|
||||
}
|
||||
case .failedToParseMessageLike, .failedToParseState:
|
||||
|
||||
@@ -40,7 +40,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
return buildRedactedTimelineItem(eventItemProxy, messageLikeContent, isOutgoing)
|
||||
case .unableToDecrypt(let encryptedMessage):
|
||||
return buildEncryptedTimelineItem(eventItemProxy, messageLikeContent, encryptedMessage, isOutgoing)
|
||||
case .other(eventType: let eventType):
|
||||
case .other:
|
||||
return nil // We shouldn't receive these without asking for custom event types.
|
||||
}
|
||||
case .failedToParseMessageLike(let eventType, let error):
|
||||
|
||||
@@ -467,7 +467,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
MXLog.info("Toggling reaction \(reaction) for event: \(eventOrTransactionID)")
|
||||
|
||||
do {
|
||||
try await timeline.toggleReaction(itemId: eventOrTransactionID.rustValue, key: reaction)
|
||||
_ = try await timeline.toggleReaction(itemId: eventOrTransactionID.rustValue, key: reaction)
|
||||
MXLog.info("Finished toggling reaction for event: \(eventOrTransactionID)")
|
||||
return .success(())
|
||||
} catch {
|
||||
|
||||
@@ -57,7 +57,7 @@ extension RestorationToken: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
extension MatrixRustSDK.Session: Codable {
|
||||
extension MatrixRustSDK.Session: @retroactive Codable {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import Combine
|
||||
import KZFileWatchers
|
||||
import SwiftUI
|
||||
|
||||
extension Notification.Name: Codable { }
|
||||
extension Notification.Name: @retroactive Codable { }
|
||||
|
||||
enum UITestsSignal: Codable, Equatable {
|
||||
/// An internal signal used to indicate that one side of the connection is ready.
|
||||
|
||||
Reference in New Issue
Block a user