parent
589f2f62e0
commit
afa22719bf
|
@ -47,9 +47,35 @@ extension MigrateContentView {
|
|||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
Text(Strings.Views.Migrate.Sections.Main.header)
|
||||
profilesSection
|
||||
}
|
||||
.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 {
|
||||
ForEach(profiles, id: \.id) {
|
||||
if isEditing {
|
||||
|
@ -64,51 +90,11 @@ extension MigrateContentView {
|
|||
}
|
||||
}
|
||||
} header: {
|
||||
editButton
|
||||
actionsHeader
|
||||
}
|
||||
.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> {
|
||||
Binding {
|
||||
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 {
|
||||
struct EditableRowView: View {
|
||||
let profile: MigratableProfile
|
||||
|
|
|
@ -45,9 +45,25 @@ extension MigrateContentView {
|
|||
|
||||
var body: some View {
|
||||
Form {
|
||||
messageSection
|
||||
profilesSection
|
||||
}
|
||||
.themeForm()
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .confirmationAction, content: performButton)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension MigrateContentView.TableView {
|
||||
var messageSection: some View {
|
||||
Section {
|
||||
Text(Strings.Views.Migrate.Sections.Main.header)
|
||||
}
|
||||
}
|
||||
|
||||
var profilesSection: some View {
|
||||
Section {
|
||||
Table(profiles) {
|
||||
TableColumn(Strings.Global.name) {
|
||||
|
@ -80,15 +96,7 @@ extension MigrateContentView {
|
|||
}
|
||||
.disabled(!step.canSelect)
|
||||
}
|
||||
.themeForm()
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .confirmationAction, content: performButton)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension MigrateContentView.TableView {
|
||||
func isIncludedBinding(for profileId: UUID) -> Binding<Bool> {
|
||||
Binding {
|
||||
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 {
|
||||
struct ControlView: View {
|
||||
let step: MigrateViewStep
|
||||
|
@ -143,9 +159,3 @@ private extension MigrateContentView.TableView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension MigratableProfile {
|
||||
var timestamp: String {
|
||||
lastUpdate?.localizedDescription(style: .timestamp) ?? ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,15 +101,7 @@ extension AppContext {
|
|||
profilesContainerName: Constants.shared.containers.legacyV2,
|
||||
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)
|
||||
#endif
|
||||
|
||||
return AppContext(
|
||||
iapManager: .sharedForApp,
|
||||
|
|
Loading…
Reference in New Issue