More Improvements!

This commit is contained in:
TheBrokenRail 2024-02-18 00:41:47 -05:00
parent 2da59312c5
commit 64f9fe7f63
11 changed files with 134 additions and 75 deletions

View File

@ -32,7 +32,6 @@ android {
dependencies {
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
// OkHttp (For HTTP)
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// Moshi (For JSON)

View File

@ -36,6 +36,7 @@ public class ListActivity extends AppCompatActivity {
// Setup RecyclerView
adapter = new ListAdapter(viewModel.task);
viewModel.task.sendDataToListeners();
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);

View File

@ -61,7 +61,9 @@ public class ItemDialog {
message.append("\n\n");
}
message.append(context.getString(R.string.portion), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
message.append(item.portion);
if (item.portion != null) {
message.append(item.portion);
}
message.append('\n');
message.append(context.getString(R.string.ingredients), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (item.ingredients != null) {

View File

@ -61,15 +61,14 @@ public class MenuActivity extends AppCompatActivity {
String name = getIntent().getStringExtra(NAME_EXTRA);
toolbar.setTitle(name);
String id = getIntent().getStringExtra(ID_EXTRA);
if (!viewModel.task.isSetup()) {
viewModel.task.setup(id, new Date());
}
viewModel.task.setup(id);
latitude = getIntent().getDoubleExtra(LATITUDE_EXTRA, 0);
longitude = getIntent().getDoubleExtra(LONGITUDE_EXTRA, 0);
street = getIntent().getStringExtra(STREET_EXTRA);
// Setup RecyclerView
adapter = new MenuAdapter(viewModel.task);
adapter = new MenuAdapter(viewModel.task, viewModel.state);
viewModel.task.sendDataToListeners();
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
@ -113,7 +112,7 @@ public class MenuActivity extends AppCompatActivity {
* @param newDate New date
*/
public void updateDate(Date newDate) {
viewModel.task.setup(null, newDate);
viewModel.state.setDate(newDate);
viewModel.task.start();
}

View File

@ -24,8 +24,14 @@ import java.util.Date;
* Adapter for listing dining halls.
*/
class MenuAdapter extends TaskAdapter<MenuData> {
MenuAdapter(Task<MenuData> task) {
/**
* Current state.
*/
private final MenuState state;
MenuAdapter(Task<MenuData> task, MenuState state) {
super(task);
this.state = state;
}
@Override
@ -43,8 +49,9 @@ class MenuAdapter extends TaskAdapter<MenuData> {
*/
private MenuData.Meal getMeal() {
if (getResult() != null) {
String selectedMeal = state.getSelectedMeal();
for (MenuData.Meal meal : getResult().meals) {
if (meal.name.equals(getResult().selectedMeal)) {
if (meal.name.equals(selectedMeal)) {
// Found Meal
return meal;
}
@ -93,8 +100,7 @@ class MenuAdapter extends TaskAdapter<MenuData> {
// Set Date
CustomDropDownView dateField = view.findViewById(R.id.menu_date_field);
MaterialAutoCompleteTextView date = view.findViewById(R.id.menu_date);
// Retrieve from Task as this must show even when result is not available.
Date current = ((MenuTask) getTask()).getDate();
Date current = state.getDate();
date.setText(DateUtil.toString(current));
// Handle Click
dateField.setup();
@ -104,26 +110,28 @@ class MenuAdapter extends TaskAdapter<MenuData> {
});
// Set Meal
boolean hasMeal = getResult() != null;
boolean isLoaded = getResult() != null;
TextInputLayout mealField = view.findViewById(R.id.menu_meal_field);
MaterialAutoCompleteTextView meal = view.findViewById(R.id.menu_meal);
if (hasMeal) {
if (isLoaded) {
// Enable/Disable Field
hasMeal = getResult().meals.size() > 0;
mealField.setEnabled(hasMeal);
if (hasMeal) {
isLoaded = getResult().meals.size() > 0;
mealField.setEnabled(isLoaded);
if (isLoaded) {
// Set Dropdown Options
meal.setSimpleItems(getResult().meals.stream().map(x -> x.name).toArray(String[]::new));
// Set Selection
meal.setText(getResult().selectedMeal, false);
meal.setText(state.getSelectedMeal(), false);
// Handle Meal Selection
meal.setOnItemClickListener((parent, view1, position, id) -> {
// Get New Meal
String newMeal = (String) parent.getAdapter().getItem(position);
// Update UI
int oldItemCount = getItemCount();
getResult().selectedMeal = newMeal;
reloadUI(oldItemCount);
if (!newMeal.equals(state.getSelectedMeal())) {
int oldItemCount = getItemCount();
state.setSelectedMeal(newMeal);
reloadUI(oldItemCount);
}
});
} else {
// Show N/A

View File

@ -17,8 +17,5 @@ class MenuData {
this.name = name;
}
}
public final List<Meal> meals = new ArrayList<>();
// This may be changed at runtime.
public String selectedMeal = null;
}

View File

@ -0,0 +1,61 @@
package com.thebrokenrail.mtudining.activity.menu;
import androidx.lifecycle.SavedStateHandle;
import java.util.Date;
/**
* Current state of menu screen.
*/
public class MenuState {
private static final String DATE_KEY = "date";
private static final String SELECTED_MEAL_KEY = "selected_meal";
/**
* Data that should survive process-death.
*/
private final SavedStateHandle savedStateHandle;
public MenuState(SavedStateHandle savedStateHandle) {
this.savedStateHandle = savedStateHandle;
if (!savedStateHandle.contains(DATE_KEY)) {
setDate(new Date());
}
if (!savedStateHandle.contains(SELECTED_MEAL_KEY)) {
setSelectedMeal("");
}
}
/**
* Get currently selected date.
* @return The data
*/
@SuppressWarnings({"DataFlowIssue"})
public Date getDate() {
return new Date((long) savedStateHandle.get(DATE_KEY));
}
/**
* Set selected date.
* @param date The new date
*/
public void setDate(Date date) {
savedStateHandle.set(DATE_KEY, date.getTime());
}
/**
* Get currently selected meal.
* @return The meal
*/
public String getSelectedMeal() {
return savedStateHandle.get(SELECTED_MEAL_KEY);
}
/**
* Set selected meal.
* @param selectedMeal The new meal
*/
public void setSelectedMeal(String selectedMeal) {
savedStateHandle.set(SELECTED_MEAL_KEY, selectedMeal);
}
}

View File

@ -8,7 +8,6 @@ import com.thebrokenrail.mtudining.util.Category;
import com.thebrokenrail.mtudining.util.Constants;
import java.util.Comparator;
import java.util.Date;
/**
* Task for loading menu information.
@ -17,44 +16,25 @@ public class MenuTask extends Task<MenuData> {
private final Connection connection;
private String locationId;
private Date date;
private final MenuState state;
public MenuTask(Connection connection) {
public MenuTask(Connection connection, MenuState state) {
this.connection = connection;
this.state = state;
}
/**
* Setup task.
* @param locationId Location ID (or null to use existing)
* @param date Date
* @param locationId Location ID
*/
void setup(String locationId, Date date) {
if (locationId != null) {
this.locationId = locationId;
}
this.date = date;
}
/**
* Check if task is setup.
* @return If the task is setup
*/
boolean isSetup() {
return locationId != null;
}
/**
* Get date.
* @return The date
*/
public Date getDate() {
return date;
void setup(String locationId) {
this.locationId = locationId;
}
@Override
protected void startImpl(long id) {
// Get Periods
Periods periods = new Periods(Constants.PLATFORM, locationId, date);
Periods periods = new Periods(Constants.PLATFORM, locationId, state.getDate());
connection.send(periods, periodsResponse -> {
// Loaded Periods
@ -69,7 +49,7 @@ public class MenuTask extends Task<MenuData> {
for (Periods.Response.Period period : periodsResponse.periods) {
// Load Period Details
MenuData.Meal meal = new MenuData.Meal(period.id, period.name);
PeriodDetail periodDetail = new PeriodDetail(Constants.PLATFORM, locationId, date, period.id);
PeriodDetail periodDetail = new PeriodDetail(Constants.PLATFORM, locationId, state.getDate(), period.id);
connection.send(periodDetail, periodDetailResponse -> {
// Loaded Period Details
@ -104,8 +84,6 @@ public class MenuTask extends Task<MenuData> {
});
data.meals.add(meal);
}
// Set Selected Meal
data.selectedMeal = data.meals.get(0).name;
} else {
// No Periods To Load
done(id, data);
@ -115,4 +93,29 @@ public class MenuTask extends Task<MenuData> {
done(id, null);
});
}
@Override
protected void done(long id, MenuData obj) {
// Update Selected Meal If Needed
if (obj != null && obj.meals.size() > 0) {
boolean currentSelectedMealIsValid = false;
String selectedMeal = state.getSelectedMeal();
if (selectedMeal != null) {
// Check If Current Selection Is Valid
for (MenuData.Meal meal : obj.meals) {
if (selectedMeal.equals(meal.name)) {
currentSelectedMealIsValid = true;
break;
}
}
}
if (!currentSelectedMealIsValid) {
// Current Selection Is Invalid, Change It
state.setSelectedMeal(obj.meals.get(0).name);
}
}
// Call Parent
super.done(id, obj);
}
}

View File

@ -1,8 +1,8 @@
package com.thebrokenrail.mtudining.activity.menu;
import androidx.lifecycle.SavedStateHandle;
import androidx.lifecycle.ViewModel;
import com.thebrokenrail.mtudining.activity.task.Task;
import com.thebrokenrail.mtudining.api.Connection;
/**
@ -10,5 +10,11 @@ import com.thebrokenrail.mtudining.api.Connection;
*/
public class MenuViewModel extends ViewModel {
private final Connection connection = new Connection();
public final MenuTask task = new MenuTask(connection);
public final MenuState state;
public final MenuTask task;
public MenuViewModel(SavedStateHandle savedStateHandle) {
state = new MenuState(savedStateHandle);
task = new MenuTask(connection, state);
}
}

View File

@ -29,6 +29,7 @@ public abstract class Task<E> {
public void start() {
lastStart = System.currentTimeMillis();
status = Status.IN_PROGRESS;
result = null;
startImpl(lastStart);
// Update Listeners
sendDataToListeners();
@ -95,25 +96,15 @@ public abstract class Task<E> {
public void addListener(Listener<E> listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
// Send Data
sendDataToListener(listener);
}
}
/**
* Send data to specific listener.
* @param listener The listener
*/
private void sendDataToListener(Listener<E> listener) {
listener.update(status, status == Status.DONE ? result : null);
}
/**
* Send data to all listeners.
*/
private void sendDataToListeners() {
public void sendDataToListeners() {
for (Listener<E> listener : listeners) {
sendDataToListener(listener);
listener.update(status, status == Status.DONE ? result : null);
}
}

View File

@ -208,12 +208,4 @@ public abstract class TaskAdapter<E> extends RecyclerView.Adapter<RecyclerView.V
// Add Items
notifyItemRangeInserted(1, getItemCount() - 1);
}
/**
* Get task.
* @return The task
*/
public Task<E> getTask() {
return task;
}
}