mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-25 11:26:47 +01:00
created UI to design custom widgets
This commit is contained in:
parent
4c86d227f1
commit
132d97ee95
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="nodomain.freeyourgadget.gadgetbridge">
|
package="nodomain.freeyourgadget.gadgetbridge">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Comment in for testing Pebble Emulator
|
Comment in for testing Pebble Emulator
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
@ -22,7 +21,6 @@
|
|||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" /> <!-- Used for reverse find device -->
|
<uses-permission android:name="android.permission.VIBRATE" /> <!-- Used for reverse find device -->
|
||||||
|
|
||||||
<uses-permission android:name="cyanogenmod.permission.ACCESS_WEATHER_MANAGER" />
|
<uses-permission android:name="cyanogenmod.permission.ACCESS_WEATHER_MANAGER" />
|
||||||
<uses-permission android:name="cyanogenmod.permission.READ_WEATHER" />
|
<uses-permission android:name="cyanogenmod.permission.READ_WEATHER" />
|
||||||
<uses-permission android:name="lineageos.permission.ACCESS_WEATHER_MANAGER" />
|
<uses-permission android:name="lineageos.permission.ACCESS_WEATHER_MANAGER" />
|
||||||
@ -44,16 +42,19 @@
|
|||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:fullBackupContent="false"
|
android:fullBackupContent="false"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:theme="@style/GadgetbridgeTheme">
|
android:theme="@style/GadgetbridgeTheme">
|
||||||
|
<activity android:name=".devices.qhybrid.WidgetSettingsActivity"></activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.ControlCenterv2"
|
android:name=".activities.ControlCenterv2"
|
||||||
android:label="@string/title_activity_controlcenter"
|
android:label="@string/title_activity_controlcenter"
|
||||||
android:theme="@style/SplashTheme">
|
android:theme="@style/SplashTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
@ -78,9 +79,9 @@
|
|||||||
android:label="@string/activity_summaries"
|
android:label="@string/activity_summaries"
|
||||||
android:parentActivityName=".activities.ControlCenterv2" />
|
android:parentActivityName=".activities.ControlCenterv2" />
|
||||||
<activity
|
<activity
|
||||||
android:launchMode="singleTop"
|
|
||||||
android:name=".activities.appmanager.AppManagerActivity"
|
android:name=".activities.appmanager.AppManagerActivity"
|
||||||
android:label="@string/title_activity_appmanager"
|
android:label="@string/title_activity_appmanager"
|
||||||
|
android:launchMode="singleTop"
|
||||||
android:parentActivityName=".activities.ControlCenterv2" />
|
android:parentActivityName=".activities.ControlCenterv2" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.AppBlacklistActivity"
|
android:name=".activities.AppBlacklistActivity"
|
||||||
@ -290,7 +291,7 @@
|
|||||||
|
|
||||||
<data android:mimeType="application/octet-stream" />
|
<data android:mimeType="application/octet-stream" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<!-- to receive firmwares from the download content provider if recognized as zip-->
|
<!-- to receive firmwares from the download content provider if recognized as zip -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
@ -306,7 +307,6 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<data android:mimeType="*/*" />
|
<data android:mimeType="*/*" />
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
@ -331,18 +331,19 @@
|
|||||||
|
|
||||||
<activity android:name=".externalevents.WeatherNotificationConfig">
|
<activity android:name=".externalevents.WeatherNotificationConfig">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="ru.gelin.android.weather.notification.ACTION_WEATHER_SKIN_PREFERENCES"/>
|
<action android:name="ru.gelin.android.weather.notification.ACTION_WEATHER_SKIN_PREFERENCES" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver android:name=".externalevents.AutoStartReceiver"
|
<receiver
|
||||||
|
android:name=".externalevents.AutoStartReceiver"
|
||||||
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
|
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".externalevents.BluetoothStateChangeReceiver"
|
android:name=".externalevents.BluetoothStateChangeReceiver"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
@ -365,12 +366,9 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
|
android:name=".database.PeriodicExporter"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:name="nodomain.freeyourgadget.gadgetbridge.database.PeriodicExporter"
|
android:exported="false"></receiver>
|
||||||
android:exported="false">
|
|
||||||
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
forcing the DebugActivity to portrait mode avoids crashes with the progress
|
forcing the DebugActivity to portrait mode avoids crashes with the progress
|
||||||
dialog when changing orientation
|
dialog when changing orientation
|
||||||
@ -429,8 +427,8 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".activities.NotificationFilterActivity"
|
android:name=".activities.NotificationFilterActivity"
|
||||||
android:label="@string/title_activity_notification_filter"
|
android:label="@string/title_activity_notification_filter"
|
||||||
android:windowSoftInputMode="stateHidden|adjustPan"
|
android:parentActivityName=".activities.AppBlacklistActivity"
|
||||||
android:parentActivityName=".activities.AppBlacklistActivity" />
|
android:windowSoftInputMode="stateHidden|adjustPan" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.FindPhoneActivity"
|
android:name=".activities.FindPhoneActivity"
|
||||||
android:label="Find Phone" />
|
android:label="Find Phone" />
|
||||||
@ -439,7 +437,6 @@
|
|||||||
android:name=".contentprovider.PebbleContentProvider"
|
android:name=".contentprovider.PebbleContentProvider"
|
||||||
android:authorities="com.getpebble.android.provider"
|
android:authorities="com.getpebble.android.provider"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.screenshot_provider"
|
android:authorities="${applicationId}.screenshot_provider"
|
||||||
@ -450,7 +447,8 @@
|
|||||||
android:resource="@xml/shared_paths" />
|
android:resource="@xml/shared_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<receiver android:name=".SleepAlarmWidget"
|
<receiver
|
||||||
|
android:name=".SleepAlarmWidget"
|
||||||
android:label="@string/appwidget_sleep_alarm_widget_label">
|
android:label="@string/appwidget_sleep_alarm_widget_label">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
@ -461,7 +459,6 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/sleep_alarm_widget_info" />
|
android:resource="@xml/sleep_alarm_widget_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".Widget"
|
android:name=".Widget"
|
||||||
android:label="@string/widget_listing_label">
|
android:label="@string/widget_listing_label">
|
||||||
@ -475,27 +472,28 @@
|
|||||||
android:resource="@xml/widget_info" />
|
android:resource="@xml/widget_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.WidgetAlarmsActivity"
|
android:name=".activities.WidgetAlarmsActivity"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
android:theme="@style/Theme.AppCompat.Light.Dialog"
|
android:theme="@style/Theme.AppCompat.Light.Dialog" />
|
||||||
android:excludeFromRecents="true"/>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:launchMode="singleTask"
|
android:name=".activities.ExternalPebbleJSActivity"
|
||||||
android:allowTaskReparenting="true"
|
android:allowTaskReparenting="true"
|
||||||
android:clearTaskOnLaunch="true"
|
android:clearTaskOnLaunch="true"
|
||||||
android:name=".activities.ExternalPebbleJSActivity"
|
|
||||||
android:label="@string/app_configure"
|
android:label="@string/app_configure"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:parentActivityName=".activities.appmanager.AppManagerActivity">
|
android:parentActivityName=".activities.appmanager.AppManagerActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2" />
|
android:value="nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2" />
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
<data android:scheme="gadgetbridge" />
|
<data android:scheme="gadgetbridge" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
|
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.SparseArray;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.TextureView;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
@ -25,21 +21,33 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.w3c.dom.Text;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.sql.Array;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
|
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
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 static nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.WidgetSettingsActivity.RESULT_CODE_WIDGET_DELETED;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.QHYBRID_COMMAND_UPDATE_WIDGETS;
|
||||||
|
|
||||||
public class HRConfigActivity extends AbstractGBActivity implements View.OnClickListener, DialogInterface.OnClickListener, AdapterView.OnItemClickListener {
|
public class HRConfigActivity extends AbstractGBActivity implements View.OnClickListener, DialogInterface.OnClickListener, AdapterView.OnItemClickListener {
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private ActionListAdapter actionListAdapter;
|
private ActionListAdapter actionListAdapter;
|
||||||
|
private WidgetListAdapter widgetListAdapter;
|
||||||
private ArrayList<MenuAction> menuActions = new ArrayList<>();
|
private ArrayList<MenuAction> menuActions = new ArrayList<>();
|
||||||
|
private ArrayList<CustomWidget> customWidgets = new ArrayList<>();
|
||||||
|
|
||||||
|
SparseArray<String> widgetButtonsMapping = new SparseArray<>(4);
|
||||||
|
|
||||||
static public final String CONFIG_KEY_Q_ACTIONS = "Q_ACTIONS";
|
static public final String CONFIG_KEY_Q_ACTIONS = "Q_ACTIONS";
|
||||||
|
|
||||||
@ -52,14 +60,266 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
|
|||||||
|
|
||||||
sharedPreferences = GBApplication.getPrefs().getPreferences();
|
sharedPreferences = GBApplication.getPrefs().getPreferences();
|
||||||
|
|
||||||
|
initMappings();
|
||||||
|
loadWidgetConfigs();
|
||||||
|
|
||||||
|
|
||||||
ListView actionListView = findViewById(R.id.qhybrid_action_list);
|
ListView actionListView = findViewById(R.id.qhybrid_action_list);
|
||||||
actionListAdapter = new ActionListAdapter(menuActions);
|
actionListAdapter = new ActionListAdapter(menuActions);
|
||||||
actionListView.setAdapter(actionListAdapter);
|
actionListView.setAdapter(actionListAdapter);
|
||||||
actionListView.setOnItemClickListener(this);
|
actionListView.setOnItemClickListener(this);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
startActivityForResult(startIntent, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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 AlertDialog.Builder(HRConfigActivity.this)
|
||||||
|
.setItems(
|
||||||
|
nameStrings,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
saveWidgetSetting(widgetButtonId, which, nameStrings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
updateSettings();
|
updateSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if(data == null) return;
|
||||||
|
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);
|
||||||
|
|
||||||
|
this.customWidgets.set(updateIndex, widget);
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (v.getId() == R.id.qhybrid_action_add) {
|
if (v.getId() == R.id.qhybrid_action_add) {
|
||||||
@ -147,7 +407,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putActionItems(List<MenuAction> actions){
|
private void putActionItems(List<MenuAction> actions) {
|
||||||
JSONArray array = new JSONArray();
|
JSONArray array = new JSONArray();
|
||||||
for (MenuAction action : actions) array.put(action.getAction());
|
for (MenuAction action : actions) array.put(action.getAction());
|
||||||
|
|
||||||
@ -170,6 +430,25 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ActionListAdapter extends ArrayAdapter<MenuAction> {
|
class ActionListAdapter extends ArrayAdapter<MenuAction> {
|
||||||
public ActionListAdapter(@NonNull ArrayList<MenuAction> objects) {
|
public ActionListAdapter(@NonNull ArrayList<MenuAction> objects) {
|
||||||
super(HRConfigActivity.this, 0, objects);
|
super(HRConfigActivity.this, 0, objects);
|
||||||
@ -183,7 +462,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
|
|||||||
|
|
||||||
view.setText(getItem(position).getAction());
|
view.setText(getItem(position).getAction());
|
||||||
// view.setTextColor(Color.WHITE);
|
// view.setTextColor(Color.WHITE);
|
||||||
view.setTextSize(30);
|
view.setTextSize(25);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,208 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.Widget;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class WidgetSettingsActivity extends AbstractGBActivity {
|
||||||
|
private CustomWidget subject;
|
||||||
|
private WidgetElementAdapter widgetElementAdapter;
|
||||||
|
|
||||||
|
public static final int RESULT_CODE_WIDGET_CREATED = 0;
|
||||||
|
public static final int RESULT_CODE_WIDGET_UPDATED = 1;
|
||||||
|
public static final int RESULT_CODE_WIDGET_DELETED = 2;
|
||||||
|
public static final int RESULT_CODE_CANCELED = 3;
|
||||||
|
|
||||||
|
private int resultCode;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.qhybrid_activity_widget_settings);
|
||||||
|
|
||||||
|
setResult(RESULT_CODE_CANCELED);
|
||||||
|
|
||||||
|
if(getIntent().hasExtra("EXTRA_WIDGET")){
|
||||||
|
subject = (CustomWidget) getIntent().getExtras().get("EXTRA_WIDGET");
|
||||||
|
((EditText) findViewById(R.id.qhybrid_widget_name)).setText(subject.getName());
|
||||||
|
resultCode = RESULT_CODE_WIDGET_UPDATED;
|
||||||
|
}else{
|
||||||
|
subject = new CustomWidget("", 0, 63);
|
||||||
|
resultCode = RESULT_CODE_WIDGET_CREATED;
|
||||||
|
findViewById(R.id.qhybrid_widget_delete).setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
findViewById(R.id.qhybrid_widget_save).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
subject.setName(((EditText) findViewById(R.id.qhybrid_widget_name)).getText().toString());
|
||||||
|
|
||||||
|
Intent resultIntent = getIntent();
|
||||||
|
resultIntent.putExtra("EXTRA_WIDGET", WidgetSettingsActivity.this.subject);
|
||||||
|
setResult(resultCode, resultIntent);
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.qhybrid_widget_delete).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
setResult(RESULT_CODE_WIDGET_DELETED, getIntent());
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
widgetElementAdapter = new WidgetElementAdapter(subject.getElements());
|
||||||
|
ListView elementList = findViewById(R.id.qhybrid_widget_elements_list);
|
||||||
|
elementList.setAdapter(widgetElementAdapter);
|
||||||
|
elementList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
showElementDialog(widgetElementAdapter.getItem(position));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.qhybrid_widget_elements_add).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showElementDialog(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showElementDialog(@Nullable final CustomWidgetElement element){
|
||||||
|
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(WidgetSettingsActivity.this)
|
||||||
|
.setView(R.layout.qhybrid_element_popup_view);
|
||||||
|
|
||||||
|
if(element == null) {
|
||||||
|
dialogBuilder
|
||||||
|
.setTitle("create element")
|
||||||
|
.setNegativeButton("cancel", null)
|
||||||
|
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
if(((RadioButton)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_elements_type_text)).isChecked()){
|
||||||
|
subject.addElement(new CustomTextWidgetElement(
|
||||||
|
((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_id)).getText().toString(),
|
||||||
|
((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_value)).getText().toString(),
|
||||||
|
CustomWidgetElement.X_CENTER,
|
||||||
|
((RadioButton)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_elements_position_uppper)).isChecked() ? CustomTextWidgetElement.Y_UPPER_HALF : CustomTextWidgetElement.Y_LOWER_HALF
|
||||||
|
));
|
||||||
|
}else{
|
||||||
|
subject.addElement(new CustomBackgroundWidgetElement(
|
||||||
|
((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_id)).getText().toString(),
|
||||||
|
((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_value)).getText().toString()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
refreshElementsList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
dialogBuilder
|
||||||
|
.setTitle("edit element")
|
||||||
|
.setNegativeButton("delete", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
WidgetSettingsActivity.this.subject.getElements().remove(element);
|
||||||
|
|
||||||
|
refreshElementsList();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
element.setId(((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_id)).getText().toString());
|
||||||
|
element.setValue(((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_value)).getText().toString());
|
||||||
|
element.setY(((RadioButton)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_elements_position_uppper)).isChecked() ? CustomTextWidgetElement.Y_UPPER_HALF : CustomTextWidgetElement.Y_LOWER_HALF);
|
||||||
|
element.setWidgetElementType(CustomWidgetElement.WidgetElementType.fromRadioButtonRessource(((RadioGroup)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_type)).getCheckedRadioButtonId()));
|
||||||
|
|
||||||
|
refreshElementsList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog dialog = dialogBuilder.show();
|
||||||
|
|
||||||
|
|
||||||
|
if(element != null){
|
||||||
|
String elementId = element.getId();
|
||||||
|
String elementValue = element.getValue();
|
||||||
|
CustomWidgetElement.WidgetElementType type = element.getWidgetElementType();
|
||||||
|
|
||||||
|
((EditText)dialog.findViewById(R.id.qhybrid_widget_element_id)).setText(elementId);
|
||||||
|
((EditText)dialog.findViewById(R.id.qhybrid_widget_element_value)).setText(elementValue);
|
||||||
|
((RadioGroup)dialog.findViewById(R.id.qhybrid_widget_element_type)).check(type.getRadioButtonResource());
|
||||||
|
((RadioGroup)dialog.findViewById(R.id.qhybrid_widget_element_position)).check(element.getY() == CustomWidgetElement.Y_UPPER_HALF ? R.id.qhybrid_widget_elements_position_uppper : R.id.qhybrid_widget_elements_position_lower);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshElementsList(){
|
||||||
|
this.widgetElementAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
class WidgetElementAdapter extends ArrayAdapter<CustomWidgetElement>{
|
||||||
|
public WidgetElementAdapter(@NonNull List<CustomWidgetElement> objects) {
|
||||||
|
super(WidgetSettingsActivity.this, 0, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||||
|
RelativeLayout layout = new RelativeLayout(WidgetSettingsActivity.this);
|
||||||
|
layout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
|
||||||
|
TextView idView = new TextView(WidgetSettingsActivity.this);
|
||||||
|
|
||||||
|
idView.setText(getItem(position).getId());
|
||||||
|
// view.setTextColor(Color.WHITE);
|
||||||
|
idView.setTextSize(25);
|
||||||
|
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
params.addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE);
|
||||||
|
idView.setLayoutParams(params);
|
||||||
|
|
||||||
|
TextView contentView = new TextView(WidgetSettingsActivity.this);
|
||||||
|
contentView.setText(getItem(position).getValue());
|
||||||
|
contentView.setTextSize(25);
|
||||||
|
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
params.addRule(RelativeLayout.ALIGN_PARENT_END, RelativeLayout.TRUE);
|
||||||
|
contentView.setLayoutParams(params);
|
||||||
|
|
||||||
|
layout.addView(idView);
|
||||||
|
layout.addView(contentView);
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -87,6 +87,7 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
public static final String QHYBRID_COMMAND_NOTIFICATION = "qhybrid_command_notification";
|
public static final String QHYBRID_COMMAND_NOTIFICATION = "qhybrid_command_notification";
|
||||||
public static final String QHYBRID_COMMAND_UPDATE_SETTINGS = "nodomain.freeyourgadget.gadgetbridge.Q_UPDATE_SETTINGS";
|
public static final String QHYBRID_COMMAND_UPDATE_SETTINGS = "nodomain.freeyourgadget.gadgetbridge.Q_UPDATE_SETTINGS";
|
||||||
public static final String QHYBRID_COMMAND_OVERWRITE_BUTTONS = "nodomain.freeyourgadget.gadgetbridge.Q_OVERWRITE_BUTTONS";
|
public static final String QHYBRID_COMMAND_OVERWRITE_BUTTONS = "nodomain.freeyourgadget.gadgetbridge.Q_OVERWRITE_BUTTONS";
|
||||||
|
public static final String QHYBRID_COMMAND_UPDATE_WIDGETS = "nodomain.freeyourgadget.gadgetbridge.Q_UPDATE_WIDGETS";
|
||||||
public static final String QHYBRID_COMMAND_SET_MENU_MESSAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_MENU_MESSAGE";
|
public static final String QHYBRID_COMMAND_SET_MENU_MESSAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_MENU_MESSAGE";
|
||||||
public static final String QHYBRID_COMMAND_SEND_MENU_ITEMS = "nodomain.freeyourgadget.gadgetbridge.Q_SEND_MENU_ITEMS";
|
public static final String QHYBRID_COMMAND_SEND_MENU_ITEMS = "nodomain.freeyourgadget.gadgetbridge.Q_SEND_MENU_ITEMS";
|
||||||
public static final String QHYBRID_COMMAND_SET_WIDGET_CONTENT = "nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT";
|
public static final String QHYBRID_COMMAND_SET_WIDGET_CONTENT = "nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT";
|
||||||
@ -143,6 +144,7 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
commandFilter.addAction(QHYBRID_COMMAND_UPDATE_SETTINGS);
|
commandFilter.addAction(QHYBRID_COMMAND_UPDATE_SETTINGS);
|
||||||
commandFilter.addAction(QHYBRID_COMMAND_OVERWRITE_BUTTONS);
|
commandFilter.addAction(QHYBRID_COMMAND_OVERWRITE_BUTTONS);
|
||||||
commandFilter.addAction(QHYBRID_COMMAND_NOTIFICATION_CONFIG_CHANGED);
|
commandFilter.addAction(QHYBRID_COMMAND_NOTIFICATION_CONFIG_CHANGED);
|
||||||
|
commandFilter.addAction(QHYBRID_COMMAND_UPDATE_WIDGETS);
|
||||||
commandFilter.addAction(QHYBRID_COMMAND_SEND_MENU_ITEMS);
|
commandFilter.addAction(QHYBRID_COMMAND_SEND_MENU_ITEMS);
|
||||||
commandReceiver = new BroadcastReceiver() {
|
commandReceiver = new BroadcastReceiver() {
|
||||||
|
|
||||||
@ -217,6 +219,10 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
watchAdapter.syncNotificationSettings();
|
watchAdapter.syncNotificationSettings();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case QHYBRID_COMMAND_UPDATE_WIDGETS: {
|
||||||
|
watchAdapter.updateWidgets();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -278,6 +284,7 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
widgetValues.put(key.substring(16), String.valueOf(intent.getExtras().get(key)));
|
widgetValues.put(key.substring(16), String.valueOf(intent.getExtras().get(key)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
boolean render = intent.getBooleanExtra("EXTRA_RENDER", true);
|
||||||
if(widgetValues.size() > 0){
|
if(widgetValues.size() > 0){
|
||||||
Iterator<String> valuesIterator = widgetValues.keySet().iterator();
|
Iterator<String> valuesIterator = widgetValues.keySet().iterator();
|
||||||
valuesIterator.next();
|
valuesIterator.next();
|
||||||
@ -289,11 +296,10 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
|
|
||||||
valuesIterator = widgetValues.keySet().iterator();
|
valuesIterator = widgetValues.keySet().iterator();
|
||||||
String id = valuesIterator.next();
|
String id = valuesIterator.next();
|
||||||
watchAdapter.setWidgetContent(id, widgetValues.get(id), true);
|
watchAdapter.setWidgetContent(id, widgetValues.get(id), render);
|
||||||
}else {
|
}else {
|
||||||
String id = String.valueOf(intent.getExtras().get("EXTRA_WIDGET_ID"));
|
String id = String.valueOf(intent.getExtras().get("EXTRA_WIDGET_ID"));
|
||||||
String content = String.valueOf(intent.getExtras().get("EXTRA_CONTENT"));
|
String content = String.valueOf(intent.getExtras().get("EXTRA_CONTENT"));
|
||||||
boolean render = intent.getBooleanExtra("EXTRA_RENDER", true);
|
|
||||||
watchAdapter.setWidgetContent(id, content, render);
|
watchAdapter.setWidgetContent(id, content, render);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -352,7 +358,7 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
.read(getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")))
|
.read(getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")))
|
||||||
.read(getCharacteristic(UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb")))
|
.read(getCharacteristic(UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb")))
|
||||||
.read(getCharacteristic(UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb")))
|
.read(getCharacteristic(UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb")))
|
||||||
.notify(getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")), true)
|
// .notify(getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")), true)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -474,6 +480,12 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
return notificationProgress;
|
return notificationProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
|
||||||
|
super.onConnectionStateChange(gatt, status, newState);
|
||||||
|
watchAdapter.onConnectionStateChange(gatt, status, newState);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO toggle "Notifications when screen on" options on this check
|
//TODO toggle "Notifications when screen on" options on this check
|
||||||
private void showNotificationCountOnActivityHand(double progress) {
|
private void showNotificationCountOnActivityHand(double progress) {
|
||||||
if (useActivityHand) {
|
if (useActivityHand) {
|
||||||
@ -612,6 +624,12 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
|
watchAdapter.onCharacteristicWrite(gatt, characteristic, status);
|
||||||
|
return super.onCharacteristicWrite(gatt, characteristic, status);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
switch (characteristic.getUuid().toString()) {
|
switch (characteristic.getUuid().toString()) {
|
||||||
|
@ -108,4 +108,13 @@ public abstract class WatchAdapter {
|
|||||||
|
|
||||||
public void setWidgetContent(String widgetID, String content, boolean render) {
|
public void setWidgetContent(String widgetID, String content, boolean render) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateWidgets() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfigHelper;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BTLEOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
|
||||||
@ -130,6 +131,25 @@ public class FossilWatchAdapter extends WatchAdapter {
|
|||||||
overwriteButtons(buttonConfig);
|
overwriteButtons(buttonConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
|
if(status != BluetoothGatt.GATT_SUCCESS){
|
||||||
|
log("characteristic write failed: " + status);
|
||||||
|
fossilRequest = null;
|
||||||
|
|
||||||
|
queueNextRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
|
||||||
|
if(newState != BluetoothGatt.STATE_CONNECTED){
|
||||||
|
log("status " + newState + " clearing queue...");
|
||||||
|
requestQueue.clear();
|
||||||
|
fossilRequest = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private SharedPreferences getDeviceSpecificPreferences(){
|
private SharedPreferences getDeviceSpecificPreferences(){
|
||||||
return GBApplication.getDeviceSpecificSharedPrefs(
|
return GBApplication.getDeviceSpecificSharedPrefs(
|
||||||
getDeviceSupport().getDevice().getAddress()
|
getDeviceSupport().getDevice().getAddress()
|
||||||
|
@ -9,47 +9,39 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.CpuUsageInfo;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.BufferOverflowException;
|
import java.nio.BufferOverflowException;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.Random;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import cyanogenmod.app.CustomTile;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.Widget;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
|
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
|
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileCloseRequest;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfigurationPutRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfigurationPutRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationGetRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationGetRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationPutRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationPutRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFile;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
|
||||||
@ -58,14 +50,12 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicInfoSetRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicInfoSetRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImage;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImagePutRequest;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.PlayNotificationHRRequest;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomBackgroundWidgetElement;
|
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.CustomTextWidgetElement;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget;
|
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.CustomWidgetElement;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.utils.StringUtils;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.Widget;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.WidgetsPutRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest.MUSIC_PHONE_REQUEST;
|
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest.MUSIC_PHONE_REQUEST;
|
||||||
@ -75,7 +65,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
private byte[] phoneRandomNumber;
|
private byte[] phoneRandomNumber;
|
||||||
private byte[] watchRandomNumber;
|
private byte[] watchRandomNumber;
|
||||||
|
|
||||||
CustomWidget[] widgets = new CustomWidget[0];
|
ArrayList<Widget> widgets = new ArrayList<>();
|
||||||
|
|
||||||
NotificationHRConfiguration[] notificationConfigurations;
|
NotificationHRConfiguration[] notificationConfigurations;
|
||||||
|
|
||||||
@ -176,37 +166,87 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
.decodeFile("/sdcard/DCIM/Camera/IMG_20191129_200726.jpg");
|
.decodeFile("/sdcard/DCIM/Camera/IMG_20191129_200726.jpg");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.backGroundImage = AssetImageFactory.createAssetImage(backgroundBitmap, false, 0, 0, 0);
|
this.backGroundImage = AssetImageFactory.createAssetImage(backgroundBitmap, false, 0,:wq
|
||||||
|
0, 0);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
GB.log("Backgroundimage error", GB.ERROR, e);
|
GB.log("Backgroundimage error", GB.ERROR, e);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadWidgets() {
|
private void loadWidgets() {
|
||||||
CustomWidget ethWidget = new CustomWidget(90, 63);
|
this.widgets.clear();
|
||||||
// ethWidget.addElement(new CustomWidgetElement(CustomWidgetElement.WidgetElementType.TYPE_TEXT, "date", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
|
String widgetJson = GBApplication.getPrefs().getPreferences().getString("FOSSIL_HR_WIDGETS", "{}");
|
||||||
ethWidget.addElement(new CustomTextWidgetElement("ETH", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
|
String customWidgetJson = GBApplication.getPrefs().getString("QHYBRID_CUSTOM_WIDGETS", "[]");
|
||||||
ethWidget.addElement(new CustomTextWidgetElement("eth", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject widgetConfig = new JSONObject(widgetJson);
|
||||||
|
JSONArray customWidgets = new JSONArray(customWidgetJson);
|
||||||
|
|
||||||
CustomWidget btcWidget = new CustomWidget(270, 63);
|
Iterator<String> keyIterator = widgetConfig.keys();
|
||||||
btcWidget.addElement(new CustomTextWidgetElement("BTC", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
|
HashMap<String, Integer> positionMap = new HashMap<>(4);
|
||||||
btcWidget.addElement(new CustomTextWidgetElement("btc", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
|
positionMap.put("top", 0);
|
||||||
|
positionMap.put("right", 90);
|
||||||
|
positionMap.put("bottom", 180);
|
||||||
|
positionMap.put("left", 270);
|
||||||
|
|
||||||
CustomWidget dateWidget = new CustomWidget(0, 63);
|
while(keyIterator.hasNext()){
|
||||||
dateWidget.addElement(new CustomTextWidgetElement("Time", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
|
String position = keyIterator.next();
|
||||||
dateWidget.addElement(new CustomTextWidgetElement("date", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
|
String identifier = widgetConfig.getString(position);
|
||||||
|
Widget.WidgetType type = Widget.WidgetType.fromJsonIdentifier(identifier);
|
||||||
|
|
||||||
CustomWidget helloWidget = new CustomWidget(180, 63);
|
Widget widget = null;
|
||||||
// helloWidget.addElement(new CustomTextWidgetElement("Hello", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
|
if(type != null) {
|
||||||
// helloWidget.addElement(new CustomTextWidgetElement("Reddit", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
|
widget = new Widget(type, positionMap.get(position), 63);
|
||||||
helloWidget.addElement(new CustomBackgroundWidgetElement("reddit", "/sdcard/reddit.png"));
|
}else{
|
||||||
this.widgets = new CustomWidget[]{
|
identifier = identifier.substring(7);
|
||||||
ethWidget,
|
for(int i = 0; i < customWidgets.length(); i++){
|
||||||
btcWidget,
|
JSONObject customWidget = customWidgets.getJSONObject(i);
|
||||||
dateWidget,
|
if(customWidget.getString("name").equals(identifier)){
|
||||||
helloWidget
|
CustomWidget newWidget = new CustomWidget(
|
||||||
};
|
customWidget.getString("name"),
|
||||||
|
positionMap.get(position),
|
||||||
|
63
|
||||||
|
);
|
||||||
|
JSONArray elements = customWidget.getJSONArray("elements");
|
||||||
|
|
||||||
|
for (int i2 = 0; i2 < elements.length(); i2++) {
|
||||||
|
JSONObject element = elements.getJSONObject(i2);
|
||||||
|
if (element.getString("type").equals("text")) {
|
||||||
|
newWidget.addElement(new CustomTextWidgetElement(
|
||||||
|
element.getString("id"),
|
||||||
|
element.getString("value"),
|
||||||
|
element.getInt("x"),
|
||||||
|
element.getInt("y")
|
||||||
|
));
|
||||||
|
} else if (element.getString("type").equals("background")) {
|
||||||
|
newWidget.addElement(new CustomBackgroundWidgetElement(
|
||||||
|
element.getString("id"),
|
||||||
|
element.getString("value")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widget = newWidget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(widget == null) continue;
|
||||||
|
this.widgets.add(widget);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadWidgets(){
|
||||||
|
negotiateSymmetricKey();
|
||||||
|
ArrayList<Widget> systemWidgets = new ArrayList<>(widgets.size());
|
||||||
|
for(Widget widget : this.widgets){
|
||||||
|
if(!(widget instanceof CustomWidget)) systemWidgets.add(widget);
|
||||||
|
}
|
||||||
|
queueWrite(new WidgetsPutRequest(systemWidgets.toArray(new Widget[0]), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderWidgets() {
|
private void renderWidgets() {
|
||||||
@ -218,8 +258,10 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < this.widgets.length; i++) {
|
for (int i = 0; i < this.widgets.size(); i++) {
|
||||||
CustomWidget widget = widgets[i];
|
Widget w = widgets.get(i);
|
||||||
|
if(!(w instanceof CustomWidget)) continue;
|
||||||
|
CustomWidget widget = (CustomWidget) w;
|
||||||
|
|
||||||
Bitmap widgetBitmap = Bitmap.createBitmap(76, 76, Bitmap.Config.ARGB_8888);
|
Bitmap widgetBitmap = Bitmap.createBitmap(76, 76, Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
@ -312,8 +354,9 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) {
|
public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) {
|
||||||
boolean update = false;
|
boolean update = false;
|
||||||
for (CustomWidget widget : this.widgets) {
|
for (Widget widget : this.widgets) {
|
||||||
if(widget.updateElementValue(widgetID, content)) update = true;
|
if(!(widget instanceof CustomWidget)) continue;
|
||||||
|
if(((CustomWidget) widget).updateElementValue(widgetID, content)) update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderOnWatch && update) renderWidgets();
|
if (renderOnWatch && update) renderWidgets();
|
||||||
@ -374,6 +417,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateWidgets() {
|
||||||
|
loadWidgets();
|
||||||
|
renderWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
private void setBackgroundImages(AssetImage background, AssetImage[] complications) {
|
private void setBackgroundImages(AssetImage background, AssetImage[] complications) {
|
||||||
queueWrite(new ImagesSetRequest(new AssetImage[]{background}, this));
|
queueWrite(new ImagesSetRequest(new AssetImage[]{background}, this));
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSuppo
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedLookupAndGetRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedLookupAndGetRequest;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest {
|
public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest {
|
||||||
public ConfigurationGetRequest(FossilHRWatchAdapter adapter) {
|
public ConfigurationGetRequest(FossilHRWatchAdapter adapter) {
|
||||||
@ -49,6 +50,8 @@ public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GB.toast("got config", 0, GB.INFO);
|
||||||
|
|
||||||
device.sendDeviceUpdateIntent(getAdapter().getContext());
|
device.sendDeviceUpdateIntent(getAdapter().getContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
|
|||||||
|
|
||||||
public class JsonPutRequest extends FilePutRawRequest {
|
public class JsonPutRequest extends FilePutRawRequest {
|
||||||
public JsonPutRequest(JSONObject object, FossilHRWatchAdapter adapter) {
|
public JsonPutRequest(JSONObject object, FossilHRWatchAdapter adapter) {
|
||||||
super((short)(0x0500 | adapter.getJsonIndex()), object.toString().getBytes(), adapter);
|
super((short)(0x0500 | (adapter.getJsonIndex() & 0xFF)), object.toString().getBytes(), adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,16 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CustomWidget {
|
public class CustomWidget extends Widget {
|
||||||
private ArrayList<CustomWidgetElement> elements = new ArrayList<>();
|
private ArrayList<CustomWidgetElement> elements = new ArrayList<>();
|
||||||
private int angle, distance;
|
private int angle, distance;
|
||||||
|
private String name;
|
||||||
|
|
||||||
public CustomWidget(int angle, int distance) {
|
public CustomWidget(String name, int angle, int distance) {
|
||||||
|
super(null, angle, distance);
|
||||||
this.angle = angle;
|
this.angle = angle;
|
||||||
this.distance = distance;
|
this.distance = distance;
|
||||||
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAngle() {
|
public int getAngle() {
|
||||||
@ -22,7 +25,23 @@ public class CustomWidget {
|
|||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<CustomWidgetElement> getElements(){
|
public void setElements(ArrayList<CustomWidgetElement> elements) {
|
||||||
|
this.elements = elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngle(int angle) {
|
||||||
|
this.angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistance(int distance) {
|
||||||
|
this.distance = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<CustomWidgetElement> getElements(){
|
||||||
return this.elements;
|
return this.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,4 +68,8 @@ public class CustomWidget {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,37 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget;
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget;
|
||||||
|
|
||||||
public class CustomWidgetElement {
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
|
||||||
|
public class CustomWidgetElement implements Serializable {
|
||||||
public enum WidgetElementType {
|
public enum WidgetElementType {
|
||||||
TYPE_TEXT,
|
TYPE_TEXT(R.id.qhybrid_widget_elements_type_text, "text"),
|
||||||
TYPE_IMAGE,
|
TYPE_IMAGE(0, "image"),
|
||||||
TYPE_BACKGROUND
|
TYPE_BACKGROUND(R.id.qhybrid_widget_elements_type_background, "background");
|
||||||
|
|
||||||
|
private String jsonIdentifier;
|
||||||
|
private int radioButtonResource;
|
||||||
|
|
||||||
|
WidgetElementType(int radioButtonResource, String jsonIdentifier){
|
||||||
|
this.radioButtonResource = radioButtonResource;
|
||||||
|
this.jsonIdentifier = jsonIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRadioButtonResource() {
|
||||||
|
return radioButtonResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJsonIdentifier() {
|
||||||
|
return jsonIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public WidgetElementType fromRadioButtonRessource(int radioButtonResource){
|
||||||
|
for(WidgetElementType type : values()){
|
||||||
|
if(type.getRadioButtonResource() == radioButtonResource) return type;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static int X_CENTER = 38;
|
public final static int X_CENTER = 38;
|
||||||
@ -15,6 +42,22 @@ public class CustomWidgetElement {
|
|||||||
private String id, value;
|
private String id, value;
|
||||||
private int x, y;
|
private int x, y;
|
||||||
|
|
||||||
|
public void setWidgetElementType(WidgetElementType widgetElementType) {
|
||||||
|
this.widgetElementType = widgetElementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
protected CustomWidgetElement(WidgetElementType widgetElementType, String id, String value, int x, int y) {
|
protected CustomWidgetElement(WidgetElementType widgetElementType, String id, String value, int x, int y) {
|
||||||
this.widgetElementType = widgetElementType;
|
this.widgetElementType = widgetElementType;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -5,12 +5,18 @@ import androidx.annotation.NonNull;
|
|||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public abstract class Widget {
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
|
||||||
|
public class Widget implements Serializable {
|
||||||
private WidgetType widgetType;
|
private WidgetType widgetType;
|
||||||
int angle, distance;
|
int angle, distance;
|
||||||
|
|
||||||
public Widget(WidgetType type, int angle, int distance){
|
public Widget(WidgetType type, int angle, int distance) {
|
||||||
this.widgetType = type;
|
this.widgetType = type;
|
||||||
|
this.angle = angle;
|
||||||
|
this.distance = distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -19,7 +25,7 @@ public abstract class Widget {
|
|||||||
return toJson().toString();
|
return toJson().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject toJson(){
|
public JSONObject toJson() {
|
||||||
JSONObject object = new JSONObject();
|
JSONObject object = new JSONObject();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -43,17 +49,35 @@ public abstract class Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum WidgetType{
|
public enum WidgetType {
|
||||||
TIMEZONE("timeZone2SSE");
|
HEART_RATE("hrSSE", R.string.hr_widget_heart_rate),
|
||||||
|
STEPS("stepsSSE", R.string.hr_widget_steps),
|
||||||
|
DATE("dateSSE", R.string.hr_widget_date),
|
||||||
|
ACTIVE_MINUTES("activeMinutesSSE", R.string.hr_widget_active_minutes),
|
||||||
|
CALORIES("caloriesSSE", R.string.hr_widget_calories),
|
||||||
|
BATTERY("batterySSE", R.string.hr_widget_battery),
|
||||||
|
NOTHING(null, R.string.hr_widget_nothing);
|
||||||
|
|
||||||
private String identifier;
|
private String identifier;
|
||||||
|
private int stringResource;
|
||||||
|
|
||||||
|
WidgetType(String identifier, int stringResource) {
|
||||||
WidgetType(String identifier){
|
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
|
this.stringResource = stringResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIdentifier(){
|
public static WidgetType fromJsonIdentifier(String jsonIdentifier){
|
||||||
|
for(WidgetType type : values()){
|
||||||
|
if(type.getIdentifier() != null && type.getIdentifier().equals(jsonIdentifier)) return type;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStringResource() {
|
||||||
|
return stringResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier() {
|
||||||
return this.identifier;
|
return this.identifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,11 @@ public class WidgetsPutRequest extends JsonPutRequest {
|
|||||||
|
|
||||||
private static JSONObject prepareFile(Widget[] widgets){
|
private static JSONObject prepareFile(Widget[] widgets){
|
||||||
try {
|
try {
|
||||||
JSONArray widgetArray = new JSONArray(widgets);
|
JSONArray widgetArray = new JSONArray();
|
||||||
|
|
||||||
|
for(Widget widget : widgets){
|
||||||
|
widgetArray.put(widget.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject object = new JSONObject()
|
JSONObject object = new JSONObject()
|
||||||
.put(
|
.put(
|
||||||
|
@ -37,4 +37,51 @@
|
|||||||
android:id="@+id/qhybrid_button_bottom_single_press"
|
android:id="@+id/qhybrid_button_bottom_single_press"
|
||||||
android:textSize="20dp"/>
|
android:textSize="20dp"/>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="20dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="top widget"
|
||||||
|
android:id="@+id/qhybrid_button_widget_top"
|
||||||
|
android:textSize="20dp"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="right widget"
|
||||||
|
android:id="@+id/qhybrid_button_widget_right"
|
||||||
|
android:textSize="20dp"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="bottom widget"
|
||||||
|
android:id="@+id/qhybrid_button_widget_bottom"
|
||||||
|
android:textSize="20dp"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="left widget"
|
||||||
|
android:id="@+id/qhybrid_button_widget_left"
|
||||||
|
android:textSize="20dp"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="custom widgets" />
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_weight="0.4"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:id="@+id/qhybrid_widget_list"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="add widget"
|
||||||
|
android:id="@+id/qhybrid_widget_add"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
73
app/src/main/res/layout/qhybrid_activity_widget_settings.xml
Normal file
73
app/src/main/res/layout/qhybrid_activity_widget_settings.xml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".devices.qhybrid.WidgetSettingsActivity">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:weightSum="1">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="widget name" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/qhybrid_widget_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="elements" />
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/qhybrid_widget_elements_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="0.4" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/qhybrid_widget_elements_add"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="add element" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:weightSum="1">
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/qhybrid_widget_delete"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="delete"
|
||||||
|
android:layout_weight="0.5" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/qhybrid_widget_save"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="save"
|
||||||
|
android:layout_weight="0.5" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
79
app/src/main/res/layout/qhybrid_element_popup_view.xml
Normal file
79
app/src/main/res/layout/qhybrid_element_popup_view.xml
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="element id" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/qhybrid_widget_element_id"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="default value" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/qhybrid_widget_element_value"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="type" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/qhybrid_widget_element_type"
|
||||||
|
android:checkedButton="@id/qhybrid_widget_elements_type_text">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="text"
|
||||||
|
android:id="@+id/qhybrid_widget_elements_type_text"/>
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="background image"
|
||||||
|
android:id="@+id/qhybrid_widget_elements_type_background" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="position" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/qhybrid_widget_element_position"
|
||||||
|
android:checkedButton="@id/qhybrid_widget_elements_position_uppper">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="upper half"
|
||||||
|
android:id="@+id/qhybrid_widget_elements_position_uppper"/>
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="lower half"
|
||||||
|
android:id="@+id/qhybrid_widget_elements_position_lower" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -773,6 +773,13 @@
|
|||||||
<string name="qhybrid_offset_timezone">offset timezone by</string>
|
<string name="qhybrid_offset_timezone">offset timezone by</string>
|
||||||
<string name="qhybrid_changes_delay_prompt">change might take some seconds…</string>
|
<string name="qhybrid_changes_delay_prompt">change might take some seconds…</string>
|
||||||
<string name="qhybrid_offset_time_by">offset time by</string>
|
<string name="qhybrid_offset_time_by">offset time by</string>
|
||||||
|
<string name="hr_widget_heart_rate">Heart rate</string>
|
||||||
|
<string name="hr_widget_steps">Steps</string>
|
||||||
|
<string name="hr_widget_date">Date</string>
|
||||||
|
<string name="hr_widget_active_minutes">Active minutes</string>
|
||||||
|
<string name="hr_widget_calories">Calories</string>
|
||||||
|
<string name="hr_widget_battery">Battery</string>
|
||||||
|
<string name="hr_widget_nothing">Nothing</string>
|
||||||
<plurals name="widget_alarm_target_hours">
|
<plurals name="widget_alarm_target_hours">
|
||||||
<item quantity="one">%d hour</item>
|
<item quantity="one">%d hour</item>
|
||||||
<item quantity="two">%d hours</item>
|
<item quantity="two">%d hours</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user