mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Some refactoring; add tests for ListHabitsScreen
This commit is contained in:
@@ -24,15 +24,12 @@ import android.content.*;
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.test.*;
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
@@ -43,8 +40,6 @@ import static junit.framework.Assert.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class BaseAndroidTest
|
||||
{
|
||||
// 8:00am, January 25th, 2015 (UTC)
|
||||
|
||||
@@ -21,11 +21,8 @@ package org.isoron.uhabits;
|
||||
|
||||
import android.content.*;
|
||||
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.intents.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.sqlite.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
@@ -42,52 +39,21 @@ public class AndroidModule
|
||||
{
|
||||
@Provides
|
||||
@Singleton
|
||||
CommandRunner provideCommandRunner()
|
||||
{
|
||||
return new CommandRunner();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
HabitList provideHabitList()
|
||||
static HabitList provideHabitList()
|
||||
{
|
||||
return SQLiteHabitList.getInstance();
|
||||
}
|
||||
|
||||
@Provides
|
||||
ModelFactory provideModelFactory()
|
||||
static ModelFactory provideModelFactory()
|
||||
{
|
||||
return new SQLModelFactory();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Preferences providePreferences()
|
||||
static Context provideApplicationContext()
|
||||
{
|
||||
return new Preferences();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
WidgetPreferences provideWidgetPreferences()
|
||||
{
|
||||
return new WidgetPreferences();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ReminderScheduler provideReminderScheduler()
|
||||
{
|
||||
Context context = HabitsApplication.getContext();
|
||||
IntentScheduler intentScheduler = new IntentScheduler(context);
|
||||
IntentFactory intentFactory = new IntentFactory(context);
|
||||
return new ReminderScheduler(intentFactory, intentScheduler);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
HabitLogger provideLogger()
|
||||
{
|
||||
return new HabitLogger();
|
||||
return HabitsApplication.getContext();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.intents.*;
|
||||
import org.isoron.uhabits.io.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.receivers.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.ui.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
import org.isoron.uhabits.ui.habits.list.*;
|
||||
import org.isoron.uhabits.ui.habits.list.controllers.*;
|
||||
@@ -40,6 +42,8 @@ import org.isoron.uhabits.widgets.*;
|
||||
*/
|
||||
public interface BaseComponent
|
||||
{
|
||||
IntentFactory getIntentFactory();
|
||||
|
||||
void inject(CheckmarkButtonController checkmarkButtonController);
|
||||
|
||||
void inject(ListHabitsController listHabitsController);
|
||||
@@ -90,7 +94,7 @@ public interface BaseComponent
|
||||
|
||||
void inject(HabitsCSVExporter habitsCSVExporter);
|
||||
|
||||
void inject(BaseDialogFragment baseDialogFragment);
|
||||
void inject(BaseDialog baseDialog);
|
||||
|
||||
void inject(ShowHabitController showHabitController);
|
||||
|
||||
@@ -109,4 +113,12 @@ public interface BaseComponent
|
||||
void inject(ReminderReceiver reminderReceiver);
|
||||
|
||||
void inject(ReminderScheduler reminderScheduler);
|
||||
|
||||
void inject(ListHabitsScreen listHabitsScreen);
|
||||
|
||||
void inject(ShowHabitScreen showHabitScreen);
|
||||
|
||||
void inject(ConfirmDeleteDialog confirmDeleteDialog);
|
||||
|
||||
void inject(PendingIntentFactory pendingIntentFactory);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,17 @@ import org.isoron.uhabits.utils.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
@Singleton
|
||||
public class HabitLogger
|
||||
{
|
||||
@Inject
|
||||
public HabitLogger()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void logReminderScheduled(@NonNull Habit habit,
|
||||
@NonNull Long reminderTime)
|
||||
{
|
||||
|
||||
@@ -26,16 +26,20 @@ import org.isoron.uhabits.tasks.BaseTask;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
/**
|
||||
* A CommandRunner executes and undoes commands.
|
||||
* <p>
|
||||
* CommandRunners also allows objects to subscribe to it, and receive events
|
||||
* whenever a command is performed.
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandRunner
|
||||
{
|
||||
private LinkedList<Listener> listeners;
|
||||
|
||||
@Inject
|
||||
public CommandRunner()
|
||||
{
|
||||
listeners = new LinkedList<>();
|
||||
|
||||
@@ -19,94 +19,53 @@
|
||||
|
||||
package org.isoron.uhabits.intents;
|
||||
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.net.*;
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.receivers.*;
|
||||
import org.isoron.uhabits.ui.about.*;
|
||||
import org.isoron.uhabits.ui.habits.show.*;
|
||||
import org.isoron.uhabits.ui.intro.*;
|
||||
import org.isoron.uhabits.ui.settings.*;
|
||||
|
||||
import static android.app.PendingIntent.*;
|
||||
import javax.inject.*;
|
||||
|
||||
public class IntentFactory
|
||||
{
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
public IntentFactory(@NonNull Context context)
|
||||
@Inject
|
||||
public IntentFactory()
|
||||
{
|
||||
this.context = context;
|
||||
|
||||
}
|
||||
|
||||
public PendingIntent buildAddCheckmark(@NonNull Habit habit,
|
||||
@Nullable Long timestamp)
|
||||
public Intent startAboutActivity(Context context)
|
||||
{
|
||||
Uri data = habit.getUri();
|
||||
Intent checkIntent = new Intent(context, WidgetReceiver.class);
|
||||
checkIntent.setData(data);
|
||||
checkIntent.setAction(WidgetReceiver.ACTION_ADD_REPETITION);
|
||||
if (timestamp != null) checkIntent.putExtra("timestamp", timestamp);
|
||||
return PendingIntent.getBroadcast(context, 1, checkIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
return new Intent(context, AboutActivity.class);
|
||||
}
|
||||
|
||||
public PendingIntent buildDismissNotification()
|
||||
public Intent startIntroActivity(Context context)
|
||||
{
|
||||
Intent deleteIntent = new Intent(context, ReminderReceiver.class);
|
||||
deleteIntent.setAction(WidgetReceiver.ACTION_DISMISS_REMINDER);
|
||||
return PendingIntent.getBroadcast(context, 0, deleteIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
return new Intent(context, IntroActivity.class);
|
||||
}
|
||||
|
||||
public PendingIntent buildShowReminder(@NonNull Habit habit,
|
||||
@Nullable Long reminderTime,
|
||||
long timestamp)
|
||||
public Intent startSettingsActivity(Context context)
|
||||
{
|
||||
Uri uri = habit.getUri();
|
||||
|
||||
Intent intent = new Intent(context, ReminderReceiver.class);
|
||||
intent.setAction(ReminderReceiver.ACTION_SHOW_REMINDER);
|
||||
intent.setData(uri);
|
||||
intent.putExtra("timestamp", timestamp);
|
||||
intent.putExtra("reminderTime", reminderTime);
|
||||
int reqCode = ((int) (habit.getId() % Integer.MAX_VALUE)) + 1;
|
||||
return PendingIntent.getBroadcast(context, reqCode, intent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
return new Intent(context, SettingsActivity.class);
|
||||
}
|
||||
|
||||
public PendingIntent buildSnoozeNotification(@NonNull Habit habit)
|
||||
public Intent startShowHabitActivity(Context context, Habit habit)
|
||||
{
|
||||
Uri data = habit.getUri();
|
||||
Intent snoozeIntent = new Intent(context, ReminderReceiver.class);
|
||||
snoozeIntent.setData(data);
|
||||
snoozeIntent.setAction(ReminderReceiver.ACTION_SNOOZE_REMINDER);
|
||||
return PendingIntent.getBroadcast(context, 0, snoozeIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent buildToggleCheckmark(@NonNull Habit habit,
|
||||
@Nullable Long timestamp)
|
||||
{
|
||||
Uri data = habit.getUri();
|
||||
Intent checkIntent = new Intent(context, WidgetReceiver.class);
|
||||
checkIntent.setData(data);
|
||||
checkIntent.setAction(WidgetReceiver.ACTION_TOGGLE_REPETITION);
|
||||
if (timestamp != null) checkIntent.putExtra("timestamp", timestamp);
|
||||
return PendingIntent.getBroadcast(context, 2, checkIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent buildViewHabit(Habit habit)
|
||||
{
|
||||
Uri uri = habit.getUri();
|
||||
|
||||
Intent intent = new Intent(context, ShowHabitActivity.class);
|
||||
intent.setData(uri);
|
||||
return android.support.v4.app.TaskStackBuilder
|
||||
.create(context)
|
||||
.addNextIntentWithParentStack(intent)
|
||||
.getPendingIntent(0, FLAG_UPDATE_CURRENT);
|
||||
intent.setData(habit.getUri());
|
||||
return intent;
|
||||
}
|
||||
|
||||
public Intent viewFAQ(Context context)
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(context.getString(R.string.helpURL)));
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,17 @@ import android.content.*;
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
import static android.app.AlarmManager.*;
|
||||
import static android.content.Context.*;
|
||||
|
||||
@Singleton
|
||||
public class IntentScheduler
|
||||
{
|
||||
private final AlarmManager manager;
|
||||
|
||||
@Inject
|
||||
public IntentScheduler(@NonNull Context context)
|
||||
{
|
||||
manager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.intents;
|
||||
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.net.*;
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.receivers.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
import static android.app.PendingIntent.*;
|
||||
|
||||
@Singleton
|
||||
public class PendingIntentFactory
|
||||
{
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
@Inject
|
||||
protected IntentFactory intentFactory;
|
||||
|
||||
@Inject
|
||||
public PendingIntentFactory(@NonNull Context context)
|
||||
{
|
||||
this.context = context;
|
||||
HabitsApplication.getComponent().inject(this);
|
||||
}
|
||||
|
||||
public PendingIntent addCheckmark(@NonNull Habit habit,
|
||||
@Nullable Long timestamp)
|
||||
{
|
||||
Uri data = habit.getUri();
|
||||
Intent checkIntent = new Intent(context, WidgetReceiver.class);
|
||||
checkIntent.setData(data);
|
||||
checkIntent.setAction(WidgetReceiver.ACTION_ADD_REPETITION);
|
||||
if (timestamp != null) checkIntent.putExtra("timestamp", timestamp);
|
||||
return PendingIntent.getBroadcast(context, 1, checkIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent dismissNotification()
|
||||
{
|
||||
Intent deleteIntent = new Intent(context, ReminderReceiver.class);
|
||||
deleteIntent.setAction(WidgetReceiver.ACTION_DISMISS_REMINDER);
|
||||
return PendingIntent.getBroadcast(context, 0, deleteIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent showReminder(@NonNull Habit habit,
|
||||
@Nullable Long reminderTime,
|
||||
long timestamp)
|
||||
{
|
||||
Uri uri = habit.getUri();
|
||||
|
||||
Intent intent = new Intent(context, ReminderReceiver.class);
|
||||
intent.setAction(ReminderReceiver.ACTION_SHOW_REMINDER);
|
||||
intent.setData(uri);
|
||||
intent.putExtra("timestamp", timestamp);
|
||||
intent.putExtra("reminderTime", reminderTime);
|
||||
int reqCode = ((int) (habit.getId() % Integer.MAX_VALUE)) + 1;
|
||||
return PendingIntent.getBroadcast(context, reqCode, intent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent snoozeNotification(@NonNull Habit habit)
|
||||
{
|
||||
Uri data = habit.getUri();
|
||||
Intent snoozeIntent = new Intent(context, ReminderReceiver.class);
|
||||
snoozeIntent.setData(data);
|
||||
snoozeIntent.setAction(ReminderReceiver.ACTION_SNOOZE_REMINDER);
|
||||
return PendingIntent.getBroadcast(context, 0, snoozeIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent toggleCheckmark(@NonNull Habit habit,
|
||||
@Nullable Long timestamp)
|
||||
{
|
||||
Uri data = habit.getUri();
|
||||
Intent checkIntent = new Intent(context, WidgetReceiver.class);
|
||||
checkIntent.setData(data);
|
||||
checkIntent.setAction(WidgetReceiver.ACTION_TOGGLE_REPETITION);
|
||||
if (timestamp != null) checkIntent.putExtra("timestamp", timestamp);
|
||||
return PendingIntent.getBroadcast(context, 2, checkIntent,
|
||||
FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent showHabit(Habit habit)
|
||||
{
|
||||
Intent intent = intentFactory.startShowHabitActivity(context, habit);
|
||||
|
||||
return android.support.v4.app.TaskStackBuilder
|
||||
.create(context)
|
||||
.addNextIntentWithParentStack(intent)
|
||||
.getPendingIntent(0, FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
}
|
||||
106
app/src/main/java/org/isoron/uhabits/io/DirFinder.java
Normal file
106
app/src/main/java/org/isoron/uhabits/io/DirFinder.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.io;
|
||||
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.util.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
import static android.support.v4.content.ContextCompat.*;
|
||||
|
||||
/**
|
||||
* A DirFinder locates suitable directories for storing user files.
|
||||
*/
|
||||
public class DirFinder
|
||||
{
|
||||
private static final String TAG = "DirFinder";
|
||||
|
||||
private final Context context;
|
||||
|
||||
@Inject
|
||||
public DirFinder()
|
||||
{
|
||||
context = HabitsApplication.getContext();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public File findSDCardDir(@Nullable String subpath)
|
||||
{
|
||||
File parents[] = new File[]{
|
||||
Environment.getExternalStorageDirectory()
|
||||
};
|
||||
|
||||
return findDir(parents, subpath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public File findStorageDir(@Nullable String relativePath)
|
||||
{
|
||||
File potentialParents[] = getExternalFilesDirs(context, null);
|
||||
|
||||
if (potentialParents == null)
|
||||
{
|
||||
Log.e(TAG, "getFilesDir: getExternalFilesDirs returned null");
|
||||
return null;
|
||||
}
|
||||
|
||||
return findDir(potentialParents, relativePath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private File findDir(@NonNull File potentialParents[],
|
||||
@Nullable String relativePath)
|
||||
{
|
||||
if (relativePath == null) relativePath = "";
|
||||
|
||||
File chosenDir = null;
|
||||
for (File dir : potentialParents)
|
||||
{
|
||||
if (dir == null || !dir.canWrite()) continue;
|
||||
chosenDir = dir;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chosenDir == null)
|
||||
{
|
||||
Log.e(TAG,
|
||||
"getDir: all potential parents are null or non-writable");
|
||||
return null;
|
||||
}
|
||||
|
||||
File dir = new File(
|
||||
String.format("%s/%s/", chosenDir.getAbsolutePath(), relativePath));
|
||||
if (!dir.exists() && !dir.mkdirs())
|
||||
{
|
||||
Log.e(TAG,
|
||||
"getDir: chosen dir does not exist and cannot be created");
|
||||
return null;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,20 @@ package org.isoron.uhabits.models.sqlite;
|
||||
|
||||
import org.isoron.uhabits.models.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
/**
|
||||
* Factory that provides models backed by an SQLite database.
|
||||
*/
|
||||
@Singleton
|
||||
public class SQLModelFactory implements ModelFactory
|
||||
{
|
||||
@Inject
|
||||
public SQLModelFactory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepetitionList buildRepetitionList(Habit habit)
|
||||
{
|
||||
|
||||
@@ -145,14 +145,15 @@ public class ReminderReceiver extends BroadcastReceiver
|
||||
context, 0, contentIntent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
IntentFactory intentFactory = new IntentFactory(context);
|
||||
PendingIntentFactory
|
||||
pendingIntentFactory = new PendingIntentFactory(context);
|
||||
|
||||
PendingIntent dismissPendingIntent;
|
||||
dismissPendingIntent = intentFactory.buildDismissNotification();
|
||||
dismissPendingIntent = pendingIntentFactory.dismissNotification();
|
||||
PendingIntent checkIntentPending =
|
||||
intentFactory.buildAddCheckmark(habit, timestamp);
|
||||
pendingIntentFactory.addCheckmark(habit, timestamp);
|
||||
PendingIntent snoozeIntentPending =
|
||||
intentFactory.buildSnoozeNotification(habit);
|
||||
pendingIntentFactory.snoozeNotification(habit);
|
||||
|
||||
Uri ringtoneUri = RingtoneUtils.getRingtoneUri(context);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v7.app.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
@@ -51,6 +52,8 @@ abstract public class BaseActivity extends AppCompatActivity
|
||||
@Nullable
|
||||
private BaseScreen screen;
|
||||
|
||||
private Toast toast;
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@Nullable Menu menu)
|
||||
{
|
||||
@@ -78,6 +81,30 @@ abstract public class BaseActivity extends AppCompatActivity
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
public void showDialog(AppCompatDialogFragment dialog, String tag)
|
||||
{
|
||||
dialog.show(getSupportFragmentManager(), tag);
|
||||
}
|
||||
|
||||
public void showDialog(AppCompatDialog dialog)
|
||||
{
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a message on the screen.
|
||||
*
|
||||
* @param stringId the string resource id for this message.
|
||||
*/
|
||||
public void showMessage(@StringRes Integer stringId)
|
||||
{
|
||||
if (stringId == null) return;
|
||||
if (toast == null)
|
||||
toast = Toast.makeText(this, stringId, Toast.LENGTH_SHORT);
|
||||
else toast.setText(stringId);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(@Nullable Thread thread,
|
||||
@Nullable Throwable ex)
|
||||
|
||||
@@ -27,12 +27,11 @@ import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v7.app.*;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.support.v7.widget.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.tasks.ProgressBar;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import java.io.*;
|
||||
@@ -48,8 +47,6 @@ public abstract class BaseScreen
|
||||
{
|
||||
protected BaseActivity activity;
|
||||
|
||||
private Toast toast;
|
||||
|
||||
@Nullable
|
||||
private BaseRootView rootView;
|
||||
|
||||
@@ -155,6 +152,11 @@ public abstract class BaseScreen
|
||||
activity.setBaseMenu(menu);
|
||||
}
|
||||
|
||||
public void showMessage(@StringRes int stringId)
|
||||
{
|
||||
activity.showMessage(stringId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root view for this screen.
|
||||
*
|
||||
@@ -179,20 +181,6 @@ public abstract class BaseScreen
|
||||
this.selectionMenu = menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a message on the screen.
|
||||
*
|
||||
* @param stringId the string resource id for this message.
|
||||
*/
|
||||
public void showMessage(@Nullable Integer stringId)
|
||||
{
|
||||
if (stringId == null) return;
|
||||
if (toast == null)
|
||||
toast = Toast.makeText(activity, stringId, Toast.LENGTH_SHORT);
|
||||
else toast.setText(stringId);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
public void showSendEmailScreen(String to, String subject, String content)
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
@@ -225,11 +213,6 @@ public abstract class BaseScreen
|
||||
activity.startSupportActionMode(new ActionModeWrapper());
|
||||
}
|
||||
|
||||
protected void showDialog(AppCompatDialogFragment dialog, String tag)
|
||||
{
|
||||
dialog.show(activity.getSupportFragmentManager(), tag);
|
||||
}
|
||||
|
||||
public void invalidateToolbar()
|
||||
{
|
||||
if (rootView == null) return;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.common.dialogs;
|
||||
|
||||
import android.content.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
/**
|
||||
* Dialog that allows the user to choose a color.
|
||||
*/
|
||||
public class ColorPickerDialog extends com.android.colorpicker.ColorPickerDialog
|
||||
{
|
||||
public static ColorPickerDialog newInstance(int paletteColor)
|
||||
{
|
||||
ColorPickerDialog dialog = new ColorPickerDialog();
|
||||
Context context = dialog.getContext();
|
||||
|
||||
int color = ColorUtils.getColor(context, paletteColor);
|
||||
|
||||
dialog.initialize(R.string.color_picker_default_title,
|
||||
ColorUtils.getPalette(context), color, 4,
|
||||
com.android.colorpicker.ColorPickerDialog.SIZE_SMALL);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public void setListener(OnColorSelectedListener listener)
|
||||
{
|
||||
super.setOnColorSelectedListener(c -> {
|
||||
c = ColorUtils.colorToPaletteIndex(getContext(), c);
|
||||
listener.onColorSelected(c);
|
||||
});
|
||||
}
|
||||
|
||||
public interface OnColorSelectedListener
|
||||
{
|
||||
void onColorSelected(int color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.common.dialogs;
|
||||
|
||||
import android.content.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v7.app.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
/**
|
||||
* Dialog that asks the user confirmation before executing a delete operation.
|
||||
*/
|
||||
public class ConfirmDeleteDialog extends AlertDialog
|
||||
{
|
||||
@BindString(R.string.delete_habits_message)
|
||||
protected String question;
|
||||
|
||||
@BindString(android.R.string.yes)
|
||||
protected String yes;
|
||||
|
||||
@BindString(android.R.string.no)
|
||||
protected String no;
|
||||
|
||||
protected ConfirmDeleteDialog(@NonNull Context context,
|
||||
@NonNull Callback callback)
|
||||
{
|
||||
super(context);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setTitle(R.string.delete_habits);
|
||||
setMessage(question);
|
||||
setButton(BUTTON_POSITIVE, yes, (dialog, which) -> callback.run());
|
||||
setButton(BUTTON_NEGATIVE, no, (dialog, which) -> {});
|
||||
}
|
||||
|
||||
public interface Callback
|
||||
{
|
||||
void run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.common.dialogs;
|
||||
|
||||
import android.content.*;
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
public class DialogFactory
|
||||
{
|
||||
@Inject
|
||||
public DialogFactory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ColorPickerDialog buildColorPicker(int paletteColor)
|
||||
{
|
||||
return ColorPickerDialog.newInstance(paletteColor);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ConfirmDeleteDialog buildConfirmDeleteDialog(
|
||||
@NonNull Context context,
|
||||
@NonNull ConfirmDeleteDialog.Callback callback)
|
||||
{
|
||||
return new ConfirmDeleteDialog(context, callback);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public CreateHabitDialog buildCreateHabitDialog()
|
||||
{
|
||||
return new CreateHabitDialog();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public EditHabitDialog buildEditHabitDialog(Habit habit)
|
||||
{
|
||||
return EditHabitDialog.newInstance(habit);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public FilePickerDialog buildFilePicker(Context context, File dir)
|
||||
{
|
||||
return new FilePickerDialog(context, dir);
|
||||
}
|
||||
}
|
||||
@@ -17,50 +17,43 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.settings;
|
||||
package org.isoron.uhabits.ui.common.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.content.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v7.app.*;
|
||||
import android.view.*;
|
||||
import android.view.WindowManager.*;
|
||||
import android.widget.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.Arrays;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Dialog that allows the user to pick a file.
|
||||
*/
|
||||
public class FilePickerDialog implements AdapterView.OnItemClickListener
|
||||
{
|
||||
private static final String PARENT_DIR = "..";
|
||||
|
||||
private final Activity activity;
|
||||
private final Context context;
|
||||
|
||||
private ListView list;
|
||||
|
||||
private Dialog dialog;
|
||||
private AppCompatDialog dialog;
|
||||
|
||||
private File currentPath;
|
||||
|
||||
public interface OnFileSelectedListener
|
||||
{
|
||||
void onFileSelected(File file);
|
||||
}
|
||||
|
||||
private OnFileSelectedListener listener;
|
||||
|
||||
public FilePickerDialog(Activity activity, File initialDirectory)
|
||||
public FilePickerDialog(Context context, File initialDirectory)
|
||||
{
|
||||
this.activity = activity;
|
||||
this.context = context;
|
||||
|
||||
list = new ListView(activity);
|
||||
list = new ListView(context);
|
||||
list.setOnItemClickListener(this);
|
||||
|
||||
dialog = new Dialog(activity);
|
||||
dialog = new AppCompatDialog(context);
|
||||
dialog.setContentView(list);
|
||||
dialog
|
||||
.getWindow()
|
||||
@@ -69,6 +62,11 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
||||
navigateTo(initialDirectory);
|
||||
}
|
||||
|
||||
public AppCompatDialog getDialog()
|
||||
{
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent,
|
||||
View view,
|
||||
@@ -92,27 +90,14 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
||||
}
|
||||
}
|
||||
|
||||
public void show()
|
||||
{
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public void setListener(OnFileSelectedListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private void navigateTo(File path)
|
||||
public void show()
|
||||
{
|
||||
if (!path.exists()) return;
|
||||
|
||||
File[] dirs = path.listFiles(new ReadableDirFilter());
|
||||
File[] files = path.listFiles(new RegularReadableFileFilter());
|
||||
if (dirs == null || files == null) return;
|
||||
|
||||
this.currentPath = path;
|
||||
dialog.setTitle(currentPath.getPath());
|
||||
list.setAdapter(new FilePickerAdapter(getFileList(path, dirs, files)));
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -144,11 +129,38 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
||||
return fileList;
|
||||
}
|
||||
|
||||
private void navigateTo(File path)
|
||||
{
|
||||
if (!path.exists()) return;
|
||||
|
||||
File[] dirs = path.listFiles(new ReadableDirFilter());
|
||||
File[] files = path.listFiles(new RegularReadableFileFilter());
|
||||
if (dirs == null || files == null) return;
|
||||
|
||||
this.currentPath = path;
|
||||
dialog.setTitle(currentPath.getPath());
|
||||
list.setAdapter(new FilePickerAdapter(getFileList(path, dirs, files)));
|
||||
}
|
||||
|
||||
public interface OnFileSelectedListener
|
||||
{
|
||||
void onFileSelected(File file);
|
||||
}
|
||||
|
||||
private static class ReadableDirFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File file)
|
||||
{
|
||||
return (file.isDirectory() && file.canRead());
|
||||
}
|
||||
}
|
||||
|
||||
private class FilePickerAdapter extends ArrayAdapter<String>
|
||||
{
|
||||
public FilePickerAdapter(@NonNull String[] fileList)
|
||||
{
|
||||
super(FilePickerDialog.this.activity,
|
||||
super(FilePickerDialog.this.context,
|
||||
android.R.layout.simple_list_item_1, fileList);
|
||||
}
|
||||
|
||||
@@ -162,15 +174,6 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReadableDirFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File file)
|
||||
{
|
||||
return (file.isDirectory() && file.canRead());
|
||||
}
|
||||
}
|
||||
|
||||
private class RegularReadableFileFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
@@ -17,7 +17,7 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.habits.edit;
|
||||
package org.isoron.uhabits.ui.common.dialogs;
|
||||
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
@@ -17,63 +17,29 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.habits.edit;
|
||||
package org.isoron.uhabits.ui.common.dialogs;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatDialogFragment;
|
||||
import android.support.v7.app.*;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.utils.DateUtils;
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
/**
|
||||
* Dialog that allows the user to pick one or more days of the week.
|
||||
*/
|
||||
public class WeekdayPickerDialog extends AppCompatDialogFragment implements
|
||||
DialogInterface.OnMultiChoiceClickListener,
|
||||
DialogInterface.OnClickListener
|
||||
{
|
||||
|
||||
public interface OnWeekdaysPickedListener
|
||||
{
|
||||
void onWeekdaysPicked(boolean[] selectedDays);
|
||||
}
|
||||
|
||||
private boolean[] selectedDays;
|
||||
|
||||
private OnWeekdaysPickedListener listener;
|
||||
|
||||
public void setListener(OnWeekdaysPickedListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setSelectedDays(boolean[] selectedDays)
|
||||
{
|
||||
this.selectedDays = selectedDays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder
|
||||
.setTitle(R.string.select_weekdays)
|
||||
.setMultiChoiceItems(DateUtils.getLongDayNames(), selectedDays,
|
||||
this)
|
||||
.setPositiveButton(android.R.string.yes, this)
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean isChecked)
|
||||
{
|
||||
@@ -85,4 +51,35 @@ public class WeekdayPickerDialog extends AppCompatDialogFragment implements
|
||||
{
|
||||
if (listener != null) listener.onWeekdaysPicked(selectedDays);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder
|
||||
.setTitle(R.string.select_weekdays)
|
||||
.setMultiChoiceItems(DateUtils.getLongDayNames(), selectedDays,
|
||||
this)
|
||||
.setPositiveButton(android.R.string.yes, this)
|
||||
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
|
||||
dismiss();
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
public void setListener(OnWeekdaysPickedListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setSelectedDays(boolean[] selectedDays)
|
||||
{
|
||||
this.selectedDays = selectedDays;
|
||||
}
|
||||
|
||||
public interface OnWeekdaysPickedListener
|
||||
{
|
||||
void onWeekdaysPicked(boolean[] selectedDays);
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,14 @@ import android.support.v7.app.*;
|
||||
import android.text.format.*;
|
||||
import android.view.*;
|
||||
|
||||
import com.android.colorpicker.*;
|
||||
import com.android.datetimepicker.time.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.utils.DateUtils;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -40,7 +40,7 @@ import javax.inject.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
||||
public abstract class BaseDialog extends AppCompatDialogFragment
|
||||
{
|
||||
@Nullable
|
||||
protected Habit originalHabit;
|
||||
@@ -60,6 +60,9 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
||||
@Inject
|
||||
protected HabitList habitList;
|
||||
|
||||
@Inject
|
||||
protected DialogFactory dialogFactory;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
@@ -83,7 +86,8 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
||||
if (position < 0 || position > 4) throw new IllegalArgumentException();
|
||||
int freqNums[] = { 1, 1, 2, 5, 3 };
|
||||
int freqDens[] = { 1, 7, 7, 7, 7 };
|
||||
modifiedHabit.setFrequency(new Frequency(freqNums[position], freqDens[position]));
|
||||
modifiedHabit.setFrequency(
|
||||
new Frequency(freqNums[position], freqDens[position]));
|
||||
helper.populateFrequencyFields(modifiedHabit);
|
||||
}
|
||||
|
||||
@@ -169,23 +173,22 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
||||
|
||||
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
||||
dialog.setListener(new OnWeekdaysPickedListener());
|
||||
dialog.setSelectedDays(
|
||||
DateUtils.unpackWeekdayList(reminder.getDays()));
|
||||
dialog.setSelectedDays(DateUtils.unpackWeekdayList(reminder.getDays()));
|
||||
dialog.show(getFragmentManager(), "weekdayPicker");
|
||||
}
|
||||
|
||||
@OnClick(R.id.buttonPickColor)
|
||||
void showColorPicker()
|
||||
{
|
||||
int androidColor =
|
||||
ColorUtils.getColor(getContext(), modifiedHabit.getColor());
|
||||
int color = modifiedHabit.getColor();
|
||||
ColorPickerDialog picker = dialogFactory.buildColorPicker(color);
|
||||
|
||||
ColorPickerDialog picker =
|
||||
ColorPickerDialog.newInstance(R.string.color_picker_default_title,
|
||||
ColorUtils.getPalette(getContext()), androidColor, 4,
|
||||
ColorPickerDialog.SIZE_SMALL);
|
||||
picker.setListener(c -> {
|
||||
prefs.setDefaultHabitColor(c);
|
||||
modifiedHabit.setColor(c);
|
||||
helper.populateColor(c);
|
||||
});
|
||||
|
||||
picker.setOnColorSelectedListener(new OnColorSelectedListener());
|
||||
picker.show(getFragmentManager(), "picker");
|
||||
}
|
||||
|
||||
@@ -198,20 +201,6 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
||||
timePicker.show(getFragmentManager(), "timePicker");
|
||||
}
|
||||
|
||||
private class OnColorSelectedListener
|
||||
implements ColorPickerSwatch.OnColorSelectedListener
|
||||
{
|
||||
@Override
|
||||
public void onColorSelected(int androidColor)
|
||||
{
|
||||
int paletteColor =
|
||||
ColorUtils.colorToPaletteIndex(getActivity(), androidColor);
|
||||
prefs.setDefaultHabitColor(paletteColor);
|
||||
modifiedHabit.setColor(paletteColor);
|
||||
helper.populateColor(paletteColor);
|
||||
}
|
||||
}
|
||||
|
||||
private class OnTimeSetListener
|
||||
implements TimePickerDialog.OnTimeSetListener
|
||||
{
|
||||
@@ -23,7 +23,7 @@ import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
|
||||
public class CreateHabitDialogFragment extends BaseDialogFragment
|
||||
public class CreateHabitDialog extends BaseDialog
|
||||
{
|
||||
@Override
|
||||
protected int getTitle()
|
||||
@@ -25,13 +25,16 @@ import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
|
||||
public class EditHabitDialogFragment extends BaseDialogFragment
|
||||
public class EditHabitDialog extends BaseDialog
|
||||
{
|
||||
public static EditHabitDialogFragment newInstance(long habitId)
|
||||
public static EditHabitDialog newInstance(Habit habit)
|
||||
{
|
||||
EditHabitDialogFragment frag = new EditHabitDialogFragment();
|
||||
if(habit.getId() == null)
|
||||
throw new IllegalArgumentException("habit not saved");
|
||||
|
||||
EditHabitDialog frag = new EditHabitDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("habitId", habitId);
|
||||
args.putLong("habitId", habit.getId());
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
@@ -48,7 +48,8 @@ public class ListHabitsController
|
||||
@NonNull
|
||||
private final HabitList habitList;
|
||||
|
||||
private HabitCardListAdapter adapter;
|
||||
@NonNull
|
||||
private final HabitCardListAdapter adapter;
|
||||
|
||||
@Inject
|
||||
Preferences prefs;
|
||||
@@ -81,6 +82,7 @@ public class ListHabitsController
|
||||
if (filename != null) screen.showSendFileScreen(filename);
|
||||
else screen.showMessage(R.string.could_not_export);
|
||||
});
|
||||
|
||||
task.execute();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,35 +20,43 @@
|
||||
package org.isoron.uhabits.ui.habits.list;
|
||||
|
||||
import android.content.*;
|
||||
import android.net.*;
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v7.app.*;
|
||||
|
||||
import com.android.colorpicker.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.intents.*;
|
||||
import org.isoron.uhabits.io.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.*;
|
||||
import org.isoron.uhabits.ui.about.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.ColorPickerDialog.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
import org.isoron.uhabits.ui.habits.show.*;
|
||||
import org.isoron.uhabits.ui.intro.*;
|
||||
import org.isoron.uhabits.ui.settings.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
public class ListHabitsScreen extends BaseScreen
|
||||
{
|
||||
@Nullable
|
||||
ListHabitsController controller;
|
||||
|
||||
@Inject
|
||||
protected DialogFactory dialogFactory;
|
||||
|
||||
@Inject
|
||||
protected IntentFactory intentFactory;
|
||||
|
||||
@Inject
|
||||
protected DirFinder dirFinder;
|
||||
|
||||
public ListHabitsScreen(@NonNull BaseActivity activity,
|
||||
ListHabitsRootView rootView)
|
||||
@NonNull ListHabitsRootView rootView)
|
||||
{
|
||||
super(activity);
|
||||
setRootView(rootView);
|
||||
HabitsApplication.getComponent().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,90 +91,83 @@ public class ListHabitsScreen extends BaseScreen
|
||||
|
||||
public void showAboutScreen()
|
||||
{
|
||||
Intent intent = new Intent(activity, AboutActivity.class);
|
||||
Intent intent = intentFactory.startAboutActivity(activity);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
public void showColorPicker(Habit habit, OnColorSelectedListener callback)
|
||||
/**
|
||||
* Displays a {@link ColorPickerDialog} to the user.
|
||||
* <p>
|
||||
* The selected color on the dialog is the color of the given habit.
|
||||
*
|
||||
* @param habit the habit
|
||||
* @param callback
|
||||
*/
|
||||
public void showColorPicker(@NonNull Habit habit,
|
||||
@NonNull OnColorSelectedListener callback)
|
||||
{
|
||||
int color = ColorUtils.getColor(activity, habit.getColor());
|
||||
|
||||
ColorPickerDialog picker =
|
||||
ColorPickerDialog.newInstance(R.string.color_picker_default_title,
|
||||
ColorUtils.getPalette(activity), color, 4,
|
||||
ColorPickerDialog.SIZE_SMALL);
|
||||
|
||||
picker.setOnColorSelectedListener(c -> {
|
||||
c = ColorUtils.colorToPaletteIndex(activity, c);
|
||||
callback.onColorSelected(c);
|
||||
});
|
||||
picker.show(activity.getSupportFragmentManager(), "picker");
|
||||
dialogFactory.buildColorPicker(habit.getColor());
|
||||
picker.setListener(callback);
|
||||
activity.showDialog(picker, "picker");
|
||||
}
|
||||
|
||||
public void showCreateHabitScreen()
|
||||
{
|
||||
showDialog(new CreateHabitDialogFragment(), "editHabit");
|
||||
CreateHabitDialog dialog = dialogFactory.buildCreateHabitDialog();
|
||||
activity.showDialog(dialog, "editHabit");
|
||||
}
|
||||
|
||||
public void showDeleteConfirmationScreen(Callback callback)
|
||||
public void showDeleteConfirmationScreen(ConfirmDeleteDialog.Callback callback)
|
||||
{
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.delete_habits)
|
||||
.setMessage(R.string.delete_habits_message)
|
||||
.setPositiveButton(android.R.string.yes,
|
||||
(dialog, which) -> callback.run())
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
ConfirmDeleteDialog dialog =
|
||||
dialogFactory.buildConfirmDeleteDialog(activity, callback);
|
||||
activity.showDialog(dialog);
|
||||
}
|
||||
|
||||
public void showEditHabitScreen(Habit habit)
|
||||
{
|
||||
BaseDialogFragment frag =
|
||||
EditHabitDialogFragment.newInstance(habit.getId());
|
||||
frag.show(activity.getSupportFragmentManager(), "editHabit");
|
||||
EditHabitDialog dialog = dialogFactory.buildEditHabitDialog(habit);
|
||||
activity.showDialog(dialog, "editHabit");
|
||||
}
|
||||
|
||||
public void showFAQScreen()
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(activity.getString(R.string.helpURL)));
|
||||
Intent intent = intentFactory.viewFAQ(activity);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
public void showHabitScreen(@NonNull Habit habit)
|
||||
{
|
||||
Intent intent = new Intent(activity, ShowHabitActivity.class);
|
||||
intent.setData(
|
||||
Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId()));
|
||||
Intent intent = intentFactory.startShowHabitActivity(activity, habit);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
public void showImportScreen()
|
||||
{
|
||||
if (controller == null) return;
|
||||
File dir = dirFinder.findStorageDir(null);
|
||||
|
||||
File dir = FileUtils.getFilesDir(null);
|
||||
if (dir == null)
|
||||
{
|
||||
showMessage(R.string.could_not_import);
|
||||
activity.showMessage(R.string.could_not_import);
|
||||
return;
|
||||
}
|
||||
|
||||
FilePickerDialog picker = new FilePickerDialog(activity, dir);
|
||||
FilePickerDialog picker = dialogFactory.buildFilePicker(activity, dir);
|
||||
if (controller != null)
|
||||
picker.setListener(file -> controller.onImportData(file));
|
||||
picker.show();
|
||||
activity.showDialog(picker.getDialog());
|
||||
}
|
||||
|
||||
public void showIntroScreen()
|
||||
{
|
||||
Intent intent = new Intent(activity, IntroActivity.class);
|
||||
Intent intent = intentFactory.startIntroActivity(activity);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
public void showSettingsScreen()
|
||||
{
|
||||
Intent intent = new Intent(activity, SettingsActivity.class);
|
||||
Intent intent = intentFactory.startSettingsActivity(activity);
|
||||
activity.startActivityForResult(intent, 0);
|
||||
}
|
||||
|
||||
@@ -182,7 +183,7 @@ public class ListHabitsScreen extends BaseScreen
|
||||
private void refreshTheme()
|
||||
{
|
||||
new Handler().postDelayed(() -> {
|
||||
Intent intent = new Intent(activity, MainActivity.class);
|
||||
Intent intent = new Intent(activity, ListHabitsScreen.class);
|
||||
|
||||
activity.finish();
|
||||
activity.overridePendingTransition(android.R.anim.fade_in,
|
||||
@@ -191,14 +192,4 @@ public class ListHabitsScreen extends BaseScreen
|
||||
|
||||
}, 500); // HACK: Let the menu disappear first
|
||||
}
|
||||
|
||||
interface Callback
|
||||
{
|
||||
void run();
|
||||
}
|
||||
|
||||
public interface OnColorSelectedListener
|
||||
{
|
||||
void onColorSelected(int color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
|
||||
@@ -20,33 +20,38 @@
|
||||
package org.isoron.uhabits.ui.habits.show;
|
||||
|
||||
import android.support.annotation.*;
|
||||
import android.support.v4.app.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
public class ShowHabitScreen extends BaseScreen
|
||||
{
|
||||
@NonNull
|
||||
private final Habit habit;
|
||||
|
||||
@Inject
|
||||
protected DialogFactory dialogFactory;
|
||||
|
||||
public ShowHabitScreen(@NonNull BaseActivity activity,
|
||||
@NonNull Habit habit,
|
||||
ShowHabitRootView view)
|
||||
{
|
||||
super(activity);
|
||||
HabitsApplication.getComponent().inject(this);
|
||||
|
||||
this.habit = habit;
|
||||
setRootView(view);
|
||||
}
|
||||
|
||||
public void showEditHabitDialog()
|
||||
{
|
||||
Long id = habit.getId();
|
||||
if (id == null) throw new RuntimeException("habit not saved");
|
||||
|
||||
FragmentManager manager = activity.getSupportFragmentManager();
|
||||
EditHabitDialogFragment.newInstance(id).show(manager, "editHabit");
|
||||
EditHabitDialog dialog = dialogFactory.buildEditHabitDialog(habit);
|
||||
activity.showDialog(dialog, "editHabit");
|
||||
}
|
||||
|
||||
public void showEditHistoryDialog(
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
package org.isoron.uhabits.ui.intro;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.content.*;
|
||||
import android.graphics.*;
|
||||
import android.os.*;
|
||||
|
||||
import com.github.paolorotolo.appintro.AppIntro2;
|
||||
import com.github.paolorotolo.appintro.AppIntroFragment;
|
||||
import com.github.paolorotolo.appintro.*;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
package org.isoron.uhabits.ui.settings;
|
||||
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v4.app.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.ui.*;
|
||||
|
||||
@@ -45,8 +45,8 @@ public class CheckmarkWidget extends BaseWidget
|
||||
@Override
|
||||
public PendingIntent getOnClickPendingIntent(Context context)
|
||||
{
|
||||
IntentFactory factory = new IntentFactory(context);
|
||||
return factory.buildToggleCheckmark(habit, null);
|
||||
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||
return factory.toggleCheckmark(habit, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,8 +46,8 @@ public class FrequencyWidget extends BaseWidget
|
||||
@Override
|
||||
public PendingIntent getOnClickPendingIntent(Context context)
|
||||
{
|
||||
IntentFactory factory = new IntentFactory(context);
|
||||
return factory.buildViewHabit(habit);
|
||||
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||
return factory.showHabit(habit);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,8 +44,8 @@ public class HistoryWidget extends BaseWidget
|
||||
@Override
|
||||
public PendingIntent getOnClickPendingIntent(Context context)
|
||||
{
|
||||
IntentFactory factory = new IntentFactory(context);
|
||||
return factory.buildViewHabit(habit);
|
||||
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||
return factory.showHabit(habit);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,8 +47,8 @@ public class ScoreWidget extends BaseWidget
|
||||
@Override
|
||||
public PendingIntent getOnClickPendingIntent(Context context)
|
||||
{
|
||||
IntentFactory factory = new IntentFactory(context);
|
||||
return factory.buildViewHabit(habit);
|
||||
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||
return factory.showHabit(habit);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,8 +49,8 @@ public class StreakWidget extends BaseWidget
|
||||
@Override
|
||||
public PendingIntent getOnClickPendingIntent(Context context)
|
||||
{
|
||||
IntentFactory factory = new IntentFactory(context);
|
||||
return factory.buildViewHabit(habit);
|
||||
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||
return factory.showHabit(habit);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,21 +19,15 @@
|
||||
|
||||
package org.isoron.uhabits.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.v4.content.*;
|
||||
import android.util.*;
|
||||
|
||||
import org.isoron.uhabits.HabitsApplication;
|
||||
import org.isoron.uhabits.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
|
||||
public abstract class FileUtils
|
||||
{
|
||||
@@ -60,35 +54,8 @@ public abstract class FileUtils
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getSDCardDir(@Nullable String relativePath)
|
||||
{
|
||||
File parents[] = new File[]{ Environment.getExternalStorageDirectory() };
|
||||
return getDir(parents, relativePath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getFilesDir(@Nullable String relativePath)
|
||||
{
|
||||
Context context = HabitsApplication.getContext();
|
||||
if(context == null)
|
||||
{
|
||||
Log.e("DatabaseHelper", "getFilesDir: no application context available");
|
||||
return null;
|
||||
}
|
||||
|
||||
File externalFilesDirs[] = ContextCompat.getExternalFilesDirs(context, null);
|
||||
|
||||
if(externalFilesDirs == null)
|
||||
{
|
||||
Log.e("DatabaseHelper", "getFilesDir: getExternalFilesDirs returned null");
|
||||
return null;
|
||||
}
|
||||
|
||||
return getDir(externalFilesDirs, relativePath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File getDir(@NonNull File potentialParentDirs[], @Nullable String relativePath)
|
||||
private static File getDir(@NonNull File potentialParentDirs[],
|
||||
@Nullable String relativePath)
|
||||
{
|
||||
if (relativePath == null) relativePath = "";
|
||||
|
||||
@@ -102,18 +69,45 @@ public abstract class FileUtils
|
||||
|
||||
if (chosenDir == null)
|
||||
{
|
||||
Log.e("DatabaseHelper", "getDir: all potential parents are null or non-writable");
|
||||
Log.e("DatabaseHelper",
|
||||
"getDir: all potential parents are null or non-writable");
|
||||
return null;
|
||||
}
|
||||
|
||||
File dir = new File(String.format("%s/%s/", chosenDir.getAbsolutePath(), relativePath));
|
||||
File dir = new File(
|
||||
String.format("%s/%s/", chosenDir.getAbsolutePath(), relativePath));
|
||||
if (!dir.exists() && !dir.mkdirs())
|
||||
{
|
||||
Log.e("DatabaseHelper", "getDir: chosen dir does not exist and cannot be created");
|
||||
Log.e("DatabaseHelper",
|
||||
"getDir: chosen dir does not exist and cannot be created");
|
||||
return null;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getFilesDir(@Nullable String relativePath)
|
||||
{
|
||||
Context context = HabitsApplication.getContext();
|
||||
File externalFilesDirs[] =
|
||||
ContextCompat.getExternalFilesDirs(context, null);
|
||||
|
||||
if (externalFilesDirs == null)
|
||||
{
|
||||
Log.e("DatabaseHelper",
|
||||
"getFilesDir: getExternalFilesDirs returned null");
|
||||
return null;
|
||||
}
|
||||
|
||||
return getDir(externalFilesDirs, relativePath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getSDCardDir(@Nullable String relativePath)
|
||||
{
|
||||
File parents[] =
|
||||
new File[]{ Environment.getExternalStorageDirectory() };
|
||||
return getDir(parents, relativePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,16 @@ import android.preference.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
@Singleton
|
||||
public class Preferences
|
||||
{
|
||||
private Context context;
|
||||
|
||||
private SharedPreferences prefs;
|
||||
|
||||
@Inject
|
||||
public Preferences()
|
||||
{
|
||||
this.context = HabitsApplication.getContext();
|
||||
|
||||
@@ -32,20 +32,21 @@ import javax.inject.*;
|
||||
|
||||
import static org.isoron.uhabits.utils.DateUtils.*;
|
||||
|
||||
@Singleton
|
||||
public class ReminderScheduler
|
||||
{
|
||||
private final IntentFactory intentFactory;
|
||||
@Inject
|
||||
protected PendingIntentFactory pendingIntentFactory;
|
||||
|
||||
private final IntentScheduler intentScheduler;
|
||||
@Inject
|
||||
protected IntentScheduler intentScheduler;
|
||||
|
||||
@Inject
|
||||
HabitLogger logger;
|
||||
|
||||
public ReminderScheduler(IntentFactory intentFactory,
|
||||
IntentScheduler intentScheduler)
|
||||
@Inject
|
||||
public ReminderScheduler()
|
||||
{
|
||||
this.intentFactory = intentFactory;
|
||||
this.intentScheduler = intentScheduler;
|
||||
HabitsApplication.getComponent().inject(this);
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ public class ReminderScheduler
|
||||
if (reminderTime == null) reminderTime = getReminderTime(reminder);
|
||||
long timestamp = getStartOfDay(toLocalTime(reminderTime));
|
||||
|
||||
PendingIntent intent = intentFactory.buildShowReminder(habit,
|
||||
PendingIntent intent = pendingIntentFactory.showReminder(habit,
|
||||
reminderTime, timestamp);
|
||||
intentScheduler.schedule(reminderTime, intent);
|
||||
logger.logReminderScheduled(habit, reminderTime);
|
||||
|
||||
@@ -22,17 +22,17 @@ package org.isoron.uhabits.utils;
|
||||
import android.content.*;
|
||||
import android.preference.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import javax.inject.*;
|
||||
|
||||
@Singleton
|
||||
public class WidgetPreferences
|
||||
{
|
||||
private Context context;
|
||||
|
||||
private SharedPreferences prefs;
|
||||
|
||||
public WidgetPreferences()
|
||||
@Inject
|
||||
public WidgetPreferences(Context context)
|
||||
{
|
||||
this.context = HabitsApplication.getContext();
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
style="@style/dialogForm"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".ui.habits.edit.BaseDialogFragment"
|
||||
tools:context=".ui.habits.edit.BaseDialog"
|
||||
tools:ignore="MergeRootFrame">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import org.isoron.uhabits.intents.*;
|
||||
import org.isoron.uhabits.io.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
|
||||
@@ -36,21 +39,41 @@ public class BaseUnitTest
|
||||
@Inject
|
||||
protected ModelFactory modelFactory;
|
||||
|
||||
@Inject
|
||||
protected DialogFactory dialogFactory;
|
||||
|
||||
@Inject
|
||||
protected IntentFactory intentFactory;
|
||||
|
||||
@Inject
|
||||
protected HabitList habitList;
|
||||
|
||||
@Inject
|
||||
protected HabitLogger logger;
|
||||
|
||||
@Inject
|
||||
protected PendingIntentFactory pendingIntentFactory;
|
||||
|
||||
@Inject
|
||||
protected IntentScheduler intentScheduler;
|
||||
|
||||
@Inject
|
||||
protected DirFinder dirFinder;
|
||||
|
||||
protected TestComponent testComponent;
|
||||
|
||||
protected HabitFixtures fixtures;
|
||||
|
||||
public void log(String format, Object... args)
|
||||
{
|
||||
System.out.println(String.format(format, args));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
DateUtils.setFixedLocalTime(FIXED_LOCAL_TIME);
|
||||
testComponent = DaggerTestComponent.builder().build();
|
||||
testComponent = DaggerTestComponent.create();
|
||||
HabitsApplication.setComponent(testComponent);
|
||||
testComponent.inject(this);
|
||||
fixtures = new HabitFixtures(habitList);
|
||||
@@ -63,9 +86,4 @@ public class BaseUnitTest
|
||||
fixtures.purgeHabits();
|
||||
|
||||
}
|
||||
|
||||
public void log(String format, Object... args)
|
||||
{
|
||||
System.out.println(String.format(format, args));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import org.isoron.uhabits.commands.*;
|
||||
import org.isoron.uhabits.intents.*;
|
||||
import org.isoron.uhabits.io.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.memory.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import javax.inject.*;
|
||||
@@ -40,6 +43,20 @@ public class TestModule
|
||||
return mock(CommandRunner.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DialogFactory provideDialogFactory()
|
||||
{
|
||||
return mock(DialogFactory.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DirFinder provideDirFinder()
|
||||
{
|
||||
return mock(DirFinder.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
Habit provideHabit()
|
||||
{
|
||||
@@ -53,6 +70,27 @@ public class TestModule
|
||||
return new MemoryHabitList();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
IntentFactory provideIntentFactory()
|
||||
{
|
||||
return mock(IntentFactory.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
IntentScheduler provideIntentScheduler()
|
||||
{
|
||||
return mock(IntentScheduler.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
HabitLogger provideLogger()
|
||||
{
|
||||
return mock(HabitLogger.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ModelFactory provideModelFactory()
|
||||
@@ -60,6 +98,13 @@ public class TestModule
|
||||
return new MemoryModelFactory();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
PendingIntentFactory providePendingIntentFactory()
|
||||
{
|
||||
return mock(PendingIntentFactory.class);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
Preferences providePreferences()
|
||||
@@ -67,13 +112,6 @@ public class TestModule
|
||||
return mock(Preferences.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
WidgetPreferences provideWidgetPreferences()
|
||||
{
|
||||
return mock(WidgetPreferences.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ReminderScheduler provideReminderScheduler()
|
||||
@@ -83,8 +121,8 @@ public class TestModule
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
HabitLogger provideLogger()
|
||||
WidgetPreferences provideWidgetPreferences()
|
||||
{
|
||||
return mock(HabitLogger.class);
|
||||
return mock(WidgetPreferences.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.habits.list;
|
||||
|
||||
|
||||
import android.content.*;
|
||||
import android.support.v7.app.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||
import org.isoron.uhabits.ui.common.dialogs.ColorPickerDialog.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
import org.junit.runners.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class ListHabitsScreenTest extends BaseUnitTest
|
||||
{
|
||||
private BaseActivity activity;
|
||||
|
||||
private ListHabitsRootView rootView;
|
||||
|
||||
private ListHabitsScreen screen;
|
||||
|
||||
private ListHabitsController controller;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
private Intent intent;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
activity = mock(BaseActivity.class);
|
||||
rootView = mock(ListHabitsRootView.class);
|
||||
controller = mock(ListHabitsController.class);
|
||||
intent = mock(Intent.class);
|
||||
|
||||
habit = new Habit();
|
||||
screen = new ListHabitsScreen(activity, rootView);
|
||||
screen.setController(controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateHabitScreen()
|
||||
{
|
||||
CreateHabitDialog dialog = mock(CreateHabitDialog.class);
|
||||
when(dialogFactory.buildCreateHabitDialog()).thenReturn(dialog);
|
||||
|
||||
screen.showCreateHabitScreen();
|
||||
|
||||
verify(activity).showDialog(eq(dialog), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnResult_bugReport()
|
||||
{
|
||||
screen.onResult(0, HabitsApplication.RESULT_BUG_REPORT, null);
|
||||
verify(controller).onSendBugReport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnResult_exportCSV()
|
||||
{
|
||||
screen.onResult(0, HabitsApplication.RESULT_EXPORT_CSV, null);
|
||||
verify(controller).onExportCSV();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnResult_exportDB()
|
||||
{
|
||||
screen.onResult(0, HabitsApplication.RESULT_EXPORT_DB, null);
|
||||
verify(controller).onExportDB();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnResult_importData()
|
||||
{
|
||||
screen.onResult(0, HabitsApplication.RESULT_IMPORT_DATA, null);
|
||||
testShowImportScreen();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowAboutScreen() throws Exception
|
||||
{
|
||||
when(intentFactory.startAboutActivity(activity)).thenReturn(intent);
|
||||
screen.showAboutScreen();
|
||||
verify(activity).startActivity(eq(intent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowColorPicker()
|
||||
{
|
||||
habit.setColor(999);
|
||||
ColorPickerDialog picker = mock(ColorPickerDialog.class);
|
||||
when(dialogFactory.buildColorPicker(999)).thenReturn(picker);
|
||||
OnColorSelectedListener callback = mock(OnColorSelectedListener.class);
|
||||
|
||||
screen.showColorPicker(habit, callback);
|
||||
|
||||
verify(activity).showDialog(eq(picker), any());
|
||||
verify(picker).setListener(callback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowDeleteConfirmationScreen()
|
||||
{
|
||||
ConfirmDeleteDialog.Callback callback;
|
||||
callback = mock(ConfirmDeleteDialog.Callback.class);
|
||||
|
||||
ConfirmDeleteDialog dialog = mock(ConfirmDeleteDialog.class);
|
||||
when(dialogFactory.buildConfirmDeleteDialog(activity,
|
||||
callback)).thenReturn(dialog);
|
||||
|
||||
screen.showDeleteConfirmationScreen(callback);
|
||||
|
||||
verify(activity).showDialog(dialog);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowEditHabitScreen()
|
||||
{
|
||||
EditHabitDialog dialog = mock(EditHabitDialog.class);
|
||||
when(dialogFactory.buildEditHabitDialog(habit)).thenReturn(dialog);
|
||||
|
||||
screen.showEditHabitScreen(habit);
|
||||
verify(activity).showDialog(eq(dialog), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowFAQScreen()
|
||||
{
|
||||
when(intentFactory.viewFAQ(activity)).thenReturn(intent);
|
||||
screen.showFAQScreen();
|
||||
verify(activity).startActivity(intent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowHabitScreen()
|
||||
{
|
||||
when(intentFactory.startShowHabitActivity(activity, habit)).thenReturn(
|
||||
intent);
|
||||
screen.showHabitScreen(habit);
|
||||
verify(activity).startActivity(intent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowImportScreen()
|
||||
{
|
||||
File dir = mock(File.class);
|
||||
when(dirFinder.findStorageDir(any())).thenReturn(dir);
|
||||
|
||||
FilePickerDialog picker = mock(FilePickerDialog.class);
|
||||
AppCompatDialog dialog = mock(AppCompatDialog.class);
|
||||
when(picker.getDialog()).thenReturn(dialog);
|
||||
when(dialogFactory.buildFilePicker(activity, dir)).thenReturn(picker);
|
||||
|
||||
screen.showImportScreen();
|
||||
|
||||
verify(activity).showDialog(dialog);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowImportScreen_withInvalidPath()
|
||||
{
|
||||
when(dirFinder.findStorageDir(any())).thenReturn(null);
|
||||
screen.showImportScreen();
|
||||
verify(activity).showMessage(R.string.could_not_import);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowIntroScreen()
|
||||
{
|
||||
when(intentFactory.startIntroActivity(activity)).thenReturn(intent);
|
||||
screen.showIntroScreen();
|
||||
verify(activity).startActivity(intent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowSettingsScreen()
|
||||
{
|
||||
when(intentFactory.startSettingsActivity(activity)).thenReturn(intent);
|
||||
screen.showSettingsScreen();
|
||||
verify(activity).startActivityForResult(eq(intent), anyInt());
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ package org.isoron.uhabits.utils;
|
||||
import android.app.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.intents.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
|
||||
@@ -31,26 +30,19 @@ import static org.mockito.Mockito.*;
|
||||
@SuppressWarnings("JavaDoc")
|
||||
public class ReminderSchedulerTest extends BaseUnitTest
|
||||
{
|
||||
private IntentFactory intentFactory;
|
||||
|
||||
private IntentScheduler intentScheduler;
|
||||
|
||||
private ReminderScheduler scheduler;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
private PendingIntent intent;
|
||||
|
||||
private ReminderScheduler reminderScheduler;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
intentFactory = mock(IntentFactory.class);
|
||||
intentScheduler = mock(IntentScheduler.class);
|
||||
intent = mock(PendingIntent.class);
|
||||
|
||||
scheduler = new ReminderScheduler(intentFactory, intentScheduler);
|
||||
reminderScheduler = new ReminderScheduler();
|
||||
habit = fixtures.createEmptyHabit();
|
||||
}
|
||||
|
||||
@@ -94,7 +86,7 @@ public class ReminderSchedulerTest extends BaseUnitTest
|
||||
|
||||
fixtures.createEmptyHabit();
|
||||
|
||||
scheduler.schedule(habitList);
|
||||
reminderScheduler.schedule(habitList);
|
||||
|
||||
verify(intentScheduler).schedule(1422347400000L, null);
|
||||
verify(intentScheduler).schedule(1422297000000L, null);
|
||||
@@ -117,7 +109,7 @@ public class ReminderSchedulerTest extends BaseUnitTest
|
||||
@Test
|
||||
public void testSchedule_withoutReminder()
|
||||
{
|
||||
scheduler.schedule(habit, null);
|
||||
reminderScheduler.schedule(habit, null);
|
||||
verifyZeroInteractions(intentScheduler);
|
||||
}
|
||||
|
||||
@@ -125,14 +117,14 @@ public class ReminderSchedulerTest extends BaseUnitTest
|
||||
long expectedCheckmarkTime,
|
||||
long expectedReminderTime)
|
||||
{
|
||||
when(intentFactory.buildShowReminder(habit, expectedReminderTime,
|
||||
when(pendingIntentFactory.showReminder(habit, expectedReminderTime,
|
||||
expectedCheckmarkTime)).thenReturn(intent);
|
||||
|
||||
scheduler.schedule(habit, atTime);
|
||||
reminderScheduler.schedule(habit, atTime);
|
||||
|
||||
verify(logger).logReminderScheduled(habit, expectedReminderTime);
|
||||
|
||||
verify(intentFactory).buildShowReminder(habit, expectedReminderTime,
|
||||
verify(pendingIntentFactory).showReminder(habit, expectedReminderTime,
|
||||
expectedCheckmarkTime);
|
||||
verify(intentScheduler).schedule(expectedReminderTime, intent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user