Added a view to main activity layout to host Snackbars, Configurations menu is mostly functional, misc.

This commit is contained in:
2020-08-24 08:49:27 -05:00
parent 06277911fc
commit 958f260d43
7 changed files with 175 additions and 25 deletions

View File

@@ -28,6 +28,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.navigation:navigation-fragment:2.1.0'
implementation 'androidx.navigation:navigation-ui:2.1.0'

View File

@@ -33,11 +33,17 @@ import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
public class Backend {
private static final String TAG = "Backend";
static private HashMap<String, Object> storage = new HashMap<>();
static private Backend instance;
private TACNET tacnet;
private Server server;
@@ -46,6 +52,10 @@ public class Backend {
private Settings settings;
private boolean configChanged, settingsChanged;
public static HashMap<String, Object> getStorage() {
return storage;
}
public Backend() {
if (Backend.instance() != null) {
throw(new RuntimeException("Backend instance already exists!"));
@@ -114,10 +124,14 @@ public class Backend {
saveConfig();
}
public boolean isConfigChanged() { return configChanged; }
public boolean hasConfigChanged() { return configChanged; }
public String configPath(String name) {
return TAC.CONFIGS_PATH + File.separator + name + ".json";
}
public void loadConfig(String name) {
String path = "" + TAC.CONFIGS_PATH + File.separator + name + ".json";
String path = configPath(name);
File file = new File(path);
if (file.exists() && file.isFile()) {
@@ -129,12 +143,38 @@ public class Backend {
public boolean saveConfig() {
if (config == null) { return false; }
final String path = "" + TAC.CONFIGS_PATH + File.separator + getConfig().getName() + ".json";
final String path = configPath(getConfig().getName());
configChanged = false;
return writeToFile(path, gsonForConfig().toJson(config));
}
public boolean moveConfig(String oldName, String newName) {
final String oldPath = configPath(oldName);
final String newPath = configPath(newName);
final File oldFile = new File(oldPath);
final File newFile = new File(newPath);
if (!oldFile.exists() || !oldFile.isFile()) {
Log.e(TAG, "moveConfig: Can not move config file \"" + oldPath + "\" does not exists!");
return false;
}
if (newFile.exists() && newFile.isFile()) {
Log.e(TAG, "moveConfig: Config file \"" + newPath + "\" already exists!");
return false;
}
return oldFile.renameTo(newFile);
}
public boolean deleteConfig(String name) {
File file = new File(configPath(name));
return file.delete();
}
public void uploadConfig() {
if (config != null && tacnet.isConnected()) {
String json = "";
@@ -149,7 +189,7 @@ public class Backend {
}
public void writeNewConfig(String name) {
String path = TAC.CONFIGS_PATH + File.separator + name + ".json";
String path = configPath(name);
File file = new File(path);
Config config = new Config(name);

View File

@@ -18,6 +18,7 @@ import java.util.regex.Pattern;
public class ConfigurationDialog extends TimeCraftersDialog {
private static final String TAG = "ConfigurationDialog";
private String configName;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -31,7 +32,14 @@ public class ConfigurationDialog extends TimeCraftersDialog {
final Button cancel = view.findViewById(R.id.cancel);
final Button mutate = view.findViewById(R.id.mutate);
title.setText("Create Configuration");
if (getArguments() != null) {
configName = getArguments().getString("config_name");
title.setText("Editing " + configName);
name.setText(configName);
mutate.setText(getResources().getString(R.string.dialog_update));
} else {
title.setText("Create Configuration");
}
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -39,16 +47,20 @@ public class ConfigurationDialog extends TimeCraftersDialog {
}
});
// mutate.setText(getResources().getString(R.string.dialog_update));
mutate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String configName = name.getText().toString();
final String newConfigName = name.getText().toString();
if (isValid(configName)) {
Backend.instance().writeNewConfig(configName);
if (isValid(newConfigName)) {
if (configName != null) {
Backend.instance().moveConfig(configName, newConfigName);
} else {
Backend.instance().writeNewConfig(newConfigName);
}
dismiss();
} else {
// TODO: Show friendly error message
Log.d(TAG, "onClick: InValid");
}
}

View File

@@ -1,6 +1,11 @@
package org.timecrafters.TimeCraftersConfigurationTool.dialogs;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -10,25 +15,30 @@ import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.google.android.material.resources.TextAppearance;
import org.timecrafters.TimeCraftersConfigurationTool.R;
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersDialog;
public class ConfirmationDialog extends TimeCraftersDialog {
private String title, message;
private Runnable action;
public ConfirmationDialog() {}
public ConfirmationDialog(String title, String message, Runnable action) {
this.title = title;
this.message = message;
this.action = action;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateView(inflater, container, savedInstanceState);
if (getArguments() != null) {
this.title = getArguments().getString("title", "Are You Sure?");
this.message = getArguments().getString("message", "");
final String actionKey = getArguments().getString("action", null);
if (actionKey != null && Backend.getStorage().containsKey(actionKey)) {
this.action = (Runnable) Backend.getStorage().get(actionKey);
}
}
final TextView title = root.findViewById(R.id.dialogTitle);
final ConstraintLayout titlebar = root.findViewById(R.id.titlebar);
final LinearLayout view = root.findViewById(R.id.dialogContent);
@@ -37,13 +47,29 @@ public class ConfirmationDialog extends TimeCraftersDialog {
final Button cancel = root.findViewById(R.id.cancel);
final Button confirm = root.findViewById(R.id.confirm);
titlebar.setBackgroundColor(getResources().getColor(R.color.dialogAlert));
if (getArguments() != null && getArguments().getBoolean("extreme_danger", false)) {
titlebar.setBackgroundColor(getResources().getColor(R.color.dialogError));
getDialog().getWindow().setDimAmount(0.8f);
cancel.setTypeface(cancel.getTypeface(), Typeface.BOLD);
} else {
titlebar.setBackgroundColor(getResources().getColor(R.color.dialogAlert));
}
title.setText(this.title);
messageView.setText(message);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (action != null) {
action.run();
}
dismiss();
}
});

View File

@@ -104,7 +104,12 @@ public class GroupsFragment extends TimeCraftersFragment {
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ConfirmationDialog dialog = new ConfirmationDialog("Are you sure?", "Really delete " + group.name + "?", null);
ConfirmationDialog dialog = new ConfirmationDialog();
Bundle bundle = new Bundle();
bundle.putString("title", "Are you sure?");
bundle.putString("message", "Delete group " + group.name + "?");
dialog.setArguments(bundle);
dialog.show(getFragmentManager(), null);
}
});

View File

@@ -1,28 +1,38 @@
package org.timecrafters.TimeCraftersConfigurationTool.ui.settings.configurations;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import androidx.annotation.NonNull;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import org.timecrafters.TimeCraftersConfigurationTool.R;
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
import org.timecrafters.TimeCraftersConfigurationTool.dialogs.ConfigurationDialog;
import org.timecrafters.TimeCraftersConfigurationTool.dialogs.ConfirmationDialog;
import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersFragment;
public class ConfigurationsFragment extends TimeCraftersFragment {
private LayoutInflater inflater;
private LinearLayout configsContainer;
private View root;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.fragment_configuration, container, false);
this.inflater = inflater;
this.root = inflater.inflate(R.layout.fragment_configuration, container, false);
final ScrollView scrollview = root.findViewById(R.id.scrollview);
final LinearLayout configsContainer = root.findViewById(R.id.container);
configsContainer = root.findViewById(R.id.container);
final FloatingActionButton actionButton = root.findViewById(R.id.actionButton);
floatingActionButtonAutoHide(actionButton, scrollview);
@@ -34,8 +44,16 @@ public class ConfigurationsFragment extends TimeCraftersFragment {
}
});
populateConfigFiles();
return root;
}
private void populateConfigFiles() {
configsContainer.removeAllViews();
int i = 0;
for (String configFile : Backend.instance().configsList()) {
for (final String configFile : Backend.instance().configsList()) {
final String config = configFile.replace(".json", "");
View view = inflater.inflate(R.layout.fragment_part_configuration, null);
@@ -45,21 +63,62 @@ public class ConfigurationsFragment extends TimeCraftersFragment {
view.setBackgroundColor(getResources().getColor(R.color.list_odd));
}
Button configName = view.findViewById(R.id.name);
final Button configName = view.findViewById(R.id.name);
final ImageButton rename = view.findViewById(R.id.rename);
final ImageButton delete = view.findViewById(R.id.delete);
configName.setText(config);
configName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Backend.instance().getSettings().config.equals(config)) {
return;
}
Backend.instance().getSettings().config = config;
Backend.instance().loadConfig(config);
Backend.instance().saveSettings();
View snackbarHost = getActivity().findViewById(R.id.snackbar_host);
Snackbar.make(snackbarHost, "Loaded config: " + config, Snackbar.LENGTH_LONG).show();
}
});
rename.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ConfigurationDialog dialog = new ConfigurationDialog();
Bundle bundle = new Bundle();
bundle.putString("config_name", config);
dialog.setArguments(bundle);
dialog.show(getFragmentManager(), null);
}
});
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ConfirmationDialog dialog = new ConfirmationDialog();
Bundle bundle = new Bundle();
final String actionKey = "delete_configuration";
bundle.putString("title", "Are you sure?");
bundle.putString("message", "Destroy configuration " + config + "?");
bundle.putString("action", actionKey);
bundle.putBoolean("extreme_danger", true);
Runnable action = new Runnable() {
@Override
public void run() {
Backend.instance().deleteConfig(config);
}
} ;
Backend.getStorage().put(actionKey, action);
dialog.setArguments(bundle);
dialog.show(getFragmentManager(), null);
}
});
i++;
configsContainer.addView(view);
}
return root;
}
}

View File

@@ -20,6 +20,13 @@
app:layout_constraintVertical_bias="0.0"
app:navGraph="@navigation/mobile_navigation" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/snackbar_host"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@id/nav_host_fragment"
app:layout_constraintStart_toStartOf="@id/nav_host_fragment" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"