Make delete file menu. Add #8

This commit is contained in:
Michael Mikovsky
2025-08-03 22:28:55 -06:00
parent 9136df04df
commit 859d3bc773
6 changed files with 206 additions and 73 deletions
@@ -1,6 +1,5 @@
package com.ridgebotics.ridgescout.ui.settings;
import static android.view.View.VISIBLE;
import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;
import static androidx.navigation.fragment.FragmentKt.findNavController;
@@ -32,13 +31,9 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -58,9 +53,7 @@ import com.ridgebotics.ridgescout.ui.views.TallyCounterView;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.FileEditor;
import com.ridgebotics.ridgescout.utility.SettingsManager;
import org.w3c.dom.Text;
import com.ridgebotics.ridgescout.utility.ToDelete;
import java.util.ArrayList;
import java.util.Arrays;
@@ -98,17 +91,10 @@ public class SettingsFragment extends Fragment {
ButtonSettingsItem corruptButton = new ButtonSettingsItem();
corruptButton.addButton("find corrupted files", view -> {
new Thread(() -> {
AlertManager.startLoading("Loading files...");
List<String> filenames = FileEditor.findCorruptedFiles();
AlertManager.stopLoading();
getActivity().runOnUiThread(() -> {
deleteFiles(filenames, true);
});
}).start();
ToDelete.findCorruptedFiles(getContext());
});
corruptButton.addButton("delete files", view -> {
deleteFiles(Arrays.asList(FileEditor.getFiles()), false);
ToDelete.deleteFiles(getContext(), Arrays.asList(FileEditor.getFiles()), false);
});
// corruptButton.setEnabled(!getEVCode().equals("unset"));
@@ -264,35 +250,7 @@ public class SettingsFragment extends Fragment {
alert.create().show();
}
private void deleteFiles(List<String> files, boolean defaultOption) {
ScrollView sv = new ScrollView(getContext());
LinearLayout ll = new LinearLayout(getContext());
ll.setOrientation(VERTICAL);
sv.addView(ll);
CheckBox[] checkboxes = new CheckBox[files.size()];
for(int i =0; i < files.size(); i++){
CheckBox cb = new CheckBox(getContext());
cb.setText(files.get(i));
cb.setChecked(defaultOption);
ll.addView(cb);
checkboxes[i] = cb;
}
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Delete files");
alert.setView(sv);
alert.setNeutralButton("Cancel", null);
// alert.setPositiveButton("Save", (dialogInterface, i) -> {
// DataManager.scoutNotice = editText.getText().toString();
// DataManager.save_scout_notice();
// });
alert.setCancelable(false);
alert.create().show();
}
private TextView createText(String title) {
TextView tv = new TextView(getContext());
@@ -311,7 +269,7 @@ public class SettingsFragment extends Fragment {
ll.addView(createText("Package: " + pInfo.packageName));
ll.addView(createText("Version: " + pInfo.versionName));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ll.addView(createText("Signature: " + (pInfo.signingInfo != null ? pInfo.signingInfo.toString() : "None")));
ll.addView(createText("Signature: " + (pInfo.signingInfo != null ? "True" : "False")));
}
} catch (PackageManager.NameNotFoundException e) {
@@ -49,7 +49,10 @@ public class FileSelectorFragment extends Fragment {
meta_string_array = new String[]{
"matches.fields",
"pits.fields",
evcode+".eventdata"
evcode+".eventdata",
evcode+".rescout",
evcode+".scoutnotice",
"todelete.colabarray",
};
String[] files = FileEditor.getEventFiles(evcode);
@@ -4,12 +4,14 @@ import static com.ridgebotics.ridgescout.utility.FileEditor.baseDir;
import android.util.Log;
import com.ridgebotics.ridgescout.types.ColabArray;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.FileEditor;
import com.ridgebotics.ridgescout.utility.HttpGetFile;
import com.ridgebotics.ridgescout.utility.HttpPutFile;
import com.ridgebotics.ridgescout.utility.RequestTask;
import com.ridgebotics.ridgescout.utility.SettingsManager;
import com.ridgebotics.ridgescout.utility.ToDelete;
import org.json.JSONException;
import org.json.JSONObject;
@@ -96,6 +98,10 @@ public class HttpSync extends Thread {
public void run() {
isRunning = true;
boolean sendMetaFiles = SettingsManager.getFTPSendMetaFiles();
ToDelete.reload_todelete_list();
List<String> removeFiles = ToDelete.todelete_list.get();
String serverIP = SettingsManager.getFTPServer();
String serverKey = SettingsManager.getFTPKey();
@@ -113,6 +119,9 @@ public class HttpSync extends Thread {
getLocalFileMetadata();
localFiles.removeIf(localFile -> removeFiles.contains(localFile.filename+","+localFile.checksum));
remoteFiles.removeIf(remoteFile -> removeFiles.contains(remoteFile.filename+","+remoteFile.checksum));
@@ -187,7 +196,7 @@ public class HttpSync extends Thread {
}
ToDelete.deleteFiles();
setUpdateIndicator("Finished, " + upCount + " Up, " + downCount + " Down");
@@ -209,25 +218,6 @@ public class HttpSync extends Thread {
return new Date(file.lastModified());
}
public static String getSHA256Hash(String filePath) throws IOException, NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(filePath);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = fis.read(byteArray)) != -1) {
digest.update(byteArray, 0, bytesCount);
}
fis.close();
byte[] bytes = digest.digest();
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
private void getLocalFileMetadata() {
File localDir = new File(baseDir);
File[] localFileNames = localDir.listFiles();
@@ -244,9 +234,10 @@ public class HttpSync extends Thread {
tf.filename = file.getName();
tf.updated = getLocalFileUtcTimestamp(file);
try {
tf.checksum = getSHA256Hash(file.getPath());
tf.checksum = FileEditor.getSHA256Hash(file.getName());
} catch (Exception e) {
AlertManager.error("Failed to get hash of: " + file.getName(), e);
continue;
}
localFiles.add(tf);
}
@@ -6,10 +6,6 @@ import com.ridgebotics.ridgescout.types.ColabArray;
import com.ridgebotics.ridgescout.types.frcEvent;
import com.ridgebotics.ridgescout.types.input.FieldType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// Static class to hold loaded data, for ease of access.
public class DataManager {
public static String evcode;
@@ -63,6 +59,10 @@ public class DataManager {
}
}
public static ColabArray rescout_list = new ColabArray();
public static void reload_rescout_list(){
String filename = evcode + ".rescout";
@@ -87,6 +87,11 @@ public class DataManager {
}
}
public static String scoutNotice = "";
public static void reload_scout_notice(){
@@ -22,6 +22,8 @@ import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -326,6 +328,29 @@ public final class FileEditor {
public static String getSHA256Hash(String filePath) throws IOException, NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(baseDir + filePath);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = fis.read(byteArray)) != -1) {
digest.update(byteArray, 0, bytesCount);
}
fis.close();
byte[] bytes = digest.digest();
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static boolean setEvent(frcEvent event){
@@ -0,0 +1,151 @@
package com.ridgebotics.ridgescout.utility;
import static android.widget.LinearLayout.VERTICAL;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.ridgebotics.ridgescout.types.ColabArray;
import java.util.ArrayList;
import java.util.List;
public class ToDelete {
public static final String filename = "todelete.colabarray";
public static void findCorruptedFiles(Context c) {
new Thread(() -> {
AlertManager.startLoading("Loading files...");
List<String> filenames = FileEditor.findCorruptedFiles();
AlertManager.stopLoading();
((Activity) c).runOnUiThread(() -> {
deleteFiles(c, filenames, true);
});
}).start();
}
public static void deleteFiles(Context c, List<String> files, boolean defaultOption) {
ScrollView sv = new ScrollView(c);
LinearLayout ll = new LinearLayout(c);
ll.setOrientation(VERTICAL);
sv.addView(ll);
CheckBox[] checkboxes = new CheckBox[files.size()];
for(int i =0; i < files.size(); i++){
CheckBox cb = new CheckBox(c);
cb.setText(files.get(i));
cb.setChecked(defaultOption);
ll.addView(cb);
checkboxes[i] = cb;
}
AlertDialog.Builder alert = new AlertDialog.Builder(c);
alert.setTitle("Delete files");
alert.setView(sv);
alert.setNeutralButton("Cancel", null);
alert.setPositiveButton("Delete", (_dialogInterface, _i) -> {
List<String> delete_files = new ArrayList<>();
for(int i = 0; i < files.size(); i++) {
if(checkboxes[i].isChecked())
delete_files.add(files.get(i));
}
AlertDialog.Builder confirm = new AlertDialog.Builder(c);
alert.setTitle("Confirm");
TextView tv = new TextView(c);
tv.setText("Are you sure you want to delete " + delete_files.size() + " files?");
alert.setView(tv);
alert.setNeutralButton("Cancel", null);
alert.setPositiveButton("Delete", (dialogInterface, i) -> {
deleteFiles(delete_files);
});
alert.setCancelable(false);
alert.create().show();
});
alert.setCancelable(false);
alert.create().show();
}
public static ColabArray todelete_list = new ColabArray();
public static void reload_todelete_list(){
if(!FileEditor.fileExist(ToDelete.filename)) {todelete_list = new ColabArray(); return;}
byte[] file = FileEditor.readFile(ToDelete.filename);
if(file == null) {todelete_list = new ColabArray(); return;}
try {
todelete_list = ColabArray.decode(file);
} catch (Exception e){
AlertManager.error("Error loading todelete list", e);
todelete_list = new ColabArray();
}
}
public static void save_todelete_list() {
try {
FileEditor.writeFile(ToDelete.filename, todelete_list.encode());
} catch (Exception e){
AlertManager.error("Error saving todelete list", e);
}
}
private static void deleteFiles(List<String> toDelete) {
reload_todelete_list();
for(String file : toDelete) {
String hash;
try {
hash = FileEditor.getSHA256Hash(file);
} catch (Exception e) {
AlertManager.error("Failed to get hash of file: " + file, e);
continue;
}
todelete_list.add(file+","+hash);
FileEditor.deleteFile(file);
}
save_todelete_list();
}
public static void deleteFiles() {
reload_todelete_list();
List<String> toDelete = todelete_list.get();
for(String filename : FileEditor.getFiles()){
try {
String hash = FileEditor.getSHA256Hash(filename);
if(toDelete.contains(filename+","+hash)) {
FileEditor.deleteFile(filename);
}
} catch (Exception e) {
AlertManager.error("Failed to get hash of file: " + filename, e);
continue;
}
}
}
public static boolean contains(String localfile) {
try {
String hash = FileEditor.getSHA256Hash(localfile);
return contains(localfile, hash);
} catch (Exception e) {
AlertManager.error("Failed to get hash of file: " + localfile, e);
return false;
}
}
public static boolean contains(String filename, String hash){
return todelete_list.contains(filename+","+hash);
}
}