From 371f0ecdd0c0e7482e89ead6fb8817fc62bd5b5c Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Fri, 21 Oct 2016 13:01:30 +0200 Subject: [PATCH] Use a new GUI for the controlcenter. The existing logic was mostly ported to the new activity, with the exception of device deletion (and all TODOs). --- app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 10 +- .../activities/ControlCenterv2.java | 255 +++++++++++++++++ .../adapter/GBDeviceAdapterv2.java | 270 ++++++++++++++++++ .../ic_action_fetch_activity_data.xml | 9 + .../main/res/drawable/ic_activity_graphs.xml | 9 + app/src/main/res/drawable/ic_battery.xml | 9 + .../res/drawable/ic_database_management.xml | 9 + app/src/main/res/drawable/ic_debug.xml | 9 + .../res/drawable/ic_device_set_alarms.xml | 9 + app/src/main/res/drawable/ic_quit.xml | 9 + .../main/res/drawable/ic_remove_device.xml | 9 + app/src/main/res/drawable/ic_screenshot.xml | 9 + app/src/main/res/drawable/ic_settings.xml | 9 + app/src/main/res/drawable/side_nav_bar.xml | 9 + .../res/layout/activity_controlcenterv2.xml | 25 ++ .../activity_controlcenterv2_app_bar_main.xml | 53 ++++ .../activity_controlcenterv2_content_main.xml | 33 +++ app/src/main/res/layout/device_itemv2.xml | 192 +++++++++++++ app/src/main/res/layout/nav_header_main.xml | 31 ++ .../activity_controlcenterv2_main_drawer.xml | 19 ++ app/src/main/res/values-v21/styles.xml | 9 + app/src/main/res/values/dimens.xml | 4 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/styles.xml | 9 + 25 files changed, 1012 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java create mode 100644 app/src/main/res/drawable/ic_action_fetch_activity_data.xml create mode 100644 app/src/main/res/drawable/ic_activity_graphs.xml create mode 100644 app/src/main/res/drawable/ic_battery.xml create mode 100644 app/src/main/res/drawable/ic_database_management.xml create mode 100644 app/src/main/res/drawable/ic_debug.xml create mode 100644 app/src/main/res/drawable/ic_device_set_alarms.xml create mode 100644 app/src/main/res/drawable/ic_quit.xml create mode 100644 app/src/main/res/drawable/ic_remove_device.xml create mode 100644 app/src/main/res/drawable/ic_screenshot.xml create mode 100644 app/src/main/res/drawable/ic_settings.xml create mode 100644 app/src/main/res/drawable/side_nav_bar.xml create mode 100644 app/src/main/res/layout/activity_controlcenterv2.xml create mode 100644 app/src/main/res/layout/activity_controlcenterv2_app_bar_main.xml create mode 100644 app/src/main/res/layout/activity_controlcenterv2_content_main.xml create mode 100644 app/src/main/res/layout/device_itemv2.xml create mode 100644 app/src/main/res/layout/nav_header_main.xml create mode 100644 app/src/main/res/menu/activity_controlcenterv2_main_drawer.xml create mode 100644 app/src/main/res/values-v21/styles.xml diff --git a/app/build.gradle b/app/build.gradle index 9a239ded3..51031f8ae 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,6 +28,7 @@ android { // note: always bump BOTH versionCode and versionName! versionName "0.13.4" versionCode 66 + vectorDrawables.useSupportLibrary = true } buildTypes { release { @@ -64,6 +65,7 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.3.0' + compile 'com.android.support:cardview-v7:23.3.0' compile 'com.android.support:support-v4:23.3.0' compile 'com.android.support:design:23.3.0' compile 'com.github.tony19:logback-android-classic:1.1.1-4' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3c3c718a7..c14f0e687 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -297,7 +297,15 @@ - + + + + + + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java new file mode 100644 index 000000000..8d7ab7907 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java @@ -0,0 +1,255 @@ +package nodomain.freeyourgadget.gadgetbridge.activities; + +import android.Manifest; +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.NavigationView; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.support.v4.content.LocalBroadcastManager; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import de.cketti.library.changelog.ChangeLog; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapterv2; +import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; +import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; + +//TODO: extend GBActivity, but it requires actionbar that is not available +public class ControlCenterv2 extends AppCompatActivity + implements NavigationView.OnNavigationItemSelectedListener { + + private DeviceManager deviceManager; + private ImageView background; + private TextView hintTextView; + + private GBDeviceAdapterv2 mGBDeviceAdapter; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + switch (action) { + case GBApplication.ACTION_QUIT: + finish(); + break; + case DeviceManager.ACTION_DEVICES_CHANGED: + refreshPairedDevices(); + break; + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_controlcenterv2); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + launchDiscoveryActivity(); + } + }); + + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.controlcenter_navigation_drawer_open, R.string.controlcenter_navigation_drawer_close); + drawer.setDrawerListener(toggle); + toggle.syncState(); + + NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + //end of material design boilerplate + deviceManager = GBApplication.getDeviceManager(); + hintTextView = (TextView) findViewById(R.id.hintTextView); + ListView deviceListView = (ListView) findViewById(R.id.deviceListView); + background = (ImageView) findViewById(R.id.no_items_bg); + + final List deviceList = deviceManager.getDevices(); + mGBDeviceAdapter = new GBDeviceAdapterv2(this, deviceList); + deviceListView.setAdapter(this.mGBDeviceAdapter); + deviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View v, int position, long id) { + GBDevice gbDevice = mGBDeviceAdapter.getItem(position); + if (gbDevice.isInitialized()) { + DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice); + Class primaryActivity = coordinator.getPrimaryActivity(); + if (primaryActivity != null) { + Intent startIntent = new Intent(ControlCenterv2.this, primaryActivity); + startIntent.putExtra(GBDevice.EXTRA_DEVICE, gbDevice); + startActivity(startIntent); + } + } else { + GBApplication.deviceService().connect(gbDevice); + } + } + }); + + registerForContextMenu(deviceListView); + + IntentFilter filterLocal = new IntentFilter(); + filterLocal.addAction(GBApplication.ACTION_QUIT); + filterLocal.addAction(DeviceManager.ACTION_DEVICES_CHANGED); + LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal); + + refreshPairedDevices(); + + /* + * Ask for permission to intercept notifications on first run. + */ + Prefs prefs = GBApplication.getPrefs(); + if (prefs.getBoolean("firstrun", true)) { + prefs.getPreferences().edit().putBoolean("firstrun", false).apply(); + Intent enableIntent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); + startActivity(enableIntent); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + checkAndRequestPermissions(); + } + + ChangeLog cl = new ChangeLog(this); + if (cl.isFirstRun()) { + cl.getLogDialog().show(); + } + + GBApplication.deviceService().start(); + + if (GB.isBluetoothEnabled() && deviceList.isEmpty() && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + startActivity(new Intent(this, DiscoveryActivity.class)); + } else { + GBApplication.deviceService().requestDeviceInfo(); + } + } + + @Override + public void onBackPressed() { + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else { + super.onBackPressed(); + } + } + + @Override + public boolean onNavigationItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.action_settings: + Intent settingsIntent = new Intent(this, SettingsActivity.class); + startActivity(settingsIntent); + return true; + case R.id.action_debug: + Intent debugIntent = new Intent(this, DebugActivity.class); + startActivity(debugIntent); + return true; + case R.id.action_db_management: + Intent dbIntent = new Intent(this, DbManagementActivity.class); + startActivity(dbIntent); + return true; + case R.id.action_quit: + GBApplication.quit(); + return true; + } + + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } + + private void launchDiscoveryActivity() { + startActivity(new Intent(this, DiscoveryActivity.class)); + } + + private void refreshPairedDevices() { + List deviceList = deviceManager.getDevices(); + GBDevice connectedDevice = null; + + for (GBDevice device : deviceList) { + if (device.isConnected() || device.isConnecting()) { + connectedDevice = device; + break; + } + } + + if (deviceList.isEmpty()) { + background.setVisibility(View.VISIBLE); + } else { + background.setVisibility(View.INVISIBLE); + } + + if (connectedDevice != null) { + DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(connectedDevice); + hintTextView.setText(coordinator.getTapString()); + } else if (!deviceList.isEmpty()) { + hintTextView.setText(R.string.tap_a_device_to_connect); + } + + mGBDeviceAdapter.notifyDataSetChanged(); + } + + @TargetApi(Build.VERSION_CODES.M) + private void checkAndRequestPermissions() { + List wantedPermissions = new ArrayList<>(); + + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.BLUETOOTH); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.BLUETOOTH_ADMIN); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.READ_CONTACTS); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.CALL_PHONE); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.READ_PHONE_STATE); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_OUTGOING_CALLS) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.PROCESS_OUTGOING_CALLS); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.READ_SMS); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.SEND_SMS); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_DENIED) + wantedPermissions.add(Manifest.permission.READ_CALENDAR); + if (ContextCompat.checkSelfPermission(this, "com.fsck.k9.permission.READ_MESSAGES") == PackageManager.PERMISSION_DENIED) + wantedPermissions.add("com.fsck.k9.permission.READ_MESSAGES"); + + if (!wantedPermissions.isEmpty()) + ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[wantedPermissions.size()]), 0); + } + + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java new file mode 100644 index 000000000..c3e43e49d --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java @@ -0,0 +1,270 @@ +package nodomain.freeyourgadget.gadgetbridge.adapter; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import java.util.Collections; +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms; +import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity; +import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.BatteryState; +import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails; +import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; + +/** + * Adapter for displaying GBDevice instances. + */ +public class GBDeviceAdapterv2 extends ArrayAdapter { + + private final Context context; + private DeviceCoordinator coordinator; + + public GBDeviceAdapterv2(Context context, List deviceList) { + super(context, 0, deviceList); + + this.context = context; + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + final GBDevice device = getItem(position); + coordinator = DeviceHelper.getInstance().getCoordinator(device); + + if (view == null) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + view = inflater.inflate(R.layout.device_itemv2, parent, false); + } + TextView deviceStatusLabel = (TextView) view.findViewById(R.id.device_status); + TextView deviceNameLabel = (TextView) view.findViewById(R.id.device_name); + + TextView batteryStatusLabel = (TextView) view.findViewById(R.id.battery_status); + final ImageView deviceImageView = (ImageView) view.findViewById(R.id.device_image); + + ProgressBar busyIndicator = (ProgressBar) view.findViewById(R.id.device_busy_indicator); + + deviceNameLabel.setText(getUniqueDeviceName(device)); + + if (device.isBusy()) { + deviceStatusLabel.setText(device.getBusyTask()); + busyIndicator.setVisibility(View.VISIBLE); + } else { + deviceStatusLabel.setText(device.getStateString()); + busyIndicator.setVisibility(View.INVISIBLE); + } + + //begin of action row + //battery + LinearLayout batteryStatusBox = (LinearLayout) view.findViewById(R.id.device_battery_status_box); + batteryStatusBox.setVisibility(View.GONE); + + ImageView batteryIcon = (ImageView) view.findViewById(R.id.device_battery_status); + + short batteryLevel = device.getBatteryLevel(); + if (batteryLevel != GBDevice.BATTERY_UNKNOWN) { + batteryStatusBox.setVisibility(View.VISIBLE); + batteryStatusLabel.setText(device.getBatteryLevel() + "%"); + BatteryState batteryState = device.getBatteryState(); + if (BatteryState.BATTERY_LOW.equals(batteryState)) { + //batteryIcon.setImageTintMode(olor.RED); + } else { + batteryStatusLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.secondarytext)); + + if (BatteryState.BATTERY_CHARGING.equals(batteryState) || + BatteryState.BATTERY_CHARGING_FULL.equals(batteryState)) { + batteryStatusLabel.append(" CHG"); + } + } + } + + + //fetch activity data + ImageView fetchActivityData = (ImageView) view.findViewById(R.id.device_action_fetch_activity); + LinearLayout fetchActivityDataBox = (LinearLayout) view.findViewById(R.id.device_action_fetch_activity_box); + + fetchActivityDataBox.setVisibility((device.isConnected() && coordinator.supportsActivityDataFetching()) ? View.VISIBLE : View.GONE); + fetchActivityData.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + GBApplication.deviceService().onFetchActivityData(); + } + } + ); + + + //take screenshot + ImageView takeScreenshotView = (ImageView) view.findViewById(R.id.device_action_take_screenshot); + takeScreenshotView.setVisibility((device.isConnected() && coordinator.supportsScreenshots()) ? View.VISIBLE : View.GONE); + takeScreenshotView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + GBApplication.deviceService().onScreenshotReq(); + } + } + ); + + //set alarms + ImageView setAlarmsView = (ImageView) view.findViewById(R.id.device_action_set_alarms); + setAlarmsView.setVisibility(coordinator.supportsAlarmConfiguration() ? View.VISIBLE : View.GONE); + setAlarmsView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent; + startIntent = new Intent(context, ConfigureAlarms.class); + context.startActivity(startIntent); + } + } + ); + + //show graphs + ImageView showActivityGraphs = (ImageView) view.findViewById(R.id.device_action_show_activity_graphs); + showActivityGraphs.setVisibility(coordinator.supportsActivityTracking() ? View.VISIBLE : View.GONE); + showActivityGraphs.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent; + startIntent = new Intent(context, ChartsActivity.class); + startIntent.putExtra(GBDevice.EXTRA_DEVICE, device); + context.startActivity(startIntent); } + } + ); + + //Info icon is last in the row + ImageView deviceInfoView = (ImageView) view.findViewById(R.id.device_info_image); + final RelativeLayout deviceInfoBox = (RelativeLayout) view.findViewById(R.id.device_item_infos_box); + final ListView deviceInfoList = (ListView) view.findViewById(R.id.device_item_infos); + //TODO: can we spare all these additional layouts? find out more. + ItemWithDetailsAdapter infoAdapter = new ItemWithDetailsAdapter(context, device.getDeviceInfos()); + infoAdapter.setHorizontalAlignment(true); + deviceInfoList.setAdapter(infoAdapter); + boolean showInfoIcon = device.hasDeviceInfos() && !device.isBusy(); + deviceInfoView.setVisibility(showInfoIcon ? View.VISIBLE : View.GONE); + deviceInfoView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (deviceInfoBox.getVisibility() == View.VISIBLE) { + deviceInfoBox.setVisibility(View.GONE); + } else { + ArrayAdapter adapter = (ArrayAdapter) deviceInfoList.getAdapter(); + adapter.clear(); + List infos = device.getDeviceInfos(); + Collections.sort(infos); + adapter.addAll(infos); + justifyListViewHeightBasedOnChildren(deviceInfoList); + deviceInfoBox.setVisibility(View.VISIBLE); + deviceInfoBox.setFocusable(false); + } + } + }); + + //remove device, hidden under details + ImageView removeDevice = (ImageView) view.findViewById(R.id.device_action_remove); + removeDevice.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //TODO: the logic is bolted to controlcenter, but I don't think it belongs here + } + } + ); + + + switch (device.getType()) { + case PEBBLE: + if (device.isConnected()) { + deviceImageView.setImageResource(R.drawable.ic_device_pebble); + } else { + deviceImageView.setImageResource(R.drawable.ic_device_pebble_disabled); + } + break; + case MIBAND: + case MIBAND2: + if (device.isConnected()) { + deviceImageView.setImageResource(R.drawable.ic_device_miband); + } else { + deviceImageView.setImageResource(R.drawable.ic_device_miband_disabled); + } + break; + case VIBRATISSIMO: + if (device.isConnected()) { + deviceImageView.setImageResource(R.drawable.ic_device_lovetoy); + } else { + deviceImageView.setImageResource(R.drawable.ic_device_lovetoy_disabled); + } + break; + default: + if (device.isConnected()) { + deviceImageView.setImageResource(R.drawable.ic_launcher); + } else { + deviceImageView.setImageResource(R.drawable.ic_device_default_disabled); + } + } + + return view; + } + + public void justifyListViewHeightBasedOnChildren(ListView listView) { + ArrayAdapter adapter = (ArrayAdapter) listView.getAdapter(); + + if (adapter == null) { + return; + } + ViewGroup vg = listView; + int totalHeight = 0; + for (int i = 0; i < adapter.getCount(); i++) { + View listItem = adapter.getView(i, null, vg); + listItem.measure(0, 0); + totalHeight += listItem.getMeasuredHeight(); + } + + ViewGroup.LayoutParams par = listView.getLayoutParams(); + par.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1)); + listView.setLayoutParams(par); + listView.requestLayout(); + } + + private String getUniqueDeviceName(GBDevice device) { + String deviceName = device.getName(); + if (!isUniqueDeviceName(device, deviceName)) { + if (device.getModel() != null) { + deviceName = deviceName + " " + device.getModel(); + if (!isUniqueDeviceName(device, deviceName)) { + deviceName = deviceName + " " + device.getShortAddress(); + } + } else { + deviceName = deviceName + " " + device.getShortAddress(); + } + } + return deviceName; + } + + private boolean isUniqueDeviceName(GBDevice device, String deviceName) { + for (int i = 0; i < getCount(); i++) { + GBDevice item = getItem(i); + if (item == device) { + continue; + } + if (deviceName.equals(item.getName())) { + return false; + } + } + return true; + } + +} diff --git a/app/src/main/res/drawable/ic_action_fetch_activity_data.xml b/app/src/main/res/drawable/ic_action_fetch_activity_data.xml new file mode 100644 index 000000000..8229a9a64 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_fetch_activity_data.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_activity_graphs.xml b/app/src/main/res/drawable/ic_activity_graphs.xml new file mode 100644 index 000000000..5048a587e --- /dev/null +++ b/app/src/main/res/drawable/ic_activity_graphs.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_battery.xml b/app/src/main/res/drawable/ic_battery.xml new file mode 100644 index 000000000..b0e57fe2c --- /dev/null +++ b/app/src/main/res/drawable/ic_battery.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_database_management.xml b/app/src/main/res/drawable/ic_database_management.xml new file mode 100644 index 000000000..6a990aff7 --- /dev/null +++ b/app/src/main/res/drawable/ic_database_management.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_debug.xml b/app/src/main/res/drawable/ic_debug.xml new file mode 100644 index 000000000..c98c256a7 --- /dev/null +++ b/app/src/main/res/drawable/ic_debug.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_device_set_alarms.xml b/app/src/main/res/drawable/ic_device_set_alarms.xml new file mode 100644 index 000000000..5f742d33a --- /dev/null +++ b/app/src/main/res/drawable/ic_device_set_alarms.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_quit.xml b/app/src/main/res/drawable/ic_quit.xml new file mode 100644 index 000000000..26272ab8d --- /dev/null +++ b/app/src/main/res/drawable/ic_quit.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_remove_device.xml b/app/src/main/res/drawable/ic_remove_device.xml new file mode 100644 index 000000000..39e64d698 --- /dev/null +++ b/app/src/main/res/drawable/ic_remove_device.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_screenshot.xml b/app/src/main/res/drawable/ic_screenshot.xml new file mode 100644 index 000000000..9e2340bd2 --- /dev/null +++ b/app/src/main/res/drawable/ic_screenshot.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 000000000..ace746c40 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 000000000..d084cbdf1 --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_controlcenterv2.xml b/app/src/main/res/layout/activity_controlcenterv2.xml new file mode 100644 index 000000000..8114dbf5c --- /dev/null +++ b/app/src/main/res/layout/activity_controlcenterv2.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/app/src/main/res/layout/activity_controlcenterv2_app_bar_main.xml b/app/src/main/res/layout/activity_controlcenterv2_app_bar_main.xml new file mode 100644 index 000000000..f779c848e --- /dev/null +++ b/app/src/main/res/layout/activity_controlcenterv2_app_bar_main.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_controlcenterv2_content_main.xml b/app/src/main/res/layout/activity_controlcenterv2_content_main.xml new file mode 100644 index 000000000..ea7abee29 --- /dev/null +++ b/app/src/main/res/layout/activity_controlcenterv2_content_main.xml @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/device_itemv2.xml b/app/src/main/res/layout/device_itemv2.xml new file mode 100644 index 000000000..07a610afa --- /dev/null +++ b/app/src/main/res/layout/device_itemv2.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml new file mode 100644 index 000000000..f052cde62 --- /dev/null +++ b/app/src/main/res/layout/nav_header_main.xml @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/app/src/main/res/menu/activity_controlcenterv2_main_drawer.xml b/app/src/main/res/menu/activity_controlcenterv2_main_drawer.xml new file mode 100644 index 000000000..1806e762a --- /dev/null +++ b/app/src/main/res/menu/activity_controlcenterv2_main_drawer.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml new file mode 100644 index 000000000..faae1f18b --- /dev/null +++ b/app/src/main/res/values-v21/styles.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index fb6e23509..8cc2ce917 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -8,4 +8,8 @@ Refer to App Widget Documentation for margin information http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout --> 8dp + + 16dp + 160dp + 16dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 689b5b6d1..4f1adaffb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,8 @@ Delete Device Delete %1$s This will delete the device and all associated data! + Open navigation drawer + Close navigation drawer Debug diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 5d6ea28d8..0924ffa5c 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -26,4 +26,13 @@ @color/chart_activity_dark --> + + + +