mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:11:45 +00:00
drop iOS 17 and removed all #available and #unavaible checks for 17 and 18
This commit is contained in:
@@ -9075,7 +9075,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 17.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
||||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.5;
|
MACOSX_DEPLOYMENT_TARGET = 14.5;
|
||||||
MARKETING_VERSION = 25.12.0;
|
MARKETING_VERSION = 25.12.0;
|
||||||
@@ -9151,7 +9151,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 17.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
||||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.5;
|
MACOSX_DEPLOYMENT_TARGET = 14.5;
|
||||||
MARKETING_VERSION = 25.12.0;
|
MARKETING_VERSION = 25.12.0;
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ import SwiftUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func barVisibility(in horizontalSizeClass: UserInterfaceSizeClass?) -> Visibility {
|
func barVisibility(in horizontalSizeClass: UserInterfaceSizeClass?) -> Visibility {
|
||||||
if #unavailable(iOS 18.0) {
|
if let barVisibilityOverride {
|
||||||
// There are glitches with the tab bar on iPadOS 17, so disable the tab bar until we have fixed it.
|
|
||||||
.hidden
|
|
||||||
} else if let barVisibilityOverride {
|
|
||||||
barVisibilityOverride
|
barVisibilityOverride
|
||||||
} else if horizontalSizeClass == .compact, navigationSplitCoordinator?.detailCoordinator != nil {
|
} else if horizontalSizeClass == .compact, navigationSplitCoordinator?.detailCoordinator != nil {
|
||||||
// Whilst we support pushing screens on the stack in the sidebarCoordinator, in practice
|
// Whilst we support pushing screens on the stack in the sidebarCoordinator, in practice
|
||||||
|
|||||||
@@ -10,43 +10,6 @@ import Compound
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
extension View {
|
extension 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
|
// MARK: iOS 26
|
||||||
|
|
||||||
@ViewBuilder func backportTabBarMinimizeBehaviorOnScrollDown() -> some View {
|
@ViewBuilder func backportTabBarMinimizeBehaviorOnScrollDown() -> some View {
|
||||||
|
|||||||
@@ -228,13 +228,9 @@ private struct FocusSearchIfHardwareKeyboardAvailableModifier: ViewModifier {
|
|||||||
@FocusState private var isFocused
|
@FocusState private var isFocused
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
if #available(iOS 18.0, *) {
|
content
|
||||||
content
|
.searchFocused($isFocused)
|
||||||
.searchFocused($isFocused)
|
.onAppear(perform: focusIfHardwareKeyboardAvailable)
|
||||||
.onAppear(perform: focusIfHardwareKeyboardAvailable)
|
|
||||||
} else {
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func focusIfHardwareKeyboardAvailable() {
|
func focusIfHardwareKeyboardAvailable() {
|
||||||
|
|||||||
@@ -51,59 +51,52 @@ struct SwipeRightAction<Label: View>: ViewModifier {
|
|||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private func mainContent(content: Content) -> some View {
|
private func mainContent(content: Content) -> some View {
|
||||||
if #available(iOS 18, *) {
|
content
|
||||||
content
|
.offset(x: xOffset, y: 0.0)
|
||||||
.offset(x: xOffset, y: 0.0)
|
.animation(.interactiveSpring().speed(0.5), value: xOffset)
|
||||||
.animation(.interactiveSpring().speed(0.5), value: xOffset)
|
.gesture(PanGestureRepresentable { gesture in
|
||||||
.gesture(PanGestureRepresentable { gesture in
|
switch gesture.state {
|
||||||
switch gesture.state {
|
case .ended, .cancelled, .failed:
|
||||||
case .ended, .cancelled, .failed:
|
if xOffset > actionThreshold {
|
||||||
if xOffset > actionThreshold {
|
action()
|
||||||
action()
|
|
||||||
}
|
|
||||||
|
|
||||||
xOffset = 0.0
|
|
||||||
default:
|
|
||||||
guard shouldStartAction() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let translation = gesture.translation(in: nil)
|
|
||||||
|
|
||||||
// Due to https://forums.developer.apple.com/forums/thread/760035 we had to make
|
|
||||||
// the drag a simultaneous gesture otherwise it was impossible to scroll the timeline.
|
|
||||||
// Therefore we need to prevent the animation to run if the user is to scrolling vertically.
|
|
||||||
// It would be nice if we could somehow abort the gesture in this case.
|
|
||||||
let width: CGFloat = if translation.x > abs(translation.y) {
|
|
||||||
translation.x
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to add a spring like behaviour to the drag in which the view
|
|
||||||
// moves slower the more it's dragged. We use a circular easing function
|
|
||||||
// to generate those values up to the `swipeThreshold`
|
|
||||||
// The final translation will be between 0 and `swipeThreshold` with the action being enabled from
|
|
||||||
// `actionThreshold` onwards
|
|
||||||
let screenWidthNormalisedTranslation = max(0.0, min(width, swipeThreshold)) / swipeThreshold
|
|
||||||
let easedTranslation = circularEaseOut(screenWidthNormalisedTranslation)
|
|
||||||
xOffset = easedTranslation * xOffsetThreshold
|
|
||||||
|
|
||||||
if xOffset > actionThreshold {
|
|
||||||
if !hasReachedActionThreshold {
|
|
||||||
feedbackGenerator.impactOccurred()
|
|
||||||
hasReachedActionThreshold = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hasReachedActionThreshold = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
} else {
|
xOffset = 0.0
|
||||||
content
|
default:
|
||||||
.offset(x: xOffset, y: 0.0)
|
guard shouldStartAction() else {
|
||||||
.animation(.interactiveSpring().speed(0.5), value: xOffset)
|
return
|
||||||
.gesture(oldGesture)
|
}
|
||||||
}
|
let translation = gesture.translation(in: nil)
|
||||||
|
|
||||||
|
// Due to https://forums.developer.apple.com/forums/thread/760035 we had to make
|
||||||
|
// the drag a simultaneous gesture otherwise it was impossible to scroll the timeline.
|
||||||
|
// Therefore we need to prevent the animation to run if the user is to scrolling vertically.
|
||||||
|
// It would be nice if we could somehow abort the gesture in this case.
|
||||||
|
let width: CGFloat = if translation.x > abs(translation.y) {
|
||||||
|
translation.x
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to add a spring like behaviour to the drag in which the view
|
||||||
|
// moves slower the more it's dragged. We use a circular easing function
|
||||||
|
// to generate those values up to the `swipeThreshold`
|
||||||
|
// The final translation will be between 0 and `swipeThreshold` with the action being enabled from
|
||||||
|
// `actionThreshold` onwards
|
||||||
|
let screenWidthNormalisedTranslation = max(0.0, min(width, swipeThreshold)) / swipeThreshold
|
||||||
|
let easedTranslation = circularEaseOut(screenWidthNormalisedTranslation)
|
||||||
|
xOffset = easedTranslation * xOffsetThreshold
|
||||||
|
|
||||||
|
if xOffset > actionThreshold {
|
||||||
|
if !hasReachedActionThreshold {
|
||||||
|
feedbackGenerator.impactOccurred()
|
||||||
|
hasReachedActionThreshold = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasReachedActionThreshold = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private var oldGesture: some Gesture {
|
private var oldGesture: some Gesture {
|
||||||
|
|||||||
@@ -21,25 +21,19 @@ struct TimelineItemMacContextMenu: View {
|
|||||||
if let menuActions = actionProvider.makeActions() {
|
if let menuActions = actionProvider.makeActions() {
|
||||||
Section {
|
Section {
|
||||||
if !menuActions.reactions.isEmpty {
|
if !menuActions.reactions.isEmpty {
|
||||||
if #available(iOS 17.0, *) {
|
let reactions = (item as? EventBasedTimelineItemProtocol)?.properties.reactions ?? []
|
||||||
let reactions = (item as? EventBasedTimelineItemProtocol)?.properties.reactions ?? []
|
ControlGroup {
|
||||||
ControlGroup {
|
ForEach(menuActions.reactions, id: \.key) {
|
||||||
ForEach(menuActions.reactions, id: \.key) {
|
ReactionToggle(reaction: $0, reactions: reactions) {
|
||||||
ReactionToggle(reaction: $0, reactions: reactions) {
|
send(.toggleReaction(key: $0))
|
||||||
send(.toggleReaction(key: $0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button { send(.react) } label: {
|
|
||||||
CompoundIcon(\.reactionAdd)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.controlGroupStyle(.palette)
|
|
||||||
} else {
|
|
||||||
Button { send(.react) } label: {
|
Button { send(.react) } label: {
|
||||||
TimelineItemMenuAction.react.label
|
CompoundIcon(\.reactionAdd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.controlGroupStyle(.palette)
|
||||||
}
|
}
|
||||||
|
|
||||||
ForEach(menuActions.actions) { action in
|
ForEach(menuActions.actions) { action in
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ struct TimelineItemMenu: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.timelineItemActionMenu)
|
.accessibilityIdentifier(A11yIdentifiers.roomScreen.timelineItemActionMenu)
|
||||||
.backportPresentationSizingPage()
|
.presentationSizing(.page)
|
||||||
.presentationDetents([.medium, .large])
|
.presentationDetents([.medium, .large])
|
||||||
.presentationBackground(Color.compound.bgCanvasDefault)
|
.presentationBackground(Color.compound.bgCanvasDefault)
|
||||||
.presentationDragIndicator(.visible)
|
.presentationDragIndicator(.visible)
|
||||||
|
|||||||
@@ -94,8 +94,7 @@ struct PollView: View {
|
|||||||
private var optionsView: some View {
|
private var optionsView: some View {
|
||||||
ForEach(poll.options, id: \.id) { option in
|
ForEach(poll.options, id: \.id) { option in
|
||||||
pollOption(option: option)
|
pollOption(option: option)
|
||||||
.backportAccessibilityHint(L10n.a11yPollsWillRemoveSelection,
|
.accessibilityHint(L10n.a11yPollsWillRemoveSelection, isEnabled: isRemovePreviousSelectionHintEnabled(option: option))
|
||||||
isEnabled: isRemovePreviousSelectionHintEnabled(option: option))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,26 +16,19 @@ struct LongPressWithFeedback: ViewModifier {
|
|||||||
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
if #available(iOS 18, *) {
|
mainContent(content: content)
|
||||||
mainContent(content: content)
|
.gesture(LongPressGestureRepresentable { gesture in
|
||||||
.gesture(LongPressGestureRepresentable { gesture in
|
switch gesture.state {
|
||||||
switch gesture.state {
|
case .began:
|
||||||
case .began:
|
handleLongPress(isPressing: true)
|
||||||
handleLongPress(isPressing: true)
|
case .ended, .cancelled, .failed:
|
||||||
case .ended, .cancelled, .failed:
|
handleLongPress(isPressing: false)
|
||||||
handleLongPress(isPressing: false)
|
case .possible, .changed:
|
||||||
case .possible, .changed:
|
break
|
||||||
break
|
@unknown default:
|
||||||
@unknown default:
|
break
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
mainContent(content: content)
|
|
||||||
.onLongPressGesture(minimumDuration: 0.25) { } onPressingChanged: { isPressing in
|
|
||||||
handleLongPress(isPressing: isPressing)
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// The gesture's minimum duration doesn't actually invoke the perform block when elapsed (thus
|
// The gesture's minimum duration doesn't actually invoke the perform block when elapsed (thus
|
||||||
|
|||||||
@@ -119,14 +119,9 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setFilter(_ filter: RoomSummaryProviderFilter) {
|
func setFilter(_ filter: RoomSummaryProviderFilter) {
|
||||||
let baseFilter: [RoomListEntriesDynamicFilterKind] = if #available(iOS 18.0, *) {
|
let baseFilter: [RoomListEntriesDynamicFilterKind] = [.any(filters: [.all(filters: [.nonSpace, .nonLeft]),
|
||||||
[.any(filters: [.all(filters: [.nonSpace, .nonLeft]),
|
.all(filters: [.space, .invite])]),
|
||||||
.all(filters: [.space, .invite])]),
|
.deduplicateVersions]
|
||||||
.deduplicateVersions]
|
|
||||||
} else {
|
|
||||||
// Don't show space invites on iOS 17 given that the tab bar is disabled due to glitches on iPad.
|
|
||||||
[.nonLeft, .nonSpace, .deduplicateVersions]
|
|
||||||
}
|
|
||||||
|
|
||||||
switch filter {
|
switch filter {
|
||||||
case .excludeAll:
|
case .excludeAll:
|
||||||
|
|||||||
@@ -123,12 +123,12 @@ public struct ListRow<Icon: View, DetailsIcon: View, CustomContent: View, Select
|
|||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
RowContent(details: details, accessory: .selection(isSelected)) { label }
|
RowContent(details: details, accessory: .selection(isSelected)) { label }
|
||||||
}
|
}
|
||||||
.isToggle()
|
.accessibilityAddTraits(.isToggle)
|
||||||
case .multiSelection(let isSelected, let action):
|
case .multiSelection(let isSelected, let action):
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
RowContent(details: details, accessory: .multiSelection(isSelected)) { label }
|
RowContent(details: details, accessory: .multiSelection(isSelected)) { label }
|
||||||
}
|
}
|
||||||
.isToggle()
|
.accessibilityAddTraits(.isToggle)
|
||||||
case .textField(let text, let axis):
|
case .textField(let text, let axis):
|
||||||
TextField(text: text, axis: axis) {
|
TextField(text: text, axis: axis) {
|
||||||
Text(label.title ?? "")
|
Text(label.title ?? "")
|
||||||
@@ -259,17 +259,6 @@ private extension TextField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Button {
|
|
||||||
/// Adds the `isToggle` accessibility trait on iOS 17+
|
|
||||||
@ViewBuilder func isToggle() -> some View {
|
|
||||||
if #available(iOS 17.0, *) {
|
|
||||||
accessibilityAddTraits(.isToggle)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
// swiftlint:disable print_deprecation
|
// swiftlint:disable print_deprecation
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ options:
|
|||||||
groupSortPosition: bottom
|
groupSortPosition: bottom
|
||||||
createIntermediateGroups: true
|
createIntermediateGroups: true
|
||||||
deploymentTarget:
|
deploymentTarget:
|
||||||
iOS: '17.5'
|
iOS: '18.5'
|
||||||
macOS: '14.5'
|
macOS: '14.5'
|
||||||
groupOrdering:
|
groupOrdering:
|
||||||
- order:
|
- order:
|
||||||
|
|||||||
Reference in New Issue
Block a user