mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-02-18 05:17:08 +01:00
Merge remote-tracking branch 'origin/master' into low_battery_notification
Conflicts: app/src/main/res/values/strings.xml
This commit is contained in:
commit
3356a4b066
@ -0,0 +1,51 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractFragmentPagerAdapter extends FragmentStatePagerAdapter {
|
||||
private Set<AbstractGBFragment> fragments = new HashSet<>();
|
||||
private Object primaryFragment;
|
||||
|
||||
public AbstractFragmentPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
Object fragment = super.instantiateItem(container, position);
|
||||
if (fragment instanceof AbstractGBFragment) {
|
||||
fragments.add((AbstractGBFragment) fragment);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
super.destroyItem(container, position, object);
|
||||
fragments.remove(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
super.setPrimaryItem(container, position, object);
|
||||
if (object != primaryFragment) {
|
||||
primaryFragment = object;
|
||||
setCurrentFragment(primaryFragment);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCurrentFragment(Object newCurrentFragment) {
|
||||
for (AbstractGBFragment frag : fragments) {
|
||||
if (frag != newCurrentFragment) {
|
||||
frag.onMadeInvisibleInActivity();
|
||||
} else {
|
||||
frag.onMadeVisibleInActivityInternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* Abstract base class for fragments. Provides hooks that are called when
|
||||
* the fragment is made visible and invisible in the activity. also allows
|
||||
* the fragment to define the title to be shown in the activity.
|
||||
* @see AbstractGBFragmentActivity
|
||||
*/
|
||||
public abstract class AbstractGBFragment extends Fragment {
|
||||
private boolean mVisibleInactivity;
|
||||
|
||||
/**
|
||||
* Called when this fragment has been fully scrolled into the activity.
|
||||
*
|
||||
* @see #isVisibleInActivity()
|
||||
* @see #onMadeInvisibleInActivity()
|
||||
*/
|
||||
protected void onMadeVisibleInActivity() {
|
||||
updateActivityTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this fragment has been scrolled out of the activity.
|
||||
* @see #isVisibleInActivity()
|
||||
* @see #onMadeVisibleInActivity()
|
||||
*/
|
||||
protected void onMadeInvisibleInActivity() {
|
||||
mVisibleInactivity = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this fragment is currently visible in the hosting
|
||||
* activity, not taking into account whether the screen is enabled at all.
|
||||
*/
|
||||
public boolean isVisibleInActivity() {
|
||||
return mVisibleInactivity;
|
||||
}
|
||||
|
||||
protected void updateActivityTitle() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
|
||||
if (getTitle() != null) {
|
||||
activity.setTitle(getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract CharSequence getTitle();
|
||||
|
||||
/**
|
||||
* Internal
|
||||
* @hide
|
||||
*/
|
||||
public void onMadeVisibleInActivityInternal() {
|
||||
mVisibleInactivity = true;
|
||||
if (isVisible()) {
|
||||
onMadeVisibleInActivity();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* A base activity that supports paging through fragments by swiping.
|
||||
* Subclasses will have to add a ViewPager to their layout and add something
|
||||
* like this to hook it to the fragments:
|
||||
*
|
||||
* <pre>
|
||||
* // Set up the ViewPager with the sections adapter.
|
||||
* ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
|
||||
* viewPager.setAdapter(getPagerAdapter());
|
||||
* </pre>
|
||||
*
|
||||
* @see AbstractGBFragment
|
||||
*/
|
||||
public abstract class AbstractGBFragmentActivity extends FragmentActivity {
|
||||
/**
|
||||
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
||||
* fragments for each of the sections. We use a
|
||||
* {@link FragmentPagerAdapter} derivative, which will keep every
|
||||
* loaded fragment in memory. If this becomes too memory intensive, it
|
||||
* may be best to switch to a
|
||||
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
|
||||
*/
|
||||
private AbstractFragmentPagerAdapter mSectionsPagerAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Create the adapter that will return a fragment for each of the three
|
||||
// primary sections of the activity.
|
||||
mSectionsPagerAdapter = createFragmentPagerAdapter(getSupportFragmentManager());
|
||||
}
|
||||
|
||||
public AbstractFragmentPagerAdapter getPagerAdapter() {
|
||||
return mSectionsPagerAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PagerAdapter that will create the fragments to be used with this
|
||||
* activity. The fragments should typically extend AbstractGBFragment
|
||||
* @param fragmentManager
|
||||
* @return
|
||||
*/
|
||||
protected abstract AbstractFragmentPagerAdapter createFragmentPagerAdapter(FragmentManager fragmentManager);
|
||||
}
|
@ -170,8 +170,10 @@ public class ControlCenter extends Activity {
|
||||
menu.removeItem(R.id.controlcenter_take_screenshot);
|
||||
}
|
||||
|
||||
if (!selectedDevice.isConnected()) {
|
||||
if (selectedDevice.getState() == GBDevice.State.NOT_CONNECTED) {
|
||||
menu.removeItem(R.id.controlcenter_disconnect);
|
||||
}
|
||||
if (!selectedDevice.isInitialized()) {
|
||||
menu.removeItem(R.id.controlcenter_find_device);
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,8 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.github.mikephil.charting.charts.BarLineChartBase;
|
||||
import com.github.mikephil.charting.charts.Chart;
|
||||
@ -33,6 +29,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
@ -43,8 +40,28 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
|
||||
public abstract class AbstractChartFragment extends Fragment {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ActivitySleepChartFragment.class);
|
||||
/**
|
||||
* A base class fragment to be used with ChartsActivity. The fragment can supply
|
||||
* a title to be displayed in the activity by returning non-null in #getTitle()
|
||||
* Broadcast events can be received by overriding #onReceive(Context,Intent).
|
||||
* The chart can be refreshed by calling #refresh()
|
||||
* Implement refreshInBackground(DBHandler, GBDevice) to fetch the samples from the DB,
|
||||
* and add the samples to the chart. The actual rendering, which must be performed in the UI
|
||||
* thread, must be done in #renderCharts().
|
||||
* Access functionality of the hosting activity with #getHost()
|
||||
*
|
||||
* The hosting ChartsHost activity provides a section for displaying a date or date range
|
||||
* being the basis for the chart, as well as two buttons for moving backwards and forward
|
||||
* in time. The date is held by the activity, so that it can be shared by multiple chart
|
||||
* fragments. It is still the responsibility of the (currently visible) chart fragment
|
||||
* to set the desired date in the ChartsActivity via #setDateRange(Date,Date).
|
||||
* The default implementations #handleDatePrev(Date,Date) and #handleDateNext(Date,Date)
|
||||
* shift the date by one day.
|
||||
*/
|
||||
public abstract class AbstractChartFragment extends AbstractGBFragment {
|
||||
protected int ANIM_TIME = 350;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractChartFragment.class);
|
||||
|
||||
private final Set<String> mIntentFilterActions;
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@ -53,6 +70,13 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
AbstractChartFragment.this.onReceive(context, intent);
|
||||
}
|
||||
};
|
||||
private boolean mChartDirty = true;
|
||||
|
||||
public boolean isChartDirty() {
|
||||
return mChartDirty;
|
||||
}
|
||||
|
||||
public abstract String getTitle();
|
||||
|
||||
protected static final class ActivityConfig {
|
||||
public final int type;
|
||||
@ -66,9 +90,6 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private Date mStartDate;
|
||||
private Date mEndDate;
|
||||
|
||||
protected ActivityConfig akActivity = new ActivityConfig(ActivityKind.TYPE_ACTIVITY, "Activity", Color.rgb(89, 178, 44));
|
||||
protected ActivityConfig akLightSleep = new ActivityConfig(ActivityKind.TYPE_LIGHT_SLEEP, "Light Sleep", Color.rgb(182, 191, 255));
|
||||
protected ActivityConfig akDeepSleep = new ActivityConfig(ActivityKind.TYPE_DEEP_SLEEP, "Deep Sleep", Color.rgb(76, 90, 255));
|
||||
@ -92,8 +113,6 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
initDates();
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
for (String action : mIntentFilterActions) {
|
||||
filter.addAction(action);
|
||||
@ -101,24 +120,34 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mReceiver, filter);
|
||||
}
|
||||
|
||||
private void setStartDate(Date date) {
|
||||
getHost().setStartDate(date);
|
||||
}
|
||||
|
||||
private void setEndDate(Date date) {
|
||||
getHost().setEndDate(date);
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return getHost().getStartDate();
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return getHost().getEndDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this fragment has been fully scrolled into the activity.
|
||||
*
|
||||
* @see #isVisibleInActivity()
|
||||
* @see #onMadeInvisibleInActivity()
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
updateDateInfo(mStartDate, mEndDate);
|
||||
return view;
|
||||
}
|
||||
|
||||
public void setStartDate(Date date) {
|
||||
mStartDate = date;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
mEndDate = endDate;
|
||||
}
|
||||
|
||||
protected void initDates() {
|
||||
setEndDate(new Date());
|
||||
setStartDate(DateTimeUtils.shiftByDays(mEndDate, -1));
|
||||
protected void onMadeVisibleInActivity() {
|
||||
super.onMadeVisibleInActivity();
|
||||
if (isChartDirty()) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -132,26 +161,62 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
if (ChartsHost.REFRESH.equals(action)) {
|
||||
refresh();
|
||||
} else if (ChartsHost.DATE_NEXT.equals(action)) {
|
||||
handleDateNext(mStartDate, mEndDate);
|
||||
handleDateNext(getStartDate(), getEndDate());
|
||||
} else if (ChartsHost.DATE_PREV.equals(action)) {
|
||||
handleDatePrev(mStartDate, mEndDate);
|
||||
handleDatePrev(getStartDate(), getEndDate());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation shifts the dates by one day, if visible
|
||||
* and calls #refreshIfVisible().
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
*/
|
||||
protected void handleDatePrev(Date startDate, Date endDate) {
|
||||
shiftDates(startDate, endDate, -1);
|
||||
if (isVisibleInActivity()) {
|
||||
if (!shiftDates(startDate, endDate, -1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
refreshIfVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation shifts the dates by one day, if visible
|
||||
* and calls #refreshIfVisible().
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
*/
|
||||
protected void handleDateNext(Date startDate, Date endDate) {
|
||||
shiftDates(startDate, endDate, +1);
|
||||
if (isVisibleInActivity()) {
|
||||
if (!shiftDates(startDate, endDate, +1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
refreshIfVisible();
|
||||
}
|
||||
|
||||
protected void shiftDates(Date startDate, Date endDate, int offset) {
|
||||
protected void refreshIfVisible() {
|
||||
if (isVisibleInActivity()) {
|
||||
refresh();
|
||||
} else {
|
||||
mChartDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts the given dates by offset days. offset may be positive or negative.
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @param offset a positive or negative number of days to shift the dates
|
||||
* @return true if the shift was successful and false otherwise
|
||||
*/
|
||||
protected boolean shiftDates(Date startDate, Date endDate, int offset) {
|
||||
Date newStart = DateTimeUtils.shiftByDays(startDate, offset);
|
||||
Date newEnd = DateTimeUtils.shiftByDays(endDate, offset);
|
||||
|
||||
setDateRange(newStart, newEnd);
|
||||
refresh();
|
||||
return setDateRange(newStart, newEnd);
|
||||
}
|
||||
|
||||
protected Integer getColorFor(int activityKind) {
|
||||
@ -250,7 +315,11 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
* #renderCharts
|
||||
*/
|
||||
protected void refresh() {
|
||||
createRefreshTask("Visualizing data", getActivity()).execute();
|
||||
if (getHost().getDevice() != null) {
|
||||
mChartDirty = false;
|
||||
updateDateInfo(getStartDate(), getEndDate());
|
||||
createRefreshTask("Visualizing data", getActivity()).execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,19 +327,15 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
* the charts. This will be called from a background task, so there must not be
|
||||
* any UI access. #renderCharts will be automatically called after this method.
|
||||
*/
|
||||
protected abstract void refreshInBackground(DBHandler db);
|
||||
protected abstract void refreshInBackground(DBHandler db, GBDevice device);
|
||||
|
||||
/**
|
||||
* Performs a re-rendering of the chart.
|
||||
* Triggers the actual (re-) rendering of the chart.
|
||||
* Always called from the UI thread.
|
||||
*/
|
||||
protected abstract void renderCharts();
|
||||
|
||||
protected void refresh(GBDevice gbDevice, BarLineChartBase chart, List<ActivitySample> samples) {
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar cal = GregorianCalendar.getInstance();
|
||||
cal.clear();
|
||||
Date date;
|
||||
@ -380,6 +445,14 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this to supply the samples to be displayed.
|
||||
* @param db
|
||||
* @param device
|
||||
* @param tsFrom
|
||||
* @param tsTo
|
||||
* @return
|
||||
*/
|
||||
protected abstract List<ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo);
|
||||
|
||||
protected abstract void setupLegend(Chart chart);
|
||||
@ -450,7 +523,7 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
protected void doInBackground(DBHandler db) {
|
||||
refreshInBackground(db);
|
||||
refreshInBackground(db, getHost().getDevice());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -465,13 +538,23 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
public void setDateRange(Date from, Date to) {
|
||||
/**
|
||||
* Returns true if the date was successfully shifted, and false if the shift
|
||||
* was ignored, e.g. when the to-value is in the future.
|
||||
* @param from
|
||||
* @param to
|
||||
*/
|
||||
public boolean setDateRange(Date from, Date to) {
|
||||
if (from.compareTo(to) > 0) {
|
||||
throw new IllegalArgumentException("Bad date range: " +from + ".." + to);
|
||||
}
|
||||
mStartDate = from;
|
||||
mEndDate = to;
|
||||
updateDateInfo(mStartDate, mEndDate);
|
||||
Date now = new Date();
|
||||
if (to.after(now)) {
|
||||
return false;
|
||||
}
|
||||
setStartDate(from);
|
||||
setEndDate(to);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updateDateInfo(Date from, Date to) {
|
||||
@ -487,11 +570,11 @@ public abstract class AbstractChartFragment extends Fragment {
|
||||
}
|
||||
|
||||
private int getTSEnd() {
|
||||
return toTimestamp(mEndDate);
|
||||
return toTimestamp(getEndDate());
|
||||
}
|
||||
|
||||
private int getTSStart() {
|
||||
return toTimestamp(mStartDate);
|
||||
return toTimestamp(getStartDate());
|
||||
}
|
||||
|
||||
private int toTimestamp(Date date) {
|
||||
|
@ -34,19 +34,12 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
|
||||
private int mSmartAlarmTo = -1;
|
||||
private int mTimestampFrom = -1;
|
||||
private int mSmartAlarmGoneOff = -1;
|
||||
private GBDevice mGBDevice = null;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_charts, container, false);
|
||||
|
||||
Bundle extras = getActivity().getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE);
|
||||
}
|
||||
|
||||
|
||||
mChart = (BarLineChartBase) rootView.findViewById(R.id.activitysleepchart);
|
||||
|
||||
setupChart();
|
||||
@ -54,6 +47,11 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return getString(R.string.activity_sleepchart_activity_and_sleep);
|
||||
}
|
||||
|
||||
private void setupChart() {
|
||||
mChart.setBackgroundColor(BACKGROUND_COLOR);
|
||||
mChart.setDescriptionColor(DESCRIPTION_COLOR);
|
||||
@ -85,6 +83,7 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
|
||||
yAxisRight.setDrawTopYLabelEntry(false);
|
||||
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
||||
|
||||
// refresh immediately instead of use refreshIfVisible(), for perceived performance
|
||||
refresh();
|
||||
}
|
||||
|
||||
@ -104,15 +103,15 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refreshInBackground(DBHandler db) {
|
||||
List<ActivitySample> samples = getSamples(db, mGBDevice);
|
||||
refresh(mGBDevice, mChart, samples);
|
||||
protected void refreshInBackground(DBHandler db, GBDevice device) {
|
||||
List<ActivitySample> samples = getSamples(db, device);
|
||||
refresh(device, mChart, samples);
|
||||
|
||||
mChart.getLegend().setTextColor(LEGEND_TEXT_COLOR);
|
||||
}
|
||||
|
||||
protected void renderCharts() {
|
||||
mChart.animateX(500, Easing.EasingOption.EaseInOutQuart);
|
||||
mChart.animateX(ANIM_TIME, Easing.EasingOption.EaseInOutQuart);
|
||||
}
|
||||
|
||||
protected void setupLegend(Chart chart) {
|
||||
|
@ -6,11 +6,10 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@ -22,37 +21,29 @@ import android.widget.TextView;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Date;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractFragmentPagerAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragmentActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
|
||||
public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
public class ChartsActivity extends AbstractGBFragmentActivity implements ChartsHost {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ChartsActivity.class);
|
||||
|
||||
/**
|
||||
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
||||
* fragments for each of the sections. We use a
|
||||
* {@link FragmentPagerAdapter} derivative, which will keep every
|
||||
* loaded fragment in memory. If this becomes too memory intensive, it
|
||||
* may be best to switch to a
|
||||
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
|
||||
*/
|
||||
private SectionsPagerAdapter mSectionsPagerAdapter;
|
||||
|
||||
/**
|
||||
* The {@link ViewPager} that will host the section contents.
|
||||
*/
|
||||
private ViewPager mViewPager;
|
||||
|
||||
private ProgressBar mProgressBar;
|
||||
private Button mPrevButton;
|
||||
private Button mNextButton;
|
||||
private TextView mDateControl;
|
||||
|
||||
private Date mStartDate;
|
||||
private Date mEndDate;
|
||||
|
||||
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@ -61,8 +52,6 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
case ControlCenter.ACTION_QUIT:
|
||||
finish();
|
||||
break;
|
||||
case ControlCenter.ACTION_REFRESH_DEVICELIST:
|
||||
break;
|
||||
case GBDevice.ACTION_DEVICE_CHANGED:
|
||||
GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
|
||||
refreshBusyState(dev);
|
||||
@ -70,6 +59,7 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
}
|
||||
}
|
||||
};
|
||||
private GBDevice mGBDevice;
|
||||
|
||||
private void refreshBusyState(GBDevice dev) {
|
||||
if (dev.isBusy()) {
|
||||
@ -88,20 +78,23 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_charts);
|
||||
|
||||
initDates();
|
||||
|
||||
IntentFilter filterLocal = new IntentFilter();
|
||||
filterLocal.addAction(ControlCenter.ACTION_QUIT);
|
||||
filterLocal.addAction(ControlCenter.ACTION_REFRESH_DEVICELIST);
|
||||
filterLocal.addAction(GBDevice.ACTION_DEVICE_CHANGED);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
|
||||
|
||||
|
||||
// Create the adapter that will return a fragment for each of the three
|
||||
// primary sections of the activity.
|
||||
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Must provide a device when invoking this activity");
|
||||
}
|
||||
|
||||
// Set up the ViewPager with the sections adapter.
|
||||
mViewPager = (ViewPager) findViewById(R.id.pager);
|
||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
|
||||
viewPager.setAdapter(getPagerAdapter());
|
||||
|
||||
mProgressBar = (ProgressBar) findViewById(R.id.charts_progress);
|
||||
mPrevButton = (Button) findViewById(R.id.charts_previous);
|
||||
@ -122,6 +115,36 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
mDateControl = (TextView) findViewById(R.id.charts_text_date);
|
||||
}
|
||||
|
||||
protected void initDates() {
|
||||
setEndDate(new Date());
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDevice getDevice() {
|
||||
return mGBDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartDate(Date startDate) {
|
||||
mStartDate = startDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEndDate(Date endDate) {
|
||||
mEndDate = endDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return mStartDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return mEndDate;
|
||||
}
|
||||
|
||||
private void handleNextButtonClicked() {
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DATE_NEXT));
|
||||
}
|
||||
@ -161,11 +184,16 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
mDateControl.setText(dateInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFragmentPagerAdapter createFragmentPagerAdapter(FragmentManager fragmentManager) {
|
||||
return new SectionsPagerAdapter(fragmentManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link FragmentStatePagerAdapter} that returns a fragment corresponding to
|
||||
* one of the sections/tabs/pages.
|
||||
*/
|
||||
public static class SectionsPagerAdapter extends FragmentStatePagerAdapter {
|
||||
public static class SectionsPagerAdapter extends AbstractFragmentPagerAdapter {
|
||||
|
||||
public SectionsPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
@ -191,19 +219,5 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
|
||||
// Show 3 total pages.
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
Locale l = Locale.getDefault();
|
||||
switch (position) {
|
||||
case 0:
|
||||
return "Today".toUpperCase(l);
|
||||
case 1:
|
||||
return "Week".toUpperCase(l);
|
||||
case 2:
|
||||
return "Month".toUpperCase(l);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,20 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
public interface ChartsHost {
|
||||
public static final String DATE_PREV = ChartsActivity.class.getName().concat(".date_prev");
|
||||
public static final String DATE_NEXT = ChartsActivity.class.getName().concat(".date_next");
|
||||
public static final String REFRESH = ChartsActivity.class.getName().concat(".refresh");
|
||||
import java.util.Date;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public interface ChartsHost {
|
||||
static final String DATE_PREV = ChartsActivity.class.getName().concat(".date_prev");
|
||||
static final String DATE_NEXT = ChartsActivity.class.getName().concat(".date_next");
|
||||
static final String REFRESH = ChartsActivity.class.getName().concat(".refresh");
|
||||
|
||||
GBDevice getDevice();
|
||||
|
||||
void setStartDate(Date startDate);
|
||||
void setEndDate(Date endDate);
|
||||
|
||||
Date getStartDate();
|
||||
Date getEndDate();
|
||||
void setDateInfo(String dateInfo);
|
||||
}
|
||||
|
@ -44,17 +44,13 @@ public class SleepChartFragment extends AbstractChartFragment {
|
||||
private int mSmartAlarmTo = -1;
|
||||
private int mTimestampFrom = -1;
|
||||
private int mSmartAlarmGoneOff = -1;
|
||||
private GBDevice mGBDevice = null;
|
||||
|
||||
@Override
|
||||
protected void refreshInBackground(DBHandler db) {
|
||||
List<ActivitySample> samples = getSamples(db);
|
||||
refresh(mGBDevice, mActivityChart, samples);
|
||||
refreshSleepAmounts(mGBDevice, mSleepAmountChart, samples);
|
||||
}
|
||||
protected void refreshInBackground(DBHandler db, GBDevice device) {
|
||||
List<ActivitySample> samples = getSamples(db, device);
|
||||
|
||||
private List<ActivitySample> getSamples(DBHandler db) {
|
||||
return getSamples(db, mGBDevice);
|
||||
refresh(device, mActivityChart, samples);
|
||||
refreshSleepAmounts(device, mSleepAmountChart, samples);
|
||||
}
|
||||
|
||||
private void refreshSleepAmounts(GBDevice mGBDevice, PieChart pieChart, List<ActivitySample> samples) {
|
||||
@ -87,22 +83,23 @@ public class SleepChartFragment extends AbstractChartFragment {
|
||||
//setupLegend(pieChart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return getString(R.string.sleepchart_your_sleep);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_sleepchart, container, false);
|
||||
|
||||
Bundle extras = getActivity().getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE);
|
||||
}
|
||||
|
||||
mActivityChart = (BarLineChartBase) rootView.findViewById(R.id.sleepchart);
|
||||
mSleepAmountChart = (PieChart) rootView.findViewById(R.id.sleepchart_pie_light_deep);
|
||||
|
||||
setupActivityChart();
|
||||
setupSleepAmountChart();
|
||||
|
||||
// refresh immediately instead of use refreshIfVisible(), for perceived performance
|
||||
refresh();
|
||||
|
||||
return rootView;
|
||||
@ -180,7 +177,7 @@ public class SleepChartFragment extends AbstractChartFragment {
|
||||
}
|
||||
|
||||
protected void renderCharts() {
|
||||
mActivityChart.animateX(500, Easing.EasingOption.EaseInOutQuart);
|
||||
mActivityChart.animateX(ANIM_TIME, Easing.EasingOption.EaseInOutQuart);
|
||||
mSleepAmountChart.invalidate();
|
||||
}
|
||||
}
|
@ -44,14 +44,12 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
private BarLineChartBase mWeekStepsChart;
|
||||
private PieChart mTodayStepsChart;
|
||||
|
||||
private GBDevice mGBDevice = null;
|
||||
|
||||
@Override
|
||||
protected void refreshInBackground(DBHandler db) {
|
||||
protected void refreshInBackground(DBHandler db, GBDevice device) {
|
||||
Calendar day = Calendar.getInstance();
|
||||
//NB: we could have omitted the day, but this way we can move things to the past easily
|
||||
refreshDaySteps(db, mTodayStepsChart, day);
|
||||
refreshWeekBeforeSteps(db, mWeekStepsChart, day);
|
||||
refreshDaySteps(db, mTodayStepsChart, day, device);
|
||||
refreshWeekBeforeSteps(db, mWeekStepsChart, day, device);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,7 +58,7 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
mTodayStepsChart.invalidate();
|
||||
}
|
||||
|
||||
private void refreshWeekBeforeSteps(DBHandler db, BarLineChartBase barChart, Calendar day) {
|
||||
private void refreshWeekBeforeSteps(DBHandler db, BarLineChartBase barChart, Calendar day, GBDevice device) {
|
||||
|
||||
ActivityAnalysis analysis = new ActivityAnalysis();
|
||||
|
||||
@ -69,7 +67,7 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
List<String> labels = new ArrayList<>();
|
||||
|
||||
for (int counter = 0; counter < 7; counter++) {
|
||||
entries.add(new BarEntry(analysis.calculateTotalSteps(getSamplesOfDay(db, day)), counter));
|
||||
entries.add(new BarEntry(analysis.calculateTotalSteps(getSamplesOfDay(db, day, device)), counter));
|
||||
labels.add(day.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, mLocale));
|
||||
day.add(Calendar.DATE, 1);
|
||||
}
|
||||
@ -89,10 +87,10 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
barChart.getLegend().setEnabled(false);
|
||||
}
|
||||
|
||||
private void refreshDaySteps(DBHandler db, PieChart pieChart, Calendar day) {
|
||||
private void refreshDaySteps(DBHandler db, PieChart pieChart, Calendar day, GBDevice device) {
|
||||
ActivityAnalysis analysis = new ActivityAnalysis();
|
||||
|
||||
int totalSteps = analysis.calculateTotalSteps(getSamplesOfDay(db, day));
|
||||
int totalSteps = analysis.calculateTotalSteps(getSamplesOfDay(db, day, device));
|
||||
|
||||
pieChart.setCenterText(NumberFormat.getNumberInstance(mLocale).format(totalSteps));
|
||||
PieData data = new PieData();
|
||||
@ -128,13 +126,9 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
|
||||
View rootView = inflater.inflate(R.layout.fragment_sleepchart, container, false);
|
||||
|
||||
Bundle extras = getActivity().getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE);
|
||||
}
|
||||
|
||||
if(mGBDevice != null) {
|
||||
mTargetSteps = MiBandCoordinator.getFitnessGoal(mGBDevice.getAddress());
|
||||
GBDevice device = getHost().getDevice();
|
||||
if(device != null) {
|
||||
mTargetSteps = MiBandCoordinator.getFitnessGoal(device.getAddress());
|
||||
}
|
||||
|
||||
mWeekStepsChart = (BarLineChartBase) rootView.findViewById(R.id.sleepchart);
|
||||
@ -143,11 +137,17 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
setupWeekStepsChart();
|
||||
setupTodayStepsChart();
|
||||
|
||||
// refresh immediately instead of use refreshIfVisible(), for perceived performance
|
||||
refresh();
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return getString(R.string.weekstepschart_steps_a_week);
|
||||
}
|
||||
|
||||
private void setupTodayStepsChart() {
|
||||
mTodayStepsChart.setBackgroundColor(BACKGROUND_COLOR);
|
||||
mTodayStepsChart.setDescriptionColor(DESCRIPTION_COLOR);
|
||||
@ -196,7 +196,7 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
chart.getLegend().setTextColor(LEGEND_TEXT_COLOR);
|
||||
}
|
||||
|
||||
private List<ActivitySample> getSamplesOfDay(DBHandler db, Calendar day) {
|
||||
private List<ActivitySample> getSamplesOfDay(DBHandler db, Calendar day, GBDevice device) {
|
||||
int startTs;
|
||||
int endTs;
|
||||
|
||||
@ -210,7 +210,7 @@ public class WeekStepsChartFragment extends AbstractChartFragment {
|
||||
day.set(Calendar.SECOND, 59);
|
||||
endTs = (int) (day.getTimeInMillis() / 1000);
|
||||
|
||||
return getSamples(db, mGBDevice, startTs, endTs);
|
||||
return getSamples(db, device, startTs, endTs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
27
app/src/main/res/layout-land/fragment_sleepchart.xml
Normal file
27
app/src/main/res/layout-land/fragment_sleepchart.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.github.mikephil.charting.charts.PieChart
|
||||
android:id="@+id/sleepchart_pie_light_deep"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="40">
|
||||
</com.github.mikephil.charting.charts.PieChart>
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.activities.charts.CustomBarChart
|
||||
android:id="@+id/sleepchart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_weight="20" />
|
||||
|
||||
<!--<TextView-->
|
||||
<!--android:text="Test"-->
|
||||
<!--android:layout_width="fill_parent"-->
|
||||
<!--android:layout_height="fill_parent"-->
|
||||
<!--android:layout_weight="20" />-->
|
||||
|
||||
</LinearLayout>
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.activities.charts.CustomBarChart
|
||||
android:id="@+id/sleepchart2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
@ -4,13 +4,6 @@
|
||||
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment"
|
||||
android:orientation="vertical">
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.activities.charts.CustomBarChart
|
||||
android:id="@+id/sleepchart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_weight="20" />
|
||||
|
||||
<com.github.mikephil.charting.charts.PieChart
|
||||
android:id="@+id/sleepchart_pie_light_deep"
|
||||
android:layout_width="fill_parent"
|
||||
@ -18,10 +11,17 @@
|
||||
android:layout_weight="20">
|
||||
</com.github.mikephil.charting.charts.PieChart>
|
||||
|
||||
<TextView
|
||||
android:text="Test"
|
||||
<nodomain.freeyourgadget.gadgetbridge.activities.charts.CustomBarChart
|
||||
android:id="@+id/sleepchart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_weight="20" />
|
||||
|
||||
<!--<TextView-->
|
||||
<!--android:text="Test"-->
|
||||
<!--android:layout_width="fill_parent"-->
|
||||
<!--android:layout_height="fill_parent"-->
|
||||
<!--android:layout_weight="20" />-->
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -166,4 +166,7 @@
|
||||
<string name="notif_battery_low_percent">%1$s battery left: %2$s%%</string>
|
||||
<string name="notif_battery_low_bigtext_last_charge_time">Last charge: %s \n</string>
|
||||
<string name="notif_battery_low_bigtext_number_of_charges">Number of charges: %s</string>
|
||||
<string name="sleepchart_your_sleep">Your Sleep</string>
|
||||
<string name="weekstepschart_steps_a_week">Steps a week</string>
|
||||
<string name="activity_sleepchart_activity_and_sleep">Your Activity and Sleep</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user