Bug fixes and UI polish

This commit is contained in:
VincentMeilinger
2024-03-10 11:56:51 +01:00
parent 29872611da
commit 2c749754f4
8 changed files with 45 additions and 14 deletions

View File

@@ -1194,6 +1194,9 @@
} }
} }
} }
},
"Deletion successful." : {
}, },
"Description" : { "Description" : {
"localizations" : { "localizations" : {
@@ -2720,6 +2723,9 @@
} }
} }
} }
},
"Recipe upload successful." : {
}, },
"Recipes" : { "Recipes" : {
"localizations" : { "localizations" : {
@@ -3253,6 +3259,9 @@
} }
} }
} }
},
"Success!" : {
}, },
"Sugar content" : { "Sugar content" : {
"comment" : "Sugar content", "comment" : "Sugar content",

View File

@@ -30,7 +30,9 @@ enum RecipeAlert: UserAlert {
case NO_TITLE, case NO_TITLE,
DUPLICATE, DUPLICATE,
UPLOAD_ERROR, UPLOAD_ERROR,
UPLOAD_SUCCESS,
CONFIRM_DELETE, CONFIRM_DELETE,
DELETE_SUCCESS,
LOGIN_FAILED, LOGIN_FAILED,
GENERIC, GENERIC,
CUSTOM(title: LocalizedStringKey, description: LocalizedStringKey) CUSTOM(title: LocalizedStringKey, description: LocalizedStringKey)
@@ -43,8 +45,12 @@ enum RecipeAlert: UserAlert {
return "A recipe with that name already exists." return "A recipe with that name already exists."
case .UPLOAD_ERROR: case .UPLOAD_ERROR:
return "Unable to upload your recipe. Please check your internet connection." return "Unable to upload your recipe. Please check your internet connection."
case .UPLOAD_SUCCESS:
return "Recipe upload successful."
case .CONFIRM_DELETE: case .CONFIRM_DELETE:
return "This action is not reversible!" return "This action is not reversible!"
case .DELETE_SUCCESS:
return "Deletion successful."
case .LOGIN_FAILED: case .LOGIN_FAILED:
return "Please check your credentials and internet connection." return "Please check your credentials and internet connection."
case .CUSTOM(title: _, description: let description): case .CUSTOM(title: _, description: let description):
@@ -62,8 +68,12 @@ enum RecipeAlert: UserAlert {
return "Duplicate recipe." return "Duplicate recipe."
case .UPLOAD_ERROR: case .UPLOAD_ERROR:
return "Network error." return "Network error."
case .UPLOAD_SUCCESS:
return "Success!"
case .CONFIRM_DELETE: case .CONFIRM_DELETE:
return "Delete recipe?" return "Delete recipe?"
case .DELETE_SUCCESS:
return "Success!"
case .LOGIN_FAILED: case .LOGIN_FAILED:
return "Login failed." return "Login failed."
case .CUSTOM(title: let title, description: _): case .CUSTOM(title: let title, description: _):
@@ -113,12 +123,14 @@ enum RecipeImportAlert: UserAlert {
enum RequestAlert: UserAlert { enum RequestAlert: UserAlert {
case REQUEST_DELAYED, case REQUEST_DELAYED,
REQUEST_DROPPED REQUEST_DROPPED,
REQUEST_SUCCESS
var localizedDescription: LocalizedStringKey { var localizedDescription: LocalizedStringKey {
switch self { switch self {
case .REQUEST_DELAYED: return "Could not establish a connection to the server. The action will be retried upon reconnection." 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_DROPPED: return "Unable to complete action."
case .REQUEST_SUCCESS: return ""
} }
} }
@@ -126,6 +138,7 @@ enum RequestAlert: UserAlert {
switch self { switch self {
case .REQUEST_DELAYED: return "Action delayed" case .REQUEST_DELAYED: return "Action delayed"
case .REQUEST_DROPPED: return "Error" case .REQUEST_DROPPED: return "Error"
case .REQUEST_SUCCESS: return "Success!"
} }
} }

View File

@@ -37,7 +37,7 @@ struct RecipeListView: View {
} }
} }
.navigationDestination(for: Recipe.self) { recipe in .navigationDestination(for: Recipe.self) { recipe in
RecipeView(isPresented: .constant(true), viewModel: RecipeView.ViewModel(recipe: recipe)) RecipeView(viewModel: RecipeView.ViewModel(recipe: recipe))
.environmentObject(appState) .environmentObject(appState)
.environmentObject(groceryList) .environmentObject(groceryList)
} }

View File

@@ -11,8 +11,10 @@ import SwiftUI
struct RecipeView: View { struct RecipeView: View {
@EnvironmentObject var appState: AppState @EnvironmentObject var appState: AppState
@Binding var isPresented: Bool @Environment(\.dismiss) private var dismiss
@StateObject var viewModel: ViewModel @StateObject var viewModel: ViewModel
@GestureState private var dragOffset = CGSize.zero
var imageHeight: CGFloat { var imageHeight: CGFloat {
if let image = viewModel.recipeImage { if let image = viewModel.recipeImage {
return image.size.height < 350 ? image.size.height : 350 return image.size.height < 350 ? image.size.height : 350
@@ -115,8 +117,9 @@ struct RecipeView: View {
.toolbar(.visible, for: .navigationBar) .toolbar(.visible, for: .navigationBar)
//.toolbarTitleDisplayMode(.inline) //.toolbarTitleDisplayMode(.inline)
.navigationTitle(viewModel.showTitle ? viewModel.recipe.name : "") .navigationTitle(viewModel.showTitle ? viewModel.recipe.name : "")
.toolbar { .toolbar {
RecipeViewToolBar(isPresented: $isPresented, viewModel: viewModel) RecipeViewToolBar(viewModel: viewModel)
} }
.sheet(isPresented: $viewModel.presentShareSheet) { .sheet(isPresented: $viewModel.presentShareSheet) {
ShareView(recipeDetail: viewModel.observableRecipeDetail.toRecipeDetail(), ShareView(recipeDetail: viewModel.observableRecipeDetail.toRecipeDetail(),
@@ -313,16 +316,18 @@ extension RecipeView {
struct RecipeViewToolBar: ToolbarContent { struct RecipeViewToolBar: ToolbarContent {
@EnvironmentObject var appState: AppState @EnvironmentObject var appState: AppState
@Binding var isPresented: Bool @Environment(\.dismiss) private var dismiss
@ObservedObject var viewModel: RecipeView.ViewModel @ObservedObject var viewModel: RecipeView.ViewModel
var body: some ToolbarContent { var body: some ToolbarContent {
if viewModel.editMode { if viewModel.editMode {
ToolbarItemGroup(placement: .topBarLeading){ ToolbarItemGroup(placement: .topBarLeading) {
Button("Cancel") { Button("Cancel") {
viewModel.editMode = false viewModel.editMode = false
isPresented = false if viewModel.newRecipe {
dismiss()
}
} }
if !viewModel.newRecipe { if !viewModel.newRecipe {
@@ -407,9 +412,10 @@ struct RecipeViewToolBar: ToolbarContent {
await appState.getCategories() await appState.getCategories()
await appState.getCategory(named: viewModel.observableRecipeDetail.recipeCategory, fetchMode: .preferServer) await appState.getCategory(named: viewModel.observableRecipeDetail.recipeCategory, fetchMode: .preferServer)
if let id = Int(viewModel.observableRecipeDetail.id) { 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.editMode = false
viewModel.presentAlert(RecipeAlert.UPLOAD_SUCCESS)
} }
func handleDelete() async { func handleDelete() async {
@@ -424,7 +430,8 @@ struct RecipeViewToolBar: ToolbarContent {
} }
await appState.getCategories() await appState.getCategories()
await appState.getCategory(named: category, fetchMode: .preferServer) await appState.getCategory(named: category, fetchMode: .preferServer)
self.isPresented = false viewModel.presentAlert(RecipeAlert.DELETE_SUCCESS)
dismiss()
} }
func recipeValid() -> RecipeAlert? { func recipeValid() -> RecipeAlert? {

View File

@@ -227,12 +227,14 @@ extension SettingsView {
func getUserData() async { func getUserData() async {
let (data, _) = await NextcloudApi.getAvatar() let (data, _) = await NextcloudApi.getAvatar()
avatarImage = data
let (userData, _) = await NextcloudApi.getHoverCard() let (userData, _) = await NextcloudApi.getHoverCard()
DispatchQueue.main.async {
self.avatarImage = data
self.userData = userData self.userData = userData
} }
} }
}
} }

View File

@@ -54,7 +54,7 @@ struct RecipeTabView: View {
.environmentObject(appState) .environmentObject(appState)
} }
.navigationDestination(isPresented: $viewModel.presentEditView) { .navigationDestination(isPresented: $viewModel.presentEditView) {
RecipeView(isPresented: $viewModel.presentEditView, viewModel: RecipeView.ViewModel()) RecipeView(viewModel: RecipeView.ViewModel())
.environmentObject(appState) .environmentObject(appState)
.environmentObject(groceryList) .environmentObject(groceryList)
} }

View File

@@ -34,7 +34,7 @@ struct SearchTabView: View {
} }
} }
.navigationDestination(for: Recipe.self) { recipe in .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") .searchable(text: $viewModel.searchText, prompt: "Search recipes/keywords")
} }