refactor: make callbacks clean
This commit is contained in:
parent
d2ad5337b9
commit
ee66b643ec
1 changed files with 56 additions and 52 deletions
|
|
@ -9,6 +9,10 @@ import client.utils.LocaleManager;
|
||||||
import client.utils.ServerUtils;
|
import client.utils.ServerUtils;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import commons.Recipe;
|
import commons.Recipe;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
|
|
@ -19,12 +23,10 @@ import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for the recipe detail view.
|
* Controller for the recipe detail view.
|
||||||
* Manages displaying and editing recipe details such as name, ingredients, and steps.
|
* Manages displaying and editing recipe details such as name, ingredients, and
|
||||||
|
* steps.
|
||||||
*/
|
*/
|
||||||
public class RecipeDetailCtrl implements LocaleAware {
|
public class RecipeDetailCtrl implements LocaleAware {
|
||||||
private final LocaleManager localeManager;
|
private final LocaleManager localeManager;
|
||||||
|
|
@ -41,10 +43,9 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
private Recipe recipe;
|
private Recipe recipe;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RecipeDetailCtrl(LocaleManager localeManager,
|
public RecipeDetailCtrl(LocaleManager localeManager, ServerUtils server,
|
||||||
ServerUtils server,
|
FoodpalApplicationCtrl appCtrl,
|
||||||
FoodpalApplicationCtrl appCtrl,
|
ConfigService configService) {
|
||||||
ConfigService configService) {
|
|
||||||
this.localeManager = localeManager;
|
this.localeManager = localeManager;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.appCtrl = appCtrl;
|
this.appCtrl = appCtrl;
|
||||||
|
|
@ -74,15 +75,14 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for a frequently needed operation to retrieve the currently
|
* Convenience method for a frequently needed operation to retrieve the
|
||||||
* selected recipe.
|
* currently selected recipe.
|
||||||
*
|
*
|
||||||
* @return The currently selected recipe in the parent recipe list.
|
* @return The currently selected recipe in the parent recipe list.
|
||||||
*/
|
*/
|
||||||
private Optional<Recipe> getSelectedRecipe() {
|
private Optional<Recipe> getSelectedRecipe() {
|
||||||
return Optional.ofNullable(
|
return Optional.ofNullable(
|
||||||
this.getParentRecipeList().getSelectionModel().getSelectedItem()
|
this.getParentRecipeList().getSelectionModel().getSelectedItem());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -98,7 +98,7 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
/**
|
/**
|
||||||
* Refreshes the recipe list from the server.
|
* Refreshes the recipe list from the server.
|
||||||
*
|
*
|
||||||
* @throws IOException Upon invalid recipe response.
|
* @throws IOException Upon invalid recipe response.
|
||||||
* @throws InterruptedException Upon request interruption.
|
* @throws InterruptedException Upon request interruption.
|
||||||
*
|
*
|
||||||
* @see FoodpalApplicationCtrl#refresh()
|
* @see FoodpalApplicationCtrl#refresh()
|
||||||
|
|
@ -135,45 +135,50 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the ingredient and step list controllers with update callbacks.
|
* Create a callback that takes in the selected recipe and a helper type
|
||||||
|
* and updates the recipe based on that.
|
||||||
|
* Also, posts the update to the server.
|
||||||
|
*
|
||||||
|
* @param recipeConsumer The helper function to use when updating the recipe -
|
||||||
|
* how to update it
|
||||||
|
* @return The created callback to use in a setUpdateCallback or related
|
||||||
|
* function
|
||||||
*/
|
*/
|
||||||
private void initStepsIngredientsList() {
|
private <T> Consumer<T> createUpdateRecipeCallback(BiConsumer<Recipe, T> recipeConsumer) {
|
||||||
// Initialize callback for ingredient list updates
|
return recipes -> {
|
||||||
this.ingredientListController.setUpdateCallback(newList -> {
|
Recipe selectedRecipe = this.getSelectedRecipe().orElseThrow(
|
||||||
var maybeSelected = this.getSelectedRecipe();
|
() -> new NullPointerException(
|
||||||
if (maybeSelected.isEmpty()) { // Safely handle edge case
|
"Null recipe whereas ingredients are edited"));
|
||||||
throw new NullPointerException("Null recipe whereas ingredients are edited");
|
|
||||||
}
|
|
||||||
|
|
||||||
Recipe selectedRecipe = maybeSelected.get();
|
recipeConsumer.accept(selectedRecipe, recipes);
|
||||||
selectedRecipe.setIngredients(newList);
|
|
||||||
try { // propagate changes to server
|
try { // propagate changes to server
|
||||||
server.updateRecipe(selectedRecipe);
|
server.updateRecipe(selectedRecipe);
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
throw new UpdateException("Unable to update recipe to server for " + selectedRecipe);
|
throw new UpdateException("Unable to update recipe to server for " +
|
||||||
|
selectedRecipe);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
// Ditto, for step list updates
|
|
||||||
this.stepListController.setUpdateCallback(newList -> {
|
|
||||||
var maybeSelected = this.getSelectedRecipe();
|
|
||||||
if (maybeSelected.isEmpty()) { // Safely handle edge case
|
|
||||||
throw new NullPointerException("Null recipe whereas ingredients are edited");
|
|
||||||
}
|
|
||||||
|
|
||||||
Recipe selectedRecipe = maybeSelected.get();
|
|
||||||
selectedRecipe.setPreparationSteps(newList);
|
|
||||||
try { // propagate changes to server
|
|
||||||
server.updateRecipe(selectedRecipe);
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
throw new UpdateException("Unable to update recipe to server for " + selectedRecipe);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revised edit recipe control flow, deprecates the use of a separate AddNameCtrl.
|
* Initializes the ingredient and step list controllers with update callbacks.
|
||||||
* This is automagically called when a new recipe is created, making for a more seamless UX.
|
*/
|
||||||
|
private void initStepsIngredientsList() {
|
||||||
|
// code does NOT get nicer than this :pray:
|
||||||
|
|
||||||
|
// Initialize callback for ingredient list updates
|
||||||
|
this.ingredientListController.setUpdateCallback(
|
||||||
|
this.createUpdateRecipeCallback(Recipe::setIngredients));
|
||||||
|
// Ditto, for step list updates
|
||||||
|
this.stepListController.setUpdateCallback(
|
||||||
|
this.createUpdateRecipeCallback(Recipe::setPreparationSteps));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revised edit recipe control flow, deprecates the use of a separate
|
||||||
|
* AddNameCtrl. This is automagically called when a new recipe is created,
|
||||||
|
* making for a more seamless UX.
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void editRecipeTitle() {
|
private void editRecipeTitle() {
|
||||||
|
|
@ -222,8 +227,8 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the favourite button state based on whether the currently viewed recipe
|
* Refreshes the favourite button state based on whether the currently viewed
|
||||||
* is marked as a favourite in the application configuration.
|
* recipe is marked as a favourite in the application configuration.
|
||||||
*/
|
*/
|
||||||
public void refreshFavouriteButton() {
|
public void refreshFavouriteButton() {
|
||||||
if (recipe == null) {
|
if (recipe == null) {
|
||||||
|
|
@ -233,14 +238,13 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
favouriteButton.setDisable(false);
|
favouriteButton.setDisable(false);
|
||||||
favouriteButton.setText(
|
favouriteButton.setText(this.getConfig().isFavourite(recipe.getId()) ? "★"
|
||||||
this.getConfig().isFavourite(recipe.getId()) ? "★" : "☆"
|
: "☆");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggles the favourite status of the currently viewed recipe in the application configuration
|
* Toggles the favourite status of the currently viewed recipe in the
|
||||||
* and writes the changes to disk.
|
* application configuration and writes the changes to disk.
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void toggleFavourite() {
|
private void toggleFavourite() {
|
||||||
|
|
@ -255,7 +259,7 @@ public class RecipeDetailCtrl implements LocaleAware {
|
||||||
|
|
||||||
configService.save();
|
configService.save();
|
||||||
|
|
||||||
//instant ui update
|
// instant ui update
|
||||||
appCtrl.applyRecipeFilterAndKeepSelection();
|
appCtrl.applyRecipeFilterAndKeepSelection();
|
||||||
this.getParentRecipeList().refresh();
|
this.getParentRecipeList().refresh();
|
||||||
refreshFavouriteButton();
|
refreshFavouriteButton();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue