Made all dialogs content be inside a ScrollView, ServerDialog data now updates, working basic server, misc. changes.

This commit is contained in:
2020-08-22 17:02:50 -05:00
parent 39c30d4096
commit b39742d17f
10 changed files with 262 additions and 74 deletions

View File

@@ -41,7 +41,9 @@ public class MainActivity extends AppCompatActivity {
if (!havePermissions()) {
new PermissionsRequestDialog().show(getSupportFragmentManager(), null);
} else {
new Backend();
if (Backend.instance() == null) {
new Backend();
}
}
}

View File

@@ -11,6 +11,7 @@ import org.timecrafters.TimeCraftersConfigurationTool.backend.config.Group;
import org.timecrafters.TimeCraftersConfigurationTool.backend.config.Preset;
import org.timecrafters.TimeCraftersConfigurationTool.serializers.SettingsDeserializer;
import org.timecrafters.TimeCraftersConfigurationTool.serializers.SettingsSerializer;
import org.timecrafters.TimeCraftersConfigurationTool.tacnet.Server;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -32,18 +33,24 @@ public class Backend {
private static final String TAG = "Backend";
static private Backend instance;
private TACNET tacnet;
private Server server;
private Exception lastServerError;
private Config config;
private Settings settings;
private boolean configChanged, settingsChanged;
public Backend() {
instance = this;
if (Backend.instance() != null) {
throw(new RuntimeException("Backend instance already exists!"));
} else {
instance = this;
}
loadSettings();
if (!settings.config.isEmpty()) {
loadConfig(settings.config);
} else {
config = new Config();
config = new Config("DEBUG DEBUG DEBUG");
}
tacnet = new TACNET();
@@ -59,6 +66,33 @@ public class Backend {
return tacnet;
}
public Server getServer() {
return server;
}
public void startServer() {
try {
server = new Server(settings.port);
server.start();
} catch (IOException error) {
lastServerError = error;
}
}
public void stopServer() {
if (server != null) {
try {
server.stop();
} catch (IOException error) {
lastServerError = error;
}
}
}
public Exception getLastServerError() {
return lastServerError;
}
public Config getConfig() {
return config;
}
@@ -76,7 +110,7 @@ public class Backend {
public boolean isConfigChanged() { return configChanged; }
public void loadConfig(String name) {
String path = "" + TAC.CONFIGS_PATH + File.separator + name;
String path = "" + TAC.CONFIGS_PATH + File.separator + name + ".json";
File file = new File(path);
if (file.exists() && file.isFile()) {
@@ -104,13 +138,10 @@ public class Backend {
}
public void writeNewConfig(String name) {
String path = "" + TAC.CONFIGS_PATH + File.separator + name;
String path = TAC.CONFIGS_PATH + File.separator + name + ".json";
File file = new File(path);
Configuration configuration = new Configuration(new Date(), new Date(), TAC.CONFIG_SPEC_VERSION, 0);
ArrayList<Group> groups = new ArrayList<>();
ArrayList<Preset> presets = new ArrayList<>();
Config config = new Config(configuration, groups, presets);
Config config = new Config(name);
Gson gson = new Gson();
@@ -136,7 +167,6 @@ public class Backend {
};
File fileList[] = directory.listFiles(filter);
for (File file : fileList) {
Log.d(TAG, "configsList: " + file.getName());
list.add(file.getName());
}
@@ -144,7 +174,7 @@ public class Backend {
}
// TODO: Write De/serializers for config
private Gson gsonForConfig() {
public Gson gsonForConfig() {
// return new GsonBuilder()
// .registerTypeAdapter(Config.class, new ConfigSerializer())
// .registerTypeAdapter(COnfig.class, new ConfigDeserializer())
@@ -186,14 +216,14 @@ public class Backend {
saveSettings();
}
private Gson gsonForSettings() {
public Gson gsonForSettings() {
return new GsonBuilder()
.registerTypeAdapter(Settings.class, new SettingsSerializer())
.registerTypeAdapter(Settings.class, new SettingsDeserializer())
.create();
}
protected String readFromFile(String path) {
public String readFromFile(String path) {
StringBuilder text = new StringBuilder();
try {
@@ -213,7 +243,7 @@ public class Backend {
return text.toString();
}
protected boolean writeToFile(String filePath, String content) {
public boolean writeToFile(String filePath, String content) {
try {
if (filePath.startsWith(TAC.ROOT_PATH)) {
createFolders(filePath);

View File

@@ -17,10 +17,9 @@ public class Config {
private ArrayList<Group> groups;
private ArrayList<Preset> presets;
// TODO: DELETE ME
public Config() {
this.name = "DEBUG ONLY";
this.configuration = new Configuration(new Date(), new Date(), 0, 32);
public Config(String name) {
this.name = name;
this.configuration = new Configuration(new Date(), new Date(), TAC.CONFIG_SPEC_VERSION, 32);
groups = new ArrayList<>();
presets = new ArrayList<>();
}

View File

@@ -13,18 +13,24 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import org.timecrafters.TimeCraftersConfigurationTool.R;
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersDialog;
import org.timecrafters.TimeCraftersConfigurationTool.tacnet.support.ServerStatsSyncHandler;
public class ServerDialog extends TimeCraftersDialog {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setCancelable(false);
View root = super.onCreateView(inflater, container, savedInstanceState);
final View root = super.onCreateView(inflater, container, savedInstanceState);
if (Backend.instance().getServer() == null) {
Backend.instance().startServer();
}
final TextView title = root.findViewById(R.id.dialogTitle);
final ConstraintLayout titlebar = root.findViewById(R.id.titlebar);
final LinearLayout view = root.findViewById(R.id.dialogContent);
view.addView(getLayoutInflater().inflate(R.layout.dialog_server, null));
new ServerStatsSyncHandler(view, 1_000);
title.setText(getResources().getString(R.string.tacnet_server_status));
@@ -33,6 +39,7 @@ public class ServerDialog extends TimeCraftersDialog {
@Override
public void onClick(View v) {
// TODO: Halt server
Backend.instance().stopServer();
dismiss();
}
});

View File

@@ -5,7 +5,7 @@ import android.util.Log;
import java.util.Arrays;
public class Packet {
final static public String PROTOCOL_VERSION = "0";
final static public String PROTOCOL_VERSION = "1";
final static public String PROTOCOL_HEADER_SEPERATOR = "|";
final static public String PROTOCOL_HEARTBEAT = "heartbeat";
private static final String TAG = "TACNET|Packet";
@@ -14,11 +14,33 @@ public class Packet {
// NOTE: PacketType is cast to a char, no more than 255 packet types can exist unless
// header is updated.
public enum PacketType {
HANDSHAKE,
HEARTBEAT,
DUMP_CONFIG,
CHANGE_ACTION,
CHANGE_VARIABLE,
HANDSHAKE(0),
HEARTBEAT(1),
ERROR(2),
DOWNLOAD_CONFIG(10),
UPLOAD_CONFIG(11),
ADD_GROUP(20),
UPDATE_GROUP(21),
DELETE_GROUP(22),
ADD_ACTION(30),
UPDATE_ACTION(31),
DELETE_ACTION(32),
ADD_VARIABLE(40),
UPDATE_VARIABLE(41),
DELETE_VARIABLE(42);
private int id;
final public int getId() {
return id;
}
PacketType(int id) {
this.id = id;
}
}
private String protocolVersion;
@@ -37,7 +59,7 @@ public class Packet {
static public Packet fromStream(String message) {
String version;
PacketType type;
PacketType type = null;
int length;
String body;
@@ -54,10 +76,22 @@ public class Packet {
}
version = slice[0];
type = PacketType.values()[Integer.parseInt(slice[1])];
// type = PacketType.values()[Integer.parseInt(slice[1])];
length = Integer.parseInt(slice[2]);
body = slice[slice.length - 1];
int typeId = Integer.parseInt(slice[1]);
for (PacketType packetType : PacketType.values()) {
if (packetType.getId() == typeId) {
type = packetType;
break;
}
}
if (type == null) {
return null;
}
return new Packet(version, type, length, body);
}
@@ -84,7 +118,7 @@ public class Packet {
String string = "";
string += PROTOCOL_VERSION;
string += PROTOCOL_HEADER_SEPERATOR;
string += packetType.ordinal();
string += packetType.getId();
string += PROTOCOL_HEADER_SEPERATOR;
string += contentLength;
string += PROTOCOL_HEADER_SEPERATOR;

View File

@@ -3,6 +3,9 @@ package org.timecrafters.TimeCraftersConfigurationTool.tacnet;
import android.util.Log;
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
import org.timecrafters.TimeCraftersConfigurationTool.backend.TAC;
import java.io.File;
import java.lang.reflect.Array;
import java.util.Arrays;
@@ -41,16 +44,26 @@ public class PacketHandler {
return;
}
case DUMP_CONFIG: {
handleDumpConfig(packet);
case ERROR: {
// handleHeartBeat(packet);
// return;
}
case DOWNLOAD_CONFIG: {
handleDownloadConfig(packet);
return;
}
case CHANGE_ACTION: {
handleChangeAction(packet);
case UPLOAD_CONFIG: {
handleUploadConfig(packet);
return;
}
// case CHANGE_ACTION: {
// handleChangeAction(packet);
// return;
// }
default: {
return;
}
@@ -62,22 +75,42 @@ public class PacketHandler {
// NO-OP
private void handleHeartBeat(Packet packet) {}
private void handleDumpConfig(Packet packet) {
if (
packet.getContent().length() > 4 && packet.getContent().charAt(0) == "[".toCharArray()[0] &&
packet.getContent().charAt(packet.getContent().length() - 1) == "]".toCharArray()[0]
) { /* "unless" keyword anyone? */ } else { return; }
private void handleUploadConfig(Packet packet) {
String[] split = packet.getContent().split("\\" + Packet.PROTOCOL_HEADER_SEPERATOR, 2);
final String configName = split[0];
final String json = split[1];
if (configName.length() == 0 && false) { //!Backend.instance().configIsValid(json)) {
return;
}
if (configName.length() == 0) {
return;
}
final String path = TAC.CONFIGS_PATH + File.separator + configName + ".json";
Log.i(TAG, "Got valid json: " + packet.getContent());
if (hostIsAConnection) {
// save and reload menu
// Writer.overwriteConfigFile(packet.getContent());
Backend.instance().writeToFile(path, json);
}
// Backend.instance().loadConfig();
private void handleDownloadConfig(Packet packet) {
final String configName = packet.getContent();
Log.i(TAG, "Got request for config: " + packet.getContent());
Packet pkt;
if (Backend.instance().configsList().contains("" + configName + ".json")) {
final String path = TAC.CONFIGS_PATH + File.separator + configName + ".json";
String content = Backend.instance().readFromFile(path);
Packet.create(Packet.PacketType.UPLOAD_CONFIG, content);
} else { // Errored
final String content = "ERROR";
Packet.create(Packet.PacketType.ERROR, content);
}
if (hostIsAConnection) {
Backend.instance().tacnet().puts(packet.toString());
} else {
// save
// Writer.overwriteConfigFile(packet.getContent());
Backend.instance().getServer().getActiveClient().puts(packet.toString());
}
}
@@ -97,9 +130,9 @@ public class PacketHandler {
return Packet.create(Packet.PacketType.HEARTBEAT, Packet.PROTOCOL_HEARTBEAT);
}
static public Packet packetDumpConfig(String string) {
string = string.replace("\n", " ");
return Packet.create(Packet.PacketType.DUMP_CONFIG, string);
}
// static public Packet packetDumpConfig(String string) {
// string = string.replace("\n", " ");
//
// return Packet.create(Packet.PacketType.DUMP_CONFIG, string);
// }
}

View File

@@ -0,0 +1,60 @@
package org.timecrafters.TimeCraftersConfigurationTool.tacnet.support;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import org.timecrafters.TimeCraftersConfigurationTool.R;
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
import org.timecrafters.TimeCraftersConfigurationTool.tacnet.Server;
import java.util.TimerTask;
public class ServerStatsSyncHandler {
private View view;
private Handler handler;
private Runnable runner;
private long delay;
private TextView clientStatus, totalPacketsIn, totalPacketsOut, totalDataIn, totalDataOut;
public ServerStatsSyncHandler(View view, long delay) {
this.view = view;
this.delay = delay;
clientStatus = view.findViewById(R.id.client_status);
totalPacketsIn = view.findViewById(R.id.total_packets_in);
totalPacketsOut = view.findViewById(R.id.total_packets_out);
totalDataIn = view.findViewById(R.id.total_data_in);
totalDataOut = view.findViewById(R.id.total_data_out);
handler = new Handler(Looper.getMainLooper());
runner = new Runnable() {
@Override
public void run() {
ServerStatsSyncHandler.this.run();
}
};
handler.postDelayed(runner, 0);
}
public void run() {
Server server = Backend.instance().getServer();
if (server != null) {
if (server.hasActiveClient()) {
clientStatus.setText("Connected");
} else {
clientStatus.setText("Disconnected");
}
totalPacketsIn.setText("" + server.getPacketsSent());
totalPacketsOut.setText("" + server.getPacketsReceived());
totalDataIn.setText("" + server.getDataSent() + " bytes");
totalDataOut.setText("" + server.getDataReceived() + " bytes");
handler.postDelayed(runner, delay);
}
}
}

View File

@@ -34,11 +34,29 @@ public class ConfigurationsFragment extends TimeCraftersFragment {
}
});
for (String config : Backend.instance().configsList()) {
int i = 0;
for (String configFile : Backend.instance().configsList()) {
final String config = configFile.replace(".json", "");
View view = inflater.inflate(R.layout.fragment_part_configuration, null);
if (i % 2 == 0) { // even
view.setBackgroundColor(getResources().getColor(R.color.list_even));
} else {
view.setBackgroundColor(getResources().getColor(R.color.list_odd));
}
Button configName = view.findViewById(R.id.name);
configName.setText(config);
configName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Backend.instance().getSettings().config = config;
Backend.instance().loadConfig(config);
Backend.instance().saveSettings();
}
});
i++;
configsContainer.addView(view);
}

View File

@@ -40,12 +40,16 @@
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/dialogContent"
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dialogBackground"
android:orientation="vertical">
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/dialogContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dialogBackground"
android:orientation="vertical" />
</ScrollView>
</LinearLayout>
</LinearLayout>

View File

@@ -66,12 +66,12 @@
android:orientation="vertical">
<TextView
android:id="@+id/total_data_out"
android:id="@+id/client_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel"/>
android:textColor="@color/dialogLabel" />
<TextView
android:id="@+id/total_packets_in"
@@ -79,23 +79,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel"/>
<TextView
android:id="@+id/total_data_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel"/>
<TextView
android:id="@+id/client_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel"/>
android:textColor="@color/dialogLabel" />
<TextView
android:id="@+id/total_packets_out"
@@ -103,7 +87,24 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel" />
<TextView
android:id="@+id/total_data_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel" />
<TextView
android:id="@+id/total_data_out"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textColor="@color/dialogLabel"/>
</LinearLayout>
</LinearLayout>