mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Fixes #978 - Message forwarding support
* Add support for message forwarding * Move the TimelineProvider within the RoomProxy to avoid it going out of sync and have it automatically register for timeline updates on init * Implement single selection form button style for message forwarding * Add searching and filter out the source room from the list * Fixed emoji screen initial search bar height * Add view models tests * Add changelog * Update strings * Tweaks following code review
This commit is contained in:
@@ -23,7 +23,8 @@ struct FormRowAccessory: View {
|
||||
enum Kind {
|
||||
case navigationLink
|
||||
case progressView
|
||||
case selection(isSelected: Bool)
|
||||
case singleSelection(isSelected: Bool)
|
||||
case multipleSelection(isSelected: Bool)
|
||||
}
|
||||
|
||||
let kind: Kind
|
||||
@@ -36,8 +37,12 @@ struct FormRowAccessory: View {
|
||||
.init(kind: .progressView)
|
||||
}
|
||||
|
||||
static func selection(isSelected: Bool) -> Self {
|
||||
.init(kind: .selection(isSelected: isSelected))
|
||||
static func singleSelection(isSelected: Bool) -> Self {
|
||||
.init(kind: .singleSelection(isSelected: isSelected))
|
||||
}
|
||||
|
||||
static func multipleSelection(isSelected: Bool) -> Self {
|
||||
.init(kind: .multipleSelection(isSelected: isSelected))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -48,7 +53,13 @@ struct FormRowAccessory: View {
|
||||
.foregroundColor(.compound.iconQuaternary)
|
||||
case .progressView:
|
||||
ProgressView()
|
||||
case .selection(let isSelected):
|
||||
case .singleSelection(let isSelected):
|
||||
if isSelected {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.font(.compound.bodyLG)
|
||||
.foregroundColor(isSelected && isEnabled ? .compound.iconPrimary : .compound.iconTertiary)
|
||||
}
|
||||
case .multipleSelection(let isSelected):
|
||||
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
|
||||
.font(.compound.bodyLG)
|
||||
.foregroundColor(isSelected && isEnabled ? .compound.iconPrimary : .compound.iconTertiary)
|
||||
@@ -94,7 +105,16 @@ struct FormButtonStyle: PrimitiveButtonStyle {
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.padding(FormRow.insets) // Re-apply the normal insets using padding.
|
||||
.background(configuration.isPressed ? Color.compound.bgSubtlePrimary : .clear)
|
||||
.background(backgroundColor(for: configuration))
|
||||
}
|
||||
|
||||
private func backgroundColor(for configuration: Configuration) -> Color {
|
||||
switch accessory?.kind {
|
||||
case .none, .navigationLink, .progressView:
|
||||
return configuration.isPressed ? .compound.bgSubtlePrimary : .element.formRowBackground
|
||||
default:
|
||||
return .element.formRowBackground
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +167,7 @@ struct FormButtonStyles_Previews: PreviewProvider {
|
||||
}
|
||||
.formSectionStyle()
|
||||
|
||||
Section {
|
||||
Section("Single selection") {
|
||||
Button { } label: {
|
||||
Text("Hello world")
|
||||
}
|
||||
@@ -156,18 +176,42 @@ struct FormButtonStyles_Previews: PreviewProvider {
|
||||
Button { } label: {
|
||||
Text("Selected")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: true)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .singleSelection(isSelected: true)))
|
||||
|
||||
Button { } label: {
|
||||
Text("Selected (disabled)")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: true)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .singleSelection(isSelected: true)))
|
||||
.disabled(true)
|
||||
|
||||
Button { } label: {
|
||||
Text("Unselected")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: false)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .singleSelection(isSelected: false)))
|
||||
}
|
||||
.formSectionStyle()
|
||||
|
||||
Section("Multiple selection") {
|
||||
Button { } label: {
|
||||
Text("Hello world")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle())
|
||||
|
||||
Button { } label: {
|
||||
Text("Selected")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: true)))
|
||||
|
||||
Button { } label: {
|
||||
Text("Selected (disabled)")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: true)))
|
||||
.disabled(true)
|
||||
|
||||
Button { } label: {
|
||||
Text("Unselected")
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: false)))
|
||||
}
|
||||
.formSectionStyle()
|
||||
|
||||
|
||||
@@ -97,33 +97,33 @@ struct UserProfileCell_Previews: PreviewProvider {
|
||||
Button(action: action) {
|
||||
UserProfileCell(user: .mockAlice, membership: nil, imageProvider: MockMediaProvider())
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: true)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: true)))
|
||||
.previewDisplayName("Selected user")
|
||||
|
||||
Button(action: action) {
|
||||
UserProfileCell(user: .mockBob, membership: nil, imageProvider: MockMediaProvider())
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: false)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: false)))
|
||||
.previewDisplayName("Unselected user")
|
||||
|
||||
Button(action: action) {
|
||||
UserProfileCell(user: .mockCharlie, membership: .join, imageProvider: MockMediaProvider())
|
||||
}
|
||||
.disabled(true)
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: true)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: true)))
|
||||
.previewDisplayName("Selected disabled user")
|
||||
|
||||
Button(action: action) {
|
||||
UserProfileCell(user: .init(userID: "@someone:matrix.org"), membership: .join, imageProvider: MockMediaProvider())
|
||||
}
|
||||
.disabled(true)
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: true)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: true)))
|
||||
.previewDisplayName("Unverified joined user")
|
||||
|
||||
Button(action: action) {
|
||||
UserProfileCell(user: .init(userID: "@someone:matrix.org"), membership: nil, imageProvider: MockMediaProvider())
|
||||
}
|
||||
.buttonStyle(FormButtonStyle(accessory: .selection(isSelected: false)))
|
||||
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: false)))
|
||||
.previewDisplayName("Unverified user")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user