Improve migrate header on iOS (#881)

Refactor into more subviews.
This commit is contained in:
Davide 2024-11-16 15:07:47 +01:00 committed by GitHub
parent 589f2f62e0
commit afa22719bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 122 additions and 94 deletions

View File

@ -47,9 +47,35 @@ extension MigrateContentView {
var body: some View { var body: some View {
List { List {
Section { profilesSection
Text(Strings.Views.Migrate.Sections.Main.header)
} }
.themeNavigationDetail()
.toolbar {
ToolbarItem(placement: .confirmationAction) {
performButton()
.disabled(isEditing)
}
}
}
}
}
private extension MigrateContentView.ListView {
var actionsHeader: some View {
VStack(alignment: .leading, spacing: 16) {
Text(Strings.Views.Migrate.Sections.Main.header)
EditProfilesButton(isEditing: $isEditing, selection: $selection) {
onDelete(profiles.filter {
selection.contains($0.id)
})
// disable isEditing after confirmation
}
}
.textCase(.none)
.listRowInsets(.init(top: 8, leading: 0, bottom: 8, trailing: 0))
}
var profilesSection: some View {
Section { Section {
ForEach(profiles, id: \.id) { ForEach(profiles, id: \.id) {
if isEditing { if isEditing {
@ -64,51 +90,11 @@ extension MigrateContentView {
} }
} }
} header: { } header: {
editButton actionsHeader
} }
.disabled(!step.canSelect) .disabled(!step.canSelect)
} }
.toolbar {
ToolbarItem(placement: .confirmationAction) {
performButton()
.disabled(isEditing)
}
}
}
}
}
private extension MigrateContentView.ListView {
var editButton: some View {
HStack {
if isEditing {
Button(Strings.Global.cancel) {
isEditing = false
}
}
Spacer()
Button(isEditing ? Strings.Global.delete : Strings.Global.edit, role: isEditing ? .destructive : nil) {
if isEditing {
if !selection.isEmpty {
onDelete(profiles.filter {
selection.contains($0.id)
})
// disable isEditing after confirmation
} else {
isEditing = false
}
} else {
selection = []
isEditing = true
}
}
.disabled(isEditing && selection.isEmpty)
}
.frame(height: 30)
}
}
private extension MigrateContentView.ListView {
func isIncludedBinding(for profileId: UUID) -> Binding<Bool> { func isIncludedBinding(for profileId: UUID) -> Binding<Bool> {
Binding { Binding {
statuses[profileId] != .excluded statuses[profileId] != .excluded
@ -134,6 +120,46 @@ private extension MigrateContentView.ListView {
} }
} }
// MARK: - Subviews
private extension MigrateContentView.ListView {
struct EditProfilesButton: View {
@Binding
var isEditing: Bool
@Binding
var selection: Set<UUID>
let onDelete: () -> Void
var body: some View {
HStack {
if isEditing {
Button(Strings.Global.cancel) {
isEditing = false
}
}
Spacer()
Button(isEditing ? Strings.Global.delete : Strings.Global.edit, role: isEditing ? .destructive : nil) {
if isEditing {
if !selection.isEmpty {
onDelete()
} else {
isEditing = false
}
} else {
selection = []
isEditing = true
}
}
.disabled(isEditing && selection.isEmpty)
}
.frame(height: 30)
}
}
}
private extension MigrateContentView.ListView { private extension MigrateContentView.ListView {
struct EditableRowView: View { struct EditableRowView: View {
let profile: MigratableProfile let profile: MigratableProfile

View File

@ -45,9 +45,25 @@ extension MigrateContentView {
var body: some View { var body: some View {
Form { Form {
messageSection
profilesSection
}
.themeForm()
.toolbar {
ToolbarItem(placement: .confirmationAction, content: performButton)
}
}
}
}
private extension MigrateContentView.TableView {
var messageSection: some View {
Section { Section {
Text(Strings.Views.Migrate.Sections.Main.header) Text(Strings.Views.Migrate.Sections.Main.header)
} }
}
var profilesSection: some View {
Section { Section {
Table(profiles) { Table(profiles) {
TableColumn(Strings.Global.name) { TableColumn(Strings.Global.name) {
@ -80,15 +96,7 @@ extension MigrateContentView {
} }
.disabled(!step.canSelect) .disabled(!step.canSelect)
} }
.themeForm()
.toolbar {
ToolbarItem(placement: .confirmationAction, content: performButton)
}
}
}
}
private extension MigrateContentView.TableView {
func isIncludedBinding(for profileId: UUID) -> Binding<Bool> { func isIncludedBinding(for profileId: UUID) -> Binding<Bool> {
Binding { Binding {
statuses[profileId] != .excluded statuses[profileId] != .excluded
@ -102,6 +110,14 @@ private extension MigrateContentView.TableView {
} }
} }
private extension MigratableProfile {
var timestamp: String {
lastUpdate?.localizedDescription(style: .timestamp) ?? ""
}
}
// MARK: - Subviews
private extension MigrateContentView.TableView { private extension MigrateContentView.TableView {
struct ControlView: View { struct ControlView: View {
let step: MigrateViewStep let step: MigrateViewStep
@ -143,9 +159,3 @@ private extension MigrateContentView.TableView {
} }
} }
} }
private extension MigratableProfile {
var timestamp: String {
lastUpdate?.localizedDescription(style: .timestamp) ?? ""
}
}

View File

@ -101,15 +101,7 @@ extension AppContext {
profilesContainerName: Constants.shared.containers.legacyV2, profilesContainerName: Constants.shared.containers.legacyV2,
cloudKitIdentifier: BundleConfiguration.mainString(for: .legacyV2CloudKitId) cloudKitIdentifier: BundleConfiguration.mainString(for: .legacyV2CloudKitId)
) )
#if DEBUG
let migrationManager = MigrationManager(profileStrategy: profileStrategy, simulation: .init(
fakeProfiles: true,
maxMigrationTime: 3.0,
randomFailures: true
))
#else
let migrationManager = MigrationManager(profileStrategy: profileStrategy) let migrationManager = MigrationManager(profileStrategy: profileStrategy)
#endif
return AppContext( return AppContext(
iapManager: .sharedForApp, iapManager: .sharedForApp,