mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-08-03 20:47:22 -04:00
Split and rename viewModels
This commit is contained in:
parent
372cceccbb
commit
89ab9d7d42
@ -25,6 +25,7 @@ struct Kiwix: App {
|
|||||||
|
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
@StateObject private var library = LibraryViewModel()
|
@StateObject private var library = LibraryViewModel()
|
||||||
|
@StateObject private var selection = SelectedZimFileViewModel(isMultiSelection: false)
|
||||||
@StateObject private var navigation = NavigationViewModel()
|
@StateObject private var navigation = NavigationViewModel()
|
||||||
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
|
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
|
||||||
private let fileMonitor: DirectoryMonitor
|
private let fileMonitor: DirectoryMonitor
|
||||||
@ -53,6 +54,7 @@ struct Kiwix: App {
|
|||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
.environment(\.managedObjectContext, Database.shared.viewContext)
|
.environment(\.managedObjectContext, Database.shared.viewContext)
|
||||||
.environmentObject(library)
|
.environmentObject(library)
|
||||||
|
.environmentObject(selection)
|
||||||
.environmentObject(navigation)
|
.environmentObject(navigation)
|
||||||
.modifier(AlertHandler())
|
.modifier(AlertHandler())
|
||||||
.modifier(OpenFileHandler())
|
.modifier(OpenFileHandler())
|
||||||
|
@ -182,8 +182,12 @@ struct RootView: View {
|
|||||||
@State private var currentNavItem: MenuItem?
|
@State private var currentNavItem: MenuItem?
|
||||||
@StateObject private var windowTracker = WindowTracker()
|
@StateObject private var windowTracker = WindowTracker()
|
||||||
@State private var paymentButtonLabel: PayWithApplePayButtonLabel?
|
@State private var paymentButtonLabel: PayWithApplePayButtonLabel?
|
||||||
|
<<<<<<< HEAD
|
||||||
@StateObject private var multiSelection = LibraryMultiSelectViewModel()
|
@StateObject private var multiSelection = LibraryMultiSelectViewModel()
|
||||||
var isSearchFocused: FocusState<Bool>.Binding
|
var isSearchFocused: FocusState<Bool>.Binding
|
||||||
|
=======
|
||||||
|
@StateObject private var selection = SelectedZimFileViewModel(isMultiSelection: false)
|
||||||
|
>>>>>>> f3ebab51 (Split and rename viewModels)
|
||||||
|
|
||||||
private let primaryItems: [MenuItem] = [.bookmarks]
|
private let primaryItems: [MenuItem] = [.bookmarks]
|
||||||
private let libraryItems: [MenuItem] = [.opened, .categories, .downloads, .new]
|
private let libraryItems: [MenuItem] = [.opened, .categories, .downloads, .new]
|
||||||
@ -231,9 +235,9 @@ struct RootView: View {
|
|||||||
Bookmarks()
|
Bookmarks()
|
||||||
.modifier(SearchFocused(isSearchFocused: isSearchFocused))
|
.modifier(SearchFocused(isSearchFocused: isSearchFocused))
|
||||||
case .opened:
|
case .opened:
|
||||||
ZimFilesOpened(dismiss: nil)
|
let multiSelection = SelectedZimFileViewModel(isMultiSelection: true)
|
||||||
.environmentObject(multiSelection)
|
ZimFilesOpened(selection: multiSelection, dismiss: nil)
|
||||||
.modifier(LibraryZimFileMultiSelectDetailSidePanel(viewModel: multiSelection))
|
.modifier(LibraryZimFileMultiSelectDetailSidePanel(selection: multiSelection))
|
||||||
case .categories:
|
case .categories:
|
||||||
ZimFilesCategories(dismiss: nil)
|
ZimFilesCategories(dismiss: nil)
|
||||||
.modifier(LibraryZimFileDetailSidePanel())
|
.modifier(LibraryZimFileDetailSidePanel())
|
||||||
|
@ -46,7 +46,7 @@ enum LibraryState {
|
|||||||
@MainActor
|
@MainActor
|
||||||
final class SelectedZimFileViewModel: ObservableObject {
|
final class SelectedZimFileViewModel: ObservableObject {
|
||||||
let isMultiSelection: Bool
|
let isMultiSelection: Bool
|
||||||
@Published private(set) var selectedZimFile: ZimFile?
|
@Published var selectedZimFile: ZimFile?
|
||||||
@Published private(set) var selectedZimFiles = Set<ZimFile>()
|
@Published private(set) var selectedZimFiles = Set<ZimFile>()
|
||||||
|
|
||||||
init(isMultiSelection: Bool) {
|
init(isMultiSelection: Bool) {
|
||||||
@ -70,7 +70,7 @@ final class SelectedZimFileViewModel: ObservableObject {
|
|||||||
selectedZimFiles = Set([zimFile])
|
selectedZimFiles = Set([zimFile])
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetSelection() {
|
func reset() {
|
||||||
selectedZimFile = nil
|
selectedZimFile = nil
|
||||||
selectedZimFiles.removeAll()
|
selectedZimFiles.removeAll()
|
||||||
}
|
}
|
||||||
@ -83,31 +83,7 @@ final class SelectedZimFileViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class LibraryMultiSelectViewModel: ObservableObject {
|
|
||||||
@Published private(set) var selectedZimFiles = Set<ZimFile>()
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func toggleMultiSelect(of zimFile: ZimFile) {
|
|
||||||
if selectedZimFiles.contains(zimFile) {
|
|
||||||
selectedZimFiles.remove(zimFile)
|
|
||||||
} else {
|
|
||||||
selectedZimFiles.insert(zimFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func singleSelect(zimFile: ZimFile) {
|
|
||||||
selectedZimFiles = Set([zimFile])
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func resetSelection() {
|
|
||||||
selectedZimFiles.removeAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class LibraryViewModel: ObservableObject {
|
final class LibraryViewModel: ObservableObject {
|
||||||
@Published var selectedZimFile: ZimFile?
|
|
||||||
@MainActor @Published private(set) var error: Error?
|
@MainActor @Published private(set) var error: Error?
|
||||||
/// Note: due to multiple instances of LibraryViewModel,
|
/// Note: due to multiple instances of LibraryViewModel,
|
||||||
/// this `state` should not be changed directly, modify the `process.state` instead
|
/// this `state` should not be changed directly, modify the `process.state` instead
|
||||||
|
@ -96,7 +96,7 @@ struct Library_Previews: PreviewProvider {
|
|||||||
|
|
||||||
/// On macOS, adds a panel to the right of the modified view to show zim file detail.
|
/// On macOS, adds a panel to the right of the modified view to show zim file detail.
|
||||||
struct LibraryZimFileMultiSelectDetailSidePanel: ViewModifier {
|
struct LibraryZimFileMultiSelectDetailSidePanel: ViewModifier {
|
||||||
@ObservedObject var viewModel: LibraryMultiSelectViewModel
|
@ObservedObject var selection: SelectedZimFileViewModel
|
||||||
@State private var isPresentingUnlinkAlert: Bool = false
|
@State private var isPresentingUnlinkAlert: Bool = false
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
@ -105,22 +105,22 @@ struct LibraryZimFileMultiSelectDetailSidePanel: ViewModifier {
|
|||||||
content.safeAreaInset(edge: .trailing, spacing: 0) {
|
content.safeAreaInset(edge: .trailing, spacing: 0) {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Divider()
|
Divider()
|
||||||
switch viewModel.selectedZimFiles.count {
|
switch selection.selectedZimFiles.count {
|
||||||
case 0:
|
case 0:
|
||||||
Message(text: LocalString.library_zim_file_details_side_panel_message)
|
Message(text: LocalString.library_zim_file_details_side_panel_message)
|
||||||
.background(.thickMaterial)
|
.background(.thickMaterial)
|
||||||
case 1:
|
case 1:
|
||||||
ZimFileDetail(zimFile: viewModel.selectedZimFiles.first!, dismissParent: nil)
|
ZimFileDetail(zimFile: selection.selectedZimFiles.first!, dismissParent: nil)
|
||||||
default:
|
default:
|
||||||
Action(title: LocalString.zim_file_action_unlink_title, isDestructive: true) {
|
Action(title: LocalString.zim_file_action_unlink_title, isDestructive: true) {
|
||||||
isPresentingUnlinkAlert = true
|
isPresentingUnlinkAlert = true
|
||||||
}.alert(isPresented: $isPresentingUnlinkAlert) {
|
}.alert(isPresented: $isPresentingUnlinkAlert) {
|
||||||
Alert(
|
Alert(
|
||||||
title: Text(LocalString.zim_file_action_unlink_title + " " + "\(viewModel.selectedZimFiles.count)"),
|
title: Text(LocalString.zim_file_action_unlink_title + " " + "\(selection.selectedZimFiles.count)"),
|
||||||
message: Text(LocalString.zim_file_action_unlink_message),
|
message: Text(LocalString.zim_file_action_unlink_message),
|
||||||
primaryButton: .destructive(Text(LocalString.zim_file_action_unlink_button_title)) {
|
primaryButton: .destructive(Text(LocalString.zim_file_action_unlink_button_title)) {
|
||||||
Task {
|
Task {
|
||||||
for zimFile in viewModel.selectedZimFiles {
|
for zimFile in selection.selectedZimFiles {
|
||||||
await LibraryOperations.unlink(zimFileID: zimFile.fileID)
|
await LibraryOperations.unlink(zimFileID: zimFile.fileID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,14 +131,14 @@ struct LibraryZimFileMultiSelectDetailSidePanel: ViewModifier {
|
|||||||
}
|
}
|
||||||
}.frame(width: 275).background(.ultraThinMaterial)
|
}.frame(width: 275).background(.ultraThinMaterial)
|
||||||
}
|
}
|
||||||
}.onAppear { viewModel.resetSelection() }
|
}.onAppear { selection.reset() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// On macOS, adds a panel to the right of the modified view to show zim file detail.
|
/// On macOS, adds a panel to the right of the modified view to show zim file detail.
|
||||||
struct LibraryZimFileDetailSidePanel: ViewModifier {
|
struct LibraryZimFileDetailSidePanel: ViewModifier {
|
||||||
@EnvironmentObject private var viewModel: LibraryViewModel
|
@EnvironmentObject private var selection: SelectedZimFileViewModel
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
@ -146,7 +146,7 @@ struct LibraryZimFileDetailSidePanel: ViewModifier {
|
|||||||
content.safeAreaInset(edge: .trailing, spacing: 0) {
|
content.safeAreaInset(edge: .trailing, spacing: 0) {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Divider()
|
Divider()
|
||||||
if let zimFile = viewModel.selectedZimFile {
|
if let zimFile = selection.selectedZimFile {
|
||||||
ZimFileDetail(zimFile: zimFile, dismissParent: nil)
|
ZimFileDetail(zimFile: zimFile, dismissParent: nil)
|
||||||
} else {
|
} else {
|
||||||
Message(text: LocalString.library_zim_file_details_side_panel_message)
|
Message(text: LocalString.library_zim_file_details_side_panel_message)
|
||||||
@ -154,7 +154,7 @@ struct LibraryZimFileDetailSidePanel: ViewModifier {
|
|||||||
}
|
}
|
||||||
}.frame(width: 275).background(.ultraThinMaterial)
|
}.frame(width: 275).background(.ultraThinMaterial)
|
||||||
}
|
}
|
||||||
}.onAppear { viewModel.selectedZimFile = nil }
|
}.onAppear { selection.selectedZimFile = nil }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -162,41 +162,39 @@ struct LibraryZimFileDetailSidePanel: ViewModifier {
|
|||||||
/// On macOS, converts the modified view to a Button that modifies the currently selected zim file
|
/// On macOS, converts the modified view to a Button that modifies the currently selected zim file
|
||||||
/// On iOS, converts the modified view to a NavigationLink that goes to the zim file detail.
|
/// On iOS, converts the modified view to a NavigationLink that goes to the zim file detail.
|
||||||
struct LibraryZimFileContext<Content: View>: View {
|
struct LibraryZimFileContext<Content: View>: View {
|
||||||
@EnvironmentObject private var viewModel: LibraryViewModel
|
@ObservedObject var selection: SelectedZimFileViewModel
|
||||||
|
|
||||||
private let content: Content
|
private let content: Content
|
||||||
private let zimFile: ZimFile
|
private let zimFile: ZimFile
|
||||||
/// iOS only
|
/// iOS only
|
||||||
private let dismiss: (() -> Void)?
|
private let dismiss: (() -> Void)?
|
||||||
/// macOS only
|
|
||||||
private let onMultiSelected: ((Bool) -> Void)?
|
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@ViewBuilder content: () -> Content,
|
@ViewBuilder content: () -> Content,
|
||||||
zimFile: ZimFile,
|
zimFile: ZimFile,
|
||||||
onMultiSelected: ((Bool) -> Void)? = nil,
|
selection: SelectedZimFileViewModel,
|
||||||
dismiss: (() -> Void)? = nil
|
dismiss: (() -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
self.content = content()
|
self.content = content()
|
||||||
self.zimFile = zimFile
|
self.zimFile = zimFile
|
||||||
self.onMultiSelected = onMultiSelected
|
self.selection = selection
|
||||||
self.dismiss = dismiss
|
self.dismiss = dismiss
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
if let onMultiSelected {
|
if selection.isMultiSelection {
|
||||||
content
|
content
|
||||||
.gesture(TapGesture().modifiers(.command).onEnded({ value in
|
.gesture(TapGesture().modifiers(.command).onEnded({ value in
|
||||||
onMultiSelected(true)
|
selection.toggleMultiSelect(of: zimFile)
|
||||||
}))
|
}))
|
||||||
.gesture(TapGesture().onEnded({ _ in
|
.gesture(TapGesture().onEnded({ _ in
|
||||||
onMultiSelected(false)
|
selection.singleSelect(zimFile: zimFile)
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
content.onTapGesture {
|
content.onTapGesture {
|
||||||
viewModel.selectedZimFile = zimFile
|
selection.singleSelect(zimFile: zimFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
|
@ -282,14 +282,14 @@ private struct FileLocator: ViewModifier {
|
|||||||
|
|
||||||
private struct DownloadTaskDetail: View {
|
private struct DownloadTaskDetail: View {
|
||||||
@ObservedObject var downloadZimFile: ZimFile
|
@ObservedObject var downloadZimFile: ZimFile
|
||||||
@EnvironmentObject var viewModel: LibraryViewModel
|
@EnvironmentObject var selection: SelectedZimFileViewModel
|
||||||
@State private var downloadState = DownloadState.empty()
|
@State private var downloadState = DownloadState.empty()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
Action(title: LocalString.zim_file_download_task_action_title_cancel, isDestructive: true) {
|
Action(title: LocalString.zim_file_download_task_action_title_cancel, isDestructive: true) {
|
||||||
DownloadService.shared.cancel(zimFileID: downloadZimFile.fileID)
|
DownloadService.shared.cancel(zimFileID: downloadZimFile.fileID)
|
||||||
viewModel.selectedZimFile = nil
|
selection.reset()
|
||||||
}
|
}
|
||||||
if let error = downloadZimFile.downloadTask?.error {
|
if let error = downloadZimFile.downloadTask?.error {
|
||||||
if downloadState.resumeData != nil {
|
if downloadState.resumeData != nil {
|
||||||
|
@ -105,6 +105,7 @@ private struct CategoryGrid: View {
|
|||||||
@Binding var searchText: String
|
@Binding var searchText: String
|
||||||
@Default(.libraryLanguageCodes) private var languageCodes
|
@Default(.libraryLanguageCodes) private var languageCodes
|
||||||
@EnvironmentObject private var viewModel: LibraryViewModel
|
@EnvironmentObject private var viewModel: LibraryViewModel
|
||||||
|
@EnvironmentObject private var selection: SelectedZimFileViewModel
|
||||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
@SectionedFetchRequest private var sections: SectionedFetchResults<String, ZimFile>
|
@SectionedFetchRequest private var sections: SectionedFetchResults<String, ZimFile>
|
||||||
private let dismiss: (() -> Void)? // iOS only
|
private let dismiss: (() -> Void)? // iOS only
|
||||||
@ -142,6 +143,7 @@ private struct CategoryGrid: View {
|
|||||||
LibraryZimFileContext(
|
LibraryZimFileContext(
|
||||||
content: { ZimFileCell(zimFile, prominent: .size) },
|
content: { ZimFileCell(zimFile, prominent: .size) },
|
||||||
zimFile: zimFile,
|
zimFile: zimFile,
|
||||||
|
selection: selection,
|
||||||
dismiss: dismiss)
|
dismiss: dismiss)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -150,6 +152,7 @@ private struct CategoryGrid: View {
|
|||||||
LibraryZimFileContext(
|
LibraryZimFileContext(
|
||||||
content: { ZimFileCell(zimFile, prominent: .size) },
|
content: { ZimFileCell(zimFile, prominent: .size) },
|
||||||
zimFile: zimFile,
|
zimFile: zimFile,
|
||||||
|
selection: selection,
|
||||||
dismiss: dismiss)
|
dismiss: dismiss)
|
||||||
}
|
}
|
||||||
} header: {
|
} header: {
|
||||||
@ -173,7 +176,7 @@ private struct CategoryGrid: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.searchable(text: $searchText)
|
.searchable(text: $searchText)
|
||||||
.onChange(of: category) { _ in viewModel.selectedZimFile = nil }
|
.onChange(of: category) { _ in selection.reset() }
|
||||||
.onChange(of: searchText) { _ in
|
.onChange(of: searchText) { _ in
|
||||||
sections.nsPredicate = ZimFilesCategory.buildPredicate(category: category, searchText: searchText)
|
sections.nsPredicate = ZimFilesCategory.buildPredicate(category: category, searchText: searchText)
|
||||||
}
|
}
|
||||||
@ -211,6 +214,7 @@ private struct CategoryList: View {
|
|||||||
@Binding var searchText: String
|
@Binding var searchText: String
|
||||||
@Default(.libraryLanguageCodes) private var languageCodes
|
@Default(.libraryLanguageCodes) private var languageCodes
|
||||||
@EnvironmentObject private var viewModel: LibraryViewModel
|
@EnvironmentObject private var viewModel: LibraryViewModel
|
||||||
|
@EnvironmentObject private var selection: SelectedZimFileViewModel
|
||||||
@FetchRequest private var zimFiles: FetchedResults<ZimFile>
|
@FetchRequest private var zimFiles: FetchedResults<ZimFile>
|
||||||
private let dismiss: (() -> Void)?
|
private let dismiss: (() -> Void)?
|
||||||
|
|
||||||
@ -247,10 +251,11 @@ private struct CategoryList: View {
|
|||||||
Message(text: LocalString.zim_file_category_section_empty_message)
|
Message(text: LocalString.zim_file_category_section_empty_message)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List(zimFiles, id: \.self, selection: $viewModel.selectedZimFile) { zimFile in
|
List(zimFiles, id: \.self, selection: $selection.selectedZimFile) { zimFile in
|
||||||
LibraryZimFileContext(
|
LibraryZimFileContext(
|
||||||
content: { ZimFileRow(zimFile) },
|
content: { ZimFileRow(zimFile) },
|
||||||
zimFile: zimFile,
|
zimFile: zimFile,
|
||||||
|
selection: selection,
|
||||||
dismiss: dismiss)
|
dismiss: dismiss)
|
||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@ -261,7 +266,7 @@ private struct CategoryList: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.searchable(text: $searchText)
|
.searchable(text: $searchText)
|
||||||
.onChange(of: category) { _ in viewModel.selectedZimFile = nil }
|
.onChange(of: category) { _ in selection.reset() }
|
||||||
.onChange(of: searchText) { _ in
|
.onChange(of: searchText) { _ in
|
||||||
zimFiles.nsPredicate = ZimFilesCategory.buildPredicate(category: category, searchText: searchText)
|
zimFiles.nsPredicate = ZimFilesCategory.buildPredicate(category: category, searchText: searchText)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import SwiftUI
|
|||||||
|
|
||||||
/// A grid of zim files that are being downloaded.
|
/// A grid of zim files that are being downloaded.
|
||||||
struct ZimFilesDownloads: View {
|
struct ZimFilesDownloads: View {
|
||||||
|
@EnvironmentObject var selection: SelectedZimFileViewModel
|
||||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
@FetchRequest(
|
@FetchRequest(
|
||||||
sortDescriptors: [NSSortDescriptor(keyPath: \DownloadTask.created, ascending: false)],
|
sortDescriptors: [NSSortDescriptor(keyPath: \DownloadTask.created, ascending: false)],
|
||||||
@ -39,6 +40,7 @@ struct ZimFilesDownloads: View {
|
|||||||
LibraryZimFileContext(
|
LibraryZimFileContext(
|
||||||
content: { DownloadTaskCell(zimFile) },
|
content: { DownloadTaskCell(zimFile) },
|
||||||
zimFile: zimFile,
|
zimFile: zimFile,
|
||||||
|
selection: selection,
|
||||||
dismiss: dismiss)
|
dismiss: dismiss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ private final class ViewModel: ObservableObject {
|
|||||||
/// A grid of zim files that are newly available.
|
/// A grid of zim files that are newly available.
|
||||||
struct ZimFilesNew: View {
|
struct ZimFilesNew: View {
|
||||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
|
@EnvironmentObject private var selection: SelectedZimFileViewModel
|
||||||
@EnvironmentObject var library: LibraryViewModel
|
@EnvironmentObject var library: LibraryViewModel
|
||||||
@Default(.libraryLanguageCodes) private var languageCodes
|
@Default(.libraryLanguageCodes) private var languageCodes
|
||||||
@StateObject private var viewModel = ViewModel()
|
@StateObject private var viewModel = ViewModel()
|
||||||
@ -115,6 +116,7 @@ struct ZimFilesNew: View {
|
|||||||
ZimFileCell(zimFile, prominent: .name)
|
ZimFileCell(zimFile, prominent: .name)
|
||||||
},
|
},
|
||||||
zimFile: zimFile,
|
zimFile: zimFile,
|
||||||
|
selection: selection,
|
||||||
dismiss: dismiss)
|
dismiss: dismiss)
|
||||||
.transition(AnyTransition.opacity)
|
.transition(AnyTransition.opacity)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct ZimFilesOpened: View {
|
|||||||
animation: .easeInOut
|
animation: .easeInOut
|
||||||
) private var zimFiles: FetchedResults<ZimFile>
|
) private var zimFiles: FetchedResults<ZimFile>
|
||||||
@State private var isFileImporterPresented = false
|
@State private var isFileImporterPresented = false
|
||||||
@EnvironmentObject private var viewModel: SelectedZimFileViewModel
|
@ObservedObject var selection: SelectedZimFileViewModel
|
||||||
let dismiss: (() -> Void)? // iOS only
|
let dismiss: (() -> Void)? // iOS only
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@ -35,28 +35,16 @@ struct ZimFilesOpened: View {
|
|||||||
spacing: 12
|
spacing: 12
|
||||||
) {
|
) {
|
||||||
ForEach(zimFiles) { zimFile in
|
ForEach(zimFiles) { zimFile in
|
||||||
let multiSelected: ((Bool) -> Void)? = if viewModel.isMultiSelection {
|
|
||||||
{ [zimFile] isSelectionMulti in
|
|
||||||
if isSelectionMulti {
|
|
||||||
viewModel.toggleMultiSelect(of: zimFile)
|
|
||||||
} else {
|
|
||||||
viewModel.singleSelect(zimFile: zimFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nil
|
|
||||||
}
|
|
||||||
|
|
||||||
LibraryZimFileContext(
|
LibraryZimFileContext(
|
||||||
content: {
|
content: {
|
||||||
ZimFileCell(
|
ZimFileCell(
|
||||||
zimFile,
|
zimFile,
|
||||||
prominent: .name,
|
prominent: .name,
|
||||||
isSelected: viewModel.isSelected(zimFile)
|
isSelected: selection.isSelected(zimFile)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
zimFile: zimFile,
|
zimFile: zimFile,
|
||||||
onMultiSelected: multiSelected,
|
selection: selection,
|
||||||
dismiss: dismiss)
|
dismiss: dismiss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,9 +58,9 @@ struct ZimFilesOpened: View {
|
|||||||
}
|
}
|
||||||
.onChange(of: zimFiles.count) { _ in
|
.onChange(of: zimFiles.count) { _ in
|
||||||
if let firstZimFile = zimFiles.first {
|
if let firstZimFile = zimFiles.first {
|
||||||
viewModel.singleSelect(zimFile: firstZimFile)
|
selection.singleSelect(zimFile: firstZimFile)
|
||||||
} else {
|
} else {
|
||||||
viewModel.resetSelection()
|
selection.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not using OpenFileButton here, because it does not work on iOS/iPadOS 15 when this view is in a modal
|
// not using OpenFileButton here, because it does not work on iOS/iPadOS 15 when this view is in a modal
|
||||||
|
@ -18,19 +18,17 @@ import SwiftUI
|
|||||||
enum CellBackground {
|
enum CellBackground {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
private static let normal: Color = Color(nsColor: NSColor.controlBackgroundColor)
|
private static let normal: Color = Color(nsColor: NSColor.controlBackgroundColor)
|
||||||
private static let hover: Color = Color(nsColor: NSColor.selectedControlColor)
|
|
||||||
private static let selected: Color = Color(nsColor: NSColor.selectedControlColor)
|
private static let selected: Color = Color(nsColor: NSColor.selectedControlColor)
|
||||||
private static let hoverSelected: Color = Color(nsColor: NSColor.selectedControlColor)
|
|
||||||
#else
|
#else
|
||||||
private static let normal: Color = .secondaryBackground
|
private static let normal: Color = .secondaryBackground
|
||||||
private static let hover: Color = .tertiaryBackground
|
private static let selected: Color = .tertiaryBackground
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static func colorFor(isHovering: Bool, isSelected: Bool = false) -> Color {
|
static func colorFor(isHovering: Bool, isSelected: Bool = false) -> Color {
|
||||||
if isSelected {
|
if isSelected {
|
||||||
isHovering ? hoverSelected : selected
|
isHovering ? selected.opacity(0.75) : selected
|
||||||
} else {
|
} else {
|
||||||
isHovering ? hover : normal
|
isHovering ? selected.opacity(0.5) : normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user