More Improvements!
This commit is contained in:
parent
2da59312c5
commit
64f9fe7f63
@ -32,7 +32,6 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("com.google.android.material:material:1.11.0")
|
implementation("com.google.android.material:material:1.11.0")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
|
||||||
// OkHttp (For HTTP)
|
// OkHttp (For HTTP)
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
// Moshi (For JSON)
|
// Moshi (For JSON)
|
||||||
|
@ -36,6 +36,7 @@ public class ListActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
// Setup RecyclerView
|
// Setup RecyclerView
|
||||||
adapter = new ListAdapter(viewModel.task);
|
adapter = new ListAdapter(viewModel.task);
|
||||||
|
viewModel.task.sendDataToListeners();
|
||||||
RecyclerView recyclerView = findViewById(R.id.recycler_view);
|
RecyclerView recyclerView = findViewById(R.id.recycler_view);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
@ -61,7 +61,9 @@ public class ItemDialog {
|
|||||||
message.append("\n\n");
|
message.append("\n\n");
|
||||||
}
|
}
|
||||||
message.append(context.getString(R.string.portion), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
message.append(context.getString(R.string.portion), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
if (item.portion != null) {
|
||||||
message.append(item.portion);
|
message.append(item.portion);
|
||||||
|
}
|
||||||
message.append('\n');
|
message.append('\n');
|
||||||
message.append(context.getString(R.string.ingredients), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
message.append(context.getString(R.string.ingredients), new StyleSpan(Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
if (item.ingredients != null) {
|
if (item.ingredients != null) {
|
||||||
|
@ -61,15 +61,14 @@ public class MenuActivity extends AppCompatActivity {
|
|||||||
String name = getIntent().getStringExtra(NAME_EXTRA);
|
String name = getIntent().getStringExtra(NAME_EXTRA);
|
||||||
toolbar.setTitle(name);
|
toolbar.setTitle(name);
|
||||||
String id = getIntent().getStringExtra(ID_EXTRA);
|
String id = getIntent().getStringExtra(ID_EXTRA);
|
||||||
if (!viewModel.task.isSetup()) {
|
viewModel.task.setup(id);
|
||||||
viewModel.task.setup(id, new Date());
|
|
||||||
}
|
|
||||||
latitude = getIntent().getDoubleExtra(LATITUDE_EXTRA, 0);
|
latitude = getIntent().getDoubleExtra(LATITUDE_EXTRA, 0);
|
||||||
longitude = getIntent().getDoubleExtra(LONGITUDE_EXTRA, 0);
|
longitude = getIntent().getDoubleExtra(LONGITUDE_EXTRA, 0);
|
||||||
street = getIntent().getStringExtra(STREET_EXTRA);
|
street = getIntent().getStringExtra(STREET_EXTRA);
|
||||||
|
|
||||||
// Setup RecyclerView
|
// 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 recyclerView = findViewById(R.id.recycler_view);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
@ -113,7 +112,7 @@ public class MenuActivity extends AppCompatActivity {
|
|||||||
* @param newDate New date
|
* @param newDate New date
|
||||||
*/
|
*/
|
||||||
public void updateDate(Date newDate) {
|
public void updateDate(Date newDate) {
|
||||||
viewModel.task.setup(null, newDate);
|
viewModel.state.setDate(newDate);
|
||||||
viewModel.task.start();
|
viewModel.task.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,14 @@ import java.util.Date;
|
|||||||
* Adapter for listing dining halls.
|
* Adapter for listing dining halls.
|
||||||
*/
|
*/
|
||||||
class MenuAdapter extends TaskAdapter<MenuData> {
|
class MenuAdapter extends TaskAdapter<MenuData> {
|
||||||
MenuAdapter(Task<MenuData> task) {
|
/**
|
||||||
|
* Current state.
|
||||||
|
*/
|
||||||
|
private final MenuState state;
|
||||||
|
|
||||||
|
MenuAdapter(Task<MenuData> task, MenuState state) {
|
||||||
super(task);
|
super(task);
|
||||||
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -43,8 +49,9 @@ class MenuAdapter extends TaskAdapter<MenuData> {
|
|||||||
*/
|
*/
|
||||||
private MenuData.Meal getMeal() {
|
private MenuData.Meal getMeal() {
|
||||||
if (getResult() != null) {
|
if (getResult() != null) {
|
||||||
|
String selectedMeal = state.getSelectedMeal();
|
||||||
for (MenuData.Meal meal : getResult().meals) {
|
for (MenuData.Meal meal : getResult().meals) {
|
||||||
if (meal.name.equals(getResult().selectedMeal)) {
|
if (meal.name.equals(selectedMeal)) {
|
||||||
// Found Meal
|
// Found Meal
|
||||||
return meal;
|
return meal;
|
||||||
}
|
}
|
||||||
@ -93,8 +100,7 @@ class MenuAdapter extends TaskAdapter<MenuData> {
|
|||||||
// Set Date
|
// Set Date
|
||||||
CustomDropDownView dateField = view.findViewById(R.id.menu_date_field);
|
CustomDropDownView dateField = view.findViewById(R.id.menu_date_field);
|
||||||
MaterialAutoCompleteTextView date = view.findViewById(R.id.menu_date);
|
MaterialAutoCompleteTextView date = view.findViewById(R.id.menu_date);
|
||||||
// Retrieve from Task as this must show even when result is not available.
|
Date current = state.getDate();
|
||||||
Date current = ((MenuTask) getTask()).getDate();
|
|
||||||
date.setText(DateUtil.toString(current));
|
date.setText(DateUtil.toString(current));
|
||||||
// Handle Click
|
// Handle Click
|
||||||
dateField.setup();
|
dateField.setup();
|
||||||
@ -104,26 +110,28 @@ class MenuAdapter extends TaskAdapter<MenuData> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Set Meal
|
// Set Meal
|
||||||
boolean hasMeal = getResult() != null;
|
boolean isLoaded = getResult() != null;
|
||||||
TextInputLayout mealField = view.findViewById(R.id.menu_meal_field);
|
TextInputLayout mealField = view.findViewById(R.id.menu_meal_field);
|
||||||
MaterialAutoCompleteTextView meal = view.findViewById(R.id.menu_meal);
|
MaterialAutoCompleteTextView meal = view.findViewById(R.id.menu_meal);
|
||||||
if (hasMeal) {
|
if (isLoaded) {
|
||||||
// Enable/Disable Field
|
// Enable/Disable Field
|
||||||
hasMeal = getResult().meals.size() > 0;
|
isLoaded = getResult().meals.size() > 0;
|
||||||
mealField.setEnabled(hasMeal);
|
mealField.setEnabled(isLoaded);
|
||||||
if (hasMeal) {
|
if (isLoaded) {
|
||||||
// Set Dropdown Options
|
// Set Dropdown Options
|
||||||
meal.setSimpleItems(getResult().meals.stream().map(x -> x.name).toArray(String[]::new));
|
meal.setSimpleItems(getResult().meals.stream().map(x -> x.name).toArray(String[]::new));
|
||||||
// Set Selection
|
// Set Selection
|
||||||
meal.setText(getResult().selectedMeal, false);
|
meal.setText(state.getSelectedMeal(), false);
|
||||||
// Handle Meal Selection
|
// Handle Meal Selection
|
||||||
meal.setOnItemClickListener((parent, view1, position, id) -> {
|
meal.setOnItemClickListener((parent, view1, position, id) -> {
|
||||||
// Get New Meal
|
// Get New Meal
|
||||||
String newMeal = (String) parent.getAdapter().getItem(position);
|
String newMeal = (String) parent.getAdapter().getItem(position);
|
||||||
// Update UI
|
// Update UI
|
||||||
|
if (!newMeal.equals(state.getSelectedMeal())) {
|
||||||
int oldItemCount = getItemCount();
|
int oldItemCount = getItemCount();
|
||||||
getResult().selectedMeal = newMeal;
|
state.setSelectedMeal(newMeal);
|
||||||
reloadUI(oldItemCount);
|
reloadUI(oldItemCount);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Show N/A
|
// Show N/A
|
||||||
|
@ -17,8 +17,5 @@ class MenuData {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<Meal> meals = new ArrayList<>();
|
public final List<Meal> meals = new ArrayList<>();
|
||||||
// This may be changed at runtime.
|
|
||||||
public String selectedMeal = null;
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,6 @@ import com.thebrokenrail.mtudining.util.Category;
|
|||||||
import com.thebrokenrail.mtudining.util.Constants;
|
import com.thebrokenrail.mtudining.util.Constants;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Task for loading menu information.
|
* Task for loading menu information.
|
||||||
@ -17,44 +16,25 @@ public class MenuTask extends Task<MenuData> {
|
|||||||
private final Connection connection;
|
private final Connection connection;
|
||||||
|
|
||||||
private String locationId;
|
private String locationId;
|
||||||
private Date date;
|
private final MenuState state;
|
||||||
|
|
||||||
public MenuTask(Connection connection) {
|
public MenuTask(Connection connection, MenuState state) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup task.
|
* Setup task.
|
||||||
* @param locationId Location ID (or null to use existing)
|
* @param locationId Location ID
|
||||||
* @param date Date
|
|
||||||
*/
|
*/
|
||||||
void setup(String locationId, Date date) {
|
void setup(String locationId) {
|
||||||
if (locationId != null) {
|
|
||||||
this.locationId = locationId;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startImpl(long id) {
|
protected void startImpl(long id) {
|
||||||
// Get Periods
|
// Get Periods
|
||||||
Periods periods = new Periods(Constants.PLATFORM, locationId, date);
|
Periods periods = new Periods(Constants.PLATFORM, locationId, state.getDate());
|
||||||
connection.send(periods, periodsResponse -> {
|
connection.send(periods, periodsResponse -> {
|
||||||
// Loaded Periods
|
// Loaded Periods
|
||||||
|
|
||||||
@ -69,7 +49,7 @@ public class MenuTask extends Task<MenuData> {
|
|||||||
for (Periods.Response.Period period : periodsResponse.periods) {
|
for (Periods.Response.Period period : periodsResponse.periods) {
|
||||||
// Load Period Details
|
// Load Period Details
|
||||||
MenuData.Meal meal = new MenuData.Meal(period.id, period.name);
|
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 -> {
|
connection.send(periodDetail, periodDetailResponse -> {
|
||||||
// Loaded Period Details
|
// Loaded Period Details
|
||||||
|
|
||||||
@ -104,8 +84,6 @@ public class MenuTask extends Task<MenuData> {
|
|||||||
});
|
});
|
||||||
data.meals.add(meal);
|
data.meals.add(meal);
|
||||||
}
|
}
|
||||||
// Set Selected Meal
|
|
||||||
data.selectedMeal = data.meals.get(0).name;
|
|
||||||
} else {
|
} else {
|
||||||
// No Periods To Load
|
// No Periods To Load
|
||||||
done(id, data);
|
done(id, data);
|
||||||
@ -115,4 +93,29 @@ public class MenuTask extends Task<MenuData> {
|
|||||||
done(id, null);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.thebrokenrail.mtudining.activity.menu;
|
package com.thebrokenrail.mtudining.activity.menu;
|
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.thebrokenrail.mtudining.activity.task.Task;
|
|
||||||
import com.thebrokenrail.mtudining.api.Connection;
|
import com.thebrokenrail.mtudining.api.Connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,5 +10,11 @@ import com.thebrokenrail.mtudining.api.Connection;
|
|||||||
*/
|
*/
|
||||||
public class MenuViewModel extends ViewModel {
|
public class MenuViewModel extends ViewModel {
|
||||||
private final Connection connection = new Connection();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ public abstract class Task<E> {
|
|||||||
public void start() {
|
public void start() {
|
||||||
lastStart = System.currentTimeMillis();
|
lastStart = System.currentTimeMillis();
|
||||||
status = Status.IN_PROGRESS;
|
status = Status.IN_PROGRESS;
|
||||||
|
result = null;
|
||||||
startImpl(lastStart);
|
startImpl(lastStart);
|
||||||
// Update Listeners
|
// Update Listeners
|
||||||
sendDataToListeners();
|
sendDataToListeners();
|
||||||
@ -95,25 +96,15 @@ public abstract class Task<E> {
|
|||||||
public void addListener(Listener<E> listener) {
|
public void addListener(Listener<E> listener) {
|
||||||
if (!listeners.contains(listener)) {
|
if (!listeners.contains(listener)) {
|
||||||
listeners.add(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.
|
* Send data to all listeners.
|
||||||
*/
|
*/
|
||||||
private void sendDataToListeners() {
|
public void sendDataToListeners() {
|
||||||
for (Listener<E> listener : listeners) {
|
for (Listener<E> listener : listeners) {
|
||||||
sendDataToListener(listener);
|
listener.update(status, status == Status.DONE ? result : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,12 +208,4 @@ public abstract class TaskAdapter<E> extends RecyclerView.Adapter<RecyclerView.V
|
|||||||
// Add Items
|
// Add Items
|
||||||
notifyItemRangeInserted(1, getItemCount() - 1);
|
notifyItemRangeInserted(1, getItemCount() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get task.
|
|
||||||
* @return The task
|
|
||||||
*/
|
|
||||||
public Task<E> getTask() {
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user