mirror of
https://github.com/TimeCrafters/TimeCraftersConfigurationTool.git
synced 2025-12-15 21:12:34 +00:00
Made all dialogs content be inside a ScrollView, ServerDialog data now updates, working basic server, misc. changes.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<>();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user