diff --git a/Nextcloud Cookbook iOS Client.xcodeproj/project.xcworkspace/xcuserdata/vincie.xcuserdatad/UserInterfaceState.xcuserstate b/Nextcloud Cookbook iOS Client.xcodeproj/project.xcworkspace/xcuserdata/vincie.xcuserdatad/UserInterfaceState.xcuserstate index 7ba3580..c61aa18 100644 Binary files a/Nextcloud Cookbook iOS Client.xcodeproj/project.xcworkspace/xcuserdata/vincie.xcuserdatad/UserInterfaceState.xcuserstate and b/Nextcloud Cookbook iOS Client.xcodeproj/project.xcworkspace/xcuserdata/vincie.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Nextcloud Cookbook iOS Client/Localizable.xcstrings b/Nextcloud Cookbook iOS Client/Localizable.xcstrings index 9c834ce..d2d72be 100644 --- a/Nextcloud Cookbook iOS Client/Localizable.xcstrings +++ b/Nextcloud Cookbook iOS Client/Localizable.xcstrings @@ -1194,6 +1194,9 @@ } } } + }, + "Deletion successful." : { + }, "Description" : { "localizations" : { @@ -2720,6 +2723,9 @@ } } } + }, + "Recipe upload successful." : { + }, "Recipes" : { "localizations" : { @@ -3253,6 +3259,9 @@ } } } + }, + "Success!" : { + }, "Sugar content" : { "comment" : "Sugar content", diff --git a/Nextcloud Cookbook iOS Client/Util/Alerts.swift b/Nextcloud Cookbook iOS Client/Util/Alerts.swift index 6608936..f435240 100644 --- a/Nextcloud Cookbook iOS Client/Util/Alerts.swift +++ b/Nextcloud Cookbook iOS Client/Util/Alerts.swift @@ -30,7 +30,9 @@ enum RecipeAlert: UserAlert { case NO_TITLE, DUPLICATE, UPLOAD_ERROR, + UPLOAD_SUCCESS, CONFIRM_DELETE, + DELETE_SUCCESS, LOGIN_FAILED, GENERIC, CUSTOM(title: LocalizedStringKey, description: LocalizedStringKey) @@ -43,8 +45,12 @@ enum RecipeAlert: UserAlert { return "A recipe with that name already exists." case .UPLOAD_ERROR: return "Unable to upload your recipe. Please check your internet connection." + case .UPLOAD_SUCCESS: + return "Recipe upload successful." case .CONFIRM_DELETE: return "This action is not reversible!" + case .DELETE_SUCCESS: + return "Deletion successful." case .LOGIN_FAILED: return "Please check your credentials and internet connection." case .CUSTOM(title: _, description: let description): @@ -62,8 +68,12 @@ enum RecipeAlert: UserAlert { return "Duplicate recipe." case .UPLOAD_ERROR: return "Network error." + case .UPLOAD_SUCCESS: + return "Success!" case .CONFIRM_DELETE: return "Delete recipe?" + case .DELETE_SUCCESS: + return "Success!" case .LOGIN_FAILED: return "Login failed." case .CUSTOM(title: let title, description: _): @@ -113,12 +123,14 @@ enum RecipeImportAlert: UserAlert { enum RequestAlert: UserAlert { case REQUEST_DELAYED, - REQUEST_DROPPED + REQUEST_DROPPED, + REQUEST_SUCCESS var localizedDescription: LocalizedStringKey { switch self { case .REQUEST_DELAYED: return "Could not establish a connection to the server. The action will be retried upon reconnection." case .REQUEST_DROPPED: return "Unable to complete action." + case .REQUEST_SUCCESS: return "" } } @@ -126,6 +138,7 @@ enum RequestAlert: UserAlert { switch self { case .REQUEST_DELAYED: return "Action delayed" case .REQUEST_DROPPED: return "Error" + case .REQUEST_SUCCESS: return "Success!" } } diff --git a/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeListView.swift b/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeListView.swift index 56480fd..7911346 100644 --- a/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeListView.swift +++ b/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeListView.swift @@ -37,7 +37,7 @@ struct RecipeListView: View { } } .navigationDestination(for: Recipe.self) { recipe in - RecipeView(isPresented: .constant(true), viewModel: RecipeView.ViewModel(recipe: recipe)) + RecipeView(viewModel: RecipeView.ViewModel(recipe: recipe)) .environmentObject(appState) .environmentObject(groceryList) } diff --git a/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeView.swift b/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeView.swift index fbc5b76..99a2edc 100644 --- a/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeView.swift +++ b/Nextcloud Cookbook iOS Client/Views/Recipes/RecipeView.swift @@ -11,8 +11,10 @@ import SwiftUI struct RecipeView: View { @EnvironmentObject var appState: AppState - @Binding var isPresented: Bool + @Environment(\.dismiss) private var dismiss @StateObject var viewModel: ViewModel + @GestureState private var dragOffset = CGSize.zero + var imageHeight: CGFloat { if let image = viewModel.recipeImage { return image.size.height < 350 ? image.size.height : 350 @@ -115,8 +117,9 @@ struct RecipeView: View { .toolbar(.visible, for: .navigationBar) //.toolbarTitleDisplayMode(.inline) .navigationTitle(viewModel.showTitle ? viewModel.recipe.name : "") + .toolbar { - RecipeViewToolBar(isPresented: $isPresented, viewModel: viewModel) + RecipeViewToolBar(viewModel: viewModel) } .sheet(isPresented: $viewModel.presentShareSheet) { ShareView(recipeDetail: viewModel.observableRecipeDetail.toRecipeDetail(), @@ -313,16 +316,18 @@ extension RecipeView { struct RecipeViewToolBar: ToolbarContent { @EnvironmentObject var appState: AppState - @Binding var isPresented: Bool + @Environment(\.dismiss) private var dismiss @ObservedObject var viewModel: RecipeView.ViewModel var body: some ToolbarContent { if viewModel.editMode { - ToolbarItemGroup(placement: .topBarLeading){ + ToolbarItemGroup(placement: .topBarLeading) { Button("Cancel") { viewModel.editMode = false - isPresented = false + if viewModel.newRecipe { + dismiss() + } } if !viewModel.newRecipe { @@ -407,9 +412,10 @@ struct RecipeViewToolBar: ToolbarContent { await appState.getCategories() await appState.getCategory(named: viewModel.observableRecipeDetail.recipeCategory, fetchMode: .preferServer) if let id = Int(viewModel.observableRecipeDetail.id) { - await appState.getRecipe(id: id, fetchMode: .onlyServer, save: true) + let _ = await appState.getRecipe(id: id, fetchMode: .onlyServer, save: true) } viewModel.editMode = false + viewModel.presentAlert(RecipeAlert.UPLOAD_SUCCESS) } func handleDelete() async { @@ -424,7 +430,8 @@ struct RecipeViewToolBar: ToolbarContent { } await appState.getCategories() await appState.getCategory(named: category, fetchMode: .preferServer) - self.isPresented = false + viewModel.presentAlert(RecipeAlert.DELETE_SUCCESS) + dismiss() } func recipeValid() -> RecipeAlert? { diff --git a/Nextcloud Cookbook iOS Client/Views/SettingsView.swift b/Nextcloud Cookbook iOS Client/Views/SettingsView.swift index 17387ae..cc49369 100644 --- a/Nextcloud Cookbook iOS Client/Views/SettingsView.swift +++ b/Nextcloud Cookbook iOS Client/Views/SettingsView.swift @@ -227,10 +227,12 @@ extension SettingsView { func getUserData() async { let (data, _) = await NextcloudApi.getAvatar() - avatarImage = data - let (userData, _) = await NextcloudApi.getHoverCard() - self.userData = userData + + DispatchQueue.main.async { + self.avatarImage = data + self.userData = userData + } } } } diff --git a/Nextcloud Cookbook iOS Client/Views/Tabs/RecipeTabView.swift b/Nextcloud Cookbook iOS Client/Views/Tabs/RecipeTabView.swift index 56d65d4..8e10b75 100644 --- a/Nextcloud Cookbook iOS Client/Views/Tabs/RecipeTabView.swift +++ b/Nextcloud Cookbook iOS Client/Views/Tabs/RecipeTabView.swift @@ -54,7 +54,7 @@ struct RecipeTabView: View { .environmentObject(appState) } .navigationDestination(isPresented: $viewModel.presentEditView) { - RecipeView(isPresented: $viewModel.presentEditView, viewModel: RecipeView.ViewModel()) + RecipeView(viewModel: RecipeView.ViewModel()) .environmentObject(appState) .environmentObject(groceryList) } diff --git a/Nextcloud Cookbook iOS Client/Views/Tabs/SearchTabView.swift b/Nextcloud Cookbook iOS Client/Views/Tabs/SearchTabView.swift index e648ea0..7a4cfae 100644 --- a/Nextcloud Cookbook iOS Client/Views/Tabs/SearchTabView.swift +++ b/Nextcloud Cookbook iOS Client/Views/Tabs/SearchTabView.swift @@ -34,7 +34,7 @@ struct SearchTabView: View { } } .navigationDestination(for: Recipe.self) { recipe in - RecipeView(isPresented: .constant(true), viewModel: RecipeView.ViewModel(recipe: recipe)) + RecipeView(viewModel: RecipeView.ViewModel(recipe: recipe)) } .searchable(text: $viewModel.searchText, prompt: "Search recipes/keywords") }