mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-10-02 03:07:09 +02:00
ControlCenter: added folders to ControlCenter
This commit is contained in:
parent
3d6940154d
commit
62f77ef8d0
@ -43,7 +43,7 @@ public class GBDaoGenerator {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
final Schema schema = new Schema(38, MAIN_PACKAGE + ".entities");
|
||||
final Schema schema = new Schema(42, MAIN_PACKAGE + ".entities");
|
||||
|
||||
Entity userAttributes = addUserAttributes(schema);
|
||||
Entity user = addUserInfo(schema, userAttributes);
|
||||
@ -181,8 +181,9 @@ public class GBDaoGenerator {
|
||||
device.addStringProperty("manufacturer").notNull();
|
||||
device.addStringProperty("identifier").notNull().unique().javaDocGetterAndSetter("The fixed identifier, i.e. MAC address of the device.");
|
||||
device.addIntProperty("type").notNull().javaDocGetterAndSetter("The DeviceType key, i.e. the GBDevice's type.");
|
||||
device.addStringProperty("model").javaDocGetterAndSetter("An optional model, further specifying the kind of device-");
|
||||
device.addStringProperty("model").javaDocGetterAndSetter("An optional model, further specifying the kind of device.");
|
||||
device.addStringProperty("alias");
|
||||
device.addStringProperty("parentFolder").javaDocGetterAndSetter("Folder name containing this device.");
|
||||
Property deviceId = deviceAttributes.addLongProperty("deviceId").notNull().getProperty();
|
||||
// sorted by the from-date, newest first
|
||||
Property deviceAttributesSortProperty = getPropertyByName(deviceAttributes, VALID_FROM_UTC);
|
||||
|
@ -121,6 +121,7 @@ public class ControlCenterv2 extends AppCompatActivity
|
||||
case DeviceManager.ACTION_DEVICES_CHANGED:
|
||||
case GBApplication.ACTION_NEW_DATA:
|
||||
createRefreshTask("get activity data", getApplication()).execute();
|
||||
mGBDeviceAdapter.rebuildFolders();
|
||||
refreshPairedDevices();
|
||||
break;
|
||||
case DeviceService.ACTION_REALTIME_SAMPLES:
|
||||
|
@ -769,7 +769,7 @@ public class DebugActivity extends AbstractGBActivity {
|
||||
try (
|
||||
DBHandler db = GBApplication.acquireDB()) {
|
||||
DaoSession daoSession = db.getDaoSession();
|
||||
GBDevice gbDevice = new GBDevice(deviceMac, deviceType.name(), "", deviceType);
|
||||
GBDevice gbDevice = new GBDevice(deviceMac, deviceType.name(), "", null, deviceType);
|
||||
gbDevice.setFirmwareVersion("N/A");
|
||||
gbDevice.setFirmwareVersion2("N/A");
|
||||
|
||||
|
@ -23,13 +23,17 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.transition.TransitionManager;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
@ -40,6 +44,7 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
@ -47,6 +52,7 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
@ -55,6 +61,7 @@ import com.github.mikephil.charting.data.PieData;
|
||||
import com.github.mikephil.charting.data.PieDataSet;
|
||||
import com.github.mikephil.charting.data.PieEntry;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.google.android.flexbox.FlexboxLayout;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
|
||||
@ -68,6 +75,7 @@ import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
@ -78,7 +86,6 @@ import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureReminders;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateDialog;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.VibrationActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsActivity;
|
||||
@ -90,6 +97,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceFolder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||
@ -99,6 +107,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FormatUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Adapter for displaying GBDevice instances.
|
||||
@ -108,16 +117,52 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
|
||||
private final Context context;
|
||||
private List<GBDevice> deviceList;
|
||||
private List<GBDevice> devicesListWithFolders;
|
||||
private String expandedDeviceAddress = "";
|
||||
private String expandedFolderName = "";
|
||||
private ViewGroup parent;
|
||||
private HashMap<String, long[]> deviceActivityMap = new HashMap();
|
||||
|
||||
public GBDeviceAdapterv2(Context context, List<GBDevice> deviceList, HashMap<String,long[]> deviceMap) {
|
||||
this.context = context;
|
||||
this.deviceList = deviceList;
|
||||
rebuildFolders();
|
||||
this.deviceActivityMap = deviceMap;
|
||||
}
|
||||
|
||||
public void rebuildFolders(){
|
||||
this.devicesListWithFolders = enrichDeviceListWithFolder(deviceList);
|
||||
}
|
||||
|
||||
private List<GBDevice> enrichDeviceListWithFolder(List<GBDevice> deviceList) {
|
||||
ArrayList<GBDevice> enrichedList = new ArrayList<>();
|
||||
Set<String> folders = new ArraySet<>();
|
||||
for(GBDevice device : deviceList){
|
||||
String parentFolder = device.getParentFolder();
|
||||
if(StringUtils.isNullOrEmpty(parentFolder)){
|
||||
enrichedList.add(device);
|
||||
continue;
|
||||
}
|
||||
folders.add(parentFolder);
|
||||
}
|
||||
|
||||
for(String folder : folders){
|
||||
enrichedList.add(new GBDeviceFolder(folder));
|
||||
for(GBDevice potentialChild : deviceList){
|
||||
String parentFolder = potentialChild.getParentFolder();
|
||||
if(StringUtils.isNullOrEmpty(parentFolder)){
|
||||
continue;
|
||||
}
|
||||
if(!parentFolder.equals(folder)){
|
||||
continue;
|
||||
}
|
||||
enrichedList.add(potentialChild);
|
||||
}
|
||||
}
|
||||
|
||||
return enrichedList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GBDeviceAdapterv2.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
@ -126,9 +171,94 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
private int countDevicesInFolder(String folderName, boolean needsToBeConnected){
|
||||
int count = 0;
|
||||
for(GBDevice device : deviceList){
|
||||
if(folderName.equals(device.getParentFolder()) && ((!needsToBeConnected) || device.isConnected())){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private void showDeviceFolder(ViewHolder holder, final GBDeviceFolder folder){
|
||||
holder.container.setVisibility(View.VISIBLE);
|
||||
holder.deviceNameLabel.setText(folder.getName());
|
||||
holder.infoIcons.setVisibility(View.GONE);
|
||||
holder.cardViewActivityCardLayout.setVisibility(View.GONE);
|
||||
if(countDevicesInFolder(folder.getName(), true) == 0){
|
||||
holder.deviceImageView.setImageResource(R.drawable.ic_device_folder_disabled);
|
||||
}else{
|
||||
|
||||
holder.deviceImageView.setImageResource(R.drawable.ic_device_folder);
|
||||
}
|
||||
holder.deviceInfoView.setVisibility(View.GONE);
|
||||
int countInFolder = countDevicesInFolder(folder.getName(), false);
|
||||
int connectedInFolder = countDevicesInFolder(folder.getName(), true);
|
||||
holder.deviceStatusLabel.setText(context.getString(R.string.controlcenter_connected_fraction, connectedInFolder, countInFolder));
|
||||
|
||||
holder.container.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(expandedFolderName.equals(folder.getName())){
|
||||
// collapse open folder
|
||||
expandedFolderName = "";
|
||||
}else {
|
||||
expandedFolderName = folder.getName();
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
holder.container.setOnLongClickListener(null);
|
||||
}
|
||||
|
||||
private void setItemMargin(ViewHolder holder, GBDevice device){
|
||||
Resources r = context.getResources();
|
||||
int widthDp = 8;
|
||||
if(!StringUtils.isNullOrEmpty(device.getParentFolder())){
|
||||
widthDp = 16;
|
||||
}
|
||||
float px = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
widthDp,
|
||||
r.getDisplayMetrics()
|
||||
);
|
||||
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) holder.container.getLayoutParams();
|
||||
layoutParams.setMarginStart((int) px);
|
||||
holder.container.setLayoutParams(layoutParams);
|
||||
|
||||
int alpha = 0;
|
||||
if(device instanceof GBDeviceFolder && device.getName().equals(expandedFolderName)){
|
||||
alpha = 50;
|
||||
}else if(!StringUtils.isNullOrEmpty(device.getParentFolder()) && expandedFolderName.equals(device.getParentFolder())){
|
||||
alpha = 50;
|
||||
}
|
||||
|
||||
holder.root.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
|
||||
final GBDevice device = deviceList.get(position);
|
||||
final GBDevice device = devicesListWithFolders.get(position);
|
||||
|
||||
setItemMargin(holder, device);
|
||||
|
||||
if(device instanceof GBDeviceFolder){
|
||||
showDeviceFolder(holder, (GBDeviceFolder) device);
|
||||
return;
|
||||
}
|
||||
|
||||
String parentFolder = device.getParentFolder();
|
||||
if(!StringUtils.isNullOrEmpty(parentFolder)){
|
||||
if(parentFolder.equals(expandedFolderName)){
|
||||
holder.container.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
holder.container.setVisibility(View.GONE);
|
||||
}
|
||||
}else{
|
||||
holder.container.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
long[] dailyTotals = new long[]{0, 0};
|
||||
if (deviceActivityMap.containsKey(device.getAddress())) {
|
||||
dailyTotals = deviceActivityMap.get(device.getAddress());
|
||||
@ -152,10 +282,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
holder.container.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (device.getState() != GBDevice.State.NOT_CONNECTED) {
|
||||
showTransientSnackbar(R.string.controlcenter_snackbar_disconnecting);
|
||||
GBApplication.deviceService().disconnect(device);
|
||||
}
|
||||
showDeviceSubmenu(v, device);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@ -385,21 +512,19 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
justifyListViewHeightBasedOnChildren(holder.deviceInfoList);
|
||||
holder.deviceInfoList.setFocusable(false);
|
||||
|
||||
holder.infoIcons.setVisibility(View.VISIBLE);
|
||||
|
||||
final boolean detailsShown = expandedDeviceAddress.equals(device.getAddress());
|
||||
boolean showInfoIcon = device.hasDeviceInfos() && !device.isBusy();
|
||||
holder.deviceInfoView.setVisibility(showInfoIcon ? View.VISIBLE : View.GONE);
|
||||
holder.deviceInfoBox.setActivated(detailsShown);
|
||||
holder.deviceInfoBox.setVisibility(detailsShown ? View.VISIBLE : View.GONE);
|
||||
holder.deviceInfoView.setVisibility(View.VISIBLE);
|
||||
holder.deviceInfoView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
expandedDeviceAddress = detailsShown ? "" : device.getAddress();
|
||||
TransitionManager.beginDelayedTransition(parent);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showDeviceSubmenu(v, device);
|
||||
}
|
||||
});
|
||||
|
||||
holder.findDevice.setVisibility(device.isInitialized() && coordinator.supportsFindDevice() ? View.VISIBLE : View.GONE);
|
||||
holder.findDevice.setOnClickListener(new View.OnClickListener() {
|
||||
@ -668,91 +793,6 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
});
|
||||
}
|
||||
|
||||
//remove device, hidden under details
|
||||
holder.removeDevice.setOnClickListener(new View.OnClickListener()
|
||||
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
new AlertDialog.Builder(context)
|
||||
.setCancelable(true)
|
||||
.setTitle(context.getString(R.string.controlcenter_delete_device_name, device.getName()))
|
||||
.setMessage(R.string.controlcenter_delete_device_dialogmessage)
|
||||
.setPositiveButton(R.string.Delete, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
try {
|
||||
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
|
||||
if (coordinator != null) {
|
||||
coordinator.deleteDevice(device);
|
||||
}
|
||||
DeviceHelper.getInstance().removeBond(device);
|
||||
} catch (Exception ex) {
|
||||
GB.toast(context, "Error deleting device: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
} finally {
|
||||
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// do nothing
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
//set alias, hidden under details
|
||||
holder.setAlias.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final EditText input = new EditText(context);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
input.setText(device.getAlias());
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = context.getResources().getDimensionPixelSize(R.dimen.dialog_margin);
|
||||
params.rightMargin = context.getResources().getDimensionPixelSize(R.dimen.dialog_margin);
|
||||
input.setLayoutParams(params);
|
||||
container.addView(input);
|
||||
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setView(container)
|
||||
.setCancelable(true)
|
||||
.setTitle(context.getString(R.string.controlcenter_set_alias))
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
DaoSession session = dbHandler.getDaoSession();
|
||||
Device dbDevice = DBHelper.getDevice(device, session);
|
||||
String alias = input.getText().toString();
|
||||
dbDevice.setAlias(alias);
|
||||
dbDevice.update();
|
||||
device.setAlias(alias);
|
||||
} catch (Exception ex) {
|
||||
GB.toast(context, context.getString(R.string.error_setting_alias) + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
} finally {
|
||||
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// do nothing
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
holder.cardViewActivityCardLayout.setVisibility(coordinator.supportsActivityTracking() ? View.VISIBLE : View.GONE);
|
||||
holder.cardViewActivityCardLayout.setMinimumWidth(coordinator.supportsActivityTracking() ? View.VISIBLE : View.GONE);
|
||||
|
||||
@ -761,13 +801,182 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
}
|
||||
}
|
||||
|
||||
private void showDeviceSubmenu(final View v, final GBDevice device) {
|
||||
boolean deviceConnected = device.getState() != GBDevice.State.NOT_CONNECTED;
|
||||
|
||||
PopupMenu menu = new PopupMenu(v.getContext(), v);
|
||||
menu.inflate(R.menu.activity_controlcenterv2_device_submenu);
|
||||
|
||||
final boolean detailsShown = expandedDeviceAddress.equals(device.getAddress());
|
||||
boolean showInfoIcon = device.hasDeviceInfos() && !device.isBusy();
|
||||
|
||||
menu.getMenu().findItem(R.id.controlcenter_device_submenu_connect).setVisible(!deviceConnected);
|
||||
menu.getMenu().findItem(R.id.controlcenter_device_submenu_disconnect).setVisible(deviceConnected);
|
||||
menu.getMenu().findItem(R.id.controlcenter_device_submenu_show_details).setEnabled(showInfoIcon);
|
||||
|
||||
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()){
|
||||
case R.id.controlcenter_device_submenu_connect:
|
||||
if (device.getState() != GBDevice.State.CONNECTED) {
|
||||
showTransientSnackbar(R.string.controlcenter_snackbar_connecting);
|
||||
GBApplication.deviceService().connect(device);
|
||||
}
|
||||
return true;
|
||||
case R.id.controlcenter_device_submenu_disconnect:
|
||||
if (device.getState() != GBDevice.State.NOT_CONNECTED) {
|
||||
showTransientSnackbar(R.string.controlcenter_snackbar_disconnecting);
|
||||
GBApplication.deviceService().disconnect(device);
|
||||
}
|
||||
return true;
|
||||
case R.id.controlcenter_device_submenu_set_alias:
|
||||
showSetAliasDialog(device);
|
||||
return true;
|
||||
case R.id.controlcenter_device_submenu_remove:
|
||||
showRemoveDeviceDialog(device);
|
||||
return true;
|
||||
case R.id.controlcenter_device_submenu_show_details:
|
||||
expandedDeviceAddress = detailsShown ? "" : device.getAddress();
|
||||
TransitionManager.beginDelayedTransition(parent);
|
||||
notifyDataSetChanged();
|
||||
return true;
|
||||
case R.id.controlcenter_device_submenu_set_parent_folder:
|
||||
showSetParentFolderDialog(device);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
menu.show();
|
||||
}
|
||||
|
||||
private void showRemoveDeviceDialog(final GBDevice device) {
|
||||
new AlertDialog.Builder(context)
|
||||
.setCancelable(true)
|
||||
.setTitle(context.getString(R.string.controlcenter_delete_device_name, device.getName()))
|
||||
.setMessage(R.string.controlcenter_delete_device_dialogmessage)
|
||||
.setPositiveButton(R.string.Delete, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
try {
|
||||
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
|
||||
if (coordinator != null) {
|
||||
coordinator.deleteDevice(device);
|
||||
}
|
||||
DeviceHelper.getInstance().removeBond(device);
|
||||
} catch (Exception ex) {
|
||||
GB.toast(context, context.getString(R.string.error_deleting_device, ex.getMessage()), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
} finally {
|
||||
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// do nothing
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showSetParentFolderDialog(final GBDevice device) {
|
||||
final EditText input = new EditText(context);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
input.setText(device.getParentFolder());
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = context.getResources().getDimensionPixelSize(R.dimen.dialog_margin);
|
||||
params.rightMargin = context.getResources().getDimensionPixelSize(R.dimen.dialog_margin);
|
||||
input.setLayoutParams(params);
|
||||
container.addView(input);
|
||||
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setView(container)
|
||||
.setCancelable(true)
|
||||
.setTitle(context.getString(R.string.controlcenter_set_parent_folder))
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
DaoSession session = dbHandler.getDaoSession();
|
||||
Device dbDevice = DBHelper.getDevice(device, session);
|
||||
String parentFolder = input.getText().toString();
|
||||
dbDevice.setParentFolder(parentFolder);
|
||||
dbDevice.update();
|
||||
device.setParentFolder(parentFolder);
|
||||
expandedFolderName = parentFolder;
|
||||
} catch (Exception ex) {
|
||||
GB.toast(context, context.getString(R.string.error_setting_parent_folder, ex.getMessage()), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
} finally {
|
||||
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// do nothing
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showSetAliasDialog(final GBDevice device) {
|
||||
final EditText input = new EditText(context);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
input.setText(device.getAlias());
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.leftMargin = context.getResources().getDimensionPixelSize(R.dimen.dialog_margin);
|
||||
params.rightMargin = context.getResources().getDimensionPixelSize(R.dimen.dialog_margin);
|
||||
input.setLayoutParams(params);
|
||||
container.addView(input);
|
||||
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setView(container)
|
||||
.setCancelable(true)
|
||||
.setTitle(context.getString(R.string.controlcenter_set_alias))
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
DaoSession session = dbHandler.getDaoSession();
|
||||
Device dbDevice = DBHelper.getDevice(device, session);
|
||||
String alias = input.getText().toString();
|
||||
dbDevice.setAlias(alias);
|
||||
dbDevice.update();
|
||||
device.setAlias(alias);
|
||||
} catch (Exception ex) {
|
||||
GB.toast(context, context.getString(R.string.error_setting_alias) + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
} finally {
|
||||
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// do nothing
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return deviceList.size();
|
||||
return devicesListWithFolders.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
View root;
|
||||
CardView container;
|
||||
|
||||
ImageView deviceImageView;
|
||||
@ -798,6 +1007,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
LinearLayout heartRateStatusBox;
|
||||
ImageView heartRateIcon;
|
||||
TextView heartRateStatusLabel;
|
||||
FlexboxLayout infoIcons;
|
||||
|
||||
|
||||
ImageView deviceInfoView;
|
||||
@ -805,8 +1015,6 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
final RelativeLayout deviceInfoBox;
|
||||
ListView deviceInfoList;
|
||||
ImageView findDevice;
|
||||
ImageView removeDevice;
|
||||
ImageView setAlias;
|
||||
LinearLayout fmFrequencyBox;
|
||||
TextView fmFrequencyLabel;
|
||||
ImageView ledColor;
|
||||
@ -821,6 +1029,8 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
ViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
root = view;
|
||||
|
||||
container = view.findViewById(R.id.card_view);
|
||||
|
||||
deviceImageView = view.findViewById(R.id.device_image);
|
||||
@ -857,8 +1067,6 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
//overflow
|
||||
deviceInfoList = view.findViewById(R.id.device_item_infos);
|
||||
findDevice = view.findViewById(R.id.device_action_find);
|
||||
removeDevice = view.findViewById(R.id.device_action_remove);
|
||||
setAlias = view.findViewById(R.id.device_action_set_alias);
|
||||
fmFrequencyBox = view.findViewById(R.id.device_fm_frequency_box);
|
||||
fmFrequencyLabel = view.findViewById(R.id.fm_frequency);
|
||||
ledColor = view.findViewById(R.id.device_led_color);
|
||||
@ -866,6 +1074,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
||||
heartRateStatusBox = view.findViewById(R.id.device_heart_rate_status_box);
|
||||
heartRateStatusLabel = view.findViewById(R.id.heart_rate_status);
|
||||
heartRateIcon = view.findViewById(R.id.device_heart_rate_status);
|
||||
infoIcons = view.findViewById(R.id.device_info_icons);
|
||||
|
||||
cardViewActivityCardLayout = view.findViewById(R.id.card_view_activity_card_layout);
|
||||
|
||||
|
@ -0,0 +1,38 @@
|
||||
/* Copyright (C) 2017-2020 Andreas Shimokawa, protomors
|
||||
|
||||
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.database.schema;
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceDao;
|
||||
|
||||
public class GadgetbridgeUpdate_42 implements DBUpdateScript {
|
||||
@Override
|
||||
public void upgradeSchema(SQLiteDatabase db) {
|
||||
if (!DBHelper.existsColumn(DeviceDao.TABLENAME, DeviceDao.Properties.ParentFolder.columnName, db)) {
|
||||
String ADD_COLUMN_CPONTAINED_FOLDER = "ALTER TABLE " + DeviceDao.TABLENAME + " ADD COLUMN "
|
||||
+ DeviceDao.Properties.ParentFolder.columnName + " TEXT";
|
||||
db.execSQL(ADD_COLUMN_CPONTAINED_FOLDER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downgradeSchema(SQLiteDatabase db) {
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
||||
|
||||
@Override
|
||||
public GBDevice createDevice(GBDeviceCandidate candidate) {
|
||||
GBDevice gbDevice = new GBDevice(candidate.getDevice().getAddress(), candidate.getName(), null, getDeviceType());
|
||||
GBDevice gbDevice = new GBDevice(candidate.getDevice().getAddress(), candidate.getName(), null, null, getDeviceType());
|
||||
for (BatteryConfig batteryConfig : getBatteryConfig()) {
|
||||
gbDevice.setBatteryIcon(batteryConfig.getBatteryIcon(), batteryConfig.getBatteryIndex());
|
||||
gbDevice.setBatteryLabel(batteryConfig.getBatteryLabel(), batteryConfig.getBatteryIndex());
|
||||
|
@ -89,7 +89,7 @@ public class DeviceManager {
|
||||
if (dev.getAddress() != null) {
|
||||
int index = deviceList.indexOf(dev); // search by address
|
||||
if (index >= 0) {
|
||||
deviceList.set(index, dev);
|
||||
deviceList.get(index).copyFromDevice(dev);
|
||||
} else {
|
||||
deviceList.add(dev);
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ public class GBDevice implements Parcelable {
|
||||
public static final String BATTERY_INDEX = "battery_index";
|
||||
private String mName;
|
||||
private String mAlias;
|
||||
private String parentFolder;
|
||||
private final String mAddress;
|
||||
private String mVolatileAddress;
|
||||
private final DeviceType mDeviceType;
|
||||
@ -98,22 +99,24 @@ public class GBDevice implements Parcelable {
|
||||
private int mNotificationIconDisconnected = R.drawable.ic_notification_disconnected;
|
||||
private int mNotificationIconLowBattery = R.drawable.ic_notification_low_battery;
|
||||
|
||||
public GBDevice(String address, String name, String alias, DeviceType deviceType) {
|
||||
this(address, null, name, alias, deviceType);
|
||||
public GBDevice(String address, String name, String alias, String parentFolder, DeviceType deviceType) {
|
||||
this(address, null, name, alias, parentFolder, deviceType);
|
||||
}
|
||||
|
||||
public GBDevice(String address, String address2, String name, String alias, DeviceType deviceType) {
|
||||
public GBDevice(String address, String address2, String name, String alias, String parentFolder, DeviceType deviceType) {
|
||||
mAddress = address;
|
||||
mVolatileAddress = address2;
|
||||
mName = (name != null) ? name : mAddress;
|
||||
mAlias = alias;
|
||||
mDeviceType = deviceType;
|
||||
this.parentFolder = parentFolder;
|
||||
validate();
|
||||
}
|
||||
|
||||
private GBDevice(Parcel in) {
|
||||
mName = in.readString();
|
||||
mAlias = in.readString();
|
||||
parentFolder = in.readString();
|
||||
mAddress = in.readString();
|
||||
mVolatileAddress = in.readString();
|
||||
mDeviceType = DeviceType.values()[in.readInt()];
|
||||
@ -138,10 +141,39 @@ public class GBDevice implements Parcelable {
|
||||
validate();
|
||||
}
|
||||
|
||||
public void copyFromDevice(GBDevice device){
|
||||
if(!device.mAddress.equals(mAddress)){
|
||||
throw new RuntimeException("Cannot copy from device with other address");
|
||||
}
|
||||
|
||||
mName = device.mName;
|
||||
mAlias = device.mAlias;
|
||||
parentFolder = device.parentFolder;
|
||||
mVolatileAddress = device.mVolatileAddress;
|
||||
mFirmwareVersion = device.mFirmwareVersion;
|
||||
mFirmwareVersion2 = device.mFirmwareVersion2;
|
||||
mModel = device.mModel;
|
||||
mState = device.mState;
|
||||
mBatteryLevel = device.mBatteryLevel;
|
||||
mBatteryVoltage = device.mBatteryVoltage;
|
||||
mBatteryThresholdPercent = device.mBatteryThresholdPercent;
|
||||
mBatteryState = device.mBatteryState;
|
||||
mBatteryIcons = device.mBatteryIcons;
|
||||
mBatteryLabels = device.mBatteryLabels;
|
||||
mRssi = device.mRssi;
|
||||
mBusyTask = device.mBusyTask;
|
||||
mDeviceInfos = device.mDeviceInfos;
|
||||
mExtraInfos = device.mExtraInfos;
|
||||
mNotificationIconConnected = device.mNotificationIconConnected;
|
||||
mNotificationIconDisconnected = device.mNotificationIconDisconnected;
|
||||
mNotificationIconLowBattery = device.mNotificationIconLowBattery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mName);
|
||||
dest.writeString(mAlias);
|
||||
dest.writeString(parentFolder);
|
||||
dest.writeString(mAddress);
|
||||
dest.writeString(mVolatileAddress);
|
||||
dest.writeInt(mDeviceType.ordinal());
|
||||
@ -186,6 +218,13 @@ public class GBDevice implements Parcelable {
|
||||
return enums;
|
||||
}
|
||||
|
||||
public String getParentFolder() {
|
||||
return parentFolder;
|
||||
}
|
||||
|
||||
public void setParentFolder(String parentFolder) {
|
||||
this.parentFolder = parentFolder;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
|
@ -0,0 +1,9 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.impl;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
|
||||
public class GBDeviceFolder extends GBDevice{
|
||||
public GBDeviceFolder(String name) {
|
||||
super("", name, null, null, null);
|
||||
}
|
||||
}
|
@ -194,14 +194,14 @@ public class DeviceHelper {
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
String miAddress = prefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, "");
|
||||
if (miAddress.length() > 0) {
|
||||
GBDevice miDevice = new GBDevice(miAddress, "MI", null, DeviceType.MIBAND);
|
||||
GBDevice miDevice = new GBDevice(miAddress, "MI", null, null, DeviceType.MIBAND);
|
||||
availableDevices.add(miDevice);
|
||||
}
|
||||
|
||||
String pebbleEmuAddr = prefs.getString("pebble_emu_addr", "");
|
||||
String pebbleEmuPort = prefs.getString("pebble_emu_port", "");
|
||||
if (pebbleEmuAddr.length() >= 7 && pebbleEmuPort.length() > 0) {
|
||||
GBDevice pebbleEmuDevice = new GBDevice(pebbleEmuAddr + ":" + pebbleEmuPort, "Pebble qemu", "", DeviceType.PEBBLE);
|
||||
GBDevice pebbleEmuDevice = new GBDevice(pebbleEmuAddr + ":" + pebbleEmuPort, "Pebble qemu", "", null, DeviceType.PEBBLE);
|
||||
availableDevices.add(pebbleEmuDevice);
|
||||
}
|
||||
return availableDevices;
|
||||
@ -361,7 +361,7 @@ public class DeviceHelper {
|
||||
*/
|
||||
public GBDevice toGBDevice(Device dbDevice) {
|
||||
DeviceType deviceType = DeviceType.fromKey(dbDevice.getType());
|
||||
GBDevice gbDevice = new GBDevice(dbDevice.getIdentifier(), dbDevice.getName(), dbDevice.getAlias(), deviceType);
|
||||
GBDevice gbDevice = new GBDevice(dbDevice.getIdentifier(), dbDevice.getName(), dbDevice.getAlias(), dbDevice.getParentFolder(), deviceType);
|
||||
DeviceCoordinator coordinator = getCoordinator(gbDevice);
|
||||
for (BatteryConfig batteryConfig : coordinator.getBatteryConfig()) {
|
||||
gbDevice.setBatteryIcon(batteryConfig.getBatteryIcon(), batteryConfig.getBatteryIndex());
|
||||
|
@ -103,6 +103,10 @@ public class StringUtils {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static boolean isNullOrEmpty(String string){
|
||||
return string == null || string.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isEmpty(String string) {
|
||||
return string != null && string.length() == 0;
|
||||
}
|
||||
|
23
app/src/main/res/drawable/ic_device_folder.xml
Normal file
23
app/src/main/res/drawable/ic_device_folder.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="45sp"
|
||||
android:height="45sp"
|
||||
android:viewportWidth="30"
|
||||
android:viewportHeight="30">
|
||||
|
||||
<path
|
||||
android:fillColor="#1f7fdb"
|
||||
android:pathData="M3.871 3.877h20.925a0.947 0.947 0 0 1 0.948 0.947v20.01a0.947 0.947 0 0 1-0.948 0.948H3.871a0.947 0.947 0 0 1-0.947-0.948V4.824a0.947 0.947 0 0 1 0.947-0.947z"
|
||||
android:strokeWidth="3.5" />
|
||||
<path
|
||||
android:fillColor="#4dabf5"
|
||||
android:pathData="M3.879 3.035h20.925a0.947 0.947 0 0 1 0.947 0.947v20.01a0.947 0.947 0 0 1-0.947 0.948H3.88a0.947 0.947 0 0 1-0.947-0.948V3.982A0.947 0.947 0 0 1 3.88 3.035z"
|
||||
android:strokeWidth="3.5" />
|
||||
<path
|
||||
android:fillColor="#2196f3"
|
||||
android:pathData="M3.871 3.413h20.925a0.947 0.947 0 0 1 0.948 0.947v20.01a0.947 0.947 0 0 1-0.948 0.948H3.871a0.947 0.947 0 0 1-0.947-0.948V4.36A0.947 0.947 0 0 1 3.87 3.413z"
|
||||
android:strokeWidth="3.5" />
|
||||
|
||||
<path
|
||||
android:pathData="M6.8,6.95C6.22,6.95 5.75,7.42 5.75,8L5.75,20.92C5.73,21 5.74,21.08 5.77,21.16C5.87,21.63 6.3,22 6.8,22L20.45,22C20.97,22 21.4,21.61 21.48,21.1C21.48,21.08 21.49,21.06 21.49,21.04C21.49,21.03 21.49,21.02 21.49,21.02L21.5,20.96C21.5,20.96 21.5,20.95 21.5,20.95L23.24,11.57L23.25,11.53L23.25,11.5C23.25,10.92 22.78,10.45 22.2,10.45L22.2,9.4C22.2,8.82 21.73,8.35 21.15,8.35L12.06,8.35C12.06,8.35 12.06,8.35 12.05,8.35C12.04,8.34 12.01,8.32 11.95,8.25C11.87,8.15 11.77,7.99 11.66,7.81C11.55,7.64 11.43,7.45 11.28,7.29C11.14,7.13 10.94,6.95 10.65,6.95ZM6.8,7.65L10.65,7.65C10.63,7.65 10.67,7.65 10.76,7.75C10.85,7.85 10.95,8.01 11.05,8.19C11.16,8.36 11.28,8.55 11.43,8.71C11.57,8.88 11.76,9.05 12.05,9.05L21.15,9.05C21.35,9.05 21.5,9.2 21.5,9.4L21.5,10.45L8.55,10.45C8,10.45 7.56,10.89 7.52,11.43L7.51,11.43L7.5,11.5L6.45,17.17L6.45,8C6.45,7.8 6.6,7.65 6.8,7.65ZM8.55,11.15L22.2,11.15C22.4,11.15 22.55,11.3 22.55,11.5L20.83,20.79L20.82,20.81C20.82,20.82 20.81,20.84 20.81,20.85C20.81,20.87 20.8,20.88 20.8,20.9C20.8,20.9 20.8,20.91 20.8,20.92C20.8,20.92 20.8,20.92 20.8,20.93C20.79,20.95 20.79,20.96 20.79,20.98C20.79,20.99 20.79,21 20.79,21.02C20.79,21.03 20.79,21.04 20.79,21.06C20.75,21.2 20.61,21.3 20.45,21.3L6.8,21.3C6.6,21.3 6.45,21.15 6.45,20.95L8.19,11.57L8.2,11.53L8.2,11.5C8.2,11.3 8.35,11.15 8.55,11.15Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
32
app/src/main/res/drawable/ic_device_folder_disabled.xml
Normal file
32
app/src/main/res/drawable/ic_device_folder_disabled.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="45sp"
|
||||
android:height="45sp"
|
||||
android:viewportWidth="30"
|
||||
android:viewportHeight="30">
|
||||
|
||||
|
||||
<path
|
||||
android:fillColor="#7a7a7a"
|
||||
android:pathData="M3.8712,3.8769L24.7963,3.8769A0.9472,0.9472 0,0 1,25.7435 4.8241L25.7435,24.8343A0.9472,0.9472 0,0 1,24.7963 25.7815L3.8712,25.7815A0.9472,0.9472 0,0 1,2.924 24.8343L2.924,4.8241A0.9472,0.9472 0,0 1,3.8712 3.8769z"
|
||||
android:strokeWidth="3.57115173"
|
||||
android:strokeColor="#00000000" />
|
||||
<path
|
||||
android:fillAlpha="0.9411765"
|
||||
android:fillColor="#9f9f9f"
|
||||
android:pathData="M3.879,3.0349L24.8041,3.0349A0.9472,0.9472 0,0 1,25.7514 3.9822L25.7514,23.9924A0.9472,0.9472 0,0 1,24.8041 24.9396L3.879,24.9396A0.9472,0.9472 0,0 1,2.9318 23.9924L2.9318,3.9822A0.9472,0.9472 0,0 1,3.879 3.0349z"
|
||||
android:strokeWidth="3.57115173"
|
||||
android:strokeColor="#00000000" />
|
||||
<path
|
||||
android:fillColor="#8a8a8a"
|
||||
android:pathData="M3.8711,3.4131L24.7962,3.4131A0.9472,0.9472 0,0 1,25.7435 4.3603L25.7435,24.3705A0.9472,0.9472 0,0 1,24.7962 25.3177L3.8711,25.3177A0.9472,0.9472 0,0 1,2.9239 24.3705L2.9239,4.3603A0.9472,0.9472 0,0 1,3.8711 3.4131z"
|
||||
android:strokeWidth="3.57115173"
|
||||
android:strokeColor="#00000000" />
|
||||
<path
|
||||
android:fillAlpha="0.9411765"
|
||||
android:fillColor="#8a8a8a"
|
||||
android:pathData="m12.4827,10.8654h3.907v6.978h-3.907z" />
|
||||
|
||||
<path
|
||||
android:pathData="M6.8,6.95C6.22,6.95 5.75,7.42 5.75,8L5.75,20.92C5.73,21 5.74,21.08 5.77,21.16C5.87,21.63 6.3,22 6.8,22L20.45,22C20.97,22 21.4,21.61 21.48,21.1C21.48,21.08 21.49,21.06 21.49,21.04C21.49,21.03 21.49,21.02 21.49,21.02L21.5,20.96C21.5,20.96 21.5,20.95 21.5,20.95L23.24,11.57L23.25,11.53L23.25,11.5C23.25,10.92 22.78,10.45 22.2,10.45L22.2,9.4C22.2,8.82 21.73,8.35 21.15,8.35L12.06,8.35C12.06,8.35 12.06,8.35 12.05,8.35C12.04,8.34 12.01,8.32 11.95,8.25C11.87,8.15 11.77,7.99 11.66,7.81C11.55,7.64 11.43,7.45 11.28,7.29C11.14,7.13 10.94,6.95 10.65,6.95ZM6.8,7.65L10.65,7.65C10.63,7.65 10.67,7.65 10.76,7.75C10.85,7.85 10.95,8.01 11.05,8.19C11.16,8.36 11.28,8.55 11.43,8.71C11.57,8.88 11.76,9.05 12.05,9.05L21.15,9.05C21.35,9.05 21.5,9.2 21.5,9.4L21.5,10.45L8.55,10.45C8,10.45 7.56,10.89 7.52,11.43L7.51,11.43L7.5,11.5L6.45,17.17L6.45,8C6.45,7.8 6.6,7.65 6.8,7.65ZM8.55,11.15L22.2,11.15C22.4,11.15 22.55,11.3 22.55,11.5L20.83,20.79L20.82,20.81C20.82,20.82 20.81,20.84 20.81,20.85C20.81,20.87 20.8,20.88 20.8,20.9C20.8,20.9 20.8,20.91 20.8,20.92C20.8,20.92 20.8,20.92 20.8,20.93C20.79,20.95 20.79,20.96 20.79,20.98C20.79,20.99 20.79,21 20.79,21.02C20.79,21.03 20.79,21.04 20.79,21.06C20.75,21.2 20.61,21.3 20.45,21.3L6.8,21.3C6.6,21.3 6.45,21.15 6.45,20.95L8.19,11.57L8.2,11.53L8.2,11.5C8.2,11.3 8.35,11.15 8.55,11.15Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
@ -10,7 +10,9 @@
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
card_view:cardCornerRadius="3dp"
|
||||
card_view:cardElevation="3dp"
|
||||
@ -35,38 +37,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_toStartOf="@+id/device_action_set_alias"
|
||||
android:focusable="false"
|
||||
android:scrollbars="none">
|
||||
</ListView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/device_action_set_alias"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="36dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/controlcenter_set_alias"
|
||||
android:focusable="true"
|
||||
card_view:srcCompat="@drawable/ic_create"
|
||||
card_view:tint="?attr/textColorTertiary" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/device_action_remove"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/controlcenter_delete_device"
|
||||
android:focusable="true"
|
||||
card_view:srcCompat="@drawable/ic_delete"
|
||||
card_view:tint="?attr/textColorTertiary" />
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/controlcenter_device_submenu_connect"
|
||||
android:title="@string/controlcenter_connect" />
|
||||
<item
|
||||
android:id="@+id/controlcenter_device_submenu_disconnect"
|
||||
android:title="@string/controlcenter_disconnect" />
|
||||
<item
|
||||
android:id="@+id/controlcenter_device_submenu_set_parent_folder"
|
||||
android:title="@string/controlcenter_set_parent_folder" />
|
||||
<item
|
||||
android:id="@+id/controlcenter_device_submenu_set_alias"
|
||||
android:title="@string/controlcenter_set_alias" />
|
||||
<item
|
||||
android:id="@+id/controlcenter_device_submenu_show_details"
|
||||
android:title="@string/controlcenter_toggle_details" />
|
||||
<item
|
||||
android:id="@+id/controlcenter_device_submenu_remove"
|
||||
android:title="@string/controlcenter_delete_device" />
|
||||
</menu>
|
@ -1734,4 +1734,7 @@
|
||||
<string name="notification_gps_title">Gadgetbridge GPS</string>
|
||||
<string name="portuguese_pt">Portugiesisch (Portugal)</string>
|
||||
<string name="notification_gps_text">Senden des GPS-Standorts an %1$d Geräte</string>
|
||||
<string name="controlcenter_set_parent_folder">Überordner setzen</string>
|
||||
<string name="controlcenter_toggle_details">Details anzeigen</string>
|
||||
<string name="controlcenter_connected_fraction">Verbunden: %d/%d</string>
|
||||
</resources>
|
@ -1678,4 +1678,9 @@
|
||||
|
||||
<string name="info_no_devices_connected">no devices connected</string>
|
||||
<string name="info_connected_count">%d devices connected</string>
|
||||
<string name="controlcenter_set_parent_folder">Set parent folder</string>
|
||||
<string name="controlcenter_toggle_details">Toggle details</string>
|
||||
<string name="controlcenter_connected_fraction">Connected: %d/%d</string>
|
||||
<string name="error_setting_parent_folder">Error setting parent folder: %s</string>
|
||||
<string name="error_deleting_device">Error deleting device: %s</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user