mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Merge branch 'feature/performance' into dev
This commit is contained in:
@@ -9,7 +9,7 @@ android {
|
|||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
|
|
||||||
buildConfigField "Integer", "databaseVersion", "12"
|
buildConfigField "Integer", "databaseVersion", "13"
|
||||||
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
|
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.support.test.InstrumentationRegistry;
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
|
||||||
@@ -27,7 +28,6 @@ import org.isoron.uhabits.helpers.DateHelper;
|
|||||||
import org.isoron.uhabits.tasks.BaseTask;
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class BaseTest
|
public class BaseTest
|
||||||
@@ -55,6 +55,12 @@ public class BaseTest
|
|||||||
|
|
||||||
protected void waitForAsyncTasks() throws InterruptedException, TimeoutException
|
protected void waitForAsyncTasks() throws InterruptedException, TimeoutException
|
||||||
{
|
{
|
||||||
BaseTask.waitForTasks(30, TimeUnit.SECONDS);
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
|
||||||
|
{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseTask.waitForTasks(10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,23 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.unit;
|
package org.isoron.uhabits.unit;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
|
import org.isoron.uhabits.helpers.DatabaseHelper;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
|
import org.isoron.uhabits.tasks.ExportDBTask;
|
||||||
|
import org.isoron.uhabits.tasks.ImportDataTask;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public class HabitFixtures
|
public class HabitFixtures
|
||||||
{
|
{
|
||||||
@@ -79,6 +93,74 @@ public class HabitFixtures
|
|||||||
return habit;
|
return habit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void generateHugeDataSet() throws Throwable
|
||||||
|
{
|
||||||
|
final int nHabits = 30;
|
||||||
|
final int nYears = 5;
|
||||||
|
|
||||||
|
DatabaseHelper.executeAsTransaction(new DatabaseHelper.Command()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
Random rand = new Random();
|
||||||
|
|
||||||
|
for(int i = 0; i < nHabits; i++)
|
||||||
|
{
|
||||||
|
Log.i("HabitFixture", String.format("Creating habit %d / %d", i, nHabits));
|
||||||
|
|
||||||
|
Habit habit = new Habit();
|
||||||
|
habit.name = String.format("Habit %d", i);
|
||||||
|
habit.save();
|
||||||
|
|
||||||
|
long today = DateHelper.getStartOfToday();
|
||||||
|
long day = DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
|
|
||||||
|
for(int j = 0; j < 365 * nYears; j++)
|
||||||
|
{
|
||||||
|
if(rand.nextBoolean())
|
||||||
|
habit.repetitions.toggle(today - j * day);
|
||||||
|
}
|
||||||
|
|
||||||
|
habit.scores.getTodayValue();
|
||||||
|
habit.streaks.getAll(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ExportDBTask task = new ExportDBTask(null);
|
||||||
|
task.setListener(new ExportDBTask.Listener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onExportDBFinished(@Nullable String filename)
|
||||||
|
{
|
||||||
|
if(filename != null)
|
||||||
|
Log.i("HabitFixture", String.format("Huge data set exported to %s", filename));
|
||||||
|
else
|
||||||
|
Log.i("HabitFixture", "Failed to save database");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.execute();
|
||||||
|
|
||||||
|
BaseTask.waitForTasks(30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadHugeDataSet(Context testContext) throws Throwable
|
||||||
|
{
|
||||||
|
File baseDir = DatabaseHelper.getFilesDir("Backups");
|
||||||
|
if(baseDir == null) fail("baseDir should not be null");
|
||||||
|
|
||||||
|
File dst = new File(String.format("%s/%s", baseDir.getPath(), "loopHuge.db"));
|
||||||
|
InputStream in = testContext.getAssets().open("fixtures/loopHuge.db");
|
||||||
|
DatabaseHelper.copy(in, dst);
|
||||||
|
|
||||||
|
ImportDataTask task = new ImportDataTask(dst, null);
|
||||||
|
task.execute();
|
||||||
|
|
||||||
|
BaseTask.waitForTasks(30000);
|
||||||
|
}
|
||||||
|
|
||||||
public static void purgeHabits()
|
public static void purgeHabits()
|
||||||
{
|
{
|
||||||
for(Habit h : Habit.getAll(true))
|
for(Habit h : Habit.getAll(true))
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.unit;
|
package org.isoron.uhabits.unit;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
|
||||||
@@ -38,6 +39,9 @@ public class HabitsApplicationTest
|
|||||||
@Test
|
@Test
|
||||||
public void getLogcat() throws IOException
|
public void getLogcat() throws IOException
|
||||||
{
|
{
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
|
||||||
|
return;
|
||||||
|
|
||||||
String msg = "LOGCAT TEST";
|
String msg = "LOGCAT TEST";
|
||||||
new RuntimeException(msg).printStackTrace();
|
new RuntimeException(msg).printStackTrace();
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||||||
import org.isoron.uhabits.BaseTest;
|
import org.isoron.uhabits.BaseTest;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.models.Repetition;
|
||||||
import org.isoron.uhabits.unit.HabitFixtures;
|
import org.isoron.uhabits.unit.HabitFixtures;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -37,6 +38,7 @@ import java.util.GregorianCalendar;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
@@ -174,4 +176,16 @@ public class RepetitionListTest extends BaseTest
|
|||||||
from = to - 5 * DateHelper.millisecondsInOneDay;
|
from = to - 5 * DateHelper.millisecondsInOneDay;
|
||||||
assertThat(habit.repetitions.count(from, to), equalTo(3));
|
assertThat(habit.repetitions.count(from, to), equalTo(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getOldest()
|
||||||
|
{
|
||||||
|
long expectedOldestTimestamp = DateHelper.getStartOfToday() - 9 * DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
|
assertThat(habit.repetitions.getOldestTimestamp(), equalTo(expectedOldestTimestamp));
|
||||||
|
|
||||||
|
Repetition oldest = habit.repetitions.getOldest();
|
||||||
|
assertFalse(oldest == null);
|
||||||
|
assertThat(oldest.timestamp, equalTo(expectedOldestTimestamp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ import org.junit.runner.RunWith;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class CheckmarkViewTest extends ViewTest
|
|||||||
habit = HabitFixtures.createShortHabit();
|
habit = HabitFixtures.createShortHabit();
|
||||||
view = new CheckmarkView(targetContext);
|
view = new CheckmarkView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
|
refreshData(view);
|
||||||
measureView(dpToPixels(100), dpToPixels(200), view);
|
measureView(dpToPixels(100), dpToPixels(200), view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class HabitFrequencyViewTest extends ViewTest
|
|||||||
|
|
||||||
view = new HabitFrequencyView(targetContext);
|
view = new HabitFrequencyView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
|
refreshData(view);
|
||||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package org.isoron.uhabits.unit.views;
|
|||||||
|
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
@@ -54,12 +53,12 @@ public class HabitHistoryViewTest extends ViewTest
|
|||||||
view = new HabitHistoryView(targetContext);
|
view = new HabitHistoryView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||||
|
refreshData(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void render() throws Throwable
|
public void render() throws Throwable
|
||||||
{
|
{
|
||||||
Log.d("HabitHistoryViewTest", String.format("height=%d", dpToPixels(100)));
|
|
||||||
assertRenders(view, "HabitHistoryView/render.png");
|
assertRenders(view, "HabitHistoryView/render.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class HabitScoreViewTest extends ViewTest
|
|||||||
view = new HabitScoreView(targetContext);
|
view = new HabitScoreView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
view.setBucketSize(7);
|
view.setBucketSize(7);
|
||||||
|
refreshData(view);
|
||||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package org.isoron.uhabits.unit.views;
|
|||||||
|
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.unit.HabitFixtures;
|
import org.isoron.uhabits.unit.HabitFixtures;
|
||||||
@@ -45,8 +44,10 @@ public class HabitStreakViewTest extends ViewTest
|
|||||||
Habit habit = HabitFixtures.createLongHabit();
|
Habit habit = HabitFixtures.createLongHabit();
|
||||||
|
|
||||||
view = new HabitStreakView(targetContext);
|
view = new HabitStreakView(targetContext);
|
||||||
view.setHabit(habit);
|
|
||||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||||
|
|
||||||
|
view.setHabit(habit);
|
||||||
|
refreshData(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -66,6 +67,8 @@ public class HabitStreakViewTest extends ViewTest
|
|||||||
public void render_withSmallSize() throws Throwable
|
public void render_withSmallSize() throws Throwable
|
||||||
{
|
{
|
||||||
measureView(dpToPixels(100), dpToPixels(100), view);
|
measureView(dpToPixels(100), dpToPixels(100), view);
|
||||||
|
refreshData(view);
|
||||||
|
|
||||||
assertRenders(view, "HabitStreakView/renderSmallSize.png");
|
assertRenders(view, "HabitStreakView/renderSmallSize.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import android.view.MotionEvent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseTest;
|
import org.isoron.uhabits.BaseTest;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -38,7 +40,7 @@ import static junit.framework.Assert.fail;
|
|||||||
|
|
||||||
public class ViewTest extends BaseTest
|
public class ViewTest extends BaseTest
|
||||||
{
|
{
|
||||||
protected static final double SIMILARITY_CUTOFF = 0.08;
|
protected static final double SIMILARITY_CUTOFF = 0.09;
|
||||||
public static final int HISTOGRAM_BIN_SIZE = 8;
|
public static final int HISTOGRAM_BIN_SIZE = 8;
|
||||||
|
|
||||||
protected void measureView(int width, int height, View view)
|
protected void measureView(int width, int height, View view)
|
||||||
@@ -179,7 +181,7 @@ public class ViewTest extends BaseTest
|
|||||||
|
|
||||||
protected int dpToPixels(int dp)
|
protected int dpToPixels(int dp)
|
||||||
{
|
{
|
||||||
return (int) DialogHelper.dpToPixels(targetContext, dp);
|
return (int) UIHelper.dpToPixels(targetContext, dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tap(GestureDetector.OnGestureListener view, int x, int y) throws InterruptedException
|
protected void tap(GestureDetector.OnGestureListener view, int x, int y) throws InterruptedException
|
||||||
@@ -190,4 +192,25 @@ public class ViewTest extends BaseTest
|
|||||||
view.onSingleTapUp(e);
|
view.onSingleTapUp(e);
|
||||||
e.recycle();
|
e.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void refreshData(final HabitDataView view)
|
||||||
|
{
|
||||||
|
new BaseTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doInBackground()
|
||||||
|
{
|
||||||
|
view.refreshData();
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
waitForAsyncTasks();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Time out");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
app/src/main/assets/migrations/13.sql
Normal file
4
app/src/main/assets/migrations/13.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
create index idx_score_habit_timestamp on score(habit, timestamp);
|
||||||
|
create index idx_checkmark_habit_timestamp on checkmarks(habit, timestamp);
|
||||||
|
create index idx_repetitions_habit_timestamp on repetitions(habit, timestamp);
|
||||||
|
create index idx_streak_habit_end on streak(habit, end);
|
||||||
@@ -37,7 +37,7 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
import org.isoron.uhabits.fragments.ListHabitsFragment;
|
import org.isoron.uhabits.fragments.ListHabitsFragment;
|
||||||
import org.isoron.uhabits.helpers.ReminderHelper;
|
import org.isoron.uhabits.helpers.ReminderHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
@@ -85,8 +85,8 @@ public class MainActivity extends BaseActivity
|
|||||||
private void onStartup()
|
private void onStartup()
|
||||||
{
|
{
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
||||||
DialogHelper.incrementLaunchCount(this);
|
UIHelper.incrementLaunchCount(this);
|
||||||
DialogHelper.updateLastAppVersion(this);
|
UIHelper.updateLastAppVersion(this);
|
||||||
showTutorial();
|
showTutorial();
|
||||||
|
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
|
|||||||
@@ -20,27 +20,16 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.fragments.ShowHabitFragment;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
public class ShowHabitActivity extends BaseActivity
|
public class ShowHabitActivity extends BaseActivity
|
||||||
{
|
{
|
||||||
|
private Habit habit;
|
||||||
public Habit habit;
|
|
||||||
private Receiver receiver;
|
|
||||||
private LocalBroadcastManager localBroadcastManager;
|
|
||||||
|
|
||||||
private ShowHabitFragment fragment;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
@@ -51,37 +40,18 @@ public class ShowHabitActivity extends BaseActivity
|
|||||||
habit = Habit.get(ContentUris.parseId(data));
|
habit = Habit.get(ContentUris.parseId(data));
|
||||||
ActionBar actionBar = getActionBar();
|
ActionBar actionBar = getActionBar();
|
||||||
|
|
||||||
if(actionBar != null)
|
if(actionBar != null && getHabit() != null)
|
||||||
{
|
{
|
||||||
actionBar.setTitle(habit.name);
|
actionBar.setTitle(getHabit().name);
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 21)
|
if (android.os.Build.VERSION.SDK_INT >= 21)
|
||||||
actionBar.setBackgroundDrawable(new ColorDrawable(habit.color));
|
actionBar.setBackgroundDrawable(new ColorDrawable(getHabit().color));
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(R.layout.show_habit_activity);
|
setContentView(R.layout.show_habit_activity);
|
||||||
|
|
||||||
fragment = (ShowHabitFragment) getFragmentManager().findFragmentById(R.id.fragment2);
|
|
||||||
|
|
||||||
receiver = new Receiver();
|
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
|
||||||
localBroadcastManager.registerReceiver(receiver,
|
|
||||||
new IntentFilter(MainActivity.ACTION_REFRESH));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Receiver extends BroadcastReceiver
|
public Habit getHabit()
|
||||||
{
|
{
|
||||||
@Override
|
return habit;
|
||||||
public void onReceive(Context context, Intent intent)
|
|
||||||
{
|
|
||||||
fragment.refreshData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy()
|
|
||||||
{
|
|
||||||
localBroadcastManager.unregisterReceiver(receiver);
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import android.util.Log;
|
|||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
import org.isoron.uhabits.views.HabitHistoryView;
|
import org.isoron.uhabits.views.HabitHistoryView;
|
||||||
|
|
||||||
public class HistoryEditorDialog extends DialogFragment
|
public class HistoryEditorDialog extends DialogFragment
|
||||||
@@ -44,7 +45,6 @@ public class HistoryEditorDialog extends DialogFragment
|
|||||||
{
|
{
|
||||||
Context context = getActivity();
|
Context context = getActivity();
|
||||||
historyView = new HabitHistoryView(context, null);
|
historyView = new HabitHistoryView(context, null);
|
||||||
int p = (int) getResources().getDimension(R.dimen.history_editor_padding);
|
|
||||||
|
|
||||||
if(savedInstanceState != null)
|
if(savedInstanceState != null)
|
||||||
{
|
{
|
||||||
@@ -52,7 +52,8 @@ public class HistoryEditorDialog extends DialogFragment
|
|||||||
if(id > 0) this.habit = Habit.get(id);
|
if(id > 0) this.habit = Habit.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
historyView.setPadding(p, 0, p, 0);
|
int padding = (int) getResources().getDimension(R.dimen.history_editor_padding);
|
||||||
|
historyView.setPadding(padding, 0, padding, 0);
|
||||||
historyView.setHabit(habit);
|
historyView.setHabit(habit);
|
||||||
historyView.setIsEditable(true);
|
historyView.setIsEditable(true);
|
||||||
|
|
||||||
@@ -61,9 +62,23 @@ public class HistoryEditorDialog extends DialogFragment
|
|||||||
.setView(historyView)
|
.setView(historyView)
|
||||||
.setPositiveButton(android.R.string.ok, this);
|
.setPositiveButton(android.R.string.ok, this);
|
||||||
|
|
||||||
|
refreshData();
|
||||||
|
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void refreshData()
|
||||||
|
{
|
||||||
|
new BaseTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doInBackground()
|
||||||
|
{
|
||||||
|
historyView.refreshData();
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume()
|
public void onResume()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import com.android.datetimepicker.time.TimePickerDialog;
|
|||||||
|
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper.OnSavedListener;
|
import org.isoron.uhabits.helpers.UIHelper.OnSavedListener;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.commands.Command;
|
import org.isoron.uhabits.commands.Command;
|
||||||
import org.isoron.uhabits.commands.CreateHabitCommand;
|
import org.isoron.uhabits.commands.CreateHabitCommand;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import org.isoron.uhabits.commands.ChangeHabitColorCommand;
|
|||||||
import org.isoron.uhabits.commands.DeleteHabitsCommand;
|
import org.isoron.uhabits.commands.DeleteHabitsCommand;
|
||||||
import org.isoron.uhabits.commands.UnarchiveHabitsCommand;
|
import org.isoron.uhabits.commands.UnarchiveHabitsCommand;
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
import org.isoron.uhabits.loaders.HabitListLoader;
|
import org.isoron.uhabits.loaders.HabitListLoader;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ public class HabitSelectionCallback implements ActionMode.Callback
|
|||||||
private List<Integer> selectedPositions;
|
private List<Integer> selectedPositions;
|
||||||
private BaseActivity activity;
|
private BaseActivity activity;
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
private DialogHelper.OnSavedListener onSavedListener;
|
private UIHelper.OnSavedListener onSavedListener;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
public interface Listener
|
public interface Listener
|
||||||
@@ -74,7 +74,7 @@ public class HabitSelectionCallback implements ActionMode.Callback
|
|||||||
this.progressBar = progressBar;
|
this.progressBar = progressBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnSavedListener(DialogHelper.OnSavedListener onSavedListener)
|
public void setOnSavedListener(UIHelper.OnSavedListener onSavedListener)
|
||||||
{
|
{
|
||||||
this.onSavedListener = onSavedListener;
|
this.onSavedListener = onSavedListener;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ import org.isoron.uhabits.commands.Command;
|
|||||||
import org.isoron.uhabits.commands.ToggleRepetitionCommand;
|
import org.isoron.uhabits.commands.ToggleRepetitionCommand;
|
||||||
import org.isoron.uhabits.dialogs.FilePickerDialog;
|
import org.isoron.uhabits.dialogs.FilePickerDialog;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper.OnSavedListener;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper.OnSavedListener;
|
|
||||||
import org.isoron.uhabits.helpers.HintManager;
|
import org.isoron.uhabits.helpers.HintManager;
|
||||||
import org.isoron.uhabits.helpers.ListHabitsHelper;
|
import org.isoron.uhabits.helpers.ListHabitsHelper;
|
||||||
import org.isoron.uhabits.helpers.ReminderHelper;
|
import org.isoron.uhabits.helpers.ReminderHelper;
|
||||||
@@ -107,7 +106,9 @@ public class ListHabitsFragment extends Fragment
|
|||||||
listView = (DragSortListView) view.findViewById(R.id.listView);
|
listView = (DragSortListView) view.findViewById(R.id.listView);
|
||||||
llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
|
llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
|
||||||
llEmpty = view.findViewById(R.id.llEmpty);
|
llEmpty = view.findViewById(R.id.llEmpty);
|
||||||
|
|
||||||
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
selectedPositions = new LinkedList<>();
|
selectedPositions = new LinkedList<>();
|
||||||
loader = new HabitListLoader();
|
loader = new HabitListLoader();
|
||||||
@@ -116,7 +117,6 @@ public class ListHabitsFragment extends Fragment
|
|||||||
|
|
||||||
loader.setListener(this);
|
loader.setListener(this);
|
||||||
loader.setCheckmarkCount(helper.getButtonCount());
|
loader.setCheckmarkCount(helper.getButtonCount());
|
||||||
loader.setProgressBar(progressBar);
|
|
||||||
|
|
||||||
llHint.setOnClickListener(this);
|
llHint.setOnClickListener(this);
|
||||||
tvStarEmpty.setTypeface(helper.getFontawesome());
|
tvStarEmpty.setTypeface(helper.getFontawesome());
|
||||||
|
|||||||
@@ -33,33 +33,32 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
|
||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.ShowHabitActivity;
|
import org.isoron.uhabits.ShowHabitActivity;
|
||||||
import org.isoron.uhabits.commands.Command;
|
import org.isoron.uhabits.commands.Command;
|
||||||
import org.isoron.uhabits.dialogs.HistoryEditorDialog;
|
import org.isoron.uhabits.dialogs.HistoryEditorDialog;
|
||||||
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
import org.isoron.uhabits.helpers.ReminderHelper;
|
import org.isoron.uhabits.helpers.ReminderHelper;
|
||||||
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.models.Score;
|
import org.isoron.uhabits.models.Score;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
import org.isoron.uhabits.views.HabitDataView;
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
import org.isoron.uhabits.views.HabitFrequencyView;
|
import org.isoron.uhabits.views.HabitFrequencyView;
|
||||||
import org.isoron.uhabits.views.HabitHistoryView;
|
import org.isoron.uhabits.views.HabitHistoryView;
|
||||||
import org.isoron.uhabits.views.HabitScoreView;
|
import org.isoron.uhabits.views.HabitScoreView;
|
||||||
import org.isoron.uhabits.views.HabitStreakView;
|
import org.isoron.uhabits.views.HabitStreakView;
|
||||||
import org.isoron.uhabits.views.RepetitionCountView;
|
|
||||||
import org.isoron.uhabits.views.RingView;
|
import org.isoron.uhabits.views.RingView;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ShowHabitFragment extends Fragment
|
public class ShowHabitFragment extends Fragment
|
||||||
implements DialogHelper.OnSavedListener, HistoryEditorDialog.Listener,
|
implements UIHelper.OnSavedListener, HistoryEditorDialog.Listener,
|
||||||
Spinner.OnItemSelectedListener
|
Spinner.OnItemSelectedListener
|
||||||
{
|
{
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -77,6 +76,8 @@ public class ShowHabitFragment extends Fragment
|
|||||||
@Nullable
|
@Nullable
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
|
private int previousScoreInterval;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart()
|
public void onStart()
|
||||||
{
|
{
|
||||||
@@ -89,7 +90,7 @@ public class ShowHabitFragment extends Fragment
|
|||||||
{
|
{
|
||||||
View view = inflater.inflate(R.layout.show_habit, container, false);
|
View view = inflater.inflate(R.layout.show_habit, container, false);
|
||||||
activity = (ShowHabitActivity) getActivity();
|
activity = (ShowHabitActivity) getActivity();
|
||||||
habit = activity.habit;
|
habit = activity.getHabit();
|
||||||
|
|
||||||
dataViews = new LinkedList<>();
|
dataViews = new LinkedList<>();
|
||||||
|
|
||||||
@@ -101,22 +102,19 @@ public class ShowHabitFragment extends Fragment
|
|||||||
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
int defaultScoreInterval = prefs.getInt("pref_score_view_interval", 1);
|
int defaultScoreInterval = prefs.getInt("pref_score_view_interval", 1);
|
||||||
if(defaultScoreInterval > 5 || defaultScoreInterval < 0) defaultScoreInterval = 1;
|
if(defaultScoreInterval > 5 || defaultScoreInterval < 0) defaultScoreInterval = 1;
|
||||||
|
previousScoreInterval = defaultScoreInterval;
|
||||||
setScoreBucketSize(defaultScoreInterval);
|
setScoreBucketSize(defaultScoreInterval);
|
||||||
|
|
||||||
|
|
||||||
sStrengthInterval.setSelection(defaultScoreInterval);
|
sStrengthInterval.setSelection(defaultScoreInterval);
|
||||||
sStrengthInterval.setOnItemSelectedListener(this);
|
sStrengthInterval.setOnItemSelectedListener(this);
|
||||||
|
|
||||||
dataViews.add((HabitStreakView) view.findViewById(R.id.streakView));
|
|
||||||
dataViews.add((HabitStreakView) view.findViewById(R.id.smallStreakView));
|
|
||||||
dataViews.add((HabitScoreView) view.findViewById(R.id.scoreView));
|
dataViews.add((HabitScoreView) view.findViewById(R.id.scoreView));
|
||||||
dataViews.add((HabitHistoryView) view.findViewById(R.id.historyView));
|
dataViews.add((HabitHistoryView) view.findViewById(R.id.historyView));
|
||||||
dataViews.add((HabitFrequencyView) view.findViewById(R.id.punchcardView));
|
dataViews.add((HabitFrequencyView) view.findViewById(R.id.punchcardView));
|
||||||
|
dataViews.add((HabitStreakView) view.findViewById(R.id.streakView));
|
||||||
LinearLayout llRepetition = (LinearLayout) view.findViewById(R.id.llRepetition);
|
|
||||||
for(int i = 0; i < llRepetition.getChildCount(); i++)
|
|
||||||
dataViews.add((RepetitionCountView) llRepetition.getChildAt(i));
|
|
||||||
|
|
||||||
updateHeaders(view);
|
updateHeaders(view);
|
||||||
updateScoreRing(view);
|
|
||||||
|
|
||||||
for(HabitDataView dataView : dataViews)
|
for(HabitDataView dataView : dataViews)
|
||||||
dataView.setHabit(habit);
|
dataView.setHabit(habit);
|
||||||
@@ -145,12 +143,21 @@ public class ShowHabitFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume()
|
||||||
|
{
|
||||||
|
super.onResume();
|
||||||
|
refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateScoreRing(View view)
|
private void updateScoreRing(View view)
|
||||||
{
|
{
|
||||||
if(habit == null) return;
|
if(habit == null) return;
|
||||||
|
if(view == null) return;
|
||||||
|
|
||||||
RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
|
RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing);
|
||||||
scoreRing.setColor(habit.color);
|
scoreRing.setColor(habit.color);
|
||||||
@@ -172,7 +179,6 @@ public class ShowHabitFragment extends Fragment
|
|||||||
updateColor(view, R.id.tvStrength);
|
updateColor(view, R.id.tvStrength);
|
||||||
updateColor(view, R.id.tvStreaks);
|
updateColor(view, R.id.tvStreaks);
|
||||||
updateColor(view, R.id.tvWeekdayFreq);
|
updateColor(view, R.id.tvWeekdayFreq);
|
||||||
updateColor(view, R.id.tvCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateColor(View view, int viewId)
|
private void updateColor(View view, int viewId)
|
||||||
@@ -229,12 +235,31 @@ public class ShowHabitFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void refreshData()
|
public void refreshData()
|
||||||
|
{
|
||||||
|
new BaseTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
if(dataViews == null) return;
|
if(dataViews == null) return;
|
||||||
updateScoreRing(getView());
|
updateScoreRing(getView());
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
for(HabitDataView view : dataViews)
|
for(HabitDataView view : dataViews)
|
||||||
|
{
|
||||||
view.refreshData();
|
view.refreshData();
|
||||||
|
onProgressUpdate(count++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Integer... values)
|
||||||
|
{
|
||||||
|
if(dataViews == null) return;
|
||||||
|
dataViews.get(values[0]).postInvalidate();
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -246,17 +271,18 @@ public class ShowHabitFragment extends Fragment
|
|||||||
|
|
||||||
private void setScoreBucketSize(int position)
|
private void setScoreBucketSize(int position)
|
||||||
{
|
{
|
||||||
|
if(scoreView == null) return;
|
||||||
|
|
||||||
int sizes[] = { 1, 7, 31, 92, 365 };
|
int sizes[] = { 1, 7, 31, 92, 365 };
|
||||||
int size = sizes[position];
|
int size = sizes[position];
|
||||||
|
|
||||||
if(scoreView != null)
|
|
||||||
{
|
|
||||||
scoreView.setBucketSize(size);
|
scoreView.setBucketSize(size);
|
||||||
scoreView.refreshData();
|
if(position != previousScoreInterval) refreshData();
|
||||||
}
|
|
||||||
|
|
||||||
if(prefs != null)
|
if(prefs != null)
|
||||||
prefs.edit().putInt("pref_score_view_interval", position).apply();
|
prefs.edit().putInt("pref_score_view_interval", position).apply();
|
||||||
|
|
||||||
|
previousScoreInterval = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,11 +20,13 @@
|
|||||||
package org.isoron.uhabits.helpers;
|
package org.isoron.uhabits.helpers;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
|
||||||
import com.activeandroid.ActiveAndroid;
|
import com.activeandroid.ActiveAndroid;
|
||||||
|
import com.activeandroid.Cache;
|
||||||
import com.activeandroid.Configuration;
|
import com.activeandroid.Configuration;
|
||||||
|
|
||||||
import org.isoron.uhabits.BuildConfig;
|
import org.isoron.uhabits.BuildConfig;
|
||||||
@@ -163,4 +165,20 @@ public class DatabaseHelper
|
|||||||
|
|
||||||
ActiveAndroid.initialize(dbConfig);
|
ActiveAndroid.initialize(dbConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long longQuery(String query, String args[])
|
||||||
|
{
|
||||||
|
Cursor c = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
c = Cache.openDatabase().rawQuery(query, args);
|
||||||
|
if (!c.moveToFirst()) return 0;
|
||||||
|
return c.getLong(0);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if(c != null) c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ import android.content.Context;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Debug;
|
||||||
|
import android.os.Looper;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
@@ -33,7 +36,7 @@ import android.view.inputmethod.InputMethodManager;
|
|||||||
import org.isoron.uhabits.BuildConfig;
|
import org.isoron.uhabits.BuildConfig;
|
||||||
import org.isoron.uhabits.commands.Command;
|
import org.isoron.uhabits.commands.Command;
|
||||||
|
|
||||||
public abstract class DialogHelper
|
public abstract class UIHelper
|
||||||
{
|
{
|
||||||
|
|
||||||
public static final String ISORON_NAMESPACE = "http://isoron.org/android";
|
public static final String ISORON_NAMESPACE = "http://isoron.org/android";
|
||||||
@@ -110,4 +113,37 @@ public abstract class DialogHelper
|
|||||||
DisplayMetrics metrics = resources.getDisplayMetrics();
|
DisplayMetrics metrics = resources.getDisplayMetrics();
|
||||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics);
|
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a runtime exception if called from the main thread. Useful to make sure that
|
||||||
|
* slow methods never accidentally slow the application down.
|
||||||
|
*
|
||||||
|
* @throws RuntimeException when run from main thread
|
||||||
|
*/
|
||||||
|
public static void throwIfMainThread() throws RuntimeException
|
||||||
|
{
|
||||||
|
Looper looper = Looper.myLooper();
|
||||||
|
if(looper == null) return;
|
||||||
|
|
||||||
|
if(looper == Looper.getMainLooper())
|
||||||
|
throw new RuntimeException("This method should never be called from the main thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startTracing()
|
||||||
|
{
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.startMethodTracingSampling("Android/data/org.isoron.uhabits/perf",
|
||||||
|
32 * 1024 * 1024, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopTracing()
|
||||||
|
{
|
||||||
|
Debug.stopMethodTracing();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,13 +19,9 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.loaders;
|
package org.isoron.uhabits.loaders;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -37,9 +33,8 @@ public class HabitListLoader
|
|||||||
void onLoadFinished();
|
void onLoadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AsyncTask<Void, Integer, Void> currentFetchTask;
|
private BaseTask currentFetchTask;
|
||||||
private int checkmarkCount;
|
private int checkmarkCount;
|
||||||
private ProgressBar progressBar;
|
|
||||||
|
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
private Long lastLoadTimestamp;
|
private Long lastLoadTimestamp;
|
||||||
@@ -56,11 +51,6 @@ public class HabitListLoader
|
|||||||
this.includeArchived = includeArchived;
|
this.includeArchived = includeArchived;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgressBar(ProgressBar progressBar)
|
|
||||||
{
|
|
||||||
this.progressBar = progressBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckmarkCount(int checkmarkCount)
|
public void setCheckmarkCount(int checkmarkCount)
|
||||||
{
|
{
|
||||||
this.checkmarkCount = checkmarkCount;
|
this.checkmarkCount = checkmarkCount;
|
||||||
@@ -98,7 +88,7 @@ public class HabitListLoader
|
|||||||
{
|
{
|
||||||
if (currentFetchTask != null) currentFetchTask.cancel(true);
|
if (currentFetchTask != null) currentFetchTask.cancel(true);
|
||||||
|
|
||||||
currentFetchTask = new AsyncTask<Void, Integer, Void>()
|
currentFetchTask = new BaseTask()
|
||||||
{
|
{
|
||||||
public HashMap<Long, Habit> newHabits;
|
public HashMap<Long, Habit> newHabits;
|
||||||
public HashMap<Long, int[]> newCheckmarks;
|
public HashMap<Long, int[]> newCheckmarks;
|
||||||
@@ -106,7 +96,7 @@ public class HabitListLoader
|
|||||||
public List<Habit> newHabitList;
|
public List<Habit> newHabitList;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params)
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
newHabits = new HashMap<>();
|
newHabits = new HashMap<>();
|
||||||
newCheckmarks = new HashMap<>();
|
newCheckmarks = new HashMap<>();
|
||||||
@@ -136,12 +126,12 @@ public class HabitListLoader
|
|||||||
|
|
||||||
commit();
|
commit();
|
||||||
|
|
||||||
if(!updateScoresAndCheckmarks) return null;
|
if(!updateScoresAndCheckmarks) return;
|
||||||
|
|
||||||
int current = 0;
|
int current = 0;
|
||||||
for (Habit h : newHabitList)
|
for (Habit h : newHabitList)
|
||||||
{
|
{
|
||||||
if (isCancelled()) return null;
|
if (isCancelled()) return;
|
||||||
|
|
||||||
Long id = h.getId();
|
Long id = h.getId();
|
||||||
newScores.put(id, h.scores.getTodayValue());
|
newScores.put(id, h.scores.getTodayValue());
|
||||||
@@ -149,8 +139,6 @@ public class HabitListLoader
|
|||||||
|
|
||||||
publishProgress(current++, newHabits.size());
|
publishProgress(current++, newHabits.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commit()
|
private void commit()
|
||||||
@@ -161,26 +149,9 @@ public class HabitListLoader
|
|||||||
habitsList = newHabitList;
|
habitsList = newHabitList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute()
|
|
||||||
{
|
|
||||||
if(progressBar != null)
|
|
||||||
{
|
|
||||||
progressBar.setIndeterminate(false);
|
|
||||||
progressBar.setProgress(0);
|
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onProgressUpdate(Integer... values)
|
protected void onProgressUpdate(Integer... values)
|
||||||
{
|
{
|
||||||
if(progressBar != null)
|
|
||||||
{
|
|
||||||
progressBar.setMax(values[1]);
|
|
||||||
progressBar.setProgress(values[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(listener != null) listener.onLoadFinished();
|
if(listener != null) listener.onLoadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,11 +160,12 @@ public class HabitListLoader
|
|||||||
{
|
{
|
||||||
if (isCancelled()) return;
|
if (isCancelled()) return;
|
||||||
|
|
||||||
if(progressBar != null) progressBar.setVisibility(View.INVISIBLE);
|
|
||||||
lastLoadTimestamp = DateHelper.getStartOfToday();
|
lastLoadTimestamp = DateHelper.getStartOfToday();
|
||||||
currentFetchTask = null;
|
currentFetchTask = null;
|
||||||
|
|
||||||
if(listener != null) listener.onLoadFinished();
|
if(listener != null) listener.onLoadFinished();
|
||||||
|
|
||||||
|
super.onPostExecute(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -203,50 +175,29 @@ public class HabitListLoader
|
|||||||
|
|
||||||
public void updateHabit(final Long id)
|
public void updateHabit(final Long id)
|
||||||
{
|
{
|
||||||
new AsyncTask<Void, Void, Void>()
|
new BaseTask()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params)
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
long dateTo = DateHelper.getStartOfDay(DateHelper.getLocalTime());
|
long dateTo = DateHelper.getStartOfDay(DateHelper.getLocalTime());
|
||||||
long dateFrom = dateTo - (checkmarkCount - 1) * DateHelper.millisecondsInOneDay;
|
long dateFrom = dateTo - (checkmarkCount - 1) * DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
Habit h = Habit.get(id);
|
Habit h = Habit.get(id);
|
||||||
|
if(h == null) return;
|
||||||
|
|
||||||
habits.put(id, h);
|
habits.put(id, h);
|
||||||
scores.put(id, h.scores.getTodayValue());
|
scores.put(id, h.scores.getTodayValue());
|
||||||
checkmarks.put(id, h.checkmarks.getValues(dateFrom, dateTo));
|
checkmarks.put(id, h.checkmarks.getValues(dateFrom, dateTo));
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute()
|
|
||||||
{
|
|
||||||
new Handler().postDelayed(new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
if (getStatus() == Status.RUNNING)
|
|
||||||
{
|
|
||||||
if(progressBar != null)
|
|
||||||
{
|
|
||||||
progressBar.setIndeterminate(true);
|
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Void aVoid)
|
protected void onPostExecute(Void aVoid)
|
||||||
{
|
{
|
||||||
if(progressBar != null) progressBar.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if(listener != null)
|
if(listener != null)
|
||||||
listener.onLoadFinished();
|
listener.onLoadFinished();
|
||||||
|
|
||||||
|
super.onPostExecute(null);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,16 @@ package org.isoron.uhabits.models;
|
|||||||
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteStatement;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.activeandroid.ActiveAndroid;
|
|
||||||
import com.activeandroid.Cache;
|
import com.activeandroid.Cache;
|
||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.Delete;
|
||||||
import com.activeandroid.query.Select;
|
import com.activeandroid.query.Select;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
@@ -134,10 +135,9 @@ public class CheckmarkList
|
|||||||
*/
|
*/
|
||||||
protected void computeAll()
|
protected void computeAll()
|
||||||
{
|
{
|
||||||
Repetition oldestRep = habit.repetitions.getOldest();
|
long fromTimestamp = habit.repetitions.getOldestTimestamp();
|
||||||
if(oldestRep == null) return;
|
if(fromTimestamp == 0) return;
|
||||||
|
|
||||||
Long fromTimestamp = oldestRep.timestamp;
|
|
||||||
Long toTimestamp = DateHelper.getStartOfToday();
|
Long toTimestamp = DateHelper.getStartOfToday();
|
||||||
|
|
||||||
compute(fromTimestamp, toTimestamp);
|
compute(fromTimestamp, toTimestamp);
|
||||||
@@ -150,9 +150,11 @@ public class CheckmarkList
|
|||||||
* @param from timestamp for the beginning of the interval
|
* @param from timestamp for the beginning of the interval
|
||||||
* @param to timestamp for the end of the interval
|
* @param to timestamp for the end of the interval
|
||||||
*/
|
*/
|
||||||
protected void compute(long from, long to)
|
protected void compute(long from, final long to)
|
||||||
{
|
{
|
||||||
long day = DateHelper.millisecondsInOneDay;
|
UIHelper.throwIfMainThread();
|
||||||
|
|
||||||
|
final long day = DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
Checkmark newestCheckmark = findNewest();
|
Checkmark newestCheckmark = findNewest();
|
||||||
if(newestCheckmark != null)
|
if(newestCheckmark != null)
|
||||||
@@ -165,9 +167,9 @@ public class CheckmarkList
|
|||||||
.selectFromTo(fromExtended, to)
|
.selectFromTo(fromExtended, to)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
int nDays = (int) ((to - from) / day) + 1;
|
final int nDays = (int) ((to - from) / day) + 1;
|
||||||
int nDaysExtended = (int) ((to - fromExtended) / day) + 1;
|
int nDaysExtended = (int) ((to - fromExtended) / day) + 1;
|
||||||
int checks[] = new int[nDaysExtended];
|
final int checks[] = new int[nDaysExtended];
|
||||||
|
|
||||||
for (Repetition rep : reps)
|
for (Repetition rep : reps)
|
||||||
{
|
{
|
||||||
@@ -187,24 +189,38 @@ public class CheckmarkList
|
|||||||
checks[i] = Checkmark.CHECKED_IMPLICITLY;
|
checks[i] = Checkmark.CHECKED_IMPLICITLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActiveAndroid.beginTransaction();
|
|
||||||
|
long timestamps[] = new long[nDays];
|
||||||
|
for (int i = 0; i < nDays; i++)
|
||||||
|
timestamps[i] = to - i * day;
|
||||||
|
|
||||||
|
insert(timestamps, checks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insert(long timestamps[], int values[])
|
||||||
|
{
|
||||||
|
String query = "insert into Checkmarks(habit, timestamp, value) values (?,?,?)";
|
||||||
|
|
||||||
|
SQLiteDatabase db = Cache.openDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (int i = 0; i < nDays; i++)
|
SQLiteStatement statement = db.compileStatement(query);
|
||||||
|
|
||||||
|
for (int i = 0; i < timestamps.length; i++)
|
||||||
{
|
{
|
||||||
Checkmark c = new Checkmark();
|
statement.bindLong(1, habit.getId());
|
||||||
c.habit = habit;
|
statement.bindLong(2, timestamps[i]);
|
||||||
c.timestamp = to - i * day;
|
statement.bindLong(3, values[i]);
|
||||||
c.value = checks[i];
|
statement.execute();
|
||||||
c.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActiveAndroid.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ActiveAndroid.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ import com.activeandroid.Cache;
|
|||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.Delete;
|
||||||
import com.activeandroid.query.From;
|
import com.activeandroid.query.From;
|
||||||
import com.activeandroid.query.Select;
|
import com.activeandroid.query.Select;
|
||||||
|
import com.activeandroid.util.SQLiteUtils;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.helpers.DatabaseHelper;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -96,22 +98,21 @@ public class RepetitionList
|
|||||||
timestamp = DateHelper.getStartOfDay(timestamp);
|
timestamp = DateHelper.getStartOfDay(timestamp);
|
||||||
|
|
||||||
if (contains(timestamp))
|
if (contains(timestamp))
|
||||||
{
|
|
||||||
delete(timestamp);
|
delete(timestamp);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
insert(timestamp);
|
||||||
Repetition rep = new Repetition();
|
|
||||||
rep.habit = habit;
|
|
||||||
rep.timestamp = timestamp;
|
|
||||||
rep.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
habit.scores.invalidateNewerThan(timestamp);
|
habit.scores.invalidateNewerThan(timestamp);
|
||||||
habit.checkmarks.deleteNewerThan(timestamp);
|
habit.checkmarks.deleteNewerThan(timestamp);
|
||||||
habit.streaks.deleteNewerThan(timestamp);
|
habit.streaks.deleteNewerThan(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void insert(long timestamp)
|
||||||
|
{
|
||||||
|
String[] args = { habit.getId().toString(), Long.toString(timestamp) };
|
||||||
|
SQLiteUtils.execSql("insert into Repetitions(habit, timestamp) values (?,?)", args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the oldest repetition for the habit. If there is no repetition, returns null.
|
* Returns the oldest repetition for the habit. If there is no repetition, returns null.
|
||||||
* Repetitions in the future are discarded.
|
* Repetitions in the future are discarded.
|
||||||
@@ -124,6 +125,21 @@ public class RepetitionList
|
|||||||
return (Repetition) select().limit(1).executeSingle();
|
return (Repetition) select().limit(1).executeSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the timestamp of the oldest repetition. If there are no repetitions, returns zero.
|
||||||
|
* Repetitions in the future are discarded.
|
||||||
|
*
|
||||||
|
* @return timestamp of the oldest repetition
|
||||||
|
*/
|
||||||
|
public long getOldestTimestamp()
|
||||||
|
{
|
||||||
|
String[] args = { habit.getId().toString(), Long.toString(DateHelper.getStartOfToday()) };
|
||||||
|
String query = "select timestamp from Repetitions where habit = ? and timestamp <= ? " +
|
||||||
|
"order by timestamp limit 1";
|
||||||
|
|
||||||
|
return DatabaseHelper.longQuery(query, args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of repetitions for each month, from the first repetition until
|
* Returns the total number of repetitions for each month, from the first repetition until
|
||||||
* today, grouped by day of week. The repetitions are returned in a HashMap. The key is the
|
* today, grouped by day of week. The repetitions are returned in a HashMap. The key is the
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package org.isoron.uhabits.models;
|
|||||||
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteStatement;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
@@ -28,9 +29,11 @@ import com.activeandroid.Cache;
|
|||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.Delete;
|
||||||
import com.activeandroid.query.From;
|
import com.activeandroid.query.From;
|
||||||
import com.activeandroid.query.Select;
|
import com.activeandroid.query.Select;
|
||||||
|
import com.activeandroid.util.SQLiteUtils;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DatabaseHelper;
|
import org.isoron.uhabits.helpers.DatabaseHelper;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
@@ -60,31 +63,6 @@ public class ScoreList
|
|||||||
.orderBy("timestamp desc");
|
.orderBy("timestamp desc");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent score already computed. If no score has been computed yet, returns
|
|
||||||
* null.
|
|
||||||
*
|
|
||||||
* @return newest score, or null if none exist
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
protected Score findNewest()
|
|
||||||
{
|
|
||||||
return select().limit(1).executeSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the most recent score that was already computed. If no score has been
|
|
||||||
* computed yet, returns zero.
|
|
||||||
*
|
|
||||||
* @return value of newest score, or zero if none exist
|
|
||||||
*/
|
|
||||||
protected int findNewestValue()
|
|
||||||
{
|
|
||||||
Score newest = findNewest();
|
|
||||||
if(newest == null) return 0;
|
|
||||||
else return newest.score;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks all scores that have timestamp equal to or newer than the given timestamp as invalid.
|
* Marks all scores that have timestamp equal to or newer than the given timestamp as invalid.
|
||||||
* Any following getValue calls will trigger the scores to be recomputed.
|
* Any following getValue calls will trigger the scores to be recomputed.
|
||||||
@@ -104,10 +82,9 @@ public class ScoreList
|
|||||||
*/
|
*/
|
||||||
private void computeAll()
|
private void computeAll()
|
||||||
{
|
{
|
||||||
Repetition oldestRep = habit.repetitions.getOldest();
|
long fromTimestamp = habit.repetitions.getOldestTimestamp();
|
||||||
if(oldestRep == null) return;
|
if(fromTimestamp == 0) return;
|
||||||
|
|
||||||
long fromTimestamp = oldestRep.timestamp;
|
|
||||||
long toTimestamp = DateHelper.getStartOfToday();
|
long toTimestamp = DateHelper.getStartOfToday();
|
||||||
compute(fromTimestamp, toTimestamp);
|
compute(fromTimestamp, toTimestamp);
|
||||||
}
|
}
|
||||||
@@ -126,38 +103,82 @@ public class ScoreList
|
|||||||
*/
|
*/
|
||||||
protected void compute(long from, long to)
|
protected void compute(long from, long to)
|
||||||
{
|
{
|
||||||
|
UIHelper.throwIfMainThread();
|
||||||
|
|
||||||
final long day = DateHelper.millisecondsInOneDay;
|
final long day = DateHelper.millisecondsInOneDay;
|
||||||
final double freq = ((double) habit.freqNum) / habit.freqDen;
|
final double freq = ((double) habit.freqNum) / habit.freqDen;
|
||||||
|
|
||||||
int newestScoreValue = findNewestValue();
|
int newestScoreValue = findNewestValue();
|
||||||
Score newestScore = findNewest();
|
long newestTimestamp = findNewestTimestamp();
|
||||||
|
|
||||||
if(newestScore != null)
|
if(newestTimestamp > 0)
|
||||||
from = newestScore.timestamp + day;
|
from = newestTimestamp + day;
|
||||||
|
|
||||||
final int checkmarkValues[] = habit.checkmarks.getValues(from, to);
|
final int checkmarkValues[] = habit.checkmarks.getValues(from, to);
|
||||||
final int firstScore = newestScoreValue;
|
|
||||||
final long beginning = from;
|
final long beginning = from;
|
||||||
|
|
||||||
DatabaseHelper.executeAsTransaction(new DatabaseHelper.Command()
|
int lastScore = newestScoreValue;
|
||||||
{
|
int size = checkmarkValues.length;
|
||||||
@Override
|
|
||||||
public void execute()
|
long timestamps[] = new long[size];
|
||||||
{
|
long values[] = new long[size];
|
||||||
int lastScore = firstScore;
|
|
||||||
|
|
||||||
for (int i = 0; i < checkmarkValues.length; i++)
|
for (int i = 0; i < checkmarkValues.length; i++)
|
||||||
{
|
{
|
||||||
int checkmarkValue = checkmarkValues[checkmarkValues.length - i - 1];
|
int checkmarkValue = checkmarkValues[checkmarkValues.length - i - 1];
|
||||||
|
lastScore = Score.compute(freq, lastScore, checkmarkValue);
|
||||||
|
timestamps[i] = beginning + day * i;
|
||||||
|
values[i] = lastScore;
|
||||||
|
}
|
||||||
|
|
||||||
Score s = new Score();
|
insert(timestamps, values);
|
||||||
s.habit = habit;
|
|
||||||
s.timestamp = beginning + day * i;
|
|
||||||
s.score = lastScore = Score.compute(freq, lastScore, checkmarkValue);
|
|
||||||
s.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the most recent score that was already computed. If no score has been
|
||||||
|
* computed yet, returns zero.
|
||||||
|
*
|
||||||
|
* @return value of newest score, or zero if none exist
|
||||||
|
*/
|
||||||
|
protected int findNewestValue()
|
||||||
|
{
|
||||||
|
String args[] = { habit.getId().toString() };
|
||||||
|
String query = "select score from Score where habit = ? order by timestamp desc limit 1";
|
||||||
|
return SQLiteUtils.intQuery(query, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long findNewestTimestamp()
|
||||||
|
{
|
||||||
|
String args[] = { habit.getId().toString() };
|
||||||
|
String query = "select timestamp from Score where habit = ? order by timestamp desc limit 1";
|
||||||
|
return DatabaseHelper.longQuery(query, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insert(long timestamps[], long values[])
|
||||||
|
{
|
||||||
|
String query = "insert into Score(habit, timestamp, score) values (?,?,?)";
|
||||||
|
|
||||||
|
SQLiteDatabase db = Cache.openDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SQLiteStatement statement = db.compileStatement(query);
|
||||||
|
|
||||||
|
for (int i = 0; i < timestamps.length; i++)
|
||||||
|
{
|
||||||
|
statement.bindLong(1, habit.getId());
|
||||||
|
statement.bindLong(2, timestamps[i]);
|
||||||
|
statement.bindLong(3, values[i]);
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,9 +206,9 @@ public class ScoreList
|
|||||||
*/
|
*/
|
||||||
public int getValue(long timestamp)
|
public int getValue(long timestamp)
|
||||||
{
|
{
|
||||||
Score s = get(timestamp);
|
computeAll();
|
||||||
if(s == null) return 0;
|
String[] args = { habit.getId().toString(), Long.toString(timestamp) };
|
||||||
else return s.score;
|
return SQLiteUtils.intQuery("select score from Score where habit = ? and timestamp = ?", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.activeandroid.query.Delete;
|
|||||||
import com.activeandroid.query.Select;
|
import com.activeandroid.query.Select;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -86,6 +87,8 @@ public class StreakList
|
|||||||
|
|
||||||
public void rebuild()
|
public void rebuild()
|
||||||
{
|
{
|
||||||
|
UIHelper.throwIfMainThread();
|
||||||
|
|
||||||
long beginning;
|
long beginning;
|
||||||
long today = DateHelper.getStartOfToday();
|
long today = DateHelper.getStartOfToday();
|
||||||
long day = DateHelper.millisecondsInOneDay;
|
long day = DateHelper.millisecondsInOneDay;
|
||||||
|
|||||||
@@ -20,42 +20,53 @@
|
|||||||
package org.isoron.uhabits.tasks;
|
package org.isoron.uhabits.tasks;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class BaseTask extends AsyncTask<Void, Void, Void>
|
public abstract class BaseTask extends AsyncTask<Void, Integer, Void>
|
||||||
{
|
{
|
||||||
private static CountDownLatch latch;
|
|
||||||
private static int activeTaskCount;
|
private static int activeTaskCount;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute()
|
protected void onPreExecute()
|
||||||
{
|
{
|
||||||
|
super.onPreExecute();
|
||||||
activeTaskCount++;
|
activeTaskCount++;
|
||||||
latch = new CountDownLatch(activeTaskCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Void aVoid)
|
protected void onPostExecute(Void aVoid)
|
||||||
{
|
{
|
||||||
activeTaskCount--;
|
activeTaskCount--;
|
||||||
latch.countDown();
|
super.onPostExecute(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void waitForTasks(long timeout, TimeUnit unit)
|
@Override
|
||||||
|
protected final Void doInBackground(Void... params)
|
||||||
|
{
|
||||||
|
doInBackground();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void doInBackground();
|
||||||
|
|
||||||
|
public static void waitForTasks(long timeout)
|
||||||
throws TimeoutException, InterruptedException
|
throws TimeoutException, InterruptedException
|
||||||
|
{
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
|
||||||
|
throw new UnsupportedOperationException("waitForTasks requires API 16+");
|
||||||
|
|
||||||
|
int poolInterval = 100;
|
||||||
|
|
||||||
|
while(timeout > 0)
|
||||||
{
|
{
|
||||||
if(activeTaskCount == 0) return;
|
if(activeTaskCount == 0) return;
|
||||||
|
|
||||||
boolean successful = latch.await(timeout, unit);
|
timeout -= poolInterval;
|
||||||
if(!successful) throw new TimeoutException();
|
Thread.sleep(poolInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TimeoutException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.tasks;
|
package org.isoron.uhabits.tasks;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
@@ -80,12 +79,12 @@ public class ExportCSVTask extends BaseTask
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params)
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File dir = DatabaseHelper.getFilesDir("CSV");
|
File dir = DatabaseHelper.getFilesDir("CSV");
|
||||||
if(dir == null) return null;
|
if(dir == null) return;
|
||||||
|
|
||||||
HabitsCSVExporter exporter = new HabitsCSVExporter(selectedHabits, dir);
|
HabitsCSVExporter exporter = new HabitsCSVExporter(selectedHabits, dir);
|
||||||
archiveFilename = exporter.writeArchive();
|
archiveFilename = exporter.writeArchive();
|
||||||
@@ -94,7 +93,5 @@ public class ExportCSVTask extends BaseTask
|
|||||||
{
|
{
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.tasks;
|
package org.isoron.uhabits.tasks;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
@@ -75,14 +74,14 @@ public class ExportDBTask extends BaseTask
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params)
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
filename = null;
|
filename = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File dir = DatabaseHelper.getFilesDir("Backups");
|
File dir = DatabaseHelper.getFilesDir("Backups");
|
||||||
if(dir == null) return null;
|
if(dir == null) return;
|
||||||
|
|
||||||
filename = DatabaseHelper.saveDatabaseCopy(dir);
|
filename = DatabaseHelper.saveDatabaseCopy(dir);
|
||||||
}
|
}
|
||||||
@@ -90,7 +89,5 @@ public class ExportDBTask extends BaseTask
|
|||||||
{
|
{
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.tasks;
|
package org.isoron.uhabits.tasks;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -86,7 +85,7 @@ public class ImportDataTask extends BaseTask
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params)
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -106,7 +105,5 @@ public class ImportDataTask extends BaseTask
|
|||||||
result = FAILED;
|
result = FAILED;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,10 +38,9 @@ public class ToggleRepetitionTask extends BaseTask
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params)
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
habit.repetitions.toggle(timestamp);
|
habit.repetitions.toggle(timestamp);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,20 +30,18 @@ import android.text.Layout;
|
|||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
public class CheckmarkView extends View
|
public class CheckmarkView extends View implements HabitDataView
|
||||||
{
|
{
|
||||||
private Paint pCard;
|
private Paint pCard;
|
||||||
private Paint pIcon;
|
private Paint pIcon;
|
||||||
|
|
||||||
private int primaryColor;
|
private int primaryColor;
|
||||||
private int backgroundColor;
|
|
||||||
private int timesColor;
|
private int timesColor;
|
||||||
private int darkGrey;
|
private int darkGrey;
|
||||||
|
|
||||||
@@ -56,12 +54,8 @@ public class CheckmarkView extends View
|
|||||||
|
|
||||||
private String fa_check;
|
private String fa_check;
|
||||||
private String fa_times;
|
private String fa_times;
|
||||||
private String fa_full_star;
|
|
||||||
private String fa_half_star;
|
|
||||||
private String fa_empty_star;
|
|
||||||
|
|
||||||
private int check_status;
|
private int check_status;
|
||||||
private int star_status;
|
|
||||||
|
|
||||||
private Rect rect;
|
private Rect rect;
|
||||||
private TextPaint textPaint;
|
private TextPaint textPaint;
|
||||||
@@ -99,25 +93,19 @@ public class CheckmarkView extends View
|
|||||||
|
|
||||||
fa_check = context.getString(R.string.fa_check);
|
fa_check = context.getString(R.string.fa_check);
|
||||||
fa_times = context.getString(R.string.fa_times);
|
fa_times = context.getString(R.string.fa_times);
|
||||||
fa_empty_star = context.getString(R.string.fa_star_o);
|
|
||||||
fa_half_star = context.getString(R.string.fa_star_half_o);
|
|
||||||
fa_full_star = context.getString(R.string.fa_star);
|
|
||||||
|
|
||||||
primaryColor = ColorHelper.palette[10];
|
primaryColor = ColorHelper.palette[10];
|
||||||
backgroundColor = Color.argb(255, 255, 255, 255);
|
|
||||||
timesColor = Color.argb(128, 255, 255, 255);
|
timesColor = Color.argb(128, 255, 255, 255);
|
||||||
darkGrey = Color.argb(64, 0, 0, 0);
|
darkGrey = Color.argb(64, 0, 0, 0);
|
||||||
|
|
||||||
rect = new Rect();
|
rect = new Rect();
|
||||||
check_status = 2;
|
check_status = 0;
|
||||||
star_status = 0;
|
label = "Habit";
|
||||||
label = "Wake up early";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHabit(Habit habit)
|
public void setHabit(Habit habit)
|
||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
refreshData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -190,21 +178,25 @@ public class CheckmarkView extends View
|
|||||||
padding = 8 * leftMargin;
|
padding = 8 * leftMargin;
|
||||||
textPaint.setTextSize(0.15f * width);
|
textPaint.setTextSize(0.15f * width);
|
||||||
|
|
||||||
refreshData();
|
updateLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshData()
|
public void refreshData()
|
||||||
{
|
{
|
||||||
this.check_status = habit.checkmarks.getTodayValue();
|
this.check_status = habit.checkmarks.getTodayValue();
|
||||||
this.star_status = habit.scores.getTodayStarStatus();
|
|
||||||
this.primaryColor = Color.argb(230, Color.red(habit.color), Color.green(habit.color),
|
this.primaryColor = Color.argb(230, Color.red(habit.color), Color.green(habit.color),
|
||||||
Color.blue(habit.color));
|
Color.blue(habit.color));
|
||||||
this.label = habit.name;
|
this.label = habit.name;
|
||||||
|
|
||||||
|
updateLabel();
|
||||||
|
postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLabel()
|
||||||
|
{
|
||||||
textPaint.setColor(Color.WHITE);
|
textPaint.setColor(Color.WHITE);
|
||||||
labelLayout = new StaticLayout(label, textPaint,
|
labelLayout = new StaticLayout(label, textPaint,
|
||||||
(int) (width - 2 * leftMargin - 2 * padding),
|
(int) (width - 2 * leftMargin - 2 * padding),
|
||||||
Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
|
Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,4 +26,6 @@ public interface HabitDataView
|
|||||||
void setHabit(Habit habit);
|
void setHabit(Habit habit);
|
||||||
|
|
||||||
void refreshData();
|
void refreshData();
|
||||||
|
|
||||||
|
void postInvalidate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,13 +84,10 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
createColors();
|
createColors();
|
||||||
refreshData();
|
|
||||||
postInvalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
refreshData();
|
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
|
|
||||||
@@ -181,7 +178,7 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV
|
|||||||
else if(habit != null)
|
else if(habit != null)
|
||||||
frequency = habit.repetitions.getWeekdayFrequency();
|
frequency = habit.repetitions.getWeekdayFrequency();
|
||||||
|
|
||||||
invalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateRandomData()
|
private void generateRandomData()
|
||||||
|
|||||||
@@ -26,15 +26,15 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Paint.Align;
|
import android.graphics.Paint.Align;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.HapticFeedbackConstants;
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
import org.isoron.uhabits.tasks.ToggleRepetitionTask;
|
import org.isoron.uhabits.tasks.ToggleRepetitionTask;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -89,13 +89,10 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
createColors();
|
createColors();
|
||||||
refreshData();
|
|
||||||
postInvalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
refreshData();
|
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
|
|
||||||
@@ -136,7 +133,7 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
|
|||||||
float baseSize = height / 8.0f;
|
float baseSize = height / 8.0f;
|
||||||
setScrollerBucketSize((int) baseSize);
|
setScrollerBucketSize((int) baseSize);
|
||||||
|
|
||||||
squareSpacing = DialogHelper.dpToPixels(getContext(), 1.0f);
|
squareSpacing = UIHelper.dpToPixels(getContext(), 1.0f);
|
||||||
float maxTextSize = getResources().getDimensionPixelSize(R.dimen.regularTextSize);
|
float maxTextSize = getResources().getDimensionPixelSize(R.dimen.regularTextSize);
|
||||||
float textSize = Math.min(baseSize * 0.5f, maxTextSize);
|
float textSize = Math.min(baseSize * 0.5f, maxTextSize);
|
||||||
|
|
||||||
@@ -221,7 +218,7 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateDate();
|
updateDate();
|
||||||
invalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateRandomData()
|
private void generateRandomData()
|
||||||
@@ -388,11 +385,23 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie
|
|||||||
this.isEditable = isEditable;
|
this.isEditable = isEditable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onToggleRepetitionFinished()
|
public void onToggleRepetitionFinished()
|
||||||
|
{
|
||||||
|
new BaseTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doInBackground()
|
||||||
{
|
{
|
||||||
refreshData();
|
refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid)
|
||||||
|
{
|
||||||
invalidate();
|
invalidate();
|
||||||
|
super.onPostExecute(null);
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,15 +93,12 @@ public class HabitScoreView extends ScrollableDataView implements HabitDataView
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
createColors();
|
createColors();
|
||||||
refreshData();
|
|
||||||
postInvalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
if(isInEditMode()) refreshData();
|
|
||||||
|
|
||||||
dfYear = new SimpleDateFormat("yyyy", Locale.getDefault());
|
dfYear = new SimpleDateFormat("yyyy", Locale.getDefault());
|
||||||
dfMonth = new SimpleDateFormat("MMM", Locale.getDefault());
|
dfMonth = new SimpleDateFormat("MMM", Locale.getDefault());
|
||||||
@@ -186,7 +183,7 @@ public class HabitScoreView extends ScrollableDataView implements HabitDataView
|
|||||||
scores = habit.scores.getAllValues(bucketSize);
|
scores = habit.scores.getAllValues(bucketSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBucketSize(int bucketSize)
|
public void setBucketSize(int bucketSize)
|
||||||
|
|||||||
@@ -78,9 +78,7 @@ public class HabitStreakView extends View implements HabitDataView
|
|||||||
public void setHabit(Habit habit)
|
public void setHabit(Habit habit)
|
||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
|
|
||||||
createColors();
|
createColors();
|
||||||
postInvalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
@@ -93,7 +91,7 @@ public class HabitStreakView extends View implements HabitDataView
|
|||||||
dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
|
dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
|
||||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
rect = new RectF();
|
rect = new RectF();
|
||||||
|
maxStreakCount = 10;
|
||||||
baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize);
|
baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +116,6 @@ public class HabitStreakView extends View implements HabitDataView
|
|||||||
em = paint.getFontSpacing();
|
em = paint.getFontSpacing();
|
||||||
textMargin = 0.5f * em;
|
textMargin = 0.5f * em;
|
||||||
|
|
||||||
refreshData();
|
|
||||||
updateMaxMin();
|
updateMaxMin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import android.view.View;
|
|||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.helpers.ColorHelper;
|
import org.isoron.uhabits.helpers.ColorHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
|
|
||||||
public class NumberView extends View
|
public class NumberView extends View
|
||||||
{
|
{
|
||||||
@@ -66,9 +66,9 @@ public class NumberView extends View
|
|||||||
|
|
||||||
this.textSize = getResources().getDimension(R.dimen.regularTextSize);
|
this.textSize = getResources().getDimension(R.dimen.regularTextSize);
|
||||||
|
|
||||||
this.label = DialogHelper.getAttribute(context, attrs, "label", "Number");
|
this.label = UIHelper.getAttribute(context, attrs, "label", "Number");
|
||||||
this.number = DialogHelper.getIntAttribute(context, attrs, "number", 0);
|
this.number = UIHelper.getIntAttribute(context, attrs, "number", 0);
|
||||||
this.textSize = DialogHelper.getFloatAttribute(context, attrs, "textSize",
|
this.textSize = UIHelper.getFloatAttribute(context, attrs, "textSize",
|
||||||
getResources().getDimension(R.dimen.regularTextSize));
|
getResources().getDimension(R.dimen.regularTextSize));
|
||||||
|
|
||||||
this.color = ColorHelper.palette[7];
|
this.color = ColorHelper.palette[7];
|
||||||
@@ -92,7 +92,6 @@ public class NumberView extends View
|
|||||||
public void setNumber(int number)
|
public void setNumber(int number)
|
||||||
{
|
{
|
||||||
this.number = number;
|
this.number = number;
|
||||||
requestLayout();
|
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import android.util.AttributeSet;
|
|||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.helpers.DateHelper;
|
import org.isoron.uhabits.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@@ -38,14 +38,12 @@ public class RepetitionCountView extends NumberView implements HabitDataView
|
|||||||
public RepetitionCountView(Context context, AttributeSet attrs)
|
public RepetitionCountView(Context context, AttributeSet attrs)
|
||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.interval = DialogHelper.getIntAttribute(context, attrs, "interval", 7);
|
this.interval = UIHelper.getIntAttribute(context, attrs, "interval", 7);
|
||||||
int labelValue = DialogHelper.getIntAttribute(context, attrs, "labelValue", 7);
|
int labelValue = UIHelper.getIntAttribute(context, attrs, "labelValue", 7);
|
||||||
String labelFormat = DialogHelper.getAttribute(context, attrs, "labelFormat",
|
String labelFormat = UIHelper.getAttribute(context, attrs, "labelFormat",
|
||||||
getResources().getString(R.string.last_x_days));
|
getResources().getString(R.string.last_x_days));
|
||||||
|
|
||||||
setLabel(String.format(labelFormat, labelValue));
|
setLabel(String.format(labelFormat, labelValue));
|
||||||
|
|
||||||
refreshData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,6 +71,8 @@ public class RepetitionCountView extends NumberView implements HabitDataView
|
|||||||
|
|
||||||
if(habit != null)
|
if(habit != null)
|
||||||
setNumber(habit.repetitions.count(from, to));
|
setNumber(habit.repetitions.count(from, to));
|
||||||
|
|
||||||
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -80,6 +80,5 @@ public class RepetitionCountView extends NumberView implements HabitDataView
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
setColor(habit.color);
|
setColor(habit.color);
|
||||||
refreshData();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,10 @@ import android.text.Layout;
|
|||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
|
|
||||||
public class RingView extends View
|
public class RingView extends View
|
||||||
{
|
{
|
||||||
@@ -63,9 +62,9 @@ public class RingView extends View
|
|||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
this.label = DialogHelper.getAttribute(context, attrs, "label", "Label");
|
this.label = UIHelper.getAttribute(context, attrs, "label", "Label");
|
||||||
this.maxDiameter = DialogHelper.getFloatAttribute(context, attrs, "maxDiameter", 100);
|
this.maxDiameter = UIHelper.getFloatAttribute(context, attrs, "maxDiameter", 100);
|
||||||
this.maxDiameter = DialogHelper.dpToPixels(context, maxDiameter);
|
this.maxDiameter = UIHelper.dpToPixels(context, maxDiameter);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +97,6 @@ public class RingView extends View
|
|||||||
|
|
||||||
fadedTextColor = getResources().getColor(R.color.fadedTextColor);
|
fadedTextColor = getResources().getColor(R.color.fadedTextColor);
|
||||||
textSize = getResources().getDimension(R.dimen.smallTextSize);
|
textSize = getResources().getDimension(R.dimen.smallTextSize);
|
||||||
Log.d("RingView", String.format("textSize=%f", textSize));
|
|
||||||
|
|
||||||
rect = new RectF();
|
rect = new RectF();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ import android.view.View;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
|
|
||||||
import org.isoron.uhabits.helpers.DialogHelper;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.helpers.UIHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -92,12 +93,12 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateWidget(Context context, AppWidgetManager manager, int widgetId, Bundle options)
|
private void updateWidget(Context context, AppWidgetManager manager,
|
||||||
|
int widgetId, Bundle options)
|
||||||
{
|
{
|
||||||
updateWidgetSize(context, options);
|
updateWidgetSize(context, options);
|
||||||
|
|
||||||
Context appContext = context.getApplicationContext();
|
Context appContext = context.getApplicationContext();
|
||||||
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), getLayoutId());
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
|
||||||
|
|
||||||
Long habitId = prefs.getLong(getHabitIdKey(widgetId), -1L);
|
Long habitId = prefs.getLong(getHabitIdKey(widgetId), -1L);
|
||||||
@@ -112,24 +113,11 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
View widgetView = buildCustomView(context, habit);
|
new RenderWidgetTask(widgetId, context, habit, manager).execute();
|
||||||
measureCustomView(context, width, height, widgetView);
|
|
||||||
|
|
||||||
widgetView.setDrawingCacheEnabled(true);
|
|
||||||
widgetView.buildDrawingCache(true);
|
|
||||||
Bitmap drawingCache = widgetView.getDrawingCache();
|
|
||||||
|
|
||||||
remoteViews.setTextViewText(R.id.label, habit.name);
|
|
||||||
remoteViews.setImageViewBitmap(R.id.imageView, drawingCache);
|
|
||||||
|
|
||||||
//savePreview(context, widgetId, drawingCache);
|
|
||||||
|
|
||||||
PendingIntent onClickIntent = getOnClickPendingIntent(context, habit);
|
|
||||||
if(onClickIntent != null) remoteViews.setOnClickPendingIntent(R.id.imageView, onClickIntent);
|
|
||||||
|
|
||||||
manager.updateAppWidget(widgetId, remoteViews);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void refreshCustomViewData(View widgetView);
|
||||||
|
|
||||||
private void savePreview(Context context, int widgetId, Bitmap widgetCache)
|
private void savePreview(Context context, int widgetId, Bitmap widgetCache)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -170,13 +158,13 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
|
|||||||
|
|
||||||
if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
|
if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
|
||||||
{
|
{
|
||||||
maxWidth = (int) DialogHelper.dpToPixels(context,
|
maxWidth = (int) UIHelper.dpToPixels(context,
|
||||||
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH));
|
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH));
|
||||||
maxHeight = (int) DialogHelper.dpToPixels(context,
|
maxHeight = (int) UIHelper.dpToPixels(context,
|
||||||
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT));
|
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT));
|
||||||
minWidth = (int) DialogHelper.dpToPixels(context,
|
minWidth = (int) UIHelper.dpToPixels(context,
|
||||||
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH));
|
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH));
|
||||||
minHeight = (int) DialogHelper.dpToPixels(context,
|
minHeight = (int) UIHelper.dpToPixels(context,
|
||||||
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT));
|
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,4 +192,60 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
|
|||||||
customView.measure(specWidth, specHeight);
|
customView.measure(specWidth, specHeight);
|
||||||
customView.layout(0, 0, customView.getMeasuredWidth(), customView.getMeasuredHeight());
|
customView.layout(0, 0, customView.getMeasuredWidth(), customView.getMeasuredHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RenderWidgetTask extends BaseTask
|
||||||
|
{
|
||||||
|
private final int widgetId;
|
||||||
|
private final Context context;
|
||||||
|
private final Habit habit;
|
||||||
|
private final AppWidgetManager manager;
|
||||||
|
public RemoteViews remoteViews;
|
||||||
|
public View widgetView;
|
||||||
|
|
||||||
|
public RenderWidgetTask(int widgetId, Context context, Habit habit,
|
||||||
|
AppWidgetManager manager)
|
||||||
|
{
|
||||||
|
this.widgetId = widgetId;
|
||||||
|
this.context = context;
|
||||||
|
this.habit = habit;
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute()
|
||||||
|
{
|
||||||
|
super.onPreExecute();
|
||||||
|
|
||||||
|
remoteViews = new RemoteViews(context.getPackageName(), getLayoutId());
|
||||||
|
widgetView = buildCustomView(context, habit);
|
||||||
|
measureCustomView(context, width, height, widgetView);
|
||||||
|
manager.updateAppWidget(widgetId, remoteViews);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doInBackground()
|
||||||
|
{
|
||||||
|
refreshCustomViewData(widgetView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid)
|
||||||
|
{
|
||||||
|
widgetView.invalidate();
|
||||||
|
widgetView.setDrawingCacheEnabled(true);
|
||||||
|
widgetView.buildDrawingCache(true);
|
||||||
|
Bitmap drawingCache = widgetView.getDrawingCache();
|
||||||
|
remoteViews.setTextViewText(R.id.label, habit.name);
|
||||||
|
remoteViews.setImageViewBitmap(R.id.imageView, drawingCache);
|
||||||
|
|
||||||
|
//savePreview(context, widgetId, drawingCache);
|
||||||
|
|
||||||
|
PendingIntent onClickIntent = getOnClickPendingIntent(context, habit);
|
||||||
|
if(onClickIntent != null) remoteViews.setOnClickPendingIntent(R.id.imageView, onClickIntent);
|
||||||
|
|
||||||
|
manager.updateAppWidget(widgetId, remoteViews);
|
||||||
|
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.isoron.uhabits.HabitBroadcastReceiver;
|
|||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.views.CheckmarkView;
|
import org.isoron.uhabits.views.CheckmarkView;
|
||||||
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
|
|
||||||
public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
||||||
{
|
{
|
||||||
@@ -37,6 +38,12 @@ public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshCustomViewData(View view)
|
||||||
|
{
|
||||||
|
((HabitDataView) view).refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
||||||
{
|
{
|
||||||
@@ -60,4 +67,6 @@ public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
|||||||
{
|
{
|
||||||
return R.layout.widget_checkmark;
|
return R.layout.widget_checkmark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.view.View;
|
|||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
import org.isoron.uhabits.views.HabitFrequencyView;
|
import org.isoron.uhabits.views.HabitFrequencyView;
|
||||||
|
|
||||||
public class FrequencyWidgetProvider extends BaseWidgetProvider
|
public class FrequencyWidgetProvider extends BaseWidgetProvider
|
||||||
@@ -39,6 +40,12 @@ public class FrequencyWidgetProvider extends BaseWidgetProvider
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshCustomViewData(View view)
|
||||||
|
{
|
||||||
|
((HabitDataView) view).refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.view.View;
|
|||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
import org.isoron.uhabits.views.HabitHistoryView;
|
import org.isoron.uhabits.views.HabitHistoryView;
|
||||||
|
|
||||||
public class HistoryWidgetProvider extends BaseWidgetProvider
|
public class HistoryWidgetProvider extends BaseWidgetProvider
|
||||||
@@ -38,6 +39,12 @@ public class HistoryWidgetProvider extends BaseWidgetProvider
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshCustomViewData(View view)
|
||||||
|
{
|
||||||
|
((HabitDataView) view).refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.view.View;
|
|||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
import org.isoron.uhabits.views.HabitScoreView;
|
import org.isoron.uhabits.views.HabitScoreView;
|
||||||
|
|
||||||
public class ScoreWidgetProvider extends BaseWidgetProvider
|
public class ScoreWidgetProvider extends BaseWidgetProvider
|
||||||
@@ -38,6 +39,12 @@ public class ScoreWidgetProvider extends BaseWidgetProvider
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshCustomViewData(View view)
|
||||||
|
{
|
||||||
|
((HabitDataView) view).refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.view.View;
|
|||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.views.HabitDataView;
|
||||||
import org.isoron.uhabits.views.HabitStreakView;
|
import org.isoron.uhabits.views.HabitStreakView;
|
||||||
|
|
||||||
public class StreakWidgetProvider extends BaseWidgetProvider
|
public class StreakWidgetProvider extends BaseWidgetProvider
|
||||||
@@ -38,6 +39,12 @@ public class StreakWidgetProvider extends BaseWidgetProvider
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshCustomViewData(View view)
|
||||||
|
{
|
||||||
|
((HabitDataView) view).refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 34 KiB |
@@ -53,75 +53,6 @@
|
|||||||
app:maxDiameter="80"
|
app:maxDiameter="80"
|
||||||
app:textSize="@dimen/smallTextSize"/>
|
app:textSize="@dimen/smallTextSize"/>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
style="@style/smallDataViewStyle"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<org.isoron.uhabits.views.HabitStreakView
|
|
||||||
android:id="@+id/smallStreakView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="80dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/best_streaks"
|
|
||||||
android:layout_marginTop="9dp"
|
|
||||||
android:textColor="@color/fadedTextColor"
|
|
||||||
android:gravity="center"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
style="@style/cardStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="top|start"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvCount"
|
|
||||||
style="@style/cardHeaderStyle"
|
|
||||||
android:text="@string/number_of_repetitions"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/llRepetition"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<org.isoron.uhabits.views.RepetitionCountView
|
|
||||||
style="@style/smallDataViewStyle"
|
|
||||||
app:interval="30"
|
|
||||||
app:labelFormat="@string/last_x_days"
|
|
||||||
app:labelValue="30"
|
|
||||||
app:textSize="12"/>
|
|
||||||
|
|
||||||
<org.isoron.uhabits.views.RepetitionCountView
|
|
||||||
style="@style/smallDataViewStyle"
|
|
||||||
app:interval="92"
|
|
||||||
app:labelFormat="@string/last_x_months"
|
|
||||||
app:labelValue="4"
|
|
||||||
app:textSize="12"/>
|
|
||||||
|
|
||||||
<org.isoron.uhabits.views.RepetitionCountView
|
|
||||||
style="@style/smallDataViewStyle"
|
|
||||||
app:interval="365"
|
|
||||||
app:labelFormat="@string/last_x_months"
|
|
||||||
app:labelValue="12"
|
|
||||||
app:textSize="12"/>
|
|
||||||
|
|
||||||
<org.isoron.uhabits.views.RepetitionCountView
|
|
||||||
style="@style/smallDataViewStyle"
|
|
||||||
app:interval="0"
|
|
||||||
app:label="@string/all_time"
|
|
||||||
app:textSize="12"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user