Run SwiftFormat.

This commit is contained in:
Doug
2026-05-27 14:38:50 +01:00
committed by Doug
parent 5138e05e47
commit fa67713726
573 changed files with 2426 additions and 2426 deletions
@@ -48,7 +48,7 @@ final class AppLockScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(AppLockScreen(context: viewModel.context))
}
@@ -30,12 +30,12 @@ struct AppLockScreenViewState: BindableState {
var numberOfDigitsEntered: Int {
bindings.pinCode.count
}
/// Whether the subtitle is in a warning state or not.
var isSubtitleWarning: Bool {
numberOfPINAttempts > 0
}
/// The string shown in the screen's subtitle.
var subtitle: String {
if !isSubtitleWarning {
@@ -18,7 +18,7 @@ class AppLockScreenViewModel: AppLockScreenViewModelType, AppLockScreenViewModel
var actions: AnyPublisher<AppLockScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(appLockService: AppLockServiceProtocol) {
self.appLockService = appLockService
@@ -42,7 +42,7 @@ final class AppLockSetupBiometricsScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(AppLockSetupBiometricsScreen(context: viewModel.context))
}
@@ -20,11 +20,11 @@ struct AppLockSetupBiometricsScreenViewState: BindableState {
var icon: SFSymbol {
biometryType.systemSymbol
}
var title: String {
L10n.screenAppLockSetupBiometricUnlockAllowTitle(biometryType.localizedString)
}
var subtitle: String {
L10n.screenAppLockSetupBiometricUnlockSubtitle(biometryType.localizedString)
}
@@ -18,7 +18,7 @@ class AppLockSetupBiometricsScreenViewModel: AppLockSetupBiometricsScreenViewMod
var actions: AnyPublisher<AppLockSetupBiometricsScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(appLockService: AppLockServiceProtocol) {
self.appLockService = appLockService
super.init(initialViewState: AppLockSetupBiometricsScreenViewState(biometryType: appLockService.biometryType))
@@ -60,7 +60,7 @@ final class AppLockSetupPINScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(AppLockSetupPINScreen(context: viewModel.context))
}
@@ -53,7 +53,7 @@ struct AppLockSetupPINScreenViewState: BindableState {
var isSubtitleWarning: Bool {
mode == .unlock && numberOfUnlockAttempts > 0
}
var subtitle: String {
guard mode == .unlock else { return L10n.screenAppLockSetupPinContext(InfoPlistReader.main.bundleDisplayName) }
if !isSubtitleWarning {
@@ -21,7 +21,7 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
var actions: AnyPublisher<AppLockSetupPINScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(initialMode: AppLockSetupPINScreenMode, isMandatory: Bool, appLockService: AppLockServiceProtocol) {
self.appLockService = appLockService
@@ -103,7 +103,7 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
return
}
}
actionsSubject.send(.complete)
}
@@ -45,7 +45,7 @@ final class AppLockSetupSettingsScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(AppLockSetupSettingsScreen(context: viewModel.context))
}
@@ -25,7 +25,7 @@ struct AppLockSetupSettingsScreenViewState: BindableState {
var supportsBiometrics: Bool {
biometryType != .none
}
var enableBiometricsTitle: String {
L10n.screenAppLockSetupBiometricUnlockAllowTitle(biometryType.localizedString)
}
@@ -30,11 +30,11 @@ enum LoginScreenCoordinatorAction {
final class LoginScreenCoordinator: CoordinatorProtocol {
private let parameters: LoginScreenCoordinatorParameters
private var viewModel: LoginScreenViewModelProtocol
private var authenticationService: AuthenticationServiceProtocol {
parameters.authenticationService
}
private let actionsSubject: PassthroughSubject<LoginScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
@@ -55,7 +55,7 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
}
// MARK: - Public
func start() {
viewModel.actions
.sink { [weak self] action in
@@ -70,7 +70,7 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func stop() {
viewModel.stopLoading()
}
@@ -21,7 +21,7 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc
var actions: AnyPublisher<LoginScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(authenticationService: AuthenticationServiceProtocol,
loginHint: String?,
userIndicatorController: UserIndicatorControllerProtocol,
@@ -48,7 +48,7 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc
.weakAssign(to: \.state.homeserver, on: self)
.store(in: &cancellables)
}
override func process(viewAction: LoginScreenViewAction) {
switch viewAction {
case .parseUsername:
@@ -92,7 +92,7 @@ struct LoginScreen: View {
.onSubmit(submit)
Spacer().frame(height: 32)
Button(action: submit) {
Text(L10n.actionContinue)
}
@@ -139,7 +139,7 @@ class OAuthAuthenticationPresenter: NSObject {
private var loadingIndicatorID: String {
"\(Self.self)-Loading"
}
private var failureIndicatorID: String {
"\(Self.self)-Failure"
}
@@ -60,7 +60,7 @@ final class ServerConfirmationScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(ServerConfirmationScreen(context: viewModel.context))
}
@@ -52,7 +52,7 @@ struct ServerConfirmationScreenViewState: BindableState {
/// The message shown beneath the title.
var message: String? {
guard case let .confirmation(homeserverAddress) = mode else { return nil }
return switch authenticationFlow {
case .login:
if homeserverAddress == "matrix.org" {
@@ -22,7 +22,7 @@ class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType,
var actions: AnyPublisher<ServerConfirmationScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(authenticationService: AuthenticationServiceProtocol,
mode: ServerConfirmationScreenMode,
authenticationFlow: AuthenticationFlow,
@@ -30,7 +30,7 @@ final class ServerSelectionScreenCoordinator: CoordinatorProtocol {
private var authenticationService: AuthenticationServiceProtocol {
parameters.authenticationService
}
private let actionsSubject: PassthroughSubject<ServerSelectionScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
@@ -22,7 +22,7 @@ class ServerSelectionScreenViewModel: ServerSelectionScreenViewModelType, Server
var actions: AnyPublisher<ServerSelectionScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(authenticationService: AuthenticationServiceProtocol,
authenticationFlow: AuthenticationFlow,
appSettings: AppSettings,
@@ -20,7 +20,7 @@ enum MockSoftLogoutScreenState: String, CaseIterable {
case oAuth
case unsupported
case keyBackupNeeded
/// Generate the view struct for the screen state.
@MainActor var viewModel: SoftLogoutScreenViewModel {
let credentials = SoftLogoutScreenCredentials(userID: "@mock:matrix.org",
@@ -46,7 +46,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
private var authenticationService: AuthenticationServiceProtocol {
parameters.authenticationService
}
private var oAuthPresenter: OAuthAuthenticationPresenter?
var actions: AnyPublisher<SoftLogoutScreenCoordinatorResult, Never> {
@@ -69,7 +69,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
.sink { [weak self] action in
guard let self else { return }
MXLog.info("Did complete with result: \(action).")
switch action {
case .login(let password):
login(withPassword: password)
@@ -117,18 +117,18 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
@MainActor private func stopLoading() {
parameters.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
/// Shows the forgot password screen.
@MainActor private func showForgotPasswordScreen() {
viewModel.displayError(.alert("Not implemented."))
}
/// Login with the supplied username and password.
@MainActor private func login(withPassword password: String) {
let username = parameters.credentials.userID
startLoading()
Task {
switch await authenticationService.login(username: username,
password: password,
@@ -143,7 +143,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
}
}
}
private func continueWithOAuth(presentationAnchor: UIWindow?) {
guard let presentationAnchor else { return }
@@ -174,7 +174,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
}
}
}
/// Processes an error to either update the flow or display it to the user.
private func handleError(_ error: AuthenticationServiceError) {
switch error {
@@ -43,16 +43,16 @@ enum SoftLogoutScreenViewModelAction: CustomStringConvertible {
struct SoftLogoutScreenViewState: BindableState {
/// Soft logout credentials
var credentials: SoftLogoutScreenCredentials
/// Data about the selected homeserver.
var homeserver: LoginHomeserver
/// Flag indicating soft logged out user needs backup for some keys
var keyBackupNeeded: Bool
/// View state that can be bound to from SwiftUI.
var bindings: SoftLogoutScreenBindings
/// The types of login supported by the homeserver.
var loginMode: LoginMode {
homeserver.loginMode
@@ -60,12 +60,12 @@ struct SoftLogoutScreenViewState: BindableState {
/// The presentation anchor used for OAuth authentication.
var window: UIWindow?
/// Whether to show recover encryption keys message
var showRecoverEncryptionKeysMessage: Bool {
keyBackupNeeded
}
/// `true` when valid credentials have been entered and a homeserver has been loaded.
var canSubmit: Bool {
!bindings.password.isEmpty
@@ -17,7 +17,7 @@ class SoftLogoutScreenViewModel: SoftLogoutScreenViewModelType, SoftLogoutScreen
var actions: AnyPublisher<SoftLogoutScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(credentials: SoftLogoutScreenCredentials,
homeserver: LoginHomeserver,
keyBackupNeeded: Bool,
@@ -45,7 +45,7 @@ class SoftLogoutScreenViewModel: SoftLogoutScreenViewModelType, SoftLogoutScreen
Task { state.window = window }
}
}
@MainActor func displayError(_ type: SoftLogoutScreenErrorType) {
switch type {
case .alert(let message):
@@ -10,10 +10,10 @@ import SwiftUI
struct SoftLogoutScreen: View {
@State private var showingClearDataConfirmation = false
/// The focus state of the password text field.
@FocusState private var isPasswordFocused: Bool
@Bindable var context: SoftLogoutScreenViewModel.Context
var body: some View {
@@ -22,7 +22,7 @@ struct SoftLogoutScreen: View {
header
.padding(.top, UIConstants.titleTopPaddingToNavigationBar)
.padding(.bottom, 36)
switch context.viewState.loginMode {
case .password:
loginForm
@@ -31,7 +31,7 @@ struct SoftLogoutScreen: View {
default:
loginUnavailableText
}
clearDataForm
.padding(.top, 16)
}
@@ -45,7 +45,7 @@ struct SoftLogoutScreen: View {
context.send(viewAction: .updateWindow(window))
}
}
/// The title, message and icon at the top of the screen.
var header: some View {
VStack(alignment: .leading, spacing: 16) {
@@ -54,13 +54,13 @@ struct SoftLogoutScreen: View {
.multilineTextAlignment(.leading)
.foregroundColor(.compound.textPrimary)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.title)
Text(UntranslatedL10n.softLogoutSigninNotice(context.viewState.credentials.homeserverName, context.viewState.credentials.userDisplayName, context.viewState.credentials.userID))
.font(.compound.bodyLG)
.multilineTextAlignment(.leading)
.foregroundColor(.compound.textPrimary)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.message)
if context.viewState.showRecoverEncryptionKeysMessage {
Text(UntranslatedL10n.softLogoutSigninE2eWarningNotice)
.font(.compound.bodyLG)
@@ -69,7 +69,7 @@ struct SoftLogoutScreen: View {
}
}
}
/// The form with text fields for username and password, along with a submit button.
var loginForm: some View {
VStack(spacing: 14) {
@@ -80,7 +80,7 @@ struct SoftLogoutScreen: View {
.submitLabel(.done)
.onSubmit(submit)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.password)
Button { context.send(viewAction: .forgotPassword) } label: {
Text(L10n.actionForgotPassword)
.font(.compound.bodyLG)
@@ -88,7 +88,7 @@ struct SoftLogoutScreen: View {
.frame(maxWidth: .infinity, alignment: .trailing)
.padding(.bottom, 8)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.forgotPassword)
Button(action: submit) {
Text(L10n.actionNext)
}
@@ -97,7 +97,7 @@ struct SoftLogoutScreen: View {
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.next)
}
}
/// The OAuth button that can be used for login.
var oAuthButton: some View {
Button { context.send(viewAction: .continueWithOAuth) } label: {
@@ -105,7 +105,7 @@ struct SoftLogoutScreen: View {
}
.buttonStyle(.compound(.primary))
}
/// Text shown if neither password or OAuth login is supported.
var loginUnavailableText: some View {
Text(L10n.screenLoginErrorUnsupportedAuthentication)
@@ -114,7 +114,7 @@ struct SoftLogoutScreen: View {
.foregroundColor(.compound.textPrimary)
.frame(maxWidth: .infinity)
}
/// The text field and submit button where the user enters an email address.
var clearDataForm: some View {
VStack(alignment: .leading, spacing: 12) {
@@ -123,14 +123,14 @@ struct SoftLogoutScreen: View {
.multilineTextAlignment(.leading)
.foregroundColor(.compound.textPrimary)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearDataTitle)
Text(UntranslatedL10n.softLogoutClearDataNotice)
.font(.compound.bodyLG)
.multilineTextAlignment(.leading)
.foregroundColor(.compound.textPrimary)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearDataMessage)
.padding(.bottom, 12)
Button(role: .destructive, action: clearData) {
Text(UntranslatedL10n.softLogoutClearDataSubmit)
}
@@ -146,13 +146,13 @@ struct SoftLogoutScreen: View {
}
}
}
/// Sends the `login` view action so long as a valid email address has been input.
func submit() {
guard context.viewState.canSubmit else { return }
context.send(viewAction: .login)
}
/// Sends the `clearAllData` view action.
func clearData() {
context.send(viewAction: .clearAllData)
@@ -167,7 +167,7 @@ struct SoftLogoutScreen_Previews: PreviewProvider, TestablePreview {
screen(for: state.viewModel)
}
}
static func screen(for viewModel: SoftLogoutScreenViewModel) -> some View {
ElementNavigationStack {
SoftLogoutScreen(context: viewModel.context)
@@ -64,12 +64,12 @@ final class AuthenticationStartScreenCoordinator: CoordinatorProtocol {
actionsSubject.send(.login)
case .register:
actionsSubject.send(.register)
case .loginDirectlyWithOAuth(let data, let window):
actionsSubject.send(.loginDirectlyWithOAuth(data: data, window: window))
case .loginDirectlyWithPassword(let loginHint):
actionsSubject.send(.loginDirectlyWithPassword(loginHint: loginHint))
case .reportProblem:
actionsSubject.send(.reportProblem)
case .developerOptions:
@@ -89,14 +89,14 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType
}
case .developerOptions:
actionsSubject.send(.developerOptions)
case .loginWithQR:
actionsSubject.send(.loginWithQR)
case .login:
Task { await login() }
case .register:
actionsSubject.send(.register)
case .continueWithClassic(let account):
Task { await login(classicAppAccount: account) }
case .otherOptions(let account):
@@ -65,12 +65,12 @@ private struct AuthenticationBrandLogoModifier: ViewModifier {
private var isLight: Bool {
colorScheme == .light
}
/// Extra padding needed to avoid cropping the shadows.
private var extra: CGFloat {
64 * scale
}
/// The shape that the logo is composed on top of.
private var outerShape: RoundedRectangle {
RoundedRectangle(cornerRadius: 44 * scale)
@@ -21,7 +21,7 @@ enum UIConstants {
/// The padding used to the top of the view for breaker screens that don't have a navigation bar.
static let startScreenBreakerScreenTopPadding: CGFloat = 80
/// The height to use for top/bottom spacers to pad the views to fit the `maxContentHeight`.
static func spacerHeight(in geometry: GeometryProxy) -> CGFloat {
max(0, (geometry.size.height - maxContentHeight) / 2)
@@ -27,7 +27,7 @@ final class BlockedUsersScreenCoordinator: CoordinatorProtocol {
func stop() {
viewModel.stop()
}
func toPresentable() -> AnyView {
AnyView(BlockedUsersScreen(context: viewModel.context))
}
@@ -15,7 +15,7 @@ class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsers
let hideProfiles: Bool
let clientProxy: ClientProxyProtocol
let userIndicatorController: UserIndicatorControllerProtocol
init(hideProfiles: Bool,
userSession: UserSessionProtocol,
userIndicatorController: UserIndicatorControllerProtocol) {
@@ -69,7 +69,7 @@ final class BugReportScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func stop() {
stopLoading()
}
@@ -20,7 +20,7 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie
private let actionsSubject: PassthroughSubject<BugReportScreenViewModelAction, Never> = .init()
// periphery:ignore - when set to nil this is automatically cancelled
@CancellableTask private var uploadTask: Task<Void, Never>?
var actions: AnyPublisher<BugReportScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
@@ -79,7 +79,7 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie
}
return true
}
private func submitBugReport() async {
let progressSubject = CurrentValueSubject<Double, Never>(0.0)
@@ -18,7 +18,7 @@ struct BugReportScreen: View {
var canSendLogFiles: Bool {
context.viewState.canSendLogFiles
}
var photosPickerTitle: String {
context.viewState.screenshot == nil ? L10n.screenBugReportAttachScreenshot : L10n.screenBugReportEditScreenshot
}
@@ -82,7 +82,7 @@ struct BugReportScreen: View {
}
}
}
private var canContactSection: some View {
Section {
ListRow(label: .plain(title: L10n.screenBugReportContactMeTitle),
@@ -93,7 +93,7 @@ struct BugReportScreen: View {
.compoundListSectionFooter()
}
}
private var attachScreenshotSection: some View {
Section {
ListRow(kind: .custom {
@@ -70,7 +70,7 @@ final class CallScreenCoordinator: CoordinatorProtocol {
func stop() {
viewModel.stop()
}
func toPresentable() -> AnyView {
AnyView(CallScreen(context: viewModel.context))
}
@@ -29,7 +29,7 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
@CancellableTask
private var timeoutTask: Task<Void, Never>?
/// Designated initialiser
/// - Parameters:
/// - elementCallService: service responsible for setting up CallKit
@@ -140,7 +140,7 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
}
// MARK: - Private
private func handleWidgetAction(message: String) async {
if timeoutTask != nil,
let decodedMessage = try? DecodedWidgetMessage.decode(message: message),
@@ -196,7 +196,7 @@ private struct CallView: UIViewRepresentable {
guard let body = message.body as? [String: String],
let level = body["level"],
let logMessage = body["message"] else { return }
switch level {
case "log", "debug":
MXLog.debug("[ElementCall]: \(logMessage)")
@@ -363,7 +363,7 @@ struct CallScreen_Previews: PreviewProvider {
widgetDriver.startBaseURLClientIDColorSchemeVoiceOnlyRageshakeURLAnalyticsConfigurationReturnValue = .success(URL.userDirectory)
roomProxy.elementCallWidgetDriverDeviceIDReturnValue = widgetDriver
return CallScreenViewModel(elementCallService: ElementCallServiceMock(.init()),
configuration: .init(roomProxy: roomProxy,
clientProxy: clientProxy,
@@ -14,12 +14,12 @@ struct ChatsSpaceFilterCell: View {
let filter: SpaceServiceFilter
let mediaProvider: MediaProviderProtocol!
private let verticalInsets = 12.0
private let horizontalInsets = 16.0
let action: (SpaceServiceFilter) -> Void
var body: some View {
Button {
action(filter)
@@ -51,7 +51,7 @@ final class PollFormScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(PollFormScreen(context: viewModel.context))
}
@@ -65,7 +65,7 @@ struct PollFormScreenViewState: BindableState {
case .edit(_, let poll):
initialBindings = .init(poll: poll)
}
return bindings != initialBindings
}
}
@@ -79,16 +79,16 @@ struct PollFormScreenViewStateBindings: Equatable {
var question = ""
var options: [Option] = [.init(), .init()]
var isUndisclosed = false
struct Option: Identifiable, Equatable {
let id = UUID()
var text = ""
}
var hasValidContent: Bool {
!question.isEmpty && options.count >= 2 && options.allSatisfy { !$0.text.isEmpty }
}
var alertInfo: AlertInfo<UUID>?
static func == (lhs: PollFormScreenViewStateBindings, rhs: PollFormScreenViewStateBindings) -> Bool {
@@ -62,7 +62,7 @@ final class CreateRoomScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(CreateRoomScreen(context: viewModel.context))
}
@@ -51,7 +51,7 @@ struct CreateRoomScreenViewState: BindableState {
var canCreateRoom: Bool {
!roomName.isEmpty && aliasErrors.isEmpty
}
var aliasErrors: Set<CreateRoomScreenAliasErrorState> = []
var aliasErrorDescription: String? {
if aliasErrors.contains(.alreadyExists) {
@@ -62,7 +62,7 @@ struct CreateRoomScreenViewState: BindableState {
nil
}
}
var availableAccessTypes: [CreateRoomScreenAccessType] {
var availableAccessTypes: [CreateRoomScreenAccessType] = []
if isSpace {
@@ -58,7 +58,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
let bindings = CreateRoomScreenViewStateBindings(roomTopic: "",
selectedAccessType: selectedAccessType,
selectedSpace: selectedSpace)
super.init(initialViewState: CreateRoomScreenViewState(isSpace: isSpace,
shouldShowCancelButton: shouldShowCancelButton,
roomName: "",
@@ -137,7 +137,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
}
// MARK: - Private
private func setupBindings() {
// Reset the state related to public rooms if the user choses the room to be empty
context.$viewState
@@ -12,7 +12,7 @@ import SwiftUI
struct CreateRoomScreen: View {
@ObservedObject var context: CreateRoomScreenViewModel.Context
@FocusState private var focus: Focus?
private enum Focus {
case name
case topic
@@ -380,7 +380,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
viewModel.context.selectedAccessType = .askToJoinWithSpaceMembers
return viewModel
}()
static var previews: some View {
ElementNavigationStack {
CreateRoomScreen(context: viewModel.context)
@@ -455,7 +455,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
let spaces = [SpaceServiceRoom].mockJoinedSpaces2
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: spaces))
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
return CreateRoomScreenViewModel(isSpace: isSpace,
spaceSelectionMode: selectionMode,
shouldShowCancelButton: isSpace,
@@ -66,9 +66,9 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview
let clientProxy = ClientProxyMock(.init(userID: "@userid:example.com"))
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2))
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let appSettings = AppSettings.volatile()
return CreateRoomScreenViewModel(isSpace: false,
spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil),
shouldShowCancelButton: false,
@@ -27,7 +27,7 @@ final class DeclineAndBlockScreenCoordinator: CoordinatorProtocol {
private let viewModel: DeclineAndBlockScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<DeclineAndBlockScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<DeclineAndBlockScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -54,7 +54,7 @@ final class DeclineAndBlockScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(DeclineAndBlockScreen(context: viewModel.context))
}
@@ -21,7 +21,7 @@ class DeclineAndBlockScreenViewModel: DeclineAndBlockScreenViewModelType, Declin
var actionsPublisher: AnyPublisher<DeclineAndBlockScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(userID: String,
roomID: String,
clientProxy: ClientProxyProtocol,
@@ -25,7 +25,7 @@ final class EditRoomAddressScreenCoordinator: CoordinatorProtocol {
private let viewModel: EditRoomAddressScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<EditRoomAddressScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<EditRoomAddressScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -49,7 +49,7 @@ final class EditRoomAddressScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(EditRoomAddressScreen(context: viewModel.context))
}
@@ -23,7 +23,7 @@ class EditRoomAddressScreenViewModel: EditRoomAddressScreenViewModelType, EditRo
}
@CancellableTask private var checkAliasAvailabilityTask: Task<Void, Never>?
init(initialViewState: EditRoomAddressScreenViewState? = nil,
roomProxy: JoinedRoomProxyProtocol,
clientProxy: ClientProxyProtocol,
@@ -169,7 +169,7 @@ class EditRoomAddressScreenViewModel: EditRoomAddressScreenViewModelType, EditRo
if savedCanonicalAlias == nil || savedCanonicalAlias?.hasSuffix(state.serverName) == true {
var newAlternativeAliases = roomProxy.infoPublisher.value.alternativeAliases
newAlternativeAliases.removeAll { $0 == savedAliasFromHomeserver }
if case .failure = await roomProxy.updateCanonicalAlias(desiredCanonicalAlias, altAliases: newAlternativeAliases) {
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
return
@@ -47,7 +47,7 @@ class EmojiPickerScreenViewModel: EmojiPickerScreenViewModelType, EmojiPickerScr
}
// MARK: - Private
private func loadEmojis() {
Task(priority: .userInitiated) { [weak self] in
guard let self else { return }
@@ -22,7 +22,7 @@ final class EncryptionResetPasswordScreenCoordinator: CoordinatorProtocol {
private let viewModel: EncryptionResetPasswordScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<EncryptionResetPasswordScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<EncryptionResetPasswordScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -46,7 +46,7 @@ final class EncryptionResetPasswordScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(EncryptionResetPasswordScreen(context: viewModel.context))
}
@@ -18,7 +18,7 @@ class EncryptionResetPasswordScreenViewModel: EncryptionResetPasswordScreenViewM
var actionsPublisher: AnyPublisher<EncryptionResetPasswordScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(passwordPublisher: PassthroughSubject<String, Never>) {
self.passwordPublisher = passwordPublisher
@@ -26,7 +26,7 @@ final class EncryptionResetScreenCoordinator: CoordinatorProtocol {
private let viewModel: EncryptionResetScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<EncryptionResetScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<EncryptionResetScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -60,7 +60,7 @@ final class EncryptionResetScreenCoordinator: CoordinatorProtocol {
func stop() {
viewModel.stop()
}
func toPresentable() -> AnyView {
AnyView(EncryptionResetScreen(context: viewModel.context))
}
@@ -35,7 +35,7 @@ struct EncryptionResetScreenViewState: BindableState {
AttributedString(L10n.screenCreateNewRecoveryKeyListItem5)
]
}
var bindings: EncryptionResetScreenViewStateBindings
}
@@ -23,7 +23,7 @@ class EncryptionResetScreenViewModel: EncryptionResetScreenViewModelType, Encryp
private var identityResetHandle: IdentityResetHandle?
private var passwordCancellable: AnyCancellable?
init(clientProxy: ClientProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol) {
self.clientProxy = clientProxy
self.userIndicatorController = userIndicatorController
@@ -69,7 +69,7 @@ struct EncryptionResetScreen: View {
.frame(maxWidth: .infinity)
.environment(\.backgroundStyle, AnyShapeStyle(.compound.bgSubtleSecondary))
}
private func checkMarkItem(title: String, position: ListPosition, positive: Bool) -> some View {
VisualListItem(title: title, position: position) {
CompoundIcon(positive ? \.check : \.info)
@@ -43,14 +43,14 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
let allowEditing: Bool
let dismissalPublisher: PassthroughSubject<Void, Never>
let onDismiss: () -> Void
func makeUIViewController(context: Context) -> PreviewHostingController {
PreviewHostingController(previewItem: previewItem,
allowEditing: allowEditing,
dismissalPublisher: dismissalPublisher,
onDismiss: onDismiss)
}
func updateUIViewController(_ uiViewController: PreviewHostingController, context: Context) { }
/// A view controller that hosts the QuickLook preview.
@@ -66,7 +66,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
private var dismissalObserver: AnyCancellable?
var previewController: QLPreviewController?
init(previewItem: MediaPreviewItem,
allowEditing: Bool,
dismissalPublisher: PassthroughSubject<Void, Never>,
@@ -74,7 +74,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
self.previewItem = previewItem
self.allowEditing = allowEditing
self.onDismiss = onDismiss
super.init(nibName: nil, bundle: nil)
// The QLPreviewController will not automatically dismiss itself when the underlying view is removed
@@ -128,7 +128,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
previewItem
}
@@ -156,9 +156,9 @@ class MediaPreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL? {
file.url
}
let previewItemTitle: String?
init(file: MediaFileHandleProxy, title: String?) {
self.file = file
previewItemTitle = title
@@ -117,7 +117,7 @@ class TimelineMediaPreviewDataSource: NSObject, QLPreviewControllerDataSource {
var firstPreviewItemIndex: Int {
backwardPadding
}
var lastPreviewItemIndex: Int {
backwardPadding + previewItems.count - 1
}
@@ -276,11 +276,11 @@ enum TimelineMediaPreviewItem: Equatable {
var caption: String? {
timelineItem.mediaCaption
}
var formattedCaption: AttributedString? {
timelineItem.formattedMediaCaption
}
var contentType: String? {
switch timelineItem {
case let audioItem as AudioRoomTimelineItem:
@@ -59,7 +59,7 @@ struct TimelineMediaPreviewViewState: BindableState {
var currentItem: TimelineMediaPreviewItem {
dataSource.currentItem
}
/// All of the available actions for the current item.
var currentItemActions: TimelineItemMenuActions?
@@ -41,13 +41,13 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
let viewModel: TimelineMediaPreviewViewModel
let dismissalPublisher: PassthroughSubject<Void, Never>
let onDismiss: () -> Void
func makeUIViewController(context: Context) -> PreviewHostingController {
PreviewHostingController(viewModel: viewModel,
dismissalPublisher: dismissalPublisher,
onDismiss: onDismiss)
}
func updateUIViewController(_ uiViewController: PreviewHostingController, context: Context) { }
/// A view controller that hosts the QuickLook preview.
@@ -69,7 +69,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
onDismiss: @escaping () -> Void) {
self.onDismiss = onDismiss
previewController = TimelineMediaPreviewController(context: viewModel.context)
super.init(nibName: nil, bundle: nil)
// The QLPreviewController will not automatically dismiss itself when the underlying view is removed
@@ -27,7 +27,7 @@ class TimelineMediaPreviewController: QLPreviewController {
private var navigationBar: UINavigationBar? {
view.subviews.first?.subviews.first { $0 is UINavigationBar } as? UINavigationBar
}
private var bottomBarItemsContainer: UIView? {
if #available(iOS 26, *) {
view.subviews.first?.subviews.last?.subviews.first
@@ -35,11 +35,11 @@ class TimelineMediaPreviewController: QLPreviewController {
view.subviews.first?.subviews.last { $0 is UIToolbar }
}
}
private var pageScrollView: UIScrollView? {
view.firstScrollView()
}
private var captionView: UIView {
captionHostingController.view
}
@@ -316,7 +316,7 @@ private struct CaptionView: View {
private var currentItem: TimelineMediaPreviewItem {
context.viewState.currentItem
}
var body: some View {
if case let .media(mediaItem) = currentItem, mediaItem.hasCaption {
CaptionScrollView(mediaItem: mediaItem)
@@ -361,7 +361,7 @@ private struct CaptionScrollView: View {
.ignoresSafeArea()
}
}
@ViewBuilder
private var captionContent: some View {
if let formattedCaption = mediaItem.formattedCaption {
@@ -15,7 +15,7 @@ struct TimelineMediaPreviewRedactConfirmationView: View {
let item: TimelineMediaPreviewItem.Media
@ObservedObject var context: TimelineMediaPreviewViewModel.Context
var preferredColorScheme: ColorScheme? = .dark
@State private var sheetHeight: CGFloat = .zero
private let topPadding: CGFloat = 19
@@ -74,12 +74,12 @@ struct TimelineMediaPreviewRedactConfirmationView: View {
.clipShape(RoundedRectangle(cornerRadius: 8))
.accessibilityHidden(true)
}
VStack(alignment: .leading, spacing: 4) {
Text(item.filename ?? "")
.font(.compound.bodyMD)
.foregroundStyle(.compound.textPrimary)
if let contentType = item.contentType {
Group {
if let fileSize = item.fileSize {
@@ -18,7 +18,7 @@ class GlobalSearchScreenViewModel: GlobalSearchScreenViewModelType, GlobalSearch
var actions: AnyPublisher<GlobalSearchScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(roomSummaryProvider: RoomSummaryProviderProtocol,
mediaProvider: MediaProviderProtocol) {
self.roomSummaryProvider = roomSummaryProvider
@@ -134,7 +134,7 @@ private struct GlobalSearchTextFieldRepresentable: UIViewRepresentable {
@Binding var text: String
let keyPressHandler: (UIKeyboardHIDUsage) -> Bool
let endEditingHandler: () -> Void
func makeUIView(context: Context) -> UITextField {
let textField = GlobalSearchTextField(keyPressHandler: keyPressHandler)
textField.delegate = context.coordinator
@@ -142,15 +142,15 @@ private struct GlobalSearchTextFieldRepresentable: UIViewRepresentable {
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(text: $text, endEditingHandler: endEditingHandler)
}
class Coordinator: NSObject, UITextFieldDelegate {
var text: Binding<String>
let endEditingHandler: () -> Void
@@ -188,7 +188,7 @@ private class GlobalSearchTextField: UITextField {
self.keyPressHandler = keyPressHandler
super.init(frame: .zero)
}
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
guard let key = presses.first?.key else {
super.pressesBegan(presses, with: event)
@@ -98,12 +98,12 @@ struct HomeScreenViewState: BindableState {
var shouldShowNewSoundBanner = false
var requiresExtraAccountSetup = false
var rooms: [HomeScreenRoom] = []
var roomListMode: HomeScreenRoomListMode = .skeletons
var hasPendingInvitations = false
var selectedRoomID: String?
var hideInviteAvatars = false
@@ -111,7 +111,7 @@ struct HomeScreenViewState: BindableState {
var roomListActivityVisibility: RoomListActivityVisibility = .current
var reportRoomEnabled = false
var shouldShowSpaceFilters = false
var selectedSpaceFilter: SpaceServiceFilter?
@@ -122,7 +122,7 @@ struct HomeScreenViewState: BindableState {
return rooms
}
var bindings: HomeScreenViewStateBindings
var placeholderRooms: [HomeScreenRoom] {
@@ -175,7 +175,7 @@ struct HomeScreenRoom: Identifiable, Equatable {
}
static let placeholderLastMessage = AttributedString("Hidden last message")
/// The list item identifier is it's room identifier.
let id: String
@@ -217,7 +217,7 @@ struct HomeScreenRoom: Identifiable, Equatable {
let lastMessageState: LastMessageState?
let avatar: RoomAvatar
let canonicalAlias: String?
let isTombstoned: Bool
@@ -354,7 +354,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
}
}
}
private func updateRooms() {
guard let roomSummaryProvider else {
MXLog.error("Room summary provider unavailable")
@@ -11,7 +11,7 @@ import SwiftUI
struct RoomListFilterView: View {
let filter: RoomListFilter
@Binding var isActive: Bool
var body: some View {
Toggle(isOn: $isActive) {
Text(filter.localizedName)
@@ -37,7 +37,7 @@ struct RoomListFiltersEmptyStateView: View {
}
return L10n.screenRoomlistFilterMixedEmptyStateSubtitle
}
var body: some View {
VStack(spacing: 24) {
Text(emptyStateTitle)
@@ -49,7 +49,7 @@ struct HomeScreen: View {
L10n.screenRoomlistMainSpaceTitle
}
}
@ToolbarContentBuilder
private var toolbar: some ToolbarContent {
ToolbarItem(placement: .navigationBarLeading) {
@@ -70,7 +70,7 @@ struct HomeScreen: View {
if #available(iOS 26, *) {
ToolbarSpacer(.fixed, placement: .primaryAction)
}
ToolbarItem(placement: .primaryAction) {
SpaceFiltersButton(selected: context.viewState.selectedSpaceFilter != nil) {
context.send(viewAction: .spaceFilters)
@@ -221,7 +221,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
roomSummaryProvider: RoomSummaryProviderMock(.init(state: roomSummaryProviderState))))
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: .volatile(),
@@ -79,7 +79,7 @@ struct HomeScreenEmptyStateLayout: Layout {
// Place the main view in the center if there is space, otherwise add it to the stack.
guard let mainView else { return }
let mainViewSize = mainView.sizeThatFits(proposal)
if (y + mainViewSize.height / 2) < bounds.height / 2 {
let center = CGPoint(x: bounds.midX, y: bounds.midY)
@@ -134,7 +134,7 @@ struct HomeScreenInviteCell: View {
.fill(Color.compound.borderDisabled)
.frame(height: 1 / UIScreen.main.scale)
}
private var title: String {
room.name
}
@@ -199,7 +199,7 @@ struct HomeScreenInviteCell_Previews: PreviewProvider, TestablePreview {
let clientProxy = ClientProxyMock(.init())
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: .volatile(),
@@ -46,7 +46,7 @@ struct HomeScreenKnockedCell: View {
}
// MARK: - Private
private var mainContent: some View {
VStack(alignment: .leading, spacing: 0) {
VStack(alignment: .leading, spacing: 0) {
@@ -86,7 +86,7 @@ struct HomeScreenKnockedCell: View {
.fill(Color.compound.borderDisabled)
.frame(height: 1 / UIScreen.main.scale)
}
private var title: String {
room.name
}
@@ -131,7 +131,7 @@ struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview {
let clientProxy = ClientProxyMock(.init())
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: .volatile(),
@@ -21,21 +21,21 @@ struct HomeScreenRecoveryKeyConfirmationBanner: View {
case .recoveryOutOfSync: L10n.confirmRecoveryKeyBannerTitle
}
}
var message: String {
switch state {
case .setUpRecovery: L10n.bannerSetUpRecoveryContent
case .recoveryOutOfSync: L10n.confirmRecoveryKeyBannerMessage
}
}
var actionTitle: String {
switch state {
case .setUpRecovery: L10n.bannerSetUpRecoverySubmit
case .recoveryOutOfSync: L10n.confirmRecoveryKeyBannerPrimaryButtonTitle
}
}
var primaryAction: HomeScreenViewAction {
switch state {
case .setUpRecovery: .setupRecovery
@@ -119,7 +119,7 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loading))))
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: .volatile(),
@@ -140,7 +140,7 @@ struct HomeScreenRoomCell: View {
CompoundIcon(\.videoCallSolid, size: .xSmall, relativeTo: .compound.bodySM)
.accessibilityLabel(L10n.a11yNotificationsOngoingCall)
}
if room.badges.isMuteShown {
CompoundIcon(\.notificationsOffSolid, size: .custom(15), relativeTo: .compound.bodyMD)
.accessibilityLabel(L10n.a11yNotificationsMuted)
@@ -159,7 +159,7 @@ struct HomeScreenRoomCell: View {
.foregroundColor(room.isHighlighted ? .compound.iconAccentTertiary : .compound.iconQuaternary)
}
}
private var mentionIcon: some View {
CompoundIcon(\.mention, size: .custom(15), relativeTo: .compound.bodyMD)
.accessibilityLabel(L10n.a11yNotificationsNewMentions)
@@ -252,7 +252,7 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
static func makeViewModel(roomSummaryProvider: RoomSummaryProviderProtocol) -> HomeScreenViewModel {
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "John Doe", roomSummaryProvider: roomSummaryProvider))))
return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: .volatile(),
@@ -37,9 +37,9 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
self.userDiscoveryService = userDiscoveryService
self.userIndicatorController = userIndicatorController
self.appSettings = appSettings
let mandatoryInvitees: [UserProfileProxy] = if case .draft(let invitees) = roomType { invitees } else { [] }
super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: mandatoryInvitees,
mandatoryInvitees: mandatoryInvitees,
isSkippable: isSkippable),
@@ -92,12 +92,12 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
toggleUser(user)
}
}
// MARK: - Private
private func toggleUser(_ user: UserProfileProxy) {
guard !state.isInviteeMandatory(user) else { return }
if state.selectedUsers.contains(user) {
state.selectedUsers.removeAll { $0.userID == user.userID }
} else {
@@ -119,10 +119,10 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private func createDraftRoom(mandatoryUserIDs: [String]) {
showLoadingIndicator(title: L10n.commonCreatingRoom)
Task {
defer { hideLoadingIndicator() }
switch await clientProxy.createRoom(name: nil,
topic: nil,
accessType: .private,
@@ -244,7 +244,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
}
}
}
private var searchQuery: String {
context.searchQuery
}
@@ -105,7 +105,7 @@ struct InviteUsersScreen: View {
}
@ScaledMetric private var selectedUserCellWidth: CGFloat = 80
private var selectedUsersSection: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 8) {
@@ -204,10 +204,10 @@ struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
isSkippable: Bool = true) -> InviteUsersScreenViewModel {
let clientProxy = ClientProxyMock(.init())
clientProxy.recentConversationCounterpartsReturnValue = [.mockAlice, .mockBob, .mockCharlie, .mockDan, .mockVerbose]
let userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
let viewModel = InviteUsersScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
roomType: roomType ?? .existingRoom(roomProxy: JoinedRoomProxyMock(.init(members: []))),
isSkippable: isSkippable,
@@ -45,7 +45,7 @@ final class JoinRoomScreenCoordinator: CoordinatorProtocol {
private let viewModel: JoinRoomScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<JoinRoomScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<JoinRoomScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -78,7 +78,7 @@ final class JoinRoomScreenCoordinator: CoordinatorProtocol {
func stop() {
viewModel.stop()
}
func toPresentable() -> AnyView {
AnyView(JoinRoomScreen(context: viewModel.context))
}
@@ -60,7 +60,7 @@ struct JoinRoomScreenViewState: BindableState {
var mode: JoinRoomScreenMode = .loading
var hideInviteAvatars = false
var bindings = JoinRoomScreenViewStateBindings()
var shouldHideAvatars: Bool {
@@ -27,7 +27,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
var actionsPublisher: AnyPublisher<JoinRoomScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(source: JoinRoomScreenSource,
appSettings: AppSettings,
userSession: UserSessionProtocol,
@@ -377,7 +377,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
}
}
}
private func showDeclineInviteConfirmationAlert() {
guard let roomDetails = state.roomDetails else {
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
@@ -26,7 +26,7 @@ struct JoinRoomScreen: View {
}
return context.viewState.mode == .knocked ? 151 : 32
}
var body: some View {
FullscreenDialog(topPadding: topPadding) {
if context.viewState.mode == .loading {
@@ -130,7 +130,7 @@ struct JoinRoomScreen: View {
}
}
}
private var knockMessage: some View {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 0) {
@@ -404,7 +404,7 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
self.customPreviewName = customPreviewName
let appSettings = AppSettings.volatile()
let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars))
clientProxy.canJoinRoomWithReturnValue = canJoinRoom
@@ -23,7 +23,7 @@ final class KnockRequestsListScreenCoordinator: CoordinatorProtocol {
private let viewModel: KnockRequestsListScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<KnockRequestsListScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<KnockRequestsListScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -36,7 +36,7 @@ final class KnockRequestsListScreenCoordinator: CoordinatorProtocol {
}
func start() { }
func toPresentable() -> AnyView {
AnyView(KnockRequestsListScreen(context: viewModel.context))
}
@@ -28,7 +28,7 @@ struct KnockRequestsListScreenViewState: BindableState {
false
}
}
// If you are in this view one of these must have been true so by default we assume all of them to be true
var canAccept = true
var canDecline = true
@@ -19,7 +19,7 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn
var actionsPublisher: AnyPublisher<KnockRequestsListScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(roomProxy: JoinedRoomProxyProtocol,
mediaProvider: MediaProviderProtocol,
userIndicatorController: UserIndicatorControllerProtocol) {
@@ -44,7 +44,7 @@ final class LabsScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(LabsScreen(context: viewModel.context))
}
@@ -24,11 +24,11 @@ struct LabsScreenViewState: BindableState {
@dynamicMemberLookup
struct LabsScreenViewStateBindings {
private let labsOptions: LabsOptionsProtocol
init(labsOptions: LabsOptionsProtocol) {
self.labsOptions = labsOptions
}
subscript<Setting>(dynamicMember keyPath: ReferenceWritableKeyPath<LabsOptionsProtocol, Setting>) -> Setting {
get { labsOptions[keyPath: keyPath] }
set { labsOptions[keyPath: keyPath] = newValue }
@@ -15,7 +15,7 @@ class LabsScreenViewModel: LabsScreenViewModelType, LabsScreenViewModelProtocol
var actionsPublisher: AnyPublisher<LabsScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(labsOptions: LabsOptionsProtocol) {
let bindings = LabsScreenViewStateBindings(labsOptions: labsOptions)
let state = LabsScreenViewState(bindings: bindings)
@@ -65,7 +65,7 @@ struct LabsScreen: View {
struct LabsScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = LabsScreenViewModel(labsOptions: AppSettings.volatile())
static var previews: some View {
ElementNavigationStack {
LabsScreen(context: viewModel.context)
@@ -24,7 +24,7 @@ final class LinkNewDeviceScreenCoordinator: CoordinatorProtocol {
private let orientationManager: OrientationManagerProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<LinkNewDeviceScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<LinkNewDeviceScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -58,7 +58,7 @@ final class LinkNewDeviceScreenCoordinator: CoordinatorProtocol {
func stop() {
orientationManager.lockOrientation(.all)
}
func toPresentable() -> AnyView {
AnyView(LinkNewDeviceScreen(context: viewModel.context))
}
@@ -18,7 +18,7 @@ class LinkNewDeviceScreenViewModel: LinkNewDeviceScreenViewModelType, LinkNewDev
var actionsPublisher: AnyPublisher<LinkNewDeviceScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(clientProxy: ClientProxyProtocol, initialState: LinkNewDeviceScreenViewState? = nil) {
self.clientProxy = clientProxy
@@ -28,12 +28,12 @@ enum LocationSharingInteractionMode: Hashable {
case picker(shouldShowLiveLocationOption: Bool)
case viewStatic(StaticLocationData)
case viewLive(sender: TimelineItemSender?, initialLiveLocationShare: LiveLocationShare?)
var isPicker: Bool {
if case .picker = self { return true }
return false
}
var shouldShowLiveLocationOption: Bool {
if case .picker(let shouldShowLiveLocationOption) = self {
return shouldShowLiveLocationOption
@@ -73,7 +73,7 @@ struct LocationSharingScreenViewState: BindableState {
case .viewStatic, .viewLive: .show
}
}
let interactionMode: LocationSharingInteractionMode
let mapURLBuilder: MapTilerURLBuilderProtocol
let ownUserID: String
@@ -112,7 +112,7 @@ struct LocationSharingScreenViewState: BindableState {
}
var bindings = LocationSharingScreenBindings(showsUserLocationMode: .hide)
/// Indicates whether the user is sharing his current location
var isSharingUserLocation: Bool {
bindings.isLocationAuthorized == true && bindings.showsUserLocationMode == .showAndFollow
@@ -148,7 +148,7 @@ struct LocationSharingScreenViewState: BindableState {
!bindings.hasLoadedUserLocation && bindings.isLocationAuthorized == true
}
}
var zoomLevel: Double {
15.0
}
@@ -194,7 +194,7 @@ struct LocationSharingScreenBindings {
/// Information describing the currently displayed alert.
var alertInfo: AlertInfo<LocationSharingViewAlert>?
var sharedAnnotation: LocationAnnotation?
}
@@ -46,7 +46,7 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati
self.analytics = analytics
self.userIndicatorController = userIndicatorController
self.notificationCenter = notificationCenter
super.init(initialViewState: .init(interactionMode: interactionMode,
mapURLBuilder: mapURLBuilder,
ownUserID: roomProxy.ownUserID),
@@ -338,7 +338,7 @@ extension LocationSharingScreenViewModel {
case viewLive
case viewLiveEmpty
}
static func mock(type: MockType,
senderID: String = "@dan:matrix.org") -> LocationSharingScreenViewModel {
let interactionMode: LocationSharingInteractionMode = switch type {
@@ -388,7 +388,7 @@ extension LocationSharingScreenViewModel {
let liveLocationServiceMock = RoomLiveLocationServiceMock(.init(shares: liveLocationShares))
let roomProxy = JoinedRoomProxyMock(.init(members: .allMembers, ownUserID: RoomMemberProxyMock.mockMe.userID))
roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock
return LocationSharingScreenViewModel(interactionMode: interactionMode,
mapURLBuilder: AppSettings.volatile().mapTilerConfiguration,
roomProxy: roomProxy,
@@ -11,14 +11,14 @@ import SwiftUI
struct LocationPickerSheet: View {
@Bindable var context: LocationSharingScreenViewModel.Context
@State private var height: CGFloat = .zero
/// Fixes an iOS 26 sheet issue
/// if the content doesn't meet a certain size
/// additional insets are added.
private var additionalHeight: CGFloat {
context.viewState.interactionMode.shouldShowLiveLocationOption ? 0 : 28
}
var body: some View {
VStack(spacing: 0) {
Text(L10n.screenSharingLocationOptionSheetTitle)
@@ -44,7 +44,7 @@ struct LocationShareSheet_Previews: PreviewProvider {
static let annotation = LocationAnnotation(id: profile.userID,
coordinate: .init(latitude: 51.509865, longitude: -0.118092),
kind: .liveUser(profile))
static var previews: some View {
LocationShareSheet(annotation: annotation)
.previewDisplayName("Live location share sheet")
@@ -126,26 +126,26 @@ struct LocationSharingScreen: View {
struct LocationSharingScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = LocationSharingScreenViewModel.mock(type: .staticSenderLocation)
static let withoutLiveSharingViewModel = LocationSharingScreenViewModel.mock(type: .pickerWithoutLiveLocationOption)
static let pinViewModel = LocationSharingScreenViewModel.mock(type: .staticPinLocation)
static let pickerViewModel = LocationSharingScreenViewModel.mock(type: .picker)
static let liveLocationViewModel = LocationSharingScreenViewModel.mock(type: .viewLive)
static var previews: some View {
ElementNavigationStack {
LocationSharingScreen(context: pickerViewModel.context)
}
.previewDisplayName("Picker")
ElementNavigationStack {
LocationSharingScreen(context: withoutLiveSharingViewModel.context)
}
.previewDisplayName("Picker without live location sharing")
ElementNavigationStack {
LocationSharingScreen(context: viewModel.context)
}
@@ -38,7 +38,7 @@ final class LogViewerScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(LogViewerScreen(context: viewModel.context))
}
@@ -17,7 +17,7 @@ class LogViewerScreenViewModel: LogViewerScreenViewModelType, LogViewerScreenVie
var actions: AnyPublisher<LogViewerScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
super.init(initialViewState: LogViewerScreenViewState(urls: Tracing.logFiles))
}
@@ -20,7 +20,7 @@ struct LogViewerScreen: View {
private struct PreviewView: UIViewControllerRepresentable {
let urls: [URL]
func makeUIViewController(context: Context) -> UIViewController {
let previewController = QLPreviewController()
previewController.dataSource = context.coordinator
@@ -28,16 +28,16 @@ private struct PreviewView: UIViewControllerRepresentable {
return UINavigationController(rootViewController: previewController)
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) { }
func makeCoordinator() -> Coordinator {
Coordinator(view: self)
}
class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate {
let view: PreviewView
init(view: PreviewView) {
self.view = view
}
@@ -47,7 +47,7 @@ private struct PreviewView: UIViewControllerRepresentable {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
view.urls.count
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
let url = view.urls[index]
@@ -65,7 +65,7 @@ private struct PreviewView: UIViewControllerRepresentable {
private class PreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL?
var previewItemTitle: String?
init(previewItemURL: URL?, previewItemTitle: String?) {
self.previewItemURL = previewItemURL
self.previewItemTitle = previewItemTitle
@@ -23,7 +23,7 @@ final class ManageAuthorizedSpacesScreenCoordinator: CoordinatorProtocol {
private let viewModel: ManageAuthorizedSpacesScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<ManageAuthorizedSpacesScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<ManageAuthorizedSpacesScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -46,7 +46,7 @@ final class ManageAuthorizedSpacesScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(ManageAuthorizedSpacesScreen(context: viewModel.context))
}
@@ -15,7 +15,7 @@ class ManageAuthorizedSpacesScreenViewModel: ManageAuthorizedSpacesScreenViewMod
var actionsPublisher: AnyPublisher<ManageAuthorizedSpacesScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(authorizedSpacesSelection: AuthorizedSpacesSelection,
mediaProvider: MediaProviderProtocol) {
super.init(initialViewState: ManageAuthorizedSpacesScreenViewState(authorizedSpacesSelection: authorizedSpacesSelection),
@@ -54,7 +54,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
}
super.init(initialViewState: .init(activeTimelineContext: activeTimelineContext, bindings: .init(screenMode: initialScreenMode)), mediaProvider: mediaProvider)
mediaTimelineViewModel.context.$viewState.sink { [weak self] timelineViewState in
guard let self, state.bindings.screenMode == .media else {
return
@@ -201,7 +201,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
items: currentItems)
newGroups.append(group)
}
state.groups = newGroups
state.isBackPaginating = timelineViewState.timelineState.paginationState.backward == .paginating

Some files were not shown because too many files have changed in this diff Show More