From ee3c3b6b9cdfdc09309a4faa486f1f5fbcf6034f Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Mon, 24 Mar 2025 12:41:43 -0600 Subject: [PATCH] Improve error popup system --- .../ridgescout/scoutingData/fields.java | 24 ----- .../ridgescout/types/input/sliderType.java | 5 +- .../ridgescout/ui/TeamSelectorFragment.java | 2 +- .../ridgescout/ui/data/FieldsFragment.java | 3 +- .../ui/scouting/MatchScoutingFragment.java | 5 +- .../ridgescout/ui/transfer/FTPSync.java | 6 +- .../ridgescout/ui/transfer/TBAFragment.java | 40 ++++++-- .../bluetooth/BluetoothReceiverFragment.java | 8 +- .../ridgescout/utility/AlertManager.java | 93 +++++++++++++------ .../ridgescout/utility/DataManager.java | 2 +- .../ridgescout/utility/RequestTask.java | 2 +- 11 files changed, 113 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java b/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java index a7b284e..366f72b 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/scoutingData/fields.java @@ -168,28 +168,4 @@ public class fields { return output; } - -// public static void test(){ -// ScoutingVersion.transferType[][] transferValues = sv.get_transfer_values(values); -// -// ScoutingVersion.ScoutingArray msa = sv.new ScoutingArray(0, new ScoutingVersion.dataType[]{ -// sv.new stringType("name", "test-username"), -// sv.new intType("How good is robot", 12) -// }, values, transferValues); -// -// msa.update(); -// -// for(ScoutingVersion.dataType dt : msa.array){ -// if(dt == null) continue; -// switch (dt.getValueType()){ -// case NUM: -// System.out.println(dt.name + " " + (int) dt.get()); -// break; -// case STRING: -// System.out.println(dt.name + " " + (String) dt.get()); -// break; -// } -// -// } -// } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java b/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java index dbbfae3..bf9e527 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/types/input/sliderType.java @@ -1,6 +1,5 @@ package com.ridgebotics.ridgescout.types.input; -import android.app.Activity; import android.content.Context; import android.graphics.Color; import android.view.View; @@ -97,7 +96,7 @@ public class sliderType extends inputType { float slidervalue = round_position*step_size; if(slidervalue > 1 || slidervalue < 0) { - AlertManager.error("Error loading slider " + name); + AlertManager.addSimpleError("Error loading slider " + name); slider.setValue(0); }else{ slider.setValue(slidervalue); @@ -130,7 +129,7 @@ public class sliderType extends inputType { int round_position = Math.round(slider_position / step_size); float value = round_position*step_size; if(value > 1 || value < 0) { - AlertManager.error("Error loading slider " + name); + AlertManager.addSimpleError("Error loading slider " + name); slider.setValue(0); }else{ slider.setValue(value); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java index 8fda4c4..0674f88 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/TeamSelectorFragment.java @@ -50,7 +50,7 @@ public class TeamSelectorFragment extends Fragment { DataManager.reload_event(); if(evcode == null || evcode.equals("unset")){ - AlertManager.error("You somehow have not loaded an event!"); + AlertManager.addSimpleError("You somehow have not loaded an event!"); return binding.getRoot(); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java index 59e43b5..e3ec678 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/data/FieldsFragment.java @@ -6,7 +6,6 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.text.InputType; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -406,7 +405,7 @@ public class FieldsFragment extends Fragment { public void onClick(DialogInterface dialog, int which) { String title = input.getText().toString(); if(title.isEmpty() || title.isBlank()) { - AlertManager.error("Title cannot be blank!"); + AlertManager.addSimpleError("Title cannot be blank!"); return; } addField_Part_2(title); diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MatchScoutingFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MatchScoutingFragment.java index 02befe8..2d0725a 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MatchScoutingFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/scouting/MatchScoutingFragment.java @@ -28,9 +28,6 @@ import com.ridgebotics.ridgescout.utility.AutoSaveManager; import com.ridgebotics.ridgescout.utility.DataManager; import com.ridgebotics.ridgescout.utility.fileEditor; -import java.util.ArrayList; -import java.util.function.Function; - public class MatchScoutingFragment extends Fragment { private FragmentScoutingMatchBinding binding; @@ -292,7 +289,7 @@ public class MatchScoutingFragment extends Fragment { frcTeam team = get_team(match); if(team == null) { - AlertManager.error("This team does not exist!"); + AlertManager.addSimpleError("This team does not exist!"); binding.teamName.setText("ERROR!"); binding.teamDescription.setText("ERROR!"); return; diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java index 7987259..e724047 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/FTPSync.java @@ -214,7 +214,7 @@ public class FTPSync extends Thread { setTimestamps(remoteTimestamps); } catch (Exception e) { - AlertManager.error(e); + AlertManager.error("Failed Syncing!", e); onResult.onResult(true, upCount, downCount); setUpdateIndicator("ERROR!"); } finally { @@ -240,7 +240,7 @@ public class FTPSync extends Thread { uploadFile(new File(baseDir + timestampsFilename)); return true; } catch (ByteBuilder.buildingException | IOException e) { - e.printStackTrace(); + AlertManager.error("Failed Syncing!", e); return false; } } @@ -268,7 +268,7 @@ public class FTPSync extends Thread { return output; }catch (IOException | BuiltByteParser.byteParsingExeption e){ - AlertManager.error(e); + AlertManager.error("Failed Syncing!", e); return new HashMap<>(); } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/TBAFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/TBAFragment.java index 08fa460..bb87019 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/TBAFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/TBAFragment.java @@ -1,5 +1,6 @@ package com.ridgebotics.ridgescout.ui.transfer; +import android.app.ProgressDialog; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; @@ -44,6 +45,8 @@ public class TBAFragment extends Fragment { private final int year = settingsManager.getYearNum(); + private ProgressDialog loadingDialog; + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -57,10 +60,14 @@ public class TBAFragment extends Fragment { addTableText(tr, "Loading Events..."); Table.addView(tr); + startLoading("Loading Events..."); + final RequestTask rq = new RequestTask(); rq.onResult(s -> { if(s == null || s.isEmpty()) { - AlertManager.error("Could not fetch event!"); + AlertManager.addSimpleError("Could not fetch event!"); + AlertManager.updateErrors(); + stopLoading(); return null; } eventTable(s); @@ -80,6 +87,8 @@ public class TBAFragment extends Fragment { } public void eventTable(String dataString){ + stopLoading(); + Table.removeAllViews(); Table.setStretchAllColumns(true); Table.bringToFront(); @@ -139,11 +148,13 @@ public class TBAFragment extends Fragment { tr.setBackgroundColor(0x30FFFF00); } } catch (Exception e) { - AlertManager.error(e); + AlertManager.error("Failed finding start and end dates!", e); + stopLoading(); } tr.setOnClickListener(v -> { + startLoading("Loading Teams and Matches..."); Table.removeAllViews(); Table.setStretchAllColumns(true); Table.bringToFront(); @@ -154,6 +165,7 @@ public class TBAFragment extends Fragment { final RequestTask rq = new RequestTask(); rq.onResult(teamsStr -> { + stopLoading(); TableRow tr11 = new TableRow(getContext()); addTableText(tr11, "Downloading Matches..."); Table.addView(tr11); @@ -175,7 +187,8 @@ public class TBAFragment extends Fragment { toggle = !toggle; } }catch (JSONException j){ - AlertManager.alert("Error", "Invalid JSON"); + AlertManager.error("Failed Downloading", j); + stopLoading(); } } @@ -348,9 +361,10 @@ public class TBAFragment extends Fragment { btn.setOnClickListener(v -> { if(saveData(matchesOBJ, teamData, eventData)){ - AlertManager.alert("Info", "Saved!"); + AlertManager.toast("Saved!"); }else{ - AlertManager.alert("Error", "Error saving files."); + AlertManager.addSimpleError("Error saving files."); + stopLoading(); } }); @@ -461,8 +475,8 @@ public class TBAFragment extends Fragment { // }); }catch (JSONException j){ - AlertManager.error(j); - AlertManager.alert("Error", "Invalid JSON"); + AlertManager.error("Failed Downloading", j); + stopLoading(); } } @@ -502,8 +516,18 @@ public class TBAFragment extends Fragment { return fileEditor.setEvent(event); }catch (JSONException j){ AlertManager.error(j); - AlertManager.alert("Error", "Invalid JSON"); + stopLoading(); return false; } } + + private void startLoading(String title){ + loadingDialog = ProgressDialog.show(getActivity(), title, "Please wait..."); + } + + private void stopLoading(){ + if(loadingDialog != null) + loadingDialog.cancel(); + loadingDialog = null; + } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiverFragment.java b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiverFragment.java index a088197..cc10ff4 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiverFragment.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/ui/transfer/bluetooth/BluetoothReceiverFragment.java @@ -68,12 +68,12 @@ public class BluetoothReceiverFragment extends Fragment { statusTextView = binding.statusTextView; if (!bluetoothReceiver.isBluetoothSupported()) { - AlertManager.error("Bluetooth is not supported on this device"); + AlertManager.addSimpleError("Bluetooth is not supported on this device"); return binding.getRoot(); } if (!bluetoothReceiver.isBluetoothEnabled()) { - AlertManager.error("Please enable Bluetooth"); + AlertManager.addSimpleError("Please enable Bluetooth"); } startListeningButton.setOnClickListener(v -> { @@ -97,7 +97,7 @@ public class BluetoothReceiverFragment extends Fragment { recievedBytes = new ArrayList<>(); } catch (IOException e) { - AlertManager.error("Failed to start listening: " + e.getMessage()); + AlertManager.error("Failed to start listening", e); } } @@ -108,7 +108,7 @@ public class BluetoothReceiverFragment extends Fragment { startListeningButton.setEnabled(true); stopListeningButton.setEnabled(false); } catch (IOException e) { - AlertManager.error("Failed to stop listening: " + e.getMessage()); + AlertManager.error("Failed to stop listening: " + e.getMessage(), e); } } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/AlertManager.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/AlertManager.java index f776db5..49bf36c 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/AlertManager.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/AlertManager.java @@ -3,10 +3,13 @@ package com.ridgebotics.ridgescout.utility; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.widget.Toast; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; public class AlertManager { public static Context context; @@ -15,55 +18,93 @@ public class AlertManager { context = c; } + private static AlertDialog currentError; + private static final List simpleErrorList = new ArrayList<>(); + private static final List errorList = new ArrayList<>(); + public static void alert(String title, String content) { - ((Activity) context).runOnUiThread(new Runnable() { - public void run() { + + ((Activity) context).runOnUiThread(() -> { AlertDialog.Builder alert = new AlertDialog.Builder(context); - alert.setMessage(content); alert.setTitle(title); + alert.setMessage(content); alert.setPositiveButton("OK", null); alert.setCancelable(true); alert.create().show(); - } - }); + }); } public static void toast(String content) { - ((Activity) context).runOnUiThread(new Runnable() { - public void run() { - Toast.makeText(context, content, Toast.LENGTH_LONG).show(); - } - }); + ((Activity) context).runOnUiThread(() -> Toast.makeText(context, content, Toast.LENGTH_LONG).show()); + } + + public static void addSimpleError(String error) { + simpleErrorList.add(error); + updateErrors(); } public static void error(String content) { - ((Activity) context).runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder alert = new AlertDialog.Builder(context); - alert.setMessage(content); - alert.setTitle("Error!"); - alert.setPositiveButton("OK", null); - alert.setCancelable(true); + errorList.add(content); + updateErrors(); + } - alert.create().show(); - } - }); + public static void error(String title, String content) { + simpleErrorList.add(title); + errorList.add(content); + updateErrors(); } public static void error(Exception e) { e.printStackTrace(); + + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + + errorList.add((sw.toString())); + updateErrors(); + } + + public static void error(String title, Exception e) { + simpleErrorList.add(title); + e.printStackTrace(); + + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + + errorList.add((sw.toString())); + updateErrors(); + } + + public static void updateErrors(){ ((Activity) context).runOnUiThread(() -> { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); + if(currentError != null && currentError.isShowing()){ + DialogInterface tmp = currentError; + currentError = null; + tmp.dismiss(); + } AlertDialog.Builder alert = new AlertDialog.Builder(context); - alert.setMessage(sw.toString()); - alert.setTitle(e.getMessage()); - alert.setPositiveButton("OK", null); + + if(!simpleErrorList.isEmpty()) + alert.setTitle(simpleErrorList.get(0) + (simpleErrorList.size() > 1 ? "..." : "")); + else + alert.setTitle(errorList.size() + " Error" + (errorList.size() != 1 ? "s" : "") + "!"); + + if(simpleErrorList.size() > 1) + alert.setMessage(String.join("\n", simpleErrorList)); + + alert.setPositiveButton("OK", (dialogInterface, i) -> {if(currentError != null){errorList.clear(); simpleErrorList.clear();}}); + if(!errorList.isEmpty()) + alert.setNeutralButton("View Detailed Error" + (errorList.size() != 1 ? "s" : ""), (dialogInterface, i) -> alert(errorList.size() + " Error" + (errorList.size() != 1 ? "s" : "") + ":", String.join("\n\n\n\n\n", errorList))); + alert.setOnDismissListener((x) -> {if(currentError != null){errorList.clear(); simpleErrorList.clear();}}); + + alert.setCancelable(true); - alert.create().show(); + currentError = alert.create(); + + currentError.show(); }); } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java index 4bae7a4..a31bbe8 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/DataManager.java @@ -16,7 +16,7 @@ public class DataManager { event = frcEvent.decode(fileEditor.readFile(evcode + ".eventdata")); if(event == null) { - AlertManager.error("Failed to load event!"); + AlertManager.addSimpleError("Failed to load event!"); settingsManager.setEVCode("unset"); evcode = "unset"; } diff --git a/app/src/main/java/com/ridgebotics/ridgescout/utility/RequestTask.java b/app/src/main/java/com/ridgebotics/ridgescout/utility/RequestTask.java index 4b5b471..94fedb8 100644 --- a/app/src/main/java/com/ridgebotics/ridgescout/utility/RequestTask.java +++ b/app/src/main/java/com/ridgebotics/ridgescout/utility/RequestTask.java @@ -36,7 +36,7 @@ public class RequestTask extends AsyncTask { return null; // See documentation for more info on response handling } } catch (IOException e) { - AlertManager.error(e); + AlertManager.error("Failed to download!", e); } return null; }