Implement support for enum/callback arguments.
This commit is contained in:
parent
4ecd4936bd
commit
75421d4c95
@ -47,10 +47,10 @@ public class ProgramakerBridgeService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
setBridgeStatusNotification(getString(R.string.bridge_service_not_started), ServiceState.LOADING);
|
setBridgeStatusNotification(getString(R.string.bridge_service_not_started), ServiceState.LOADING, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBridgeStatusNotification(String title, ServiceState state) {
|
private void setBridgeStatusNotification(String title, ServiceState state, String description) {
|
||||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
assert notificationManager != null;
|
assert notificationManager != null;
|
||||||
|
|
||||||
@ -94,6 +94,10 @@ public class ProgramakerBridgeService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (description != null) {
|
||||||
|
builder.setContentText(description);
|
||||||
|
}
|
||||||
|
|
||||||
Notification notification = builder.build();
|
Notification notification = builder.build();
|
||||||
|
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
@ -164,7 +168,7 @@ public class ProgramakerBridgeService extends Service {
|
|||||||
bridgeId);
|
bridgeId);
|
||||||
ProgramakerBridgeService.this.bridge.start(
|
ProgramakerBridgeService.this.bridge.start(
|
||||||
() -> { // On ready
|
() -> { // On ready
|
||||||
setBridgeStatusNotification(getString(R.string.bridge_service_online), ServiceState.RUNNING);
|
setBridgeStatusNotification(getString(R.string.bridge_service_online), ServiceState.RUNNING, null);
|
||||||
if (config.getBridgeConnectionId() == null) {
|
if (config.getBridgeConnectionId() == null) {
|
||||||
new DoAsync().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
|
new DoAsync().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
|
||||||
new Tuple2<>(
|
new Tuple2<>(
|
||||||
@ -183,25 +187,29 @@ public class ProgramakerBridgeService extends Service {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
() -> { // On completed
|
() -> { // On completed
|
||||||
ProgramakerBridgeService.this.bridge = null;
|
|
||||||
onBridgeFailedAfterConnected();
|
onBridgeFailedAfterConnected();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
Log.e(LogTag, "Error on bridge", ex);
|
Log.e(LogTag, "Error on bridge", ex);
|
||||||
ProgramakerBridgeService.this.bridge = null;
|
ProgramakerBridgeService.this.bridge = null;
|
||||||
|
setBridgeStatusNotification(getString(R.string.bridge_service_starting),
|
||||||
|
ServiceState.STOPPED,
|
||||||
|
getString(R.string.error_establishing_connection));
|
||||||
}
|
}
|
||||||
}, "ServiceStartArguments");
|
}, "ServiceStartArguments");
|
||||||
thread.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
thread.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||||
|
|
||||||
setBridgeStatusNotification(getString(R.string.bridge_service_starting), ServiceState.LOADING);
|
setBridgeStatusNotification(getString(R.string.bridge_service_starting), ServiceState.LOADING, null);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBridgeFailedAfterConnected() {
|
private void onBridgeFailedAfterConnected() {
|
||||||
|
ProgramakerBridgeService.this.bridge = null;
|
||||||
|
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
Log.e(LogTag, "Bridge stopped after connected. Waiting 10s then restarting");
|
Log.e(LogTag, "Bridge stopped after connected. Waiting 10s then restarting");
|
||||||
setBridgeStatusNotification(getString(R.string.bridge_service_failed_restarting), ServiceState.LOADING);
|
setBridgeStatusNotification(getString(R.string.bridge_service_failed_restarting), ServiceState.LOADING, null);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(WAIT_TIME_BEFORE_RESTART_MILLIS);
|
Thread.sleep(WAIT_TIME_BEFORE_RESTART_MILLIS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -224,6 +232,6 @@ public class ProgramakerBridgeService extends Service {
|
|||||||
if (bridge != null) {
|
if (bridge != null) {
|
||||||
bridge.stop();
|
bridge.stop();
|
||||||
}
|
}
|
||||||
setBridgeStatusNotification(getString(R.string.bridge_service_failed_stopping), ServiceState.STOPPED);
|
setBridgeStatusNotification(getString(R.string.bridge_service_failed_stopping), ServiceState.STOPPED, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen
|
|||||||
savedTo = arg;
|
savedTo = arg;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ConnectorTypeInfo typeInfo = ConnectorTypeInfo.FromTypeName(arg.getType());
|
ConnectorTypeInfo typeInfo = ConnectorTypeInfo.FromArgument(arg);
|
||||||
inputs.add(new Tuple2<>(typeInfo,
|
inputs.add(new Tuple2<>(typeInfo,
|
||||||
new ProgramakerCustomBlockInputConnector(this, _partGrid,
|
new ProgramakerCustomBlockInputConnector(this, _partGrid,
|
||||||
0, 0,
|
0, 0,
|
||||||
@ -199,7 +199,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen
|
|||||||
Tuple2<ConnectorTypeInfo, AnyRoundOutputConnector> saveToOutput = null;
|
Tuple2<ConnectorTypeInfo, AnyRoundOutputConnector> saveToOutput = null;
|
||||||
|
|
||||||
if (savedTo != null) {
|
if (savedTo != null) {
|
||||||
saveToOutput = new Tuple2<>(ConnectorTypeInfo.FromTypeName(savedTo.getType()),
|
saveToOutput = new Tuple2<>(ConnectorTypeInfo.FromTypeName(savedTo.getComputedType()),
|
||||||
new AnyRoundOutputConnector(this, this._partGrid, 0, 0, IO_RADIUS));
|
new AnyRoundOutputConnector(this, this._partGrid, 0, 0, IO_RADIUS));
|
||||||
outputs.add(new Tuple2<>(saveToOutput.item1, saveToOutput.item2));
|
outputs.add(new Tuple2<>(saveToOutput.item1, saveToOutput.item2));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.codigoparallevar.minicards.parts.connectors;
|
package com.codigoparallevar.minicards.parts.connectors;
|
||||||
|
|
||||||
import com.codigoparallevar.minicards.parts.style.CardTheme;
|
import com.codigoparallevar.minicards.parts.style.CardTheme;
|
||||||
|
import com.programaker.api.data.ProgramakerCustomBlockArgument;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -8,6 +9,9 @@ import org.json.JSONObject;
|
|||||||
public class ConnectorTypeInfo {
|
public class ConnectorTypeInfo {
|
||||||
private final Type _type;
|
private final Type _type;
|
||||||
private static final String SERIALIZED_TYPE_KEY = "type";
|
private static final String SERIALIZED_TYPE_KEY = "type";
|
||||||
|
private static final String SERIALIZED_ARGUMENT_KEY = "argument";
|
||||||
|
|
||||||
|
private ProgramakerCustomBlockArgument _blockArgument = null;
|
||||||
|
|
||||||
public static ConnectorTypeInfo FromTypeName(String type) {
|
public static ConnectorTypeInfo FromTypeName(String type) {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
@ -66,7 +70,20 @@ public class ConnectorTypeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ConnectorTypeInfo deserialize(JSONObject jsonTypeInfo) {
|
public static ConnectorTypeInfo deserialize(JSONObject jsonTypeInfo) {
|
||||||
return ConnectorTypeInfo.FromTypeName(jsonTypeInfo.optString(SERIALIZED_TYPE_KEY));
|
ConnectorTypeInfo type = ConnectorTypeInfo.FromTypeName(jsonTypeInfo.optString(SERIALIZED_TYPE_KEY));
|
||||||
|
|
||||||
|
JSONObject arg = jsonTypeInfo.optJSONObject(SERIALIZED_ARGUMENT_KEY);
|
||||||
|
if (arg != null) {
|
||||||
|
type._blockArgument = ProgramakerCustomBlockArgument.deserialize(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectorTypeInfo FromArgument(ProgramakerCustomBlockArgument arg) {
|
||||||
|
ConnectorTypeInfo type = ConnectorTypeInfo.FromTypeName(arg.getComputedType());
|
||||||
|
type._blockArgument = arg;
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOuterColor() {
|
public int getOuterColor() {
|
||||||
@ -120,12 +137,20 @@ public class ConnectorTypeInfo {
|
|||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
try {
|
try {
|
||||||
obj.put(SERIALIZED_TYPE_KEY, ConnectorTypeInfo.typeToString(this._type));
|
obj.put(SERIALIZED_TYPE_KEY, ConnectorTypeInfo.typeToString(this._type));
|
||||||
|
|
||||||
|
if (_blockArgument != null) {
|
||||||
|
obj.put(SERIALIZED_ARGUMENT_KEY, _blockArgument.serialize());
|
||||||
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProgramakerCustomBlockArgument getBlockArgument() {
|
||||||
|
return _blockArgument;
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
PULSE,
|
PULSE,
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package com.codigoparallevar.minicards.parts.values;
|
package com.codigoparallevar.minicards.parts.values;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.codigoparallevar.minicards.R;
|
import com.codigoparallevar.minicards.R;
|
||||||
import com.codigoparallevar.minicards.ScrolledCanvas;
|
import com.codigoparallevar.minicards.ScrolledCanvas;
|
||||||
@ -21,8 +25,14 @@ import com.codigoparallevar.minicards.types.PartGrid;
|
|||||||
import com.codigoparallevar.minicards.types.connectors.Wiring.AnyWire;
|
import com.codigoparallevar.minicards.types.connectors.Wiring.AnyWire;
|
||||||
import com.codigoparallevar.minicards.types.connectors.input.InputConnector;
|
import com.codigoparallevar.minicards.types.connectors.input.InputConnector;
|
||||||
import com.codigoparallevar.minicards.types.connectors.output.OutputConnector;
|
import com.codigoparallevar.minicards.types.connectors.output.OutputConnector;
|
||||||
|
import com.codigoparallevar.minicards.types.functional.Consumer;
|
||||||
import com.codigoparallevar.minicards.types.functional.Tuple2;
|
import com.codigoparallevar.minicards.types.functional.Tuple2;
|
||||||
|
import com.codigoparallevar.minicards.types.functional.Tuple3;
|
||||||
import com.codigoparallevar.minicards.types.wireData.WireDataType;
|
import com.codigoparallevar.minicards.types.wireData.WireDataType;
|
||||||
|
import com.codigoparallevar.minicards.ui_helpers.GetAsync;
|
||||||
|
import com.codigoparallevar.minicards.utils.Serializations;
|
||||||
|
import com.programaker.api.data.ProgramakerCustomBlockArgument;
|
||||||
|
import com.programaker.api.data.ProgramakerCustomBlockArgumentValue;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@ -51,12 +61,14 @@ public class StaticValuePart implements Part {
|
|||||||
private int _left;
|
private int _left;
|
||||||
private int _top;
|
private int _top;
|
||||||
private String _value = null;
|
private String _value = null;
|
||||||
|
private String _valueId = null;
|
||||||
|
|
||||||
public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo, String value) {
|
public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo, String value, String valueId) {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this._typeInfo = typeInfo;
|
this._typeInfo = typeInfo;
|
||||||
this._grid = grid;
|
this._grid = grid;
|
||||||
this._value = value;
|
this._value = value;
|
||||||
|
this._valueId = valueId;
|
||||||
|
|
||||||
this.updateWidthHeight();
|
this.updateWidthHeight();
|
||||||
|
|
||||||
@ -66,6 +78,9 @@ public class StaticValuePart implements Part {
|
|||||||
this._left + _width / 2,
|
this._left + _width / 2,
|
||||||
this._top + _height, IO_RADIUS);
|
this._top + _height, IO_RADIUS);
|
||||||
}
|
}
|
||||||
|
public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo, String value) {
|
||||||
|
this(id, grid, centerx, centery, typeInfo, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo) {
|
public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo) {
|
||||||
this(id, grid, centerx, centery, typeInfo, null);
|
this(id, grid, centerx, centery, typeInfo, null);
|
||||||
@ -80,9 +95,10 @@ public class StaticValuePart implements Part {
|
|||||||
JSONObject serialized = new JSONObject();
|
JSONObject serialized = new JSONObject();
|
||||||
|
|
||||||
serialized.put("id", _id);
|
serialized.put("id", _id);
|
||||||
serialized.put("left", _left);
|
serialized.put("center_x", _left + _width / 2);
|
||||||
serialized.put("top", _top);
|
serialized.put("center_y", _top + _height / 2);
|
||||||
serialized.put("value", _value == null ? JSONObject.NULL : _value);
|
serialized.put("value", _value == null ? JSONObject.NULL : _value);
|
||||||
|
serialized.put("value_id", _valueId == null ? JSONObject.NULL : _valueId);
|
||||||
|
|
||||||
JSONObject jsonTypeInfo = _typeInfo.serialize();
|
JSONObject jsonTypeInfo = _typeInfo.serialize();
|
||||||
serialized.put("type_info", jsonTypeInfo);
|
serialized.put("type_info", jsonTypeInfo);
|
||||||
@ -109,13 +125,14 @@ public class StaticValuePart implements Part {
|
|||||||
|
|
||||||
public static Tuple2<Part, List<PartConnection>> deserialize(PartGrid grid, JSONObject data) throws JSONException {
|
public static Tuple2<Part, List<PartConnection>> deserialize(PartGrid grid, JSONObject data) throws JSONException {
|
||||||
String id = data.getString("id");
|
String id = data.getString("id");
|
||||||
int left = data.getInt("left");
|
int centerx = data.getInt("center_x");
|
||||||
int top = data.getInt("top");
|
int centery = data.getInt("center_y");
|
||||||
String value = data.optString("value");
|
String value = Serializations.getString(data, "value");
|
||||||
|
String valueId = Serializations.getString(data, "value_id");
|
||||||
|
|
||||||
JSONObject jsonTypeInfo = data.getJSONObject("type_info");
|
JSONObject jsonTypeInfo = data.getJSONObject("type_info");
|
||||||
ConnectorTypeInfo typeInfo = ConnectorTypeInfo.deserialize(jsonTypeInfo);
|
ConnectorTypeInfo typeInfo = ConnectorTypeInfo.deserialize(jsonTypeInfo);
|
||||||
StaticValuePart part = new StaticValuePart(id, grid, left, top, typeInfo, value);
|
StaticValuePart part = new StaticValuePart(id, grid, centerx, centery, typeInfo, value, valueId);
|
||||||
|
|
||||||
List<PartConnection> connections = new LinkedList<>();
|
List<PartConnection> connections = new LinkedList<>();
|
||||||
|
|
||||||
@ -177,6 +194,14 @@ public class StaticValuePart implements Part {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getMessage() {
|
private String getMessage() {
|
||||||
|
if (_value == null) {
|
||||||
|
return "-";
|
||||||
|
} else {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMessageForEdit() {
|
||||||
ConnectorTypeInfo.Type type = _typeInfo.get_type();
|
ConnectorTypeInfo.Type type = _typeInfo.get_type();
|
||||||
if (type == ConnectorTypeInfo.Type.INTEGER || type == ConnectorTypeInfo.Type.FLOAT) {
|
if (type == ConnectorTypeInfo.Type.INTEGER || type == ConnectorTypeInfo.Type.FLOAT) {
|
||||||
if (_value == null) {
|
if (_value == null) {
|
||||||
@ -192,10 +217,9 @@ public class StaticValuePart implements Part {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (_value == null) {
|
if (_value == null) {
|
||||||
return "-";
|
return "";
|
||||||
} else {
|
|
||||||
return _value;
|
|
||||||
}
|
}
|
||||||
|
return _value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,52 +236,131 @@ public class StaticValuePart implements Part {
|
|||||||
return; // Can't show dialog if can't retrieve context
|
return; // Can't show dialog if can't retrieve context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Context ctx = ((View) this._grid).getContext();
|
||||||
ConnectorTypeInfo.Type type = this._typeInfo.get_type();
|
ConnectorTypeInfo.Type type = this._typeInfo.get_type();
|
||||||
if (type == ConnectorTypeInfo.Type.PULSE) {
|
if (type == ConnectorTypeInfo.Type.PULSE) {
|
||||||
return; // Nothing to do here
|
return; // Nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
Context ctx = ((View) this._grid).getContext();
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
|
|
||||||
|
|
||||||
builder.setTitle(R.string.set_value);
|
|
||||||
Runnable prepareOnAccept = () -> {};
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
break;
|
break;
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
case FLOAT:
|
case FLOAT: {
|
||||||
{
|
|
||||||
final EditText input = new EditText(ctx);
|
final EditText input = new EditText(ctx);
|
||||||
|
|
||||||
input.setText(getMessage());
|
input.setText(getMessageForEdit());
|
||||||
input.setInputType(InputType.TYPE_CLASS_NUMBER);
|
input.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||||
builder.setView(input);
|
|
||||||
prepareOnAccept = () -> {
|
dialogAskUserForValue(ctx, input,
|
||||||
_value = input.getText().toString();
|
() -> {
|
||||||
};
|
_value = input.getText().toString();
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
case ENUM:
|
|
||||||
// TODO: Show enumerated values
|
|
||||||
case ANY:
|
case ANY:
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
case STRING:
|
case STRING: {
|
||||||
{
|
|
||||||
final EditText input = new EditText(ctx);
|
final EditText input = new EditText(ctx);
|
||||||
|
|
||||||
input.setText(getMessage());
|
input.setText(getMessageForEdit());
|
||||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
builder.setView(input);
|
dialogAskUserForValue(ctx, input,
|
||||||
prepareOnAccept = () -> {
|
() -> {
|
||||||
_value = input.getText().toString();
|
_value = input.getText().toString();
|
||||||
};
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
case ENUM:
|
||||||
|
ProgramakerCustomBlockArgument blockArg = _typeInfo.getBlockArgument();
|
||||||
|
String callback = null;
|
||||||
|
if (blockArg != null) {
|
||||||
|
callback = blockArg.getCallback();
|
||||||
|
if (callback.equals("null")) { // TODO: Fix this on server
|
||||||
|
callback = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Runnable onAccept = prepareOnAccept;
|
if (callback == null) {
|
||||||
|
new AlertDialog.Builder(ctx)
|
||||||
|
.setMessage(R.string.error_recovering_allowed_values)
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog loadingDialog = createLoadingDialog(ctx);
|
||||||
|
loadingDialog.show();
|
||||||
|
|
||||||
|
new GetAsync<List<ProgramakerCustomBlockArgumentValue>>().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
|
||||||
|
new Tuple3<>(
|
||||||
|
() -> _grid.getApi().fetchAllowedValues(blockArg),
|
||||||
|
results -> {
|
||||||
|
Log.i(LogTag, "Result: " + results);
|
||||||
|
loadingDialog.cancel();
|
||||||
|
|
||||||
|
String[] names = new String[results.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (ProgramakerCustomBlockArgumentValue value : results) {
|
||||||
|
names[i] = value.getName();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog d = createItemDialog(ctx, names, idx -> {
|
||||||
|
StaticValuePart.this._value = results.get(idx).getName();
|
||||||
|
StaticValuePart.this._valueId = results.get(idx).getId();
|
||||||
|
StaticValuePart.this._grid.update();
|
||||||
|
});
|
||||||
|
d.show();
|
||||||
|
},
|
||||||
|
ex -> {
|
||||||
|
Log.e(LogTag, "Error retrieving values: " + ex, ex);
|
||||||
|
new AlertDialog.Builder(ctx)
|
||||||
|
.setMessage(R.string.error_recovering_allowed_values)
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog createItemDialog(Context ctx, CharSequence[] itemNames, Consumer<Integer> onSelected) {
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
|
||||||
|
|
||||||
|
builder.setTitle(R.string.loading_available_values);
|
||||||
|
|
||||||
|
final ProgressBar progressBar = new ProgressBar(ctx);
|
||||||
|
progressBar.setIndeterminate(true);
|
||||||
|
builder.setItems(itemNames, (DialogInterface.OnClickListener) (dialog, which) -> {
|
||||||
|
try {
|
||||||
|
onSelected.apply(which);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog createLoadingDialog(Context ctx) {
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
|
||||||
|
|
||||||
|
builder.setTitle(R.string.loading_available_values);
|
||||||
|
|
||||||
|
final ProgressBar progressBar = new ProgressBar(ctx);
|
||||||
|
progressBar.setIndeterminate(true);
|
||||||
|
builder.setView(progressBar);
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dialogAskUserForValue(Context ctx, EditText input, Runnable onAccept) {
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
|
||||||
|
|
||||||
|
builder.setTitle(R.string.set_value);
|
||||||
builder
|
builder
|
||||||
.setPositiveButton(R.string.ok_accept_changes, (dialog, which) -> {
|
.setPositiveButton(R.string.ok_accept_changes, (dialog, which) -> {
|
||||||
onAccept.run();
|
onAccept.run();
|
||||||
@ -266,10 +369,12 @@ public class StaticValuePart implements Part {
|
|||||||
})
|
})
|
||||||
.setNegativeButton(R.string.cancel_discard_changes, (dialog, which) -> {
|
.setNegativeButton(R.string.cancel_discard_changes, (dialog, which) -> {
|
||||||
// No change
|
// No change
|
||||||
} );
|
})
|
||||||
|
.setView(input);
|
||||||
|
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -321,6 +426,10 @@ public class StaticValuePart implements Part {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object query(Object lastValue) {
|
public Object query(Object lastValue) {
|
||||||
|
if (this._valueId != null) {
|
||||||
|
return this._valueId;
|
||||||
|
}
|
||||||
|
|
||||||
return this._value;
|
return this._value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,4 +72,18 @@ public class Serializations {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getString(JSONObject map, String key) {
|
||||||
|
if (!map.has(key)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (map.opt(key) == JSONObject.NULL) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return map.getString(key);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,7 @@ import android.os.Build
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.programaker.api.data.ProgramakerBridgeInfo
|
import com.programaker.api.data.*
|
||||||
import com.programaker.api.data.ProgramakerCustomBlock
|
|
||||||
import com.programaker.api.data.ProgramakerFunctionCallResult
|
|
||||||
import com.programaker.api.data.api_results.*
|
import com.programaker.api.data.api_results.*
|
||||||
import com.programaker.api.exceptions.ProgramakerLoginRequiredException
|
import com.programaker.api.exceptions.ProgramakerLoginRequiredException
|
||||||
import com.programaker.api.exceptions.ProgramakerProtocolException
|
import com.programaker.api.exceptions.ProgramakerProtocolException
|
||||||
@ -138,6 +136,29 @@ class ProgramakerApi(private val ApiRoot: String="https://programaker.com/api")
|
|||||||
return result.result
|
return result.result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fetchAllowedValues(blockArg: ProgramakerCustomBlockArgument): List<ProgramakerCustomBlockArgumentValue>? {
|
||||||
|
val conn = URL(getArgumentValuesUrl(blockArg)).openConnection() as HttpURLConnection
|
||||||
|
|
||||||
|
addAuthHeader(conn)
|
||||||
|
|
||||||
|
var results: List<ProgramakerCustomBlockArgumentValue>? = null
|
||||||
|
try {
|
||||||
|
val serialized: HashMap<String,*> = parseJson(conn.inputStream, HashMap::class.java)
|
||||||
|
val returnInfo = ProgramakerCustomBlockArgumentValuesReturnInfo.deserialize(serialized)
|
||||||
|
if (!returnInfo.success) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
results = returnInfo.values
|
||||||
|
} catch (ex: FileNotFoundException) {
|
||||||
|
ex.logError(LogTag)
|
||||||
|
return null
|
||||||
|
} catch(ex: Exception) {
|
||||||
|
Log.e(LogTag, ex.toString(), ex)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
fun callBlock(block: ProgramakerCustomBlock, arguments: List<String>): ProgramakerFunctionCallResult {
|
fun callBlock(block: ProgramakerCustomBlock, arguments: List<String>): ProgramakerFunctionCallResult {
|
||||||
val conn = URL(getBlockUrl(block)).openConnection() as HttpURLConnection
|
val conn = URL(getBlockUrl(block)).openConnection() as HttpURLConnection
|
||||||
conn.setRequestProperty("Content-Type", "application/json")
|
conn.setRequestProperty("Content-Type", "application/json")
|
||||||
@ -278,6 +299,11 @@ class ProgramakerApi(private val ApiRoot: String="https://programaker.com/api")
|
|||||||
return "$ApiRoot/v0/users/id/$userId/bridges/id/$bridgeId/signals/$key"
|
return "$ApiRoot/v0/users/id/$userId/bridges/id/$bridgeId/signals/$key"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getArgumentValuesUrl(blockArg: ProgramakerCustomBlockArgument): String {
|
||||||
|
this.withUserId()
|
||||||
|
return "$ApiRoot/v0/users/id/$userId/bridges/id/${blockArg.bridge_id}/callback/${blockArg.callback}"
|
||||||
|
}
|
||||||
|
|
||||||
fun getUserId(): String? {
|
fun getUserId(): String? {
|
||||||
this.withUserId()
|
this.withUserId()
|
||||||
return userId;
|
return userId;
|
||||||
|
@ -11,16 +11,28 @@ class ProgramakerCustomBlockArgument(
|
|||||||
// val class: String,
|
// val class: String,
|
||||||
val callback: String?
|
val callback: String?
|
||||||
) {
|
) {
|
||||||
|
var bridge_id: String? = null
|
||||||
|
|
||||||
fun serialize(): JSONObject {
|
fun serialize(): JSONObject {
|
||||||
val serialized = hashMapOf<String, String?>(
|
val serialized = hashMapOf<String, String?>(
|
||||||
"type" to type,
|
"type" to type,
|
||||||
"default_value" to default_value,
|
"default_value" to default_value,
|
||||||
"callback" to callback
|
"callback" to callback,
|
||||||
|
"bridge_id" to bridge_id
|
||||||
)
|
)
|
||||||
|
|
||||||
return JSONObject(serialized as Map<*, *>)
|
return JSONObject(serialized as Map<*, *>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getComputedType(): String? {
|
||||||
|
if (callback != null && callback != "null") {
|
||||||
|
return "ENUM";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun deserialize(arguments: JSONArray?): List<ProgramakerCustomBlockArgument> {
|
fun deserialize(arguments: JSONArray?): List<ProgramakerCustomBlockArgument> {
|
||||||
@ -45,12 +57,16 @@ class ProgramakerCustomBlockArgument(
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deserialize(arguments: JSONObject): ProgramakerCustomBlockArgument {
|
@JvmStatic
|
||||||
|
fun deserialize(arguments: JSONObject): ProgramakerCustomBlockArgument {
|
||||||
val type: String? = arguments.optString("type")
|
val type: String? = arguments.optString("type")
|
||||||
val default_value: String? = arguments.optString("default_value")
|
val default_value: String? = arguments.optString("default_value")
|
||||||
val callback: String? = arguments.optString("callback")
|
val callback: String? = arguments.optString("callback")
|
||||||
|
val bridge_id: String? = arguments.optString("bridge_id")
|
||||||
|
|
||||||
return ProgramakerCustomBlockArgument(type, default_value, callback)
|
val arg = ProgramakerCustomBlockArgument(type, default_value, callback)
|
||||||
|
arg.bridge_id = bridge_id
|
||||||
|
return arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.programaker.api.data
|
||||||
|
|
||||||
|
import com.programaker.api.optGet
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class ProgramakerCustomBlockArgumentValue (
|
||||||
|
val id: String,
|
||||||
|
val name: String
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun deserializeList(value: Object): List<ProgramakerCustomBlockArgumentValue> {
|
||||||
|
if (value is Map<*, *>) {
|
||||||
|
return deserialize(value as Map<*, *>)
|
||||||
|
} else if (value is List<*>) {
|
||||||
|
return deserialize(value as List<*>)
|
||||||
|
} else {
|
||||||
|
throw IllegalArgumentException("Error deserializing: $value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun deserialize(value: Map<*, *>): List<ProgramakerCustomBlockArgumentValue> {
|
||||||
|
val results = LinkedList<ProgramakerCustomBlockArgumentValue>()
|
||||||
|
for (entry in value.asIterable()) {
|
||||||
|
var value = entry.value.toString()
|
||||||
|
if (entry.value is Map<*, *>) {
|
||||||
|
if ((entry.value as Map<String, *>).containsKey("name")) {
|
||||||
|
value = (entry.value as Map<*, *>)["name"].toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.add(ProgramakerCustomBlockArgumentValue(entry.key.toString(), value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun deserialize(value: List<*>): List<ProgramakerCustomBlockArgumentValue> {
|
||||||
|
val results = LinkedList<ProgramakerCustomBlockArgumentValue>()
|
||||||
|
for (entry in value) {
|
||||||
|
if (entry is Map<*,*>) {
|
||||||
|
var name = (entry as Map<String, *>).optGet("name")
|
||||||
|
var id = (entry as Map<String, *>).optGet("id")
|
||||||
|
|
||||||
|
if (name == null && id == null) {
|
||||||
|
throw IllegalArgumentException("Error deserializing: $entry")
|
||||||
|
}
|
||||||
|
else if (name == null) {
|
||||||
|
name = id
|
||||||
|
}
|
||||||
|
else if (id == null) {
|
||||||
|
id = name
|
||||||
|
}
|
||||||
|
|
||||||
|
results.add(ProgramakerCustomBlockArgumentValue(id.toString(), name.toString()))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw IllegalArgumentException("Error deserializing: $entry")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.programaker.api.data
|
||||||
|
|
||||||
|
import com.programaker.api.optGet
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class ProgramakerCustomBlockArgumentValuesReturnInfo(
|
||||||
|
val success: Boolean,
|
||||||
|
val values: List<ProgramakerCustomBlockArgumentValue>
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun deserialize(value: HashMap<String,*>): ProgramakerCustomBlockArgumentValuesReturnInfo {
|
||||||
|
val _success: Boolean? = value.optGet("success") as Boolean?
|
||||||
|
val _result: Object? = value.optGet("result") as Object
|
||||||
|
|
||||||
|
var success = false
|
||||||
|
if (_success != null) {
|
||||||
|
success = _success
|
||||||
|
}
|
||||||
|
|
||||||
|
var result: List<ProgramakerCustomBlockArgumentValue> = Collections.emptyList<ProgramakerCustomBlockArgumentValue>()
|
||||||
|
if (_result != null) {
|
||||||
|
result = ProgramakerCustomBlockArgumentValue.deserializeList(_result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProgramakerCustomBlockArgumentValuesReturnInfo(success, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,11 @@ internal class ProgramakerGetCustomBlocksResultTypeAdapter : JsonSerializer<Prog
|
|||||||
for (value in value1.asJsonArray) {
|
for (value in value1.asJsonArray) {
|
||||||
val block = gson.fromJson(value, ProgramakerCustomBlock::class.java)
|
val block = gson.fromJson(value, ProgramakerCustomBlock::class.java)
|
||||||
block.bridge_id = bridgeId
|
block.bridge_id = bridgeId
|
||||||
|
if (block.arguments != null) {
|
||||||
|
for (arg in block.arguments) {
|
||||||
|
arg.bridge_id = bridgeId
|
||||||
|
}
|
||||||
|
}
|
||||||
blocks.add(block)
|
blocks.add(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
app/src/main/java/com/programaker/api/utils.kt
Normal file
19
app/src/main/java/com/programaker/api/utils.kt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.programaker.api
|
||||||
|
|
||||||
|
internal fun <K, V> java.util.HashMap<K, V>.optGet(key: K): V? {
|
||||||
|
if (this.containsKey(key)) {
|
||||||
|
return this.get(key)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <K, V> Map<K, V>.optGet(key: K): V? {
|
||||||
|
if (this.containsKey(key)) {
|
||||||
|
return this.get(key)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@ -29,4 +29,7 @@
|
|||||||
<string name="set_value">Set block value</string>
|
<string name="set_value">Set block value</string>
|
||||||
<string name="ok_accept_changes">OK</string>
|
<string name="ok_accept_changes">OK</string>
|
||||||
<string name="cancel_discard_changes">Cancel</string>
|
<string name="cancel_discard_changes">Cancel</string>
|
||||||
|
<string name="error_establishing_connection">Error establishing connection</string>
|
||||||
|
<string name="error_recovering_allowed_values">Error recovering allowed values</string>
|
||||||
|
<string name="loading_available_values">Loading available values...</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user