Use Compound ListRow instead of Compound form styles. (#1484)

* Adopt ListRow Component.

* Update snapshots.

To check in future PR:
- Pseudo Bug Report Attach Screenshot label
- Bug Report screenshot padding (Use ListRow .custom?)
- De-bold Analytics & Notification Settings footer links
- Inline picker alignment perhaps?

* Changelog

* Update Compound.

* Use the label on the login screen.
This commit is contained in:
Doug
2023-08-16 16:08:30 +01:00
committed by GitHub
parent 7c69012667
commit c64fb44c96
98 changed files with 499 additions and 557 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ let package = Package(
.library(name: "DesignKit", targets: ["DesignKit"])
],
dependencies: [
.package(url: "https://github.com/vector-im/compound-ios", revision: "89e3ed5adef33be7eb65137b861833ffae64f961"),
.package(url: "https://github.com/vector-im/compound-ios", revision: "50bb7cf313bd1ad17201fc7e4c1184737a0f44c2"),
.package(url: "https://github.com/vector-im/element-design-tokens", exact: "0.0.3"),
.package(url: "https://github.com/siteline/SwiftUI-Introspect", from: "0.9.0")
],
+1 -1
View File
@@ -5475,7 +5475,7 @@
repositoryURL = "https://github.com/vector-im/compound-ios";
requirement = {
kind = revision;
revision = 89e3ed5adef33be7eb65137b861833ffae64f961;
revision = 50bb7cf313bd1ad17201fc7e4c1184737a0f44c2;
};
};
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
@@ -5,7 +5,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/vector-im/compound-design-tokens.git",
"state" : {
"revision" : "aa55111d94486acbfd3344cf4d08b64723bd6703"
"revision" : "387d2b7211f07761c67e849c59414a1bb803defa"
}
},
{
@@ -13,7 +13,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/vector-im/compound-ios",
"state" : {
"revision" : "89e3ed5adef33be7eb65137b861833ffae64f961"
"revision" : "50bb7cf313bd1ad17201fc7e4c1184737a0f44c2"
}
},
{
@@ -151,6 +151,15 @@
"version" : "8.6.0"
}
},
{
"identity" : "sfsafesymbols",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SFSafeSymbols/SFSafeSymbols.git",
"state" : {
"revision" : "7cca2d60925876b5953a2cf7341cd80fbeac983c",
"version" : "4.1.1"
}
},
{
"identity" : "swift-algorithms",
"kind" : "remoteSourceControl",
@@ -72,29 +72,27 @@ struct LoginScreen: View {
.padding(.horizontal, 16)
.padding(.bottom, 8)
TextField(L10n.commonUsername,
text: $context.username,
// Prompt colour fixes a flicker that occurs before the text field style introspects the field.
prompt: Text(L10n.commonUsername).foregroundColor(.compound.textPlaceholder))
.focused($isUsernameFocused)
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.emailUsername))
.disableAutocorrection(true)
.textContentType(.username)
.autocapitalization(.none)
.submitLabel(.next)
.onChange(of: isUsernameFocused, perform: usernameFocusChanged)
.onSubmit { isPasswordFocused = true }
.padding(.bottom, 20)
TextField(text: $context.username) {
Text(L10n.commonUsername).foregroundColor(.compound.textPlaceholder)
}
.focused($isUsernameFocused)
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.emailUsername))
.disableAutocorrection(true)
.textContentType(.username)
.autocapitalization(.none)
.submitLabel(.next)
.onChange(of: isUsernameFocused, perform: usernameFocusChanged)
.onSubmit { isPasswordFocused = true }
.padding(.bottom, 20)
SecureField(L10n.commonPassword,
text: $context.password,
// Prompt colour fixes a flicker that occurs before the text field style introspects the field.
prompt: Text(L10n.commonPassword).foregroundColor(.compound.textPlaceholder))
.focused($isPasswordFocused)
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.password))
.textContentType(.password)
.submitLabel(.done)
.onSubmit(submit)
SecureField(text: $context.password) {
Text(L10n.commonPassword).foregroundColor(.compound.textPlaceholder)
}
.focused($isPasswordFocused)
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.password))
.textContentType(.password)
.submitLabel(.done)
.onSubmit(submit)
Spacer().frame(height: 32)
@@ -23,6 +23,8 @@ struct BugReportScreen: View {
@ObservedObject var context: BugReportScreenViewModel.Context
var photosPickerTitle: String { context.viewState.screenshot == nil ? L10n.screenBugReportAttachScreenshot : L10n.screenBugReportEditScreenshot }
var body: some View {
Form {
textFieldSection
@@ -31,7 +33,7 @@ struct BugReportScreen: View {
canContactSection
}
.scrollDismissesKeyboard(.immediately)
.compoundForm()
.compoundList()
.navigationTitle(L10n.commonReportABug)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
@@ -50,53 +52,48 @@ struct BugReportScreen: View {
private var textFieldSection: some View {
Section {
TextField(L10n.screenBugReportEditorPlaceholder,
text: $context.reportText,
prompt: Text(L10n.screenBugReportEditorPlaceholder).compoundFormTextFieldPlaceholder(),
axis: .vertical)
ListRow(label: .plain(title: L10n.screenBugReportEditorPlaceholder),
kind: .textField(text: $context.reportText))
.lineLimit(4, reservesSpace: true)
.textFieldStyle(.compoundForm)
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.report)
} footer: {
Text(L10n.screenBugReportEditorDescription)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
private var sendLogsSection: some View {
Section {
Toggle(L10n.screenBugReportIncludeLogs, isOn: $context.sendingLogsEnabled)
.toggleStyle(.compoundForm)
ListRow(label: .plain(title: L10n.screenBugReportIncludeLogs),
kind: .toggle($context.sendingLogsEnabled))
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.sendLogs)
} footer: {
Text(L10n.screenBugReportLogsDescription)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
private var canContactSection: some View {
Section {
Toggle(L10n.screenBugReportContactMeTitle, isOn: $context.canContact)
.toggleStyle(.compoundForm)
ListRow(label: .plain(title: L10n.screenBugReportContactMeTitle),
kind: .toggle($context.canContact))
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.canContact)
} footer: {
Text(L10n.screenBugReportContactMe)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
@ViewBuilder
private var attachScreenshotSection: some View {
Section {
PhotosPicker(selection: $selectedScreenshot,
matching: .screenshots,
photoLibrary: .shared()) {
Label(context.viewState.screenshot == nil ? L10n.screenBugReportAttachScreenshot : L10n.screenBugReportEditScreenshot, systemImage: "camera")
}
.buttonStyle(.compoundForm())
ListRow(kind: .custom {
PhotosPicker(selection: $selectedScreenshot,
matching: .screenshots,
photoLibrary: .shared()) {
ListLabel.default(title: photosPickerTitle, systemIcon: .camera)
}
})
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.attachScreenshot)
} footer: {
if let screenshot = context.viewState.screenshot {
@@ -117,7 +114,6 @@ struct BugReportScreen: View {
.padding(.horizontal, 16)
}
}
.compoundFormSection()
}
@ToolbarContentBuilder
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct ReportContentScreen: View {
@@ -32,7 +33,7 @@ struct ReportContentScreen: View {
ignoreUserSection
}
.scrollDismissesKeyboard(.immediately)
.compoundForm()
.compoundList()
.navigationTitle(L10n.actionReportContent)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
@@ -41,27 +42,23 @@ struct ReportContentScreen: View {
private var reasonSection: some View {
Section {
TextField(L10n.reportContentHint,
text: $context.reasonText,
prompt: Text(L10n.reportContentHint).compoundFormTextFieldPlaceholder(),
axis: .vertical)
ListRow(label: .plain(title: L10n.reportContentHint),
kind: .textField(text: $context.reasonText))
.lineLimit(4, reservesSpace: true)
.textFieldStyle(.compoundForm)
} footer: {
Text(L10n.reportContentExplanation)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
private var ignoreUserSection: some View {
Section {
Toggle(L10n.screenReportContentBlockUser, isOn: $context.ignoreUser)
.toggleStyle(.compoundForm)
ListRow(label: .plain(title: L10n.screenReportContentBlockUser),
kind: .toggle($context.ignoreUser))
.accessibilityIdentifier(A11yIdentifiers.reportContent.ignoreUser)
} footer: {
Text(L10n.screenReportContentBlockUserHint)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
}
@@ -46,6 +46,16 @@ struct RoomDetailsEditScreenViewState: BindableState {
bindings.name != initialName
}
/// The string shown for the room's name when it can't be edited.
var nameRowTitle: String {
bindings.name.isEmpty ? L10n.commonRoomName : bindings.name
}
/// The string shown for the room's topic when it can't be edited.
var topicRowTitle: String {
bindings.topic.isEmpty ? L10n.commonTopic : bindings.topic
}
var topicDidChange: Bool {
bindings.topic != initialTopic
}
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct RoomDetailsEditScreen: View {
@@ -31,7 +32,7 @@ struct RoomDetailsEditScreen: View {
nameSection
topicSection
}
.compoundForm()
.compoundList()
.scrollDismissesKeyboard(.immediately)
.navigationTitle(L10n.screenRoomDetailsEditRoomTitle)
.navigationBarTitleDisplayMode(.inline)
@@ -85,42 +86,39 @@ struct RoomDetailsEditScreen: View {
private var nameSection: some View {
Section {
let canEditName = context.viewState.canEditName
TextField(L10n.commonRoomName,
text: $context.name,
prompt: canEditName ? Text(L10n.commonRoomNamePlaceholder) : nil,
axis: .horizontal)
.focused($focus, equals: .name)
.textFieldStyle(.compoundForm)
.disabled(!canEditName)
.listRowBackground(canEditName ? Color.element.formRowBackground : .clear)
.clipShape(RoundedRectangle(cornerRadius: 8))
if context.viewState.canEditName {
ListRow(label: .plain(title: L10n.commonRoomNamePlaceholder),
kind: .textField(text: $context.name, axis: .horizontal))
.focused($focus, equals: .name)
} else {
ListRow(kind: .custom {
ListLabel.plain(title: context.viewState.nameRowTitle)
.listRowBackground(Color.clear)
})
}
} header: {
Text(L10n.commonRoomName)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
private var topicSection: some View {
Section {
let canEditTopic = context.viewState.canEditTopic
TextField(L10n.commonTopic,
text: $context.topic,
prompt: canEditTopic ? Text(L10n.commonTopicPlaceholder).foregroundColor(.compound.textPlaceholder) : nil,
axis: .vertical)
.focused($focus, equals: .topic)
.textFieldStyle(.compoundForm)
.disabled(!canEditTopic)
.listRowBackground(canEditTopic ? Color.element.formRowBackground : .clear)
.lineLimit(3...)
if context.viewState.canEditTopic {
ListRow(label: .plain(title: L10n.commonTopicPlaceholder),
kind: .textField(text: $context.topic, axis: .vertical))
.focused($focus, equals: .topic)
.lineLimit(3...)
} else {
ListRow(kind: .custom {
ListLabel.plain(title: context.viewState.topicRowTitle)
.listRowBackground(Color.clear)
})
}
} header: {
Text(L10n.commonTopic)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
private var avatarOverlayIcon: some View {
@@ -166,9 +164,23 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider {
roomProxy: RoomProxyMock(with: .init(name: "Room", displayName: "Room")),
userIndicatorController: UserIndicatorControllerMock.default)
static let readOnlyViewModel = {
let accountOwner = RoomMemberProxyMock.mockOwner(allowedStateEvents: [])
return RoomDetailsEditScreenViewModel(accountOwner: accountOwner,
mediaProvider: MockMediaProvider(),
roomProxy: RoomProxyMock(with: .init(name: "Room", displayName: "Room")),
userIndicatorController: UserIndicatorControllerMock.default)
}()
static var previews: some View {
NavigationStack {
RoomDetailsEditScreen(context: viewModel.context)
}
.previewDisplayName("Normal")
NavigationStack {
RoomDetailsEditScreen(context: readOnlyViewModel.context)
}
.previewDisplayName("Read only")
}
}
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct RoomDetailsScreen: View {
@@ -47,7 +48,7 @@ struct RoomDetailsScreen: View {
leaveRoomSection
}
.compoundForm()
.compoundList()
.alert(item: $context.alertInfo)
.alert(item: $context.leaveRoomAlertItem,
actions: leaveRoomAlertActions,
@@ -125,74 +126,55 @@ struct RoomDetailsScreen: View {
if context.viewState.hasTopicSection {
Section {
if let topic = context.viewState.topic, !topic.isEmpty {
Text(topic)
.compoundFormSecondaryTextRow()
ListRow(label: .description(topic), kind: .label)
.lineLimit(isTopicExpanded ? nil : 3)
.onTapGesture { isTopicExpanded.toggle() }
} else {
Button {
context.send(viewAction: .processTapAddTopic)
} label: {
Text(L10n.screenRoomDetailsAddTopicTitle)
}
.buttonStyle(.compoundForm())
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.addTopic)
ListRow(label: .plain(title: L10n.screenRoomDetailsAddTopicTitle),
kind: .button { context.send(viewAction: .processTapAddTopic) })
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.addTopic)
}
} header: {
Text(L10n.commonTopic)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
}
private var aboutSection: some View {
Section {
Button {
context.send(viewAction: .processTapPeople)
} label: {
LabeledContent {
Text(String(context.viewState.joinedMembersCount))
} label: {
Label(L10n.commonPeople, systemImage: "person")
}
}
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people)
ListRow(label: .default(title: L10n.commonPeople, systemIcon: .person),
details: .title(String(context.viewState.joinedMembersCount)),
kind: .navigationLink {
context.send(viewAction: .processTapPeople)
})
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people)
if context.viewState.canInviteUsers {
Button {
context.send(viewAction: .processTapInvite)
} label: {
Label(L10n.screenRoomDetailsInvitePeopleTitle, systemImage: "person.badge.plus")
}
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.invite)
ListRow(label: .default(title: L10n.screenRoomDetailsInvitePeopleTitle,
systemIcon: .personBadgePlus),
kind: .navigationLink {
context.send(viewAction: .processTapInvite)
})
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.invite)
}
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.compoundFormSection()
}
@ViewBuilder
private var notificationSection: some View {
Section {
Button {
context.send(viewAction: .processTapNotifications)
} label: {
LabeledContent {
if context.viewState.notificationSettingsState.isLoading {
ProgressView()
} else if context.viewState.notificationSettingsState.isError {
Image(systemName: "exclamationmark.circle")
} else {
Text(context.viewState.notificationSettingsState.label)
}
} label: {
Label(L10n.screenRoomDetailsNotificationTitle, systemImage: "bell")
}
}
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.notifications)
ListRow(label: .default(title: L10n.screenRoomDetailsNotificationTitle,
systemIcon: .bell),
details: context.viewState.notificationSettingsState.isLoading ? .isWaiting(true)
: context.viewState.notificationSettingsState.isError ? .systemIcon(.exclamationmarkCircle)
: .title(context.viewState.notificationSettingsState.label),
kind: .navigationLink {
context.send(viewAction: .processTapNotifications)
})
.disabled(context.viewState.notificationSettingsState.isLoading)
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.notifications)
}
.buttonStyle(.compoundForm(accessory: context.viewState.notificationSettingsState.isLoaded ? .navigationLink : nil))
.disabled(context.viewState.notificationSettingsState.isLoading)
}
@@ -215,51 +197,38 @@ struct RoomDetailsScreen: View {
private var securitySection: some View {
if context.viewState.isEncrypted {
Section {
Label {
Text(L10n.screenRoomDetailsEncryptionEnabledTitle)
} icon: {
Image(systemName: "lock.shield")
}
.labelStyle(.compoundFormRow(secondaryText: L10n.screenRoomDetailsEncryptionEnabledSubtitle,
alignment: .top))
ListRow(label: .default(title: L10n.screenRoomDetailsEncryptionEnabledTitle,
description: L10n.screenRoomDetailsEncryptionEnabledSubtitle,
systemIcon: .lockShield,
iconAlignment: .top),
kind: .label)
} header: {
Text(L10n.commonSecurity)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
}
private var leaveRoomSection: some View {
Section {
Button(role: .destructive) {
context.send(viewAction: .processTapLeave)
} label: {
Label(L10n.actionLeaveRoom, systemImage: "door.right.hand.open")
}
.buttonStyle(.compoundForm())
ListRow(label: .default(title: L10n.actionLeaveRoom,
systemIcon: .doorRightHandOpen,
role: .destructive),
kind: .button { context.send(viewAction: .processTapLeave) })
}
.compoundFormSection()
}
private func ignoreUserSection(user: RoomMemberDetails) -> some View {
Section {
Button(role: user.isIgnored ? nil : .destructive) {
context.send(viewAction: user.isIgnored ? .processTapUnignore : .processTapIgnore)
} label: {
LabeledContent {
if context.viewState.isProcessingIgnoreRequest {
ProgressView()
}
} label: {
Label(user.isIgnored ? L10n.screenDmDetailsUnblockUser : L10n.screenDmDetailsBlockUser,
systemImage: "slash.circle")
}
}
.buttonStyle(.compoundForm())
.disabled(context.viewState.isProcessingIgnoreRequest)
ListRow(label: .default(title: user.isIgnored ? L10n.screenDmDetailsUnblockUser : L10n.screenDmDetailsBlockUser,
systemIcon: .slashCircle,
role: user.isIgnored ? nil : .destructive),
details: .isWaiting(context.viewState.isProcessingIgnoreRequest),
kind: .button {
context.send(viewAction: user.isIgnored ? .processTapUnignore : .processTapIgnore)
})
.disabled(context.viewState.isProcessingIgnoreRequest)
}
.compoundFormSection()
}
@ViewBuilder
@@ -54,7 +54,7 @@ struct RoomNotificationSettingsScreenViewState: BindableState {
let strings = RoomNotificationSettingsScreenStrings()
var notificationSettingsState: RoomNotificationSettingsState = .loading
var availableCustomRoomNotificationModes: [RoomNotificationModeProxy] = [.allMessages, .mentionsAndKeywordsOnly, .mute]
var isRestoringDefautSetting = false
var isRestoringDefaultSetting = false
var pendingCustomMode: RoomNotificationModeProxy?
}
@@ -82,7 +82,7 @@ class RoomNotificationSettingsScreenViewModel: RoomNotificationSettingsScreenVie
isOneToOne: roomProxy.activeMembersCount == 2)
guard !Task.isCancelled else { return }
state.notificationSettingsState = .loaded(settings: settings)
if !state.isRestoringDefautSetting {
if !state.isRestoringDefaultSetting {
state.bindings.allowCustomSetting = !settings.isDefault
}
if state.pendingCustomMode == nil {
@@ -106,14 +106,14 @@ class RoomNotificationSettingsScreenViewModel: RoomNotificationSettingsScreenVie
}
private func restoreDefaultSetting() {
state.isRestoringDefautSetting = true
state.isRestoringDefaultSetting = true
Task {
do {
try await notificationSettingsProxy.restoreDefaultNotificationMode(roomId: roomProxy.id)
} catch {
displayError(.restoreDefaultFailed)
}
state.isRestoringDefautSetting = false
state.isRestoringDefaultSetting = false
}
}
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct RoomNotificationSettingsScreen: View {
@@ -29,7 +30,7 @@ struct RoomNotificationSettingsScreen: View {
customSettingsSection
}
}
.compoundForm()
.compoundList()
.navigationTitle(L10n.screenRoomDetailsNotificationTitle)
.alert(item: $context.alertInfo)
.track(screen: .roomNotifications)
@@ -40,35 +41,28 @@ struct RoomNotificationSettingsScreen: View {
@ViewBuilder
private var allowCustomSettingSection: some View {
Section {
Toggle(isOn: $context.allowCustomSetting) {
Text(L10n.screenRoomNotificationSettingsAllowCustom)
}
.toggleStyle(.compoundForm)
.accessibilityIdentifier(A11yIdentifiers.roomNotificationSettingsScreen.allowCustomSetting)
.disabled(context.viewState.notificationSettingsState.isLoading)
.onChange(of: context.allowCustomSetting) { _ in
context.send(viewAction: .changedAllowCustomSettings)
}
ListRow(label: .plain(title: L10n.screenRoomNotificationSettingsAllowCustom),
kind: .toggle($context.allowCustomSetting))
.accessibilityIdentifier(A11yIdentifiers.roomNotificationSettingsScreen.allowCustomSetting)
.disabled(context.viewState.notificationSettingsState.isLoading)
.onChange(of: context.allowCustomSetting) { _ in
context.send(viewAction: .changedAllowCustomSettings)
}
} footer: {
Text(L10n.screenRoomNotificationSettingsAllowCustomFootnote)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
@ViewBuilder
private var defaultSettingSection: some View {
Section {
if context.viewState.isRestoringDefautSetting {
Text(L10n.commonLoading)
.foregroundColor(.compound.textPlaceholder)
} else {
Text(context.viewState.strings.string(for: context.viewState.notificationSettingsState))
.foregroundColor(.compound.textPrimary)
}
ListRow(label: .plain(title: context.viewState.isRestoringDefaultSetting ? L10n.commonLoading : context.viewState.strings.string(for: context.viewState.notificationSettingsState)),
kind: .label)
.disabled(context.viewState.isRestoringDefaultSetting)
} header: {
Text(L10n.screenRoomNotificationSettingsDefaultSettingTitle)
.compoundFormSectionHeader()
.compoundListSectionHeader()
} footer: {
Text(context.viewState.strings.customSettingFootnote)
.environment(\.openURL, OpenURLAction { url in
@@ -76,30 +70,25 @@ struct RoomNotificationSettingsScreen: View {
context.send(viewAction: .customSettingFootnoteLinkTapped)
return .handled
})
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
@ViewBuilder
private var customSettingsSection: some View {
Section {
Picker("", selection: $context.customMode) {
ForEach(context.viewState.availableCustomRoomNotificationModes, id: \.self) { mode in
Text(context.viewState.strings.string(for: mode))
.tag(mode)
}
}
.onChange(of: context.customMode) { mode in
context.send(viewAction: .setCustomMode(mode))
}
.labelsHidden()
.pickerStyle(.inline)
ListRow(label: .plain(title: L10n.screenRoomNotificationSettingsCustomSettingsTitle),
kind: .inlinePicker(selection: $context.customMode,
items: context.viewState.availableCustomRoomNotificationModes.map {
(title: context.viewState.strings.string(for: $0), tag: $0)
}))
.onChange(of: context.customMode) { mode in
context.send(viewAction: .setCustomMode(mode))
}
} header: {
Text(L10n.screenRoomNotificationSettingsCustomSettingsTitle)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
}
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct AnalyticsSettingsScreen: View {
@@ -23,25 +24,23 @@ struct AnalyticsSettingsScreen: View {
Form {
analyticsSection
}
.compoundForm()
.compoundList()
.navigationTitle(L10n.commonAnalytics)
.navigationBarTitleDisplayMode(.inline)
}
var analyticsSection: some View {
Section {
Toggle(isOn: $context.enableAnalytics) {
Label(L10n.screenAnalyticsSettingsShareData, systemImage: "chart.bar")
}
.toggleStyle(.compoundForm)
.onChange(of: context.enableAnalytics) { _ in
context.send(viewAction: .toggleAnalytics)
}
ListRow(label: .default(title: L10n.screenAnalyticsSettingsShareData,
systemIcon: .chartBar),
kind: .toggle($context.enableAnalytics))
.onChange(of: context.enableAnalytics) { _ in
context.send(viewAction: .toggleAnalytics)
}
} footer: {
Text(context.viewState.strings.sectionFooter)
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
.compoundFormSection()
}
}
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct LegalInformationScreen: View {
@@ -23,20 +24,15 @@ struct LegalInformationScreen: View {
var body: some View {
Form {
Section {
Button(L10n.commonCopyright) {
openURL("https://element.io/copyright")
}
Button(L10n.commonAcceptableUsePolicy) {
openURL("https://element.io/acceptable-use-policy-terms")
}
Button(L10n.commonPrivacyPolicy) {
openURL("https://element.io/privacy")
}
ListRow(label: .plain(title: L10n.commonCopyright),
kind: .navigationLink { openURL("https://element.io/copyright") })
ListRow(label: .plain(title: L10n.commonAcceptableUsePolicy),
kind: .navigationLink { openURL("https://element.io/acceptable-use-policy-terms") })
ListRow(label: .plain(title: L10n.commonPrivacyPolicy),
kind: .navigationLink { openURL("https://element.io/privacy") })
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.compoundFormSection()
}
.compoundForm()
.compoundList()
.navigationTitle(L10n.commonAbout)
.navigationBarTitleDisplayMode(.inline)
}
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct NotificationSettingsScreen: View {
@@ -35,7 +36,7 @@ struct NotificationSettingsScreen: View {
}
}
}
.compoundForm()
.compoundList()
.navigationTitle(L10n.screenNotificationSettingsTitle)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
@@ -58,120 +59,98 @@ struct NotificationSettingsScreen: View {
private var userPermissionSection: some View {
Section {
HStack(alignment: .firstTextBaseline, spacing: 13) {
Image(systemName: "exclamationmark.circle.fill")
.foregroundColor(.compound.iconTertiaryAlpha)
VStack(alignment: .leading, spacing: 2) {
Text(L10n.screenNotificationSettingsSystemNotificationsTurnedOff)
.font(.compound.bodyLG)
.foregroundColor(.compound.textPrimary)
Text(context.viewState.strings.changeYourSystemSettings)
.font(.compound.bodySM)
.foregroundColor(.compound.textSecondary)
.tint(.compound.textPrimary)
.environment(\.openURL, OpenURLAction { url in
context.send(viewAction: .linkClicked(url: url))
return .systemAction
})
ListRow(kind: .custom {
HStack(alignment: .firstTextBaseline, spacing: 13) {
Image(systemSymbol: .exclamationmarkCircleFill)
.foregroundColor(.compound.iconTertiaryAlpha)
VStack(alignment: .leading, spacing: 2) {
Text(L10n.screenNotificationSettingsSystemNotificationsTurnedOff)
.font(.compound.bodyLG)
.foregroundColor(.compound.textPrimary)
Text(context.viewState.strings.changeYourSystemSettings)
.font(.compound.bodySM)
.foregroundColor(.compound.textSecondary)
.tint(.compound.textPrimary)
}
}
.padding(.vertical, 5)
}
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, 8)
.environment(\.openURL, OpenURLAction { url in
context.send(viewAction: .linkClicked(url: url))
return .systemAction
})
})
}
.compoundFormSection()
}
private var enableNotificationSection: some View {
Section {
Toggle(isOn: $context.enableNotifications) {
Text(L10n.screenNotificationSettingsEnableNotifications)
}
.toggleStyle(.compoundForm)
.onChange(of: context.enableNotifications) { _ in
context.send(viewAction: .changedEnableNotifications)
}
ListRow(label: .plain(title: L10n.screenNotificationSettingsEnableNotifications),
kind: .toggle($context.enableNotifications))
.onChange(of: context.enableNotifications) { _ in
context.send(viewAction: .changedEnableNotifications)
}
}
.compoundFormSection()
}
private var roomsNotificationSection: some View {
Section {
// Group chats
Button {
context.send(viewAction: .groupChatsTapped)
} label: {
LabeledContent {
if let settings = context.viewState.settings {
Text(context.viewState.strings.string(for: settings.groupChatsMode))
} else {
ProgressView()
}
} label: {
Text(L10n.screenNotificationSettingsGroupChats)
}
}
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.notifications)
.buttonStyle(.compoundForm(accessory: context.viewState.settings.flatMap { _ in .navigationLink }))
.disabled(context.viewState.settings == nil)
ListRow(label: .plain(title: L10n.screenNotificationSettingsGroupChats),
details: context.viewState.settings.map {
ListDetailsLabel.title(context.viewState.strings.string(for: $0.groupChatsMode))
} ?? .isWaiting(true),
kind: .navigationLink {
context.send(viewAction: .groupChatsTapped)
})
.disabled(context.viewState.settings == nil)
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.notifications)
// Direct chats
Button {
context.send(viewAction: .directChatsTapped)
} label: {
LabeledContent {
if let settings = context.viewState.settings {
Text(context.viewState.strings.string(for: settings.directChatsMode))
} else {
ProgressView()
}
} label: {
Text(L10n.screenNotificationSettingsDirectChats)
}
}
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.notifications)
.buttonStyle(.compoundForm(accessory: context.viewState.settings.flatMap { _ in .navigationLink }))
.disabled(context.viewState.settings == nil)
ListRow(label: .plain(title: L10n.screenNotificationSettingsDirectChats),
details: context.viewState.settings.map {
ListDetailsLabel.title(context.viewState.strings.string(for: $0.directChatsMode))
} ?? .isWaiting(true),
kind: .navigationLink {
context.send(viewAction: .directChatsTapped)
})
.disabled(context.viewState.settings == nil)
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.notifications)
} header: {
Text(L10n.screenNotificationSettingsNotificationSectionTitle)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
private var mentionsSection: some View {
Section {
Toggle(isOn: $context.roomMentionsEnabled) {
Text(L10n.screenNotificationSettingsRoomMentionLabel)
}
.toggleStyle(.compoundForm)
.onChange(of: context.roomMentionsEnabled) { _ in
context.send(viewAction: .roomMentionChanged)
}
.disabled(context.viewState.settings?.roomMentionsEnabled == nil)
.allowsHitTesting(!context.viewState.applyingChange)
ListRow(label: .plain(title: L10n.screenNotificationSettingsRoomMentionLabel),
kind: .toggle($context.roomMentionsEnabled))
.disabled(context.viewState.settings?.roomMentionsEnabled == nil)
.allowsHitTesting(!context.viewState.applyingChange)
.onChange(of: context.roomMentionsEnabled) { _ in
context.send(viewAction: .roomMentionChanged)
}
} header: {
Text(L10n.screenNotificationSettingsMentionsSectionTitle)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
private var callsSection: some View {
Section {
Toggle(isOn: $context.callsEnabled) {
Text(L10n.screenNotificationSettingsCallsLabel)
}
.toggleStyle(.compoundForm)
.onChange(of: context.callsEnabled) { _ in
context.send(viewAction: .callsChanged)
}
.disabled(context.viewState.settings?.callsEnabled == nil)
.allowsHitTesting(!context.viewState.applyingChange)
ListRow(label: .plain(title: L10n.screenNotificationSettingsCallsLabel),
kind: .toggle($context.callsEnabled))
.disabled(context.viewState.settings?.callsEnabled == nil)
.allowsHitTesting(!context.viewState.applyingChange)
.onChange(of: context.callsEnabled) { _ in
context.send(viewAction: .callsChanged)
}
} header: {
Text(L10n.screenNotificationSettingsAdditionalSettingsSectionTitle)
.compoundFormSectionHeader()
.compoundListSectionHeader()
}
.compoundFormSection()
}
}
@@ -38,7 +38,7 @@ struct SettingsScreen: View {
signOutSection
}
.compoundForm()
.compoundList()
.navigationTitle(L10n.commonSettings)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
@@ -48,118 +48,118 @@ struct SettingsScreen: View {
}
}
private var versionText: some View {
private var versionText: Text {
Text(L10n.settingsVersionNumber(InfoPlistReader.main.bundleShortVersionString, InfoPlistReader.main.bundleVersion))
}
private var userSection: some View {
Section {
HStack(spacing: 12) {
LoadableAvatarImage(url: context.viewState.userAvatarURL,
name: context.viewState.userDisplayName,
contentID: context.viewState.userID,
avatarSize: .user(on: .settings),
imageProvider: context.imageProvider)
.accessibilityHidden(true)
VStack(alignment: .leading, spacing: 2) {
Text(context.viewState.userDisplayName ?? "")
.font(.compound.headingMD)
.foregroundColor(.compound.textPrimary)
Text(context.viewState.userID)
.font(.compound.bodySM)
.foregroundColor(.compound.textSecondary)
ListRow(kind: .custom {
HStack(spacing: 12) {
LoadableAvatarImage(url: context.viewState.userAvatarURL,
name: context.viewState.userDisplayName,
contentID: context.viewState.userID,
avatarSize: .user(on: .settings),
imageProvider: context.imageProvider)
.accessibilityHidden(true)
VStack(alignment: .leading, spacing: 2) {
Text(context.viewState.userDisplayName ?? "")
.font(.compound.headingMD)
.foregroundColor(.compound.textPrimary)
Text(context.viewState.userID)
.font(.compound.bodySM)
.foregroundColor(.compound.textSecondary)
}
.accessibilityElement(children: .combine)
}
.accessibilityElement(children: .combine)
}
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, 8)
})
}
.compoundFormSection()
}
private var sessionVerificationSection: some View {
Section {
Button { context.send(viewAction: .sessionVerification) } label: {
Label(L10n.actionCompleteVerification, systemImage: "checkmark.shield")
}
.buttonStyle(.compoundForm())
ListRow(label: .default(title: L10n.actionCompleteVerification,
systemIcon: .checkmarkShield),
kind: .button { context.send(viewAction: .sessionVerification) })
}
.compoundFormSection()
}
private var developerOptionsSection: some View {
Section {
Button { context.send(viewAction: .developerOptions) } label: {
Label(L10n.commonDeveloperOptions, systemImage: "hammer.circle")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("developerOptionsButton")
ListRow(label: .default(title: L10n.commonDeveloperOptions,
systemIcon: .hammerCircle),
kind: .navigationLink {
context.send(viewAction: .developerOptions)
})
.accessibilityIdentifier("developerOptionsButton")
}
.compoundFormSection()
}
private var simplifiedSection: some View {
Section {
Picker(selection: $context.timelineStyle) {
ForEach(TimelineStyle.allCases, id: \.self) { style in
Text(style.name)
.tag(style)
ListRow(label: .default(title: L10n.commonMessageLayout,
systemIcon: .rectangleGrid1x2),
kind: .picker(selection: $context.timelineStyle,
items: TimelineStyle.allCases.map { (title: $0.name, tag: $0) }))
.accessibilityIdentifier("timelineStylePicker")
.onChange(of: context.timelineStyle) { _ in
context.send(viewAction: .changedTimelineStyle)
}
} label: {
Label(L10n.commonMessageLayout, systemImage: "rectangle.grid.1x2")
}
.labelStyle(.compoundFormRow())
.accessibilityIdentifier("timelineStylePicker")
.onChange(of: context.timelineStyle) { _ in
context.send(viewAction: .changedTimelineStyle)
}
// Notifications
if context.viewState.showNotificationSettings {
Button { context.send(viewAction: .notifications) } label: {
Label(L10n.screenNotificationSettingsTitle, systemImage: "bell")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("notificationsButton")
ListRow(label: .default(title: L10n.screenNotificationSettingsTitle,
systemIcon: .bell),
kind: .navigationLink {
context.send(viewAction: .notifications)
})
.accessibilityIdentifier("notificationsButton")
}
// Analytics
Button { context.send(viewAction: .analytics) } label: {
Label(L10n.commonAnalytics, systemImage: "chart.bar")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("analyticsButton")
ListRow(label: .default(title: L10n.commonAnalytics,
systemIcon: .chartBar),
kind: .navigationLink {
context.send(viewAction: .analytics)
})
.accessibilityIdentifier("analyticsButton")
// Report Bug
Button { context.send(viewAction: .reportBug) } label: {
Label(L10n.commonReportABug, systemImage: "ladybug")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("reportBugButton")
ListRow(label: .default(title: L10n.commonReportABug,
systemIcon: .ladybug),
kind: .navigationLink {
context.send(viewAction: .reportBug)
})
.accessibilityIdentifier("reportBugButton")
// About
Button { context.send(viewAction: .about) } label: {
Label(L10n.commonAbout, systemImage: "questionmark.circle")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("aboutButton")
ListRow(label: .default(title: L10n.commonAbout,
systemIcon: .questionmarkCircle),
kind: .navigationLink {
context.send(viewAction: .about)
})
.accessibilityIdentifier("aboutButton")
}
.compoundFormSection()
}
private var signOutSection: some View {
Section {
Button { showingLogoutConfirmation = true } label: {
Label(L10n.screenSignoutPreferenceItem, systemImage: "rectangle.portrait.and.arrow.right")
}
.buttonStyle(.compoundForm())
.accessibilityIdentifier("logoutButton")
.alert(L10n.screenSignoutConfirmationDialogTitle, isPresented: $showingLogoutConfirmation) {
Button(L10n.screenSignoutConfirmationDialogSubmit,
role: .destructive,
action: logout)
} message: {
Text(L10n.screenSignoutConfirmationDialogContent)
}
ListRow(label: .default(title: L10n.screenSignoutPreferenceItem,
systemIcon: .rectanglePortraitAndArrowRight),
kind: .button {
showingLogoutConfirmation = true
})
.accessibilityIdentifier("logoutButton")
.alert(L10n.screenSignoutConfirmationDialogTitle, isPresented: $showingLogoutConfirmation) {
Button(L10n.screenSignoutConfirmationDialogSubmit,
role: .destructive,
action: logout)
} message: {
Text(L10n.screenSignoutConfirmationDialogContent)
}
} footer: {
VStack {
versionText
@@ -169,11 +169,10 @@ struct SettingsScreen: View {
Text(deviceID)
}
}
.compoundFormSectionFooter()
.compoundListSectionFooter()
.textSelection(.enabled)
.padding(.top, 24)
}
.compoundFormSection()
}
private var doneButton: some View {
@@ -204,7 +203,10 @@ private extension TimelineStyle {
struct SettingsScreen_Previews: PreviewProvider {
static let viewModel = {
let userSession = MockUserSession(clientProxy: MockClientProxy(userID: "@userid:example.com",
let verificationController = SessionVerificationControllerProxyMock()
verificationController.isVerified = false
let userSession = MockUserSession(sessionVerificationController: verificationController,
clientProxy: MockClientProxy(userID: "@userid:example.com",
deviceID: "AAAAAAAAAAA"),
mediaProvider: MockMediaProvider())
ServiceLocator.shared.settings.notificationSettingsEnabled = true
@@ -18,7 +18,7 @@ import Combine
struct MockUserSession: UserSessionProtocol {
let callbacks = PassthroughSubject<UserSessionCallback, Never>()
let sessionVerificationController: SessionVerificationControllerProxyProtocol? = nil
var sessionVerificationController: SessionVerificationControllerProxyProtocol?
var userID: String { clientProxy.userID }
var deviceID: String? { clientProxy.deviceID }
var homeserver: String { clientProxy.homeserver }
@@ -149,7 +149,10 @@ class MockScreen: Identifiable {
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .templateScreen:
return TemplateScreenCoordinator(parameters: .init())
let navigationStackCoordinator = NavigationStackCoordinator()
let coordinator = TemplateScreenCoordinator(parameters: .init())
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .home:
let navigationStackCoordinator = NavigationStackCoordinator()
let session = MockUserSession(clientProxy: MockClientProxy(userID: "@mock:matrix.org"),
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct TemplateScreen: View {
@@ -22,22 +23,15 @@ struct TemplateScreen: View {
var body: some View {
Form {
Section {
TextField(text: $context.composerText) {
Text(context.viewState.placeholder)
.compoundFormTextFieldPlaceholder()
}
.textFieldStyle(.compoundForm)
ListRow(label: .plain(title: context.viewState.placeholder),
kind: .textField(text: $context.composerText))
Button {
context.send(viewAction: .done)
} label: {
Label("Done", systemImage: "door.left.hand.closed")
}
.buttonStyle(.compoundFormCentred())
ListRow(label: .centeredAction(title: L10n.actionDone,
systemIcon: .doorLeftHandClosed),
kind: .button { context.send(viewAction: .done) })
}
.compoundFormSection()
}
.compoundForm()
.compoundList()
.navigationTitle(context.viewState.title)
.onChange(of: context.composerText) { _ in
context.send(viewAction: .textChanged)
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3716163032f1387a23ec46e2a7a0418f82dff973028d9029cd543a0b75b79c6b
size 78825
oid sha256:bced59675a1e38b3a11f01ccad5ffcb5311b88b62ab4e0e67c0be45c9d618bb8
size 78828
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:70935aa783ef9392f8a1160fb68af5b7bf16dea9709ce1a5f049bcf6276309f1
size 126496
oid sha256:0e998dc5ad773333476549bd07aa33c35c5b85fac14054b010586f229f355b4f
size 126414
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:16e201d435c12a555bbee2746ebc35f011c6d2bb3a20bacf87c3341f1b5b0229
size 194229
oid sha256:f9613904ca4f73523857a261447563b4d67559671f01dc57d608c86454a3ae40
size 193362
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d1eb3e91e264f86c6e9cded9159bbce88bd4bbe50242a609c37b514fdc2b0590
size 201099
oid sha256:5ffbb02dbe9e489e8b3eef39ee398378dc9437a46270f3343b68f24e3153bcb3
size 200366
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6ee871f1bbee6b3b9208880b6d5b5da72422ffde72c6131dbaec96422b576caa
size 137938
oid sha256:0fa656e56fbbb76dde9792413e85e6c784a53c06bff22ebc48e0b4daab0585c0
size 138861
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c5e16b7b56132cb5c7c30d502911dcb29b41efe3228c10053576fe4b34e5178e
size 94846
oid sha256:c514aee9863e5e4f98416dad06dd9cdc3712866355790936c53ef598f40d7646
size 94913
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1e733ae4dfab4652031797c366ddd025e3d1bf42cf1cf3b4095943aac7b7fc43
size 92844
oid sha256:4b9fc8986e2a36e20975c4e4cb7eea2ceddb9f331092d5a84bdf608b36aeecb0
size 92603
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c5c2128f0c2ff8eacd789bf31b0ca5575a3815b0baf7efc594d5c4f6382a107c
size 107997
oid sha256:a7764e39c3df507246e0312e4d65dbf1eee09486e69b8d2aee1d86b6c3632173
size 107609
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:94c6d983f73986c694ae68c70a0ee223916185a361d6067f7c3ffc286d89547d
size 110720
oid sha256:b8b39f26310f411a198277dd56c86d697d1fc2a1c481de578bd9a22306881125
size 110753
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:742dc32fe782bc6b75b8c1ec4e3cb373504fc43df728b189ca6f50d131e1acc9
size 98511
oid sha256:ba1231592153758bb1bb6f2bf14cf6aa315817d9feda1596146f2a7702938bfb
size 98119
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4e88bae68d81e42f597de343d8a66a6f70c76d9878e3d7697c34ed533b568094
size 116369
oid sha256:dc84e5329532d7ceb2bd86ed36f92a81e8351f1de261496762f83cbb259b8b7a
size 115979
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3572d040c35de4772462d1627f92467af9cd383d454af08a71ba36cb2a7d2b4f
size 78185
oid sha256:6c80ca3aec401030496c7cc9991bcd22c083e3d42d986bdda929b79978d59177
size 78871
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:25869965443a0580f2e0e3ac5cc69a0e576868b56e7d8550af77fbb3698c90e1
size 75225
oid sha256:53a24ac906105f23d0a10340d5b59c998ffa0d621fde848a1b073241cd4ea4da
size 74591
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:31971d8da2139d035c3dd59c595ea887ecd33a11c496464a4798dabb04503ab1
size 91579
oid sha256:55ce6c018bba62f121ac067f1d7f048f0c9e93cbe4f01f759adc9d052d8bb6dc
size 91307
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6360b213d0c017f9dcf7747e621887c4dab3995e4603e87440bcfa7f1b9661be
size 89003
oid sha256:58ce388eac7c5b42632e3c541f97eb7ec69c7bc6b099e07180f299b63bf82bea
size 89276
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:63da6c8b58724413818fdc5ec9a2b2712ac45b1195cad40121b9ae3d4c5186a1
size 113836
oid sha256:8ce135e012a85e14fdbf8ad7a62d002d64b1b64b43be51cccc64c75793c7601f
size 113300
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f8bcaae035fbde1d607e93ac048f3dbdefc5b35e6c8c48b59338744e43557ea6
size 84542
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5c746f86864de6f4824352c0f019ba43ac90646cc26b8343721eec3564f5fffe
size 78946
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8028144ace72558a2191de668a45a2e33e67012c8108c04d25445b4139d81092
size 66099
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c295c1382e70b6eea9dddd502cf06b4008a46a2699daa05b079c29b25a9f54f7
size 87780
oid sha256:cee7780c3b1110911c4de1f35b9ead6e36b10992c0a8c59b1fa5a87d43cdb5e2
size 87879
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:75b4447894f5d3b8278c6118dc41f7c99efa5626491894d0ab287ff89af7f9ef
size 166816
oid sha256:4b2ab425b5e78387e8c7685a560062ced41ce64082483982fd9343f3bc8092dd
size 167217
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6ab050acaee21d58c9afcf68fa7ee861c4d67cd87156aaf46f299ce23c49790d
size 210535
oid sha256:641877828c934248454d8f194a497e7b52eafdbde2d523125d3492cec357136e
size 208966
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e47165276d97ab3f740508db22c7cea02c9de7954eb4d556870242521a8271b3
size 219096
oid sha256:b8a88d419e02c297f10ac1b0c2f696e89a03ff762047251e70a15ac85234c22a
size 215655
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:55f92756942d4a336258c2b3f46eec47561f1a2e3dd1265756fdeb7c66c54205
size 181095
oid sha256:b535f994068f704ec7b52f5898843734f5412159f091f76e0e5cde22a7d8c3a9
size 181099
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5a330b8acd8f2a4ebdda45d125c29c17e21f6cd8fb2397443d7527988ff5a943
size 117146
oid sha256:fc55ae0adc15b48788ee406d0bb425441744f11a3dc3f8cd5e8f0eb9180aedac
size 119435
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:185f7126eff79219bb9cd832ba4acfba1775c96d26c8fe52099d431b76b5e430
size 114420
oid sha256:3c074fc387e5d9602cd8190fa5697af2dc0ab2660d2a930229b07ff3d15662a4
size 114440
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:829664b07f3eea5dd69b58bb264b11b9f4770e640d71a27951fcd25242d2777f
size 136151
oid sha256:90aefb602146db2b9b35e1d48f5fe1fa6158f5fc9e610685764a0951e7488a39
size 136987
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d1e011a2f3b8072bbe30da83609f309ef1b3c910ea54cd2389bd96e9e65b95d3
size 138268
oid sha256:a0f44c495b3cf91392ca144a313c991871f3f4a3c015a5493abe2fb1d42c8823
size 139719
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:916377b6b5bfaaff8bcd1a7b6bff1bded2e439aa5364b1184eec41bf39e49aa1
size 123198
oid sha256:df987fbf67919cae3eaa9c767796ed51d3e58459dd421cefff0084b393e37216
size 122485
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1a820dde15ddb4376bc22624b150a20fdda8395c942d57b75cb16e0e24e27a10
size 149669
oid sha256:81a321deafd52084901be8907e16b6c9ed1f985f986afcee4b1967544a25199e
size 148265
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9b7cc76e76d37b4055a3153487ce349995a4c601d15efaa4b1e8c96cdd8b704b
size 90944
oid sha256:fa9107df62d20d07a343b9600a7f411ef30146be4eae75a0a8659e5d5ef2617a
size 90779
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1a85d3a70bc441b5f0e581c04c3556f0b5d7f3e5f72e5c48cc2f8a320bc9a067
size 80902
oid sha256:95ffabb3ae988f93a288fcf1729cb350a60f983385130348fc004607576bd447
size 82948
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ec5118beb0691f8df57b51c372d0df418c63dc1b73233efea058da41291e9e3
size 107915
oid sha256:a9eed804e596319fb87cac52da8955d2cf41c3fb11f92c0e33db65db72d84fcc
size 107614
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:aabd8e46d32b82e9a69081de0ba2d6ea505fb1f1c9bd649b87695b33556112dd
size 101243
oid sha256:5027c07eea41bbbb36dd8998e58fc1860010d4a262e18dc250af63ccae500084
size 102222
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fcda94a55d0456e49c5f99c7ad04101ab89d1726f4d95e814e95f100002c3afa
size 140993
oid sha256:8bd929af18ca9f589d6cc6a2c9448708b62b70a922cb9e5ffe1e20a4fed1b672
size 140569
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4f9577ed8a31d061a32dac2cdf34269d671f322e4979c6d217dec6b9ec3e5eb6
size 94364
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a64a7abea5bf7ac3a9e53d5101f59d496c5870304d782b109268565eb7ff8d1b
size 87262
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c48aaef513925827d7774b85fffea975d9ffdc043cf51bf9b5fa9a94726828ad
size 69059
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:597805023ec0194a04c4f7bea7780f80db38fa6805727a807710139c67bf68a9
size 84672
oid sha256:a7bfc98d7d2024f103efe75384acf86d067f3dc970865bde9a79ef89e7623dfc
size 84685
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c807972e64f0977aca1a0db35ecbeda82aaf6452889473a9dcc197b6e976f757
size 160832
oid sha256:b9f1ab523823eae1bf7e339c7ecab26fa09176df26f2304bce796e2ba75e30eb
size 163306
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fd33425f8f03217992dbe5a9b8f5356c23c6360cabbe880f696d95eb1dd80049
size 226953
oid sha256:a8895fdf5762413792e00cf685fc305a51b0cced4e888ca851aedc14482a0290
size 228639
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bf757b59634c398a83226d31292c5667c74493434c7e3aea00b6dac73270b1e8
size 232739
oid sha256:5c884047dd87c37ae1ab336c90033aba6111272b0a98bac865bc7610a84904b7
size 234583
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:05aaadb39c04411e8d6aec7d486e59a22dd2995245fadbe7605faf7288f1daa8
size 169803
oid sha256:eef6560ed80a70c9bf0685aab1d5e98fcf5a30bd500f1c921bf53d7e4495f051
size 172279
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c253c4c823104c55bf916c9d112ad87e4de3db24fd324a61350a834584edf275
size 116667
oid sha256:d0efa2cd49b26741b545224a2eea39e07685e5959551a8f43025a48040399248
size 116939
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:549644bff6fcada9a12199a92c111c74e18e0ff0ac6eb85d4700403103e27241
size 105359
oid sha256:8f6ee652a9eab0203f0cd6878d6bb5adb6d23177b3ea48e9b73043783b5b68d0
size 105449
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:66e014c94785dd5129c4896890f6787ac06600becf5030e4fd829a5b154fab63
size 120575
oid sha256:4b390c1b74ec7f33edfbba06401d69667c4ed391ce6e042051440c82e5233792
size 121126
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:da3e0d71f240a71947ea66d9033b7b1d9245eee7d352f7687c2992d7ae668b49
size 124736
oid sha256:1cc2e48c7ada9bb111857c7104b6ac106bb74568db73b38288cbc43d495880be
size 125491
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2ef23872b8799a221776f2eaecdee660666a0feda377f98071f9830420c24d51
size 111545
oid sha256:e791c5c530f41afc2d69614b58840c5e69fa77e2aaf822ede85878bfde292d02
size 111094
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a3be342a42c214c7854e236d15d0d58f66c23fd78dfce4852b07ae809df37a98
size 129000
oid sha256:86d7ba9ce9b8745510e218f8b22a53e57f20459a7a50af2a0eb13eff7e8c80eb
size 129148
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9a89be8c8f12f3adf095b56b79961990b7f47a0a6d34c2731fac8934bc21ff7d
size 80805
oid sha256:fb95587da3d636ab0d1779c1f76084a2c227c4b3e7c31a530eaa939e534429c0
size 81487
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c0f78e30a5abce712da516ad6a825c9562f0fa3c37903dc1d9c0e8be74099616
size 77822
oid sha256:73f3777590b52f858bbb4b5d78870c671d76d5e94921746a0260bb3ffae2da36
size 77246
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f68bab9b84c6747f8ea4610da46c3c79b138bfb95d75216a62e05c28c9ce2373
size 99103
oid sha256:6155979ba94debfdcb27a884dda577190a10c663feec56ba6ce68ccdc208709a
size 98799
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:911c455aadd9bb40c83b7f759cd51f03c2d091855274550de31f35a0a9001d9a
size 99273
oid sha256:1baf0e4839787015887b734f7b5403f1017f21d40677aa148408e7ddd2a5efe0
size 101441
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c01d4c5c2002e68ccb49924348380372e301ed178676df164b62f55248872bab
size 120615
oid sha256:4efcb97579d3cfc8140578e9c5d0a2945435013c16ad2cfff3b1de970608bd50
size 120591
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a3b1b5a3cd47c4dc67182c50681c4415a56996027002fcc7456c2f1be9b8c0a2
size 86357
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:538c1934c9d2fa998b22fad1101959d060a272088d39529f664d30c014a7e81f
size 80783
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:92dd675595b5a9cf9f90ba89d30821621dd60be7af3241fa34858b55eb0f2785
size 66398
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a81e4fbd557c2220fc1b75086b757ca4edfcf8384dd0bdaa40f52ebae959e115
size 108213
oid sha256:134b67cc2665eb48f3a9fde825c81cdf9be0b7d252f54aa6863f6bc3d709502f
size 108305
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:074800a57b21edd7d9b54e1d01a85a9cb29b3e96045ef999a66ac386fe366220
size 235638
oid sha256:0c58d7a7f01c75c0d943404ccfb84e494924ebf159e9db66a2101b76800b211f
size 231174
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7602c21904a1b961e3841bbf881a0e972fcfe075d68502c95583a3e4a42a9860
size 227310
oid sha256:ef0d509ad85ab4461c86fe5687377a3a12045be68e5cc6441e101a0f7a2fec92
size 215240
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d1039489d9d16dcc6367118caf0621aacd96994eb27251f2b05998824fca45d5
size 234278
oid sha256:8b1f4eba9e53a005cc1adffd93cc15b73a9dfe8408b467127edde2b80e710dd2
size 221063
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ef8aaf01bff6866112fa5c34c53cce291811be26a12c6ec16011a92987074cb5
size 239739
oid sha256:0e6e559bebe737b75e5df7c705203cdee7647441f631743bf7d33de0ce5244df
size 227071
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4781fa334f9c08adf7ba7e3b0885e9b04a7f28c7e1e407553a74171570775a41
size 162791
oid sha256:6a4024d9401d54a37dda66f36ba0972dcf57c2fd07f4d3c2bc479ca1a4108573
size 163180
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c7cdba22264783b0c6dcdab920ad76536d14607386407699064bdaa74e823ada
size 144165
oid sha256:9a99af45d33c1c8b9277494aa0f2b07bf0108891a78594cb16e7b2ad3c84be61
size 143610
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:06c2c94823623f270e9b35ba02cd4f85c1bcbe3471e3a19ac45137afb26c0763
size 166192
oid sha256:14b719940a2d55d51291830227a0b9e9f7a5a5fe942a3ecc119407f40458398a
size 169433
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bf95a30eb5467febc2d83044e336f9da867266c1fc3c59c1656ded916f6bad68
size 175545
oid sha256:d721ab3fb80283367fb3b0573d223589197767e98d03da7d860b6107d59ee99b
size 163565
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:05805475c80e08fc4060eaf32dcc7a2d775c1dd81504000016b766ec386267c7
size 153202
oid sha256:aebe694c734af52a98cf0b881d440a086f04c65d7a132afc951a668c7183c864
size 152113
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:13a6ddd1704e0ff6c6810b2001faa6922099b952dce95773c8013c9d8df00c78
size 179534
oid sha256:60d93b489ac8051eb8ceb3deaca5ee050bd7b3f22350fe3eebb680f0f60a31bf
size 178195
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:186bf0ae6879b52dbe2b995a2cb589aac5f41aca525adc0cea8cacc7d561ad35
size 93837
oid sha256:c2af92bb5c92ae8c680fc1f6c89d1ca037faa52f4a498169d74490518e6298fd
size 93774
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:19d1f76b44e8dc394ce0c1bf5df4874615e5e534fe7e5a488a095aa7608c044f
size 85855
oid sha256:002fdf44ed4ee5ee2bc4ecb72f21bc726f655dfd1abdf29697f4b4bd31dd8265
size 85629
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5bcf4fd1f00368481f8688abdb60bffe8aa65234d64f6bf44d9ff9dfe0421b25
size 141085
oid sha256:56e470c713c4b51e58c3027c66039d191a63d81d1ec04809c6cdc087ed088c50
size 140627
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fe711a53de7a85957694d9f19ef81f99ec3e51dddcda0f6537d4fcfd7ceb9906
size 126350
oid sha256:705b68a0dadbbc56003594a768b37400368efc4c6bd78e6a908b2d32ff383746
size 127571
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5292689319bfed500832759b2ecf924eacbd6e3c413f520b52f6fe1e2e1c9900
size 164822
oid sha256:2e014fead3ae053429a182e79b1cf3951323977d602f4c45667cb5ba2ba3057a
size 165296
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0a82fdc687804e32734a290ec1d02d3d8230efc3d1b182cd0666e8c824db9ee2
size 98594
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0f61b2f1e18df77cbb1c65ab803a14c2db1b2bc0718cde1187266eb6796954e9
size 91945
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:df5cdbe45d6259ab51d151deaca7a558ac7b370c98679cb0c47205906c608a97
size 71474
@@ -83,7 +83,7 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
try await deferred.fulfill()
let deferredIsRestoringDefaultSettings = deferFulfillment(context.$viewState.map(\.isRestoringDefautSetting)
let deferredIsRestoringDefaultSettings = deferFulfillment(context.$viewState.map(\.isRestoringDefaultSetting)
.removeDuplicates()
.collect(3).first())
viewModel.state.bindings.allowCustomSetting = false
+1
View File
@@ -0,0 +1 @@
Use Compound ListRow instead of .xyzStyle(.compoundRow)
+1 -1
View File
@@ -51,7 +51,7 @@ packages:
path: DesignKit
Compound:
url: https://github.com/vector-im/compound-ios
revision: 89e3ed5adef33be7eb65137b861833ffae64f961
revision: 50bb7cf313bd1ad17201fc7e4c1184737a0f44c2
# path: ../compound-ios
AnalyticsEvents:
url: https://github.com/matrix-org/matrix-analytics-events