1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-29 00:10:26 +02:00
Gadgetbridge/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HRConfigActivity.java
2023-08-08 08:47:26 +00:00

426 lines
19 KiB
Java

/* Copyright (C) 2019-2021 Andreas Shimokawa, Daniel Dakhno
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.QHYBRID_COMMAND_UPDATE_WIDGETS;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomBackgroundWidgetElement;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomTextWidgetElement;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidgetElement;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.Widget;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Version;
public class HRConfigActivity extends AbstractGBActivity {
private SharedPreferences sharedPreferences;
private WidgetListAdapter widgetListAdapter;
private ArrayList<CustomWidget> customWidgets = new ArrayList<>();
SparseArray<String> widgetButtonsMapping = new SparseArray<>(4);
private static final int REQUEST_CODE_WIDGET_EDIT = 0;
private static final int REQUEST_CODE_IMAGE_PICK = 1;
private static final int REQUEST_CODE_IMAGE_EDIT = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qhybrid_hr_settings);
sharedPreferences = GBApplication.getPrefs().getPreferences();
initMappings();
loadWidgetConfigs();
final ListView widgetListView = findViewById(R.id.qhybrid_widget_list);
widgetListAdapter = new WidgetListAdapter(customWidgets);
widgetListView.setAdapter(widgetListAdapter);
widgetListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Widget widget = widgetListAdapter.getItem(position);
Intent startIntent = new Intent(HRConfigActivity.this, WidgetSettingsActivity.class);
startIntent.putExtra("EXTRA_WIDGET", widget);
startIntent.putExtra("EXTRA_WIDGET_IDNEX", position);
startIntent.putExtra("EXTRA_WIDGET_INITIAL_NAME", ((CustomWidget) widget).getName());
startActivityForResult(startIntent, REQUEST_CODE_WIDGET_EDIT);
}
});
loadCustomWidgetList();
findViewById(R.id.qhybrid_widget_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(HRConfigActivity.this, WidgetSettingsActivity.class);
startActivityForResult(startIntent, REQUEST_CODE_WIDGET_EDIT);
}
});
findViewById(R.id.qhybrid_set_background).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new MaterialAlertDialogBuilder(HRConfigActivity.this)
.setTitle("whoop whoop")
.setMessage("background has to be pushed every time a custom widget changes, causing traffic and battery drain. Consider that when using custom widgets.")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent pickIntent = new Intent(Intent.ACTION_PICK);
pickIntent.setType("image/*");
startActivityForResult(pickIntent, REQUEST_CODE_IMAGE_PICK);
}
})
.setNegativeButton("nah", null)
.show();
}
});
findViewById(R.id.qhybrid_unset_background).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(QHybridSupport.QHYBRID_COMMAND_SET_BACKGROUND_IMAGE);
intent.putIntegerArrayListExtra("EXTRA_PIXELS", null);
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(intent);
}
});
for (int i = 0; i < widgetButtonsMapping.size(); i++) {
final int widgetButtonId = widgetButtonsMapping.keyAt(i);
findViewById(widgetButtonId).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Widget.WidgetType[] types = Widget.WidgetType.values();
final ArrayList<String> names = new ArrayList<>(types.length);
for (Widget.WidgetType type : types) {
names.add(getResources().getString(type.getStringResource()));
}
for(CustomWidget customWidget : customWidgets){
names.add(customWidget.getName());
}
final String[] nameStrings = names.toArray(new String[0]);
new MaterialAlertDialogBuilder(HRConfigActivity.this)
.setItems(
nameStrings,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
saveWidgetSetting(widgetButtonId, which, nameStrings);
}
}
)
.show();
}
});
}
// Disable some functions on watches with too new firmware (from official app 4.6.0 and higher)
List<GBDevice> devices = GBApplication.app().getDeviceManager().getSelectedDevices();
for (GBDevice device : devices) {
if (device.getType() == DeviceType.FOSSILQHYBRID) {
String fwVersion_str = device.getFirmwareVersion2();
Version fwVersion = new Version(fwVersion_str);
if (fwVersion.compareTo(new Version("2.20")) >= 0) {
findViewById(R.id.qhybrid_widget_add).setEnabled(false);
for (int i = 0; i < widgetButtonsMapping.size(); i++) {
final int widgetButtonId = widgetButtonsMapping.keyAt(i);
findViewById(widgetButtonId).setEnabled(false);
}
findViewById(R.id.qhybrid_set_background).setEnabled(false);
findViewById(R.id.qhybrid_unset_background).setEnabled(false);
GB.toast(getString(R.string.fossil_hr_warning_firmware_too_new), Toast.LENGTH_LONG, GB.INFO);
}
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data == null) return;
if(requestCode == REQUEST_CODE_WIDGET_EDIT) {
if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_CREATED) {
CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
this.customWidgets.add(widget);
refreshWidgetList();
saveCustomWidgetList();
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
} else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_UPDATED) {
CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
String initialName = data.getStringExtra("EXTRA_WIDGET_INITIAL_NAME");
String newName = widget.getName();
String widgetJSON = sharedPreferences.getString("FOSSIL_HR_WIDGETS", "{}");
widgetJSON = widgetJSON.replace("custom_" + initialName, "custom_" + newName);
sharedPreferences.edit().putString("FOSSIL_HR_WIDGETS", widgetJSON).apply();
this.customWidgets.set(updateIndex, widget);
loadWidgetConfigs();
refreshWidgetList();
saveCustomWidgetList();
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
} else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_DELETED) {
int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
this.customWidgets.remove(updateIndex);
refreshWidgetList();
saveCustomWidgetList();
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
}
}else if(requestCode == REQUEST_CODE_IMAGE_PICK){
if (resultCode == RESULT_OK)
{
Uri imageUri = data.getData();
Intent activityIntent = new Intent();
activityIntent.setClass(this, ImageEditActivity.class);
activityIntent.setData(imageUri);
startActivityForResult(activityIntent, REQUEST_CODE_IMAGE_EDIT);
}
}else if(requestCode == REQUEST_CODE_IMAGE_EDIT){
if(resultCode == ImageEditActivity.RESULT_CODE_EDIT_SUCCESS){
data.setAction(QHybridSupport.QHYBRID_COMMAND_SET_BACKGROUND_IMAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(data);
}
}
}
private void saveCustomWidgetList() {
try {
JSONArray widgetArray = new JSONArray();
for(CustomWidget widget : customWidgets){
JSONArray elementArray = new JSONArray();
for(CustomWidgetElement element : widget.getElements()){
JSONObject elementObject = new JSONObject();
elementObject
.put("type", element.getWidgetElementType().getJsonIdentifier())
.put("id", element.getId())
.put("value", element.getValue())
.put("x", element.getX())
.put("y", element.getY());
elementArray.put(elementObject);
}
JSONObject widgetObject = new JSONObject();
widgetObject
.put("name", widget.getName())
.put("elements", elementArray);
widgetArray.put(widgetObject);
}
sharedPreferences.edit().putString("QHYBRID_CUSTOM_WIDGETS", widgetArray.toString()).apply();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void loadCustomWidgetList() {
String customWidgetJson = sharedPreferences.getString("QHYBRID_CUSTOM_WIDGETS", "[]");
try {
JSONArray customWidgets = new JSONArray(customWidgetJson);
this.customWidgets.clear();
for (int i = 0; i < customWidgets.length(); i++) {
JSONObject customWidgetObject = customWidgets.getJSONObject(i);
CustomWidget widget = new CustomWidget(
customWidgetObject.getString("name"), 0, 0, "default" // FIXME: handle force white background
);
JSONArray elements = customWidgetObject.getJSONArray("elements");
for (int i2 = 0; i2 < elements.length(); i2++) {
JSONObject element = elements.getJSONObject(i2);
if (element.getString("type").equals("text")) {
widget.addElement(new CustomTextWidgetElement(
element.getString("id"),
element.getString("value"),
element.getInt("x"),
element.getInt("y")
));
} else if (element.getString("type").equals("background")) {
widget.addElement(new CustomBackgroundWidgetElement(
element.getString("id"),
element.getString("value")
));
}
}
this.customWidgets.add(widget);
}
refreshWidgetList();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void refreshWidgetList() {
widgetListAdapter.notifyDataSetChanged();
}
private void saveWidgetSetting(int buttonId, int option, String[] names) {
String jsonKey = widgetButtonsMapping.get(buttonId);
Widget.WidgetType[] types = Widget.WidgetType.values();
String identifier = null;
if(option < types.length){
Widget.WidgetType type = types[option];
identifier = type.getIdentifier();
}else{
identifier = "custom_" + names[option];
}
try {
JSONObject keyConfig = new JSONObject(sharedPreferences.getString("FOSSIL_HR_WIDGETS", "{}"));
if (identifier != null) {
keyConfig.put(jsonKey, identifier);
} else {
keyConfig.remove(jsonKey);
}
sharedPreferences.edit().putString("FOSSIL_HR_WIDGETS", keyConfig.toString()).apply();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
loadWidgetConfigs();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void loadWidgetConfigs() {
try {
for (int i = 0; i < widgetButtonsMapping.size(); i++) {
((TextView) findViewById(widgetButtonsMapping.keyAt(i))).setText(widgetButtonsMapping.valueAt(i) + " widget");
}
JSONObject keyConfig = new JSONObject(sharedPreferences.getString("FOSSIL_HR_WIDGETS", "{}"));
Iterator<String> keyIterator = keyConfig.keys();
loop:
while (keyIterator.hasNext()) {
String position = keyIterator.next();
for (int widgetButtonIndex = 0; widgetButtonIndex < widgetButtonsMapping.size(); widgetButtonIndex++) {
if (position.equals(widgetButtonsMapping.valueAt(widgetButtonIndex))) {
int buttonId = widgetButtonsMapping.keyAt(widgetButtonIndex);
String function = keyConfig.getString(position);
Widget.WidgetType[] types = Widget.WidgetType.values();
if(function.startsWith("custom_")){
((TextView) findViewById(buttonId)).setText(
position + " widget: " + function.substring(7)
);
continue loop;
}
for (int widgetIdIndex = 0; widgetIdIndex < types.length; widgetIdIndex++) {
String widgetIdMappingValue = types[widgetIdIndex].getIdentifier();
if (widgetIdMappingValue != null && widgetIdMappingValue.equals(function)) {
((TextView) findViewById(buttonId)).setText(
position + " widget: "
+ getResources().getText(
types[widgetIdIndex].getStringResource()
)
);
break;
}
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
private void initMappings() {
widgetButtonsMapping.put(R.id.qhybrid_button_widget_top, "top");
widgetButtonsMapping.put(R.id.qhybrid_button_widget_right, "right");
widgetButtonsMapping.put(R.id.qhybrid_button_widget_bottom, "bottom");
widgetButtonsMapping.put(R.id.qhybrid_button_widget_left, "left");
}
class WidgetListAdapter extends ArrayAdapter<CustomWidget> {
public WidgetListAdapter(@NonNull List<CustomWidget> objects) {
super(HRConfigActivity.this, 0, objects);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
if (convertView == null) convertView = new TextView(getContext());
TextView view = (TextView) convertView;
view.setText(getItem(position).getName());
// view.setTextColor(Color.WHITE);
view.setTextSize(25);
return view;
}
}
}