diff --git a/iosVariant/Variant.xcodeproj/project.pbxproj b/iosVariant/Variant.xcodeproj/project.pbxproj index 9a37b03b..3e52e86d 100644 --- a/iosVariant/Variant.xcodeproj/project.pbxproj +++ b/iosVariant/Variant.xcodeproj/project.pbxproj @@ -256,6 +256,9 @@ knownRegions = ( en, Base, + es, + fr, + "pt-BR", ); mainGroup = 7555FF72242A565900829871; packageReferences = ( diff --git a/iosVariant/iosVariant/HomeView.swift b/iosVariant/iosVariant/HomeView.swift index 31e84202..d52a236f 100644 --- a/iosVariant/iosVariant/HomeView.swift +++ b/iosVariant/iosVariant/HomeView.swift @@ -59,24 +59,96 @@ struct HomeView: View { } }, onDeleteComics: { - Log().info(tag: TAG, message: "Deleting \(variantViewModel.selectionList.count) comic book(s)") + Log().info( + tag: TAG, + message: + "Deleting \(variantViewModel.selectionList.count) comic book(s)" + ) Task { try await variantViewModel.deleteSelections() } } ) .tag(AppDestination.comics) - .tabItem { Label("Comics", systemImage: "book.fill") } + .tabItem { + Label( + String( + localized: "destination.comics.label", + defaultValue: "Comics" + ), + systemImage: "book.fill" + ) + } - ServerView() - .tag(AppDestination.browseServer) - .tabItem { - Label("Browse", systemImage: "person.crop.circle.fill") + ServerView( + comicBookList: self.variantViewModel.comicBookList, + currentPath: self.variantViewModel.browsingState.currentPath, + title: self.variantViewModel.browsingState.title, + parentPath: self.variantViewModel.browsingState.parentPath, + directoryContents: self.variantViewModel.browsingState.contents, + downloadingState: self.variantViewModel.browsingState + .downloadingState, + loading: self.variantViewModel.loading, + onLoadDirectory: { path, reload in + Log().debug( + tag: TAG, + message: "Loading path: \(path) reload=\(reload)" + ) + self.variantViewModel.loadDirectory( + path: path, + reload: reload + ) + }, + onDownloadFile: { path, filename in + Task { + Log().debug( + tag: TAG, + message: "Downloading file: \(filename)" + ) + + self.variantViewModel.downloadFile( + path: path, + filename: filename + ) + } } + ) + .tag(AppDestination.browseServer) + .tabItem { + Label( + String( + localized: "destination.browse-server.label", + defaultValue: "Browse" + ), + systemImage: "person.crop.circle.fill" + ) + } - SettingsView() - .tag(AppDestination.settings) - .tabItem { Label("Settings", systemImage: "gearshape.fill") } + SettingsView( + address: variantViewModel.address, + username: variantViewModel.username, + password: variantViewModel.password, + onSaveChanges: { address, username, password in + Log().debug( + tag: TAG, + message: + "Saving server settings: \(address), \(username), \(password)" + ) + variantViewModel.address = address + variantViewModel.username = username + variantViewModel.password = password + } + ) + .tag(AppDestination.settings) + .tabItem { + Label( + String( + localized: "destination.settings.label", + defaultValue: "Settings" + ), + systemImage: "gearshape.fill" + ) + } } .edgesIgnoringSafeArea(.bottom) .onChange(of: currentDestination) { tab in diff --git a/iosVariant/iosVariant/Views/Comics/ComicBookListView.swift b/iosVariant/iosVariant/Views/Comics/ComicBookListView.swift index d4e307f0..ff5c875e 100644 --- a/iosVariant/iosVariant/Views/Comics/ComicBookListView.swift +++ b/iosVariant/iosVariant/Views/Comics/ComicBookListView.swift @@ -46,7 +46,12 @@ struct ComicBookListView: View { } .padding(.horizontal) } - .navigationTitle("Comic List") + .navigationTitle( + String( + localized: "comic-book-list.title", + defaultValue: "Comic List" + ) + ) } } } diff --git a/iosVariant/iosVariant/Views/Servers/BrowseServerView.swift b/iosVariant/iosVariant/Views/Servers/BrowseServerView.swift index 8b4633c4..5e563aea 100644 --- a/iosVariant/iosVariant/Views/Servers/BrowseServerView.swift +++ b/iosVariant/iosVariant/Views/Servers/BrowseServerView.swift @@ -23,8 +23,7 @@ import shared private let TAG = "BrowseServerView" struct BrowseServerView: View { - @EnvironmentViewModel var variantViewModel: VariantViewModel - + let comicBookList: [ComicBook] let path: String let title: String let parentPath: String @@ -44,8 +43,8 @@ struct BrowseServerView: View { } var body: some View { - ZStack { - NavigationStack { + NavigationStack { + ZStack { List(directoryContents, id: \.id, selection: $selected) { entry in if entry.isDirectory { @@ -62,7 +61,7 @@ struct BrowseServerView: View { } else { FileItemView( entry: entry, - comicBookFiles: variantViewModel.comicBookList.map { + comicBookFiles: comicBookList.map { $0.filename }, downloadingState: downloadingState, @@ -70,48 +69,67 @@ struct BrowseServerView: View { ) } } - .refreshable { - if !loading { - Log().info( - tag: TAG, - message: - "Reloading path: \(variantViewModel.browsingState.currentPath)" - ) - onLoadDirectory( - variantViewModel.browsingState.currentPath, - true - ) - } + .grayscale(loading ? 1 : 0) + + if loading { + ProgressView() } - .navigationTitle(displayableTitle) - .toolbar { - if parentPath != "" { - ToolbarItem(placement: .topBarLeading) { - Button("Back") { - Log().info( - tag: TAG, - message: "Loading parent: \(parentPath)" - ) - onLoadDirectory(parentPath, false) - } + } + + .refreshable { + if !loading { + Log().info( + tag: TAG, + message: + "Reloading path: \(path)" + ) + onLoadDirectory( + path, + true + ) + } + } + .navigationTitle(displayableTitle) + .toolbar { + if parentPath != "" { + ToolbarItem(placement: .topBarLeading) { + Button { + Log().info( + tag: TAG, + message: "Loading parent: \(parentPath)" + ) + onLoadDirectory(parentPath, false) + } label: { + Image(systemName: "arrow.backward") } } } } - - if loading { - ProgressView() - } } } } -#Preview("normal") { +#Preview("directories") { + BrowseServerView( + comicBookList: COMIC_BOOK_LIST, + path: "/reader/v1", + title: "", + parentPath: "", + directoryContents: DIRECTORY_LIST.filter { $0.isDirectory }, + downloadingState: [], + loading: false, + onLoadDirectory: { _, _ in }, + onDownloadFile: { _, _ in } + ) +} + +#Preview("files") { BrowseServerView( + comicBookList: COMIC_BOOK_LIST, path: "/reader/v1", title: "", parentPath: "", - directoryContents: DIRECTORY_LIST, + directoryContents: DIRECTORY_LIST.filter { $0.isDirectory == false }, downloadingState: [], loading: false, onLoadDirectory: { _, _ in }, @@ -121,10 +139,11 @@ struct BrowseServerView: View { #Preview("loading") { BrowseServerView( + comicBookList: COMIC_BOOK_LIST, path: "/reader/v1", title: "", parentPath: "", - directoryContents: DIRECTORY_LIST, + directoryContents: DIRECTORY_LIST.filter { $0.isDirectory }, downloadingState: [], loading: true, onLoadDirectory: { _, _ in }, diff --git a/iosVariant/iosVariant/Views/Servers/FileItemView.swift b/iosVariant/iosVariant/Views/Servers/FileItemView.swift index 372a5a68..fa922e06 100644 --- a/iosVariant/iosVariant/Views/Servers/FileItemView.swift +++ b/iosVariant/iosVariant/Views/Servers/FileItemView.swift @@ -53,23 +53,21 @@ struct FileItemView: View { var body: some View { HStack { if isDownloaded { - Button( - "", - systemImage: "checkmark.circle.fill", - action: {} - ) + Button { + + } label: { + Image(systemName: "checkmark.circle.fill") + } } else { - Button( - "", - systemImage: "plus.circle.fill", - action: { - Log().info( - tag: TAG, - message: "Downloading file: \(entry.path)" - ) - onDownloadFile(entry.path, entry.filename) - } - ) + Button { + Log().info( + tag: TAG, + message: "Downloading file: \(entry.path)" + ) + onDownloadFile(entry.path, entry.filename) + } label: { + Image(systemName: "plus.circle.fill") + } } VStack(alignment: .leading) { diff --git a/iosVariant/iosVariant/Views/Servers/ServerView.swift b/iosVariant/iosVariant/Views/Servers/ServerView.swift index 187fcee1..b4c39062 100644 --- a/iosVariant/iosVariant/Views/Servers/ServerView.swift +++ b/iosVariant/iosVariant/Views/Servers/ServerView.swift @@ -23,44 +23,42 @@ import shared private let TAG = "ServerView" struct ServerView: View { - @EnvironmentViewModel var variantViewModel: VariantViewModel + let comicBookList: [ComicBook] + let currentPath: String + let title: String + let parentPath: String + let directoryContents: [DirectoryEntry] + let downloadingState: [DownloadingState] + let loading: Bool + + let onLoadDirectory: (String, Bool) -> Void + let onDownloadFile: (String, String) -> Void var body: some View { BrowseServerView( - path: self.variantViewModel.browsingState.currentPath, - title: self.variantViewModel.browsingState.title, - parentPath: self.variantViewModel.browsingState.parentPath, - directoryContents: self.variantViewModel.browsingState.contents, - downloadingState: self.variantViewModel.browsingState - .downloadingState, - loading: self.variantViewModel.loading, - onLoadDirectory: { path, reload in - Log().debug( - tag: TAG, - message: "Loading path: \(path) reload=\(reload)" - ) - self.variantViewModel.loadDirectory( - path: path, - reload: reload - ) - }, - onDownloadFile: { path, filename in - Task { - Log().debug( - tag: TAG, - message: "Downloading file: \(filename)" - ) - - self.variantViewModel.downloadFile( - path: path, - filename: filename - ) - } - } + comicBookList: comicBookList, + path: currentPath, + title: title, + parentPath: parentPath, + directoryContents: directoryContents, + downloadingState: downloadingState, + loading: loading, + onLoadDirectory: onLoadDirectory, + onDownloadFile: onDownloadFile ) } } #Preview { - ServerView() + ServerView( + comicBookList: COMIC_BOOK_LIST, + currentPath: "The current path", + title: "The Title", + parentPath: "The parent path", + directoryContents: DIRECTORY_LIST, + downloadingState: [], + loading: false, + onLoadDirectory: { _, _ in }, + onDownloadFile: { _, _ in } + ) } diff --git a/iosVariant/iosVariant/Views/Settings/EditServerView.swift b/iosVariant/iosVariant/Views/Settings/EditServerView.swift index aec41126..1168aa7a 100644 --- a/iosVariant/iosVariant/Views/Settings/EditServerView.swift +++ b/iosVariant/iosVariant/Views/Settings/EditServerView.swift @@ -54,30 +54,57 @@ struct EditServerView: View { NavigationView { VStack { Section(header: Text("Server Details").font(.headline)) { - TextField("Server address", text: $addressValue) - .keyboardType(.URL) - .textContentType(.URL) - .disableAutocorrection(true) - .autocapitalization(.none) + TextField( + String( + localized: "edit-server.label.server-address", + defaultValue: "Server address" + ), + text: $addressValue + ) + .keyboardType(.URL) + .textContentType(.URL) + .disableAutocorrection(true) + .autocapitalization(.none) } - Section(header: Text("Account Details").font(.headline)) { - TextField("Username", text: $usernameValue) - .textContentType(.emailAddress) - .disableAutocorrection(true) - .autocapitalization(.none) - SecureField("Password", text: $passwordValue) - .textContentType(.password) - .disableAutocorrection(true) - .autocapitalization(.none) + Section( + header: Text( + String( + localized: "edit-server.header.account-details", + defaultValue: "Account Details" + ) + ).font(.headline) + ) { + TextField( + String( + localized: "edit-server.label.username", + defaultValue: "Username" + ), + text: $usernameValue + ) + .textContentType(.emailAddress) + .disableAutocorrection(true) + .autocapitalization(.none) + SecureField( + String( + localized: "edit-server.label.password", + defaultValue: "Password" + ), + text: $passwordValue + ) + .textContentType(.password) + .disableAutocorrection(true) + .autocapitalization(.none) } Spacer() } .padding() .toolbar { - Button("Save") { + Button { onSaveChanges(addressValue, usernameValue, passwordValue) + } label: { + Image(systemName: "checkmark.circle.fill") } } }.navigationViewStyle(StackNavigationViewStyle()) diff --git a/iosVariant/iosVariant/Views/Settings/SettingsView.swift b/iosVariant/iosVariant/Views/Settings/SettingsView.swift index 8bc7fb77..3d0e6f50 100644 --- a/iosVariant/iosVariant/Views/Settings/SettingsView.swift +++ b/iosVariant/iosVariant/Views/Settings/SettingsView.swift @@ -23,29 +23,29 @@ import shared private let TAG = "SettingsView" struct SettingsView: View { - @EnvironmentViewModel var variantViewModel: VariantViewModel + let address: String + let username: String + let password: String + + let onSaveChanges: (String, String, String) -> Void var body: some View { VStack { EditServerView( - address: variantViewModel.address, - username: variantViewModel.username, - password: variantViewModel.password, - onSaveChanges: { address, username, password in - Log().debug( - tag: TAG, - message: - "Saving server settings: \(address), \(username), \(password)" - ) - variantViewModel.address = address - variantViewModel.username = username - variantViewModel.password = password - } + address: address, + username: username, + password: password, + onSaveChanges: onSaveChanges ) } } } #Preview { - SettingsView() + SettingsView( + address: "http://www.comixedproject.org:7171", + username: "reader@comixedproject.org", + password: "the!password", + onSaveChanges: { _, _, _ in } + ) }