1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-24 05:50:47 +02:00
Gadgetbridge/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesFilter.java
vanous 874b510784 Add more features to ActivitySummariesFilter
Add possibility to pick individual SportsItem items into filtered view
Add quick time range selector
add deviceFilter for devices that supportsActivityTracks
add baseAltitude
add average speed, calculated from from distance/active time
make Activity Details layout scrollable
2020-09-05 20:22:04 +02:00

454 lines
18 KiB
Java

/* Copyright (C) 2019-2020 vanous
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.activities;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
public class ActivitySummariesFilter extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(ActivitySummariesActivity.class);
private static final String DATE_FILTER_FROM = "dateFromFilter";
private static final String DATE_FILTER_TO = "dateToFilter";
public static long ALL_DEVICES = 999;
int activityFilter = 0;
long dateFromFilter = 0;
long dateToFilter = 0;
String nameContainsFilter;
HashMap<String, Integer> activityKindMap = new HashMap<>(1);
List<Long> itemsFilter;
long deviceFilter;
long initial_deviceFilter;
int BACKGROUND_COLOR;
LinkedHashMap<String, Long> allDevices;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = this.getIntent().getExtras();
activityKindMap = (HashMap<String, Integer>) bundle.getSerializable("activityKindMap");
itemsFilter = (List<Long>) bundle.getSerializable("itemsFilter");
activityFilter = bundle.getInt("activityFilter", 0);
dateFromFilter = bundle.getLong("dateFromFilter", 0);
dateToFilter = bundle.getLong("dateToFilter", 0);
initial_deviceFilter = deviceFilter = bundle.getLong("deviceFilter", 0);
nameContainsFilter = bundle.getString("nameContainsFilter");
Context appContext = this.getApplicationContext();
if (appContext instanceof GBApplication) {
setContentView(R.layout.sport_activity_filter);
}
BACKGROUND_COLOR = GBApplication.getBackgroundColor(appContext);
allDevices = getAllDevices(appContext);
//device filter spinner
final Spinner deviceFilterSpinner = findViewById(R.id.select_device);
ArrayList<String> filterDevicesArray = new ArrayList<String>(allDevices.keySet());
final ArrayAdapter<String> filterDevicesAdapter = new ArrayAdapter<String>(this,
R.layout.simple_spinner_item_themed, filterDevicesArray);
deviceFilterSpinner.setAdapter(filterDevicesAdapter);
deviceFilterSpinner.setSelection(filterDevicesAdapter.getPosition(getDeviceById(deviceFilter)));
addListenerOnSpinnerDeviceSelection();
//Kind filter spinner - assign data, set selected item...
final Spinner filterKindSpinner = findViewById(R.id.select_kind);
ArrayList<String> kindArray = new ArrayList<>(activityKindMap.keySet());
//ensure that all items is always first in the list
kindArray.remove(getString(R.string.activity_summaries_all_activities));
kindArray.add(0, getString(R.string.activity_summaries_all_activities));
ArrayAdapter<String> filterKindAdapter = new ArrayAdapter<String>(this,
R.layout.simple_spinner_item_themed, kindArray);
filterKindSpinner.setAdapter(filterKindAdapter);
filterKindSpinner.setSelection(filterKindAdapter.getPosition(getKindByValue(activityFilter)));
addListenerOnSpinnerKindSelection();
//quick date filter selection
final Spinner quick_filter_period_select = findViewById(R.id.quick_filter_period_select);
ArrayList<String> quickDateArray = new ArrayList<>(activityKindMap.keySet());
ArrayList activity_filter_quick_filter_period_items = new ArrayList(Arrays.asList(getResources().getStringArray(R.array.activity_filter_quick_filter_period_items)));
ArrayAdapter<String> filterDateAdapter = new ArrayAdapter<String>(this,
R.layout.simple_spinner_item_themed, activity_filter_quick_filter_period_items);
quick_filter_period_select.setAdapter(filterDateAdapter);
addListenerOnQuickFilterSelection();
//set current values coming from parent
update_filter_fields();
final LinearLayout filterfrom = findViewById(R.id.filterfrom);
final LinearLayout filterto = findViewById(R.id.filterto);
final EditText nameContainsFilterdata = findViewById(R.id.textViewNameData);
final Button reset_filter_button = findViewById(R.id.reset_filter_button);
final Button apply_filter_button = findViewById(R.id.apply_filter_button);
nameContainsFilterdata.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
nameContainsFilter = s.toString();
update_filter_fields();
}
});
reset_filter_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activityFilter = 0;
dateFromFilter = 0;
dateToFilter = 0;
nameContainsFilter = "";
filterKindSpinner.setSelection(0);
itemsFilter = null;
deviceFilter = initial_deviceFilter;
deviceFilterSpinner.setSelection(filterDevicesAdapter.getPosition(getDeviceById(deviceFilter)));
quick_filter_period_select.setSelection(0);
update_filter_fields();
}
});
apply_filter_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text = nameContainsFilterdata.getText().toString();
if (text != null && text.length() > 0) {
nameContainsFilter = text;
}
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putInt("activityFilter", activityFilter);
bundle.putSerializable("itemsFilter", (Serializable) itemsFilter);
bundle.putLong("dateFromFilter", dateFromFilter);
bundle.putLong("dateToFilter", dateToFilter);
bundle.putLong("deviceFilter", deviceFilter);
bundle.putString("nameContainsFilter", nameContainsFilter);
intent.putExtras(bundle);
setResult(1, intent);
finish();
}
});
filterfrom.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getDate(DATE_FILTER_FROM, dateFromFilter);
quick_filter_period_select.setSelection(0);
}
});
filterto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getDate(DATE_FILTER_TO, dateToFilter);
quick_filter_period_select.setSelection(0);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// back button
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void addListenerOnSpinnerDeviceSelection() {
Spinner spinner = findViewById(R.id.select_device);
spinner.setOnItemSelectedListener(new CustomOnDeviceSelectedListener());
}
public void addListenerOnSpinnerKindSelection() {
Spinner spinner = findViewById(R.id.select_kind);
spinner.setOnItemSelectedListener(new CustomOnKindSelectedListener());
}
public void addListenerOnQuickFilterSelection() {
Spinner spinner = findViewById(R.id.quick_filter_period_select);
spinner.setOnItemSelectedListener(new CustomQuickFilterSelectionListener());
}
public void update_filter_fields() {
TextView filterDateFromDataView = findViewById(R.id.textViewFromData);
TextView filterDateToDataView = findViewById(R.id.textViewToData);
Button reset_filter_button = findViewById(R.id.reset_filter_button);
TextView textViewItemsData = findViewById(R.id.textViewItemsData);
final EditText nameContainsFilterdata = findViewById(R.id.textViewNameData);
if (dateFromFilter > 0) {
filterDateFromDataView.setText(DateTimeUtils.formatDate(new Date(dateFromFilter)));
} else {
filterDateFromDataView.setText("");
}
if (dateToFilter > 0) {
filterDateToDataView.setText(DateTimeUtils.formatDate(new Date(dateToFilter)));
} else {
filterDateToDataView.setText("");
}
if (dateToFilter < dateFromFilter && dateToFilter > 0) {
filterDateFromDataView.setBackgroundColor(Color.RED);
filterDateToDataView.setBackgroundColor(Color.RED);
} else {
filterDateFromDataView.setBackgroundColor(BACKGROUND_COLOR);
filterDateToDataView.setBackgroundColor(BACKGROUND_COLOR);
}
if (itemsFilter != null) {
textViewItemsData.setText(String.format("%s", itemsFilter.size()));
} else {
textViewItemsData.setText("0");
}
if (nameContainsFilter != null && !nameContainsFilter.equals(nameContainsFilterdata.getText().toString())) {
nameContainsFilterdata.setText(nameContainsFilter);
}
if (dateToFilter != 0 || dateFromFilter != 0 || activityFilter != 0 || nameContainsFilterdata.length() > 0 || itemsFilter != null || deviceFilter != initial_deviceFilter) {
reset_filter_button.getBackground().clearColorFilter();
} else {
reset_filter_button.getBackground().setColorFilter(new LightingColorFilter(0x0, 0x00888888));
}
}
public void getDate(final String filter, long currentDatemillis) {
Calendar currentDate = Calendar.getInstance();
if (currentDatemillis > 0) {
currentDate = GregorianCalendar.getInstance();
currentDate.setTimeInMillis(currentDatemillis);
}
new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
Calendar date = Calendar.getInstance();
if (filter.equals(DATE_FILTER_FROM)) {
date.set(year, monthOfYear, dayOfMonth, 0, 0);
dateFromFilter = date.getTimeInMillis();
} else {
date.set(year, monthOfYear, dayOfMonth, 23, 59);
dateToFilter = date.getTimeInMillis();
}
update_filter_fields();
}
}, currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DATE)).show();
}
private void setTimePeriodFilter(String selection) {
Calendar date = Calendar.getInstance();
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
long firstdate;
long lastdate;
switch (selection) {
case "thisweek":
date.set(Calendar.DAY_OF_WEEK, date.getFirstDayOfWeek());
firstdate = date.getTimeInMillis();
lastdate = Calendar.getInstance().getTimeInMillis();
break;
case "thismonth":
date.set(Calendar.DAY_OF_MONTH, 1);
firstdate = date.getTimeInMillis();
lastdate = Calendar.getInstance().getTimeInMillis();
break;
case "lastweek":
int i = date.get(Calendar.DAY_OF_WEEK) - date.getFirstDayOfWeek();
date.add(Calendar.DATE, -i - 7);
firstdate = date.getTimeInMillis();
date.add(Calendar.DATE, 6);
lastdate = date.getTimeInMillis();
break;
case "lastmonth":
date.set(Calendar.DATE, 1);
date.add(Calendar.DAY_OF_MONTH, -1);
lastdate = date.getTimeInMillis();
date.set(Calendar.DATE, 1);
firstdate = date.getTimeInMillis();
break;
case "7days":
date.add(Calendar.DATE, -7);
firstdate = date.getTimeInMillis();
lastdate = Calendar.getInstance().getTimeInMillis();
break;
case "30days":
date.add(Calendar.DATE, -30);
firstdate = date.getTimeInMillis();
lastdate = Calendar.getInstance().getTimeInMillis();
break;
default:
return;
}
dateFromFilter = firstdate;
dateToFilter = lastdate;
update_filter_fields();
}
private LinkedHashMap getAllDevices(Context appContext) {
DaoSession daoSession;
GBApplication gbApp = (GBApplication) appContext;
LinkedHashMap<String, Long> newMap = new LinkedHashMap<>(1);
List<? extends GBDevice> devices = gbApp.getDeviceManager().getDevices();
newMap.put(getString(R.string.activity_summaries_all_devices), ALL_DEVICES);
try (DBHandler handler = GBApplication.acquireDB()) {
daoSession = handler.getDaoSession();
for (GBDevice device : devices) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
Device dbDevice = DBHelper.findDevice(device, daoSession);
if (dbDevice != null && coordinator != null
&& coordinator.supportsActivityTracks()
&& !newMap.containsKey(device.getAliasOrName())) {
newMap.put(device.getAliasOrName(), dbDevice.getId());
}
}
} catch (Exception e) {
LOG.debug("Error getting list of all devices: " + e);
}
return newMap;
}
public String getKindByValue(Integer value) {
for (Map.Entry<String, Integer> entry : activityKindMap.entrySet()) {
if (Objects.equals(value, entry.getValue())) {
return entry.getKey();
}
}
return null;
}
public String getDeviceById(long id) {
for (Map.Entry<String, Long> device : allDevices.entrySet()) {
if (Objects.equals(id, device.getValue())) {
return device.getKey();
}
}
return null;
}
public class CustomOnKindSelectedListener implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
activityFilter = activityKindMap.get(parent.getItemAtPosition(pos));
update_filter_fields();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
public class CustomOnDeviceSelectedListener implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
deviceFilter = allDevices.get(parent.getItemAtPosition(pos));
update_filter_fields();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
public class CustomQuickFilterSelectionListener implements AdapterView.OnItemSelectedListener {
ArrayList activity_filter_quick_filter_period_values = new ArrayList(Arrays.asList(getResources().getStringArray(R.array.activity_filter_quick_filter_period_values)));
String selection;
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
selection = activity_filter_quick_filter_period_values.get(pos).toString();
setTimePeriodFilter(selection);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
}