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.os.*;
|
||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
import android.support.test.*;
|
import android.support.test.*;
|
||||||
import android.support.test.runner.*;
|
|
||||||
import android.test.suitebuilder.annotation.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.tasks.*;
|
import org.isoron.uhabits.tasks.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.runner.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
@@ -43,8 +40,6 @@ import static junit.framework.Assert.*;
|
|||||||
import static org.hamcrest.MatcherAssert.*;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
@MediumTest
|
|
||||||
public class BaseAndroidTest
|
public class BaseAndroidTest
|
||||||
{
|
{
|
||||||
// 8:00am, January 25th, 2015 (UTC)
|
// 8:00am, January 25th, 2015 (UTC)
|
||||||
|
|||||||
@@ -21,11 +21,8 @@ package org.isoron.uhabits;
|
|||||||
|
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.commands.*;
|
|
||||||
import org.isoron.uhabits.intents.*;
|
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.sqlite.*;
|
import org.isoron.uhabits.models.sqlite.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
|
||||||
|
|
||||||
import javax.inject.*;
|
import javax.inject.*;
|
||||||
|
|
||||||
@@ -42,52 +39,21 @@ public class AndroidModule
|
|||||||
{
|
{
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
CommandRunner provideCommandRunner()
|
static HabitList provideHabitList()
|
||||||
{
|
|
||||||
return new CommandRunner();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
HabitList provideHabitList()
|
|
||||||
{
|
{
|
||||||
return SQLiteHabitList.getInstance();
|
return SQLiteHabitList.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
ModelFactory provideModelFactory()
|
static ModelFactory provideModelFactory()
|
||||||
{
|
{
|
||||||
return new SQLModelFactory();
|
return new SQLModelFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Preferences providePreferences()
|
static Context provideApplicationContext()
|
||||||
{
|
{
|
||||||
return new Preferences();
|
return HabitsApplication.getContext();
|
||||||
}
|
|
||||||
|
|
||||||
@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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,13 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
|
import org.isoron.uhabits.intents.*;
|
||||||
import org.isoron.uhabits.io.*;
|
import org.isoron.uhabits.io.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.receivers.*;
|
import org.isoron.uhabits.receivers.*;
|
||||||
import org.isoron.uhabits.tasks.*;
|
import org.isoron.uhabits.tasks.*;
|
||||||
import org.isoron.uhabits.ui.*;
|
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.edit.*;
|
||||||
import org.isoron.uhabits.ui.habits.list.*;
|
import org.isoron.uhabits.ui.habits.list.*;
|
||||||
import org.isoron.uhabits.ui.habits.list.controllers.*;
|
import org.isoron.uhabits.ui.habits.list.controllers.*;
|
||||||
@@ -40,6 +42,8 @@ import org.isoron.uhabits.widgets.*;
|
|||||||
*/
|
*/
|
||||||
public interface BaseComponent
|
public interface BaseComponent
|
||||||
{
|
{
|
||||||
|
IntentFactory getIntentFactory();
|
||||||
|
|
||||||
void inject(CheckmarkButtonController checkmarkButtonController);
|
void inject(CheckmarkButtonController checkmarkButtonController);
|
||||||
|
|
||||||
void inject(ListHabitsController listHabitsController);
|
void inject(ListHabitsController listHabitsController);
|
||||||
@@ -90,7 +94,7 @@ public interface BaseComponent
|
|||||||
|
|
||||||
void inject(HabitsCSVExporter habitsCSVExporter);
|
void inject(HabitsCSVExporter habitsCSVExporter);
|
||||||
|
|
||||||
void inject(BaseDialogFragment baseDialogFragment);
|
void inject(BaseDialog baseDialog);
|
||||||
|
|
||||||
void inject(ShowHabitController showHabitController);
|
void inject(ShowHabitController showHabitController);
|
||||||
|
|
||||||
@@ -109,4 +113,12 @@ public interface BaseComponent
|
|||||||
void inject(ReminderReceiver reminderReceiver);
|
void inject(ReminderReceiver reminderReceiver);
|
||||||
|
|
||||||
void inject(ReminderScheduler reminderScheduler);
|
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.text.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class HabitLogger
|
public class HabitLogger
|
||||||
{
|
{
|
||||||
|
@Inject
|
||||||
|
public HabitLogger()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void logReminderScheduled(@NonNull Habit habit,
|
public void logReminderScheduled(@NonNull Habit habit,
|
||||||
@NonNull Long reminderTime)
|
@NonNull Long reminderTime)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,16 +26,20 @@ import org.isoron.uhabits.tasks.BaseTask;
|
|||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CommandRunner executes and undoes commands.
|
* A CommandRunner executes and undoes commands.
|
||||||
* <p>
|
* <p>
|
||||||
* CommandRunners also allows objects to subscribe to it, and receive events
|
* CommandRunners also allows objects to subscribe to it, and receive events
|
||||||
* whenever a command is performed.
|
* whenever a command is performed.
|
||||||
*/
|
*/
|
||||||
|
@Singleton
|
||||||
public class CommandRunner
|
public class CommandRunner
|
||||||
{
|
{
|
||||||
private LinkedList<Listener> listeners;
|
private LinkedList<Listener> listeners;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public CommandRunner()
|
public CommandRunner()
|
||||||
{
|
{
|
||||||
listeners = new LinkedList<>();
|
listeners = new LinkedList<>();
|
||||||
|
|||||||
@@ -19,94 +19,53 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.intents;
|
package org.isoron.uhabits.intents;
|
||||||
|
|
||||||
import android.app.*;
|
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.net.*;
|
import android.net.*;
|
||||||
import android.support.annotation.*;
|
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.models.*;
|
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.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
|
public class IntentFactory
|
||||||
{
|
{
|
||||||
@NonNull
|
@Inject
|
||||||
private final Context context;
|
public IntentFactory()
|
||||||
|
|
||||||
public IntentFactory(@NonNull Context context)
|
|
||||||
{
|
{
|
||||||
this.context = context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PendingIntent buildAddCheckmark(@NonNull Habit habit,
|
public Intent startAboutActivity(Context context)
|
||||||
@Nullable Long timestamp)
|
|
||||||
{
|
{
|
||||||
Uri data = habit.getUri();
|
return new Intent(context, AboutActivity.class);
|
||||||
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 buildDismissNotification()
|
public Intent startIntroActivity(Context context)
|
||||||
{
|
{
|
||||||
Intent deleteIntent = new Intent(context, ReminderReceiver.class);
|
return new Intent(context, IntroActivity.class);
|
||||||
deleteIntent.setAction(WidgetReceiver.ACTION_DISMISS_REMINDER);
|
|
||||||
return PendingIntent.getBroadcast(context, 0, deleteIntent,
|
|
||||||
FLAG_UPDATE_CURRENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PendingIntent buildShowReminder(@NonNull Habit habit,
|
public Intent startSettingsActivity(Context context)
|
||||||
@Nullable Long reminderTime,
|
|
||||||
long timestamp)
|
|
||||||
{
|
{
|
||||||
Uri uri = habit.getUri();
|
return new Intent(context, SettingsActivity.class);
|
||||||
|
|
||||||
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 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 intent = new Intent(context, ShowHabitActivity.class);
|
||||||
intent.setData(uri);
|
intent.setData(habit.getUri());
|
||||||
return android.support.v4.app.TaskStackBuilder
|
return intent;
|
||||||
.create(context)
|
}
|
||||||
.addNextIntentWithParentStack(intent)
|
|
||||||
.getPendingIntent(0, FLAG_UPDATE_CURRENT);
|
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.os.*;
|
||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
import static android.app.AlarmManager.*;
|
import static android.app.AlarmManager.*;
|
||||||
import static android.content.Context.*;
|
import static android.content.Context.*;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class IntentScheduler
|
public class IntentScheduler
|
||||||
{
|
{
|
||||||
private final AlarmManager manager;
|
private final AlarmManager manager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public IntentScheduler(@NonNull Context context)
|
public IntentScheduler(@NonNull Context context)
|
||||||
{
|
{
|
||||||
manager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
|
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 org.isoron.uhabits.models.*;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory that provides models backed by an SQLite database.
|
* Factory that provides models backed by an SQLite database.
|
||||||
*/
|
*/
|
||||||
|
@Singleton
|
||||||
public class SQLModelFactory implements ModelFactory
|
public class SQLModelFactory implements ModelFactory
|
||||||
{
|
{
|
||||||
|
@Inject
|
||||||
|
public SQLModelFactory()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RepetitionList buildRepetitionList(Habit habit)
|
public RepetitionList buildRepetitionList(Habit habit)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -145,14 +145,15 @@ public class ReminderReceiver extends BroadcastReceiver
|
|||||||
context, 0, contentIntent,
|
context, 0, contentIntent,
|
||||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
IntentFactory intentFactory = new IntentFactory(context);
|
PendingIntentFactory
|
||||||
|
pendingIntentFactory = new PendingIntentFactory(context);
|
||||||
|
|
||||||
PendingIntent dismissPendingIntent;
|
PendingIntent dismissPendingIntent;
|
||||||
dismissPendingIntent = intentFactory.buildDismissNotification();
|
dismissPendingIntent = pendingIntentFactory.dismissNotification();
|
||||||
PendingIntent checkIntentPending =
|
PendingIntent checkIntentPending =
|
||||||
intentFactory.buildAddCheckmark(habit, timestamp);
|
pendingIntentFactory.addCheckmark(habit, timestamp);
|
||||||
PendingIntent snoozeIntentPending =
|
PendingIntent snoozeIntentPending =
|
||||||
intentFactory.buildSnoozeNotification(habit);
|
pendingIntentFactory.snoozeNotification(habit);
|
||||||
|
|
||||||
Uri ringtoneUri = RingtoneUtils.getRingtoneUri(context);
|
Uri ringtoneUri = RingtoneUtils.getRingtoneUri(context);
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.os.*;
|
|||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
import android.support.v7.app.*;
|
import android.support.v7.app.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
import android.widget.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
@@ -51,6 +52,8 @@ abstract public class BaseActivity extends AppCompatActivity
|
|||||||
@Nullable
|
@Nullable
|
||||||
private BaseScreen screen;
|
private BaseScreen screen;
|
||||||
|
|
||||||
|
private Toast toast;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(@Nullable Menu menu)
|
public boolean onCreateOptionsMenu(@Nullable Menu menu)
|
||||||
{
|
{
|
||||||
@@ -78,6 +81,30 @@ abstract public class BaseActivity extends AppCompatActivity
|
|||||||
this.screen = screen;
|
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
|
@Override
|
||||||
public void uncaughtException(@Nullable Thread thread,
|
public void uncaughtException(@Nullable Thread thread,
|
||||||
@Nullable Throwable ex)
|
@Nullable Throwable ex)
|
||||||
|
|||||||
@@ -27,12 +27,11 @@ import android.os.*;
|
|||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
import android.support.v7.app.*;
|
import android.support.v7.app.*;
|
||||||
import android.support.v7.view.ActionMode;
|
import android.support.v7.view.ActionMode;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.tasks.ProgressBar;
|
import org.isoron.uhabits.tasks.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -48,8 +47,6 @@ public abstract class BaseScreen
|
|||||||
{
|
{
|
||||||
protected BaseActivity activity;
|
protected BaseActivity activity;
|
||||||
|
|
||||||
private Toast toast;
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private BaseRootView rootView;
|
private BaseRootView rootView;
|
||||||
|
|
||||||
@@ -155,6 +152,11 @@ public abstract class BaseScreen
|
|||||||
activity.setBaseMenu(menu);
|
activity.setBaseMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showMessage(@StringRes int stringId)
|
||||||
|
{
|
||||||
|
activity.showMessage(stringId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the root view for this screen.
|
* Sets the root view for this screen.
|
||||||
*
|
*
|
||||||
@@ -179,20 +181,6 @@ public abstract class BaseScreen
|
|||||||
this.selectionMenu = menu;
|
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)
|
public void showSendEmailScreen(String to, String subject, String content)
|
||||||
{
|
{
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
@@ -225,11 +213,6 @@ public abstract class BaseScreen
|
|||||||
activity.startSupportActionMode(new ActionModeWrapper());
|
activity.startSupportActionMode(new ActionModeWrapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void showDialog(AppCompatDialogFragment dialog, String tag)
|
|
||||||
{
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidateToolbar()
|
public void invalidateToolbar()
|
||||||
{
|
{
|
||||||
if (rootView == null) return;
|
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/>.
|
* 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.content.*;
|
||||||
import android.app.Dialog;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.v7.app.*;
|
||||||
import android.view.View;
|
import android.view.*;
|
||||||
import android.view.ViewGroup;
|
import android.view.WindowManager.*;
|
||||||
import android.view.WindowManager.LayoutParams;
|
import android.widget.*;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileFilter;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog that allows the user to pick a file.
|
||||||
|
*/
|
||||||
public class FilePickerDialog implements AdapterView.OnItemClickListener
|
public class FilePickerDialog implements AdapterView.OnItemClickListener
|
||||||
{
|
{
|
||||||
private static final String PARENT_DIR = "..";
|
private static final String PARENT_DIR = "..";
|
||||||
|
|
||||||
private final Activity activity;
|
private final Context context;
|
||||||
|
|
||||||
private ListView list;
|
private ListView list;
|
||||||
|
|
||||||
private Dialog dialog;
|
private AppCompatDialog dialog;
|
||||||
|
|
||||||
private File currentPath;
|
private File currentPath;
|
||||||
|
|
||||||
public interface OnFileSelectedListener
|
|
||||||
{
|
|
||||||
void onFileSelected(File file);
|
|
||||||
}
|
|
||||||
|
|
||||||
private OnFileSelectedListener listener;
|
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);
|
list.setOnItemClickListener(this);
|
||||||
|
|
||||||
dialog = new Dialog(activity);
|
dialog = new AppCompatDialog(context);
|
||||||
dialog.setContentView(list);
|
dialog.setContentView(list);
|
||||||
dialog
|
dialog
|
||||||
.getWindow()
|
.getWindow()
|
||||||
@@ -69,6 +62,11 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
|||||||
navigateTo(initialDirectory);
|
navigateTo(initialDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AppCompatDialog getDialog()
|
||||||
|
{
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent,
|
public void onItemClick(AdapterView<?> parent,
|
||||||
View view,
|
View view,
|
||||||
@@ -92,27 +90,14 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show()
|
|
||||||
{
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setListener(OnFileSelectedListener listener)
|
public void setListener(OnFileSelectedListener listener)
|
||||||
{
|
{
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void navigateTo(File path)
|
public void show()
|
||||||
{
|
{
|
||||||
if (!path.exists()) return;
|
dialog.show();
|
||||||
|
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -144,11 +129,38 @@ public class FilePickerDialog implements AdapterView.OnItemClickListener
|
|||||||
return fileList;
|
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>
|
private class FilePickerAdapter extends ArrayAdapter<String>
|
||||||
{
|
{
|
||||||
public FilePickerAdapter(@NonNull String[] fileList)
|
public FilePickerAdapter(@NonNull String[] fileList)
|
||||||
{
|
{
|
||||||
super(FilePickerDialog.this.activity,
|
super(FilePickerDialog.this.context,
|
||||||
android.R.layout.simple_list_item_1, fileList);
|
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
|
private class RegularReadableFileFilter implements FileFilter
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.app.*;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
@@ -17,63 +17,29 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.app.*;
|
||||||
import android.content.DialogInterface;
|
import android.content.*;
|
||||||
import android.os.Bundle;
|
import android.os.*;
|
||||||
import android.support.v7.app.AlertDialog;
|
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.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
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
|
public class WeekdayPickerDialog extends AppCompatDialogFragment implements
|
||||||
DialogInterface.OnMultiChoiceClickListener,
|
DialogInterface.OnMultiChoiceClickListener,
|
||||||
DialogInterface.OnClickListener
|
DialogInterface.OnClickListener
|
||||||
{
|
{
|
||||||
|
|
||||||
public interface OnWeekdaysPickedListener
|
|
||||||
{
|
|
||||||
void onWeekdaysPicked(boolean[] selectedDays);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean[] selectedDays;
|
private boolean[] selectedDays;
|
||||||
|
|
||||||
private OnWeekdaysPickedListener listener;
|
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
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which, boolean isChecked)
|
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);
|
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.text.format.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
|
||||||
import com.android.colorpicker.*;
|
|
||||||
import com.android.datetimepicker.time.*;
|
import com.android.datetimepicker.time.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.models.*;
|
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.DateUtils;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ import javax.inject.*;
|
|||||||
|
|
||||||
import butterknife.*;
|
import butterknife.*;
|
||||||
|
|
||||||
public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
public abstract class BaseDialog extends AppCompatDialogFragment
|
||||||
{
|
{
|
||||||
@Nullable
|
@Nullable
|
||||||
protected Habit originalHabit;
|
protected Habit originalHabit;
|
||||||
@@ -60,6 +60,9 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
|||||||
@Inject
|
@Inject
|
||||||
protected HabitList habitList;
|
protected HabitList habitList;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected DialogFactory dialogFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater,
|
public View onCreateView(LayoutInflater inflater,
|
||||||
ViewGroup container,
|
ViewGroup container,
|
||||||
@@ -83,7 +86,8 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
|||||||
if (position < 0 || position > 4) throw new IllegalArgumentException();
|
if (position < 0 || position > 4) throw new IllegalArgumentException();
|
||||||
int freqNums[] = { 1, 1, 2, 5, 3 };
|
int freqNums[] = { 1, 1, 2, 5, 3 };
|
||||||
int freqDens[] = { 1, 7, 7, 7, 7 };
|
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);
|
helper.populateFrequencyFields(modifiedHabit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,23 +173,22 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
|||||||
|
|
||||||
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
||||||
dialog.setListener(new OnWeekdaysPickedListener());
|
dialog.setListener(new OnWeekdaysPickedListener());
|
||||||
dialog.setSelectedDays(
|
dialog.setSelectedDays(DateUtils.unpackWeekdayList(reminder.getDays()));
|
||||||
DateUtils.unpackWeekdayList(reminder.getDays()));
|
|
||||||
dialog.show(getFragmentManager(), "weekdayPicker");
|
dialog.show(getFragmentManager(), "weekdayPicker");
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.buttonPickColor)
|
@OnClick(R.id.buttonPickColor)
|
||||||
void showColorPicker()
|
void showColorPicker()
|
||||||
{
|
{
|
||||||
int androidColor =
|
int color = modifiedHabit.getColor();
|
||||||
ColorUtils.getColor(getContext(), modifiedHabit.getColor());
|
ColorPickerDialog picker = dialogFactory.buildColorPicker(color);
|
||||||
|
|
||||||
ColorPickerDialog picker =
|
picker.setListener(c -> {
|
||||||
ColorPickerDialog.newInstance(R.string.color_picker_default_title,
|
prefs.setDefaultHabitColor(c);
|
||||||
ColorUtils.getPalette(getContext()), androidColor, 4,
|
modifiedHabit.setColor(c);
|
||||||
ColorPickerDialog.SIZE_SMALL);
|
helper.populateColor(c);
|
||||||
|
});
|
||||||
|
|
||||||
picker.setOnColorSelectedListener(new OnColorSelectedListener());
|
|
||||||
picker.show(getFragmentManager(), "picker");
|
picker.show(getFragmentManager(), "picker");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,20 +201,6 @@ public abstract class BaseDialogFragment extends AppCompatDialogFragment
|
|||||||
timePicker.show(getFragmentManager(), "timePicker");
|
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
|
private class OnTimeSetListener
|
||||||
implements TimePickerDialog.OnTimeSetListener
|
implements TimePickerDialog.OnTimeSetListener
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,7 @@ import org.isoron.uhabits.*;
|
|||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
|
|
||||||
public class CreateHabitDialogFragment extends BaseDialogFragment
|
public class CreateHabitDialog extends BaseDialog
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected int getTitle()
|
protected int getTitle()
|
||||||
@@ -25,13 +25,16 @@ import org.isoron.uhabits.*;
|
|||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.models.*;
|
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();
|
Bundle args = new Bundle();
|
||||||
args.putLong("habitId", habitId);
|
args.putLong("habitId", habit.getId());
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,8 @@ public class ListHabitsController
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final HabitList habitList;
|
private final HabitList habitList;
|
||||||
|
|
||||||
private HabitCardListAdapter adapter;
|
@NonNull
|
||||||
|
private final HabitCardListAdapter adapter;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Preferences prefs;
|
Preferences prefs;
|
||||||
@@ -81,6 +82,7 @@ public class ListHabitsController
|
|||||||
if (filename != null) screen.showSendFileScreen(filename);
|
if (filename != null) screen.showSendFileScreen(filename);
|
||||||
else screen.showMessage(R.string.could_not_export);
|
else screen.showMessage(R.string.could_not_export);
|
||||||
});
|
});
|
||||||
|
|
||||||
task.execute();
|
task.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,35 +20,43 @@
|
|||||||
package org.isoron.uhabits.ui.habits.list;
|
package org.isoron.uhabits.ui.habits.list;
|
||||||
|
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.net.*;
|
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
import android.support.v7.app.*;
|
|
||||||
|
|
||||||
import com.android.colorpicker.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.intents.*;
|
||||||
|
import org.isoron.uhabits.io.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.ui.*;
|
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.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 org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
public class ListHabitsScreen extends BaseScreen
|
public class ListHabitsScreen extends BaseScreen
|
||||||
{
|
{
|
||||||
@Nullable
|
@Nullable
|
||||||
ListHabitsController controller;
|
ListHabitsController controller;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected DialogFactory dialogFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected IntentFactory intentFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected DirFinder dirFinder;
|
||||||
|
|
||||||
public ListHabitsScreen(@NonNull BaseActivity activity,
|
public ListHabitsScreen(@NonNull BaseActivity activity,
|
||||||
ListHabitsRootView rootView)
|
@NonNull ListHabitsRootView rootView)
|
||||||
{
|
{
|
||||||
super(activity);
|
super(activity);
|
||||||
setRootView(rootView);
|
setRootView(rootView);
|
||||||
|
HabitsApplication.getComponent().inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,90 +91,83 @@ public class ListHabitsScreen extends BaseScreen
|
|||||||
|
|
||||||
public void showAboutScreen()
|
public void showAboutScreen()
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(activity, AboutActivity.class);
|
Intent intent = intentFactory.startAboutActivity(activity);
|
||||||
activity.startActivity(intent);
|
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 picker =
|
||||||
ColorPickerDialog.newInstance(R.string.color_picker_default_title,
|
dialogFactory.buildColorPicker(habit.getColor());
|
||||||
ColorUtils.getPalette(activity), color, 4,
|
picker.setListener(callback);
|
||||||
ColorPickerDialog.SIZE_SMALL);
|
activity.showDialog(picker, "picker");
|
||||||
|
|
||||||
picker.setOnColorSelectedListener(c -> {
|
|
||||||
c = ColorUtils.colorToPaletteIndex(activity, c);
|
|
||||||
callback.onColorSelected(c);
|
|
||||||
});
|
|
||||||
picker.show(activity.getSupportFragmentManager(), "picker");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showCreateHabitScreen()
|
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)
|
ConfirmDeleteDialog dialog =
|
||||||
.setTitle(R.string.delete_habits)
|
dialogFactory.buildConfirmDeleteDialog(activity, callback);
|
||||||
.setMessage(R.string.delete_habits_message)
|
activity.showDialog(dialog);
|
||||||
.setPositiveButton(android.R.string.yes,
|
|
||||||
(dialog, which) -> callback.run())
|
|
||||||
.setNegativeButton(android.R.string.no, null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showEditHabitScreen(Habit habit)
|
public void showEditHabitScreen(Habit habit)
|
||||||
{
|
{
|
||||||
BaseDialogFragment frag =
|
EditHabitDialog dialog = dialogFactory.buildEditHabitDialog(habit);
|
||||||
EditHabitDialogFragment.newInstance(habit.getId());
|
activity.showDialog(dialog, "editHabit");
|
||||||
frag.show(activity.getSupportFragmentManager(), "editHabit");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showFAQScreen()
|
public void showFAQScreen()
|
||||||
{
|
{
|
||||||
Intent intent = new Intent();
|
Intent intent = intentFactory.viewFAQ(activity);
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
|
||||||
intent.setData(Uri.parse(activity.getString(R.string.helpURL)));
|
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showHabitScreen(@NonNull Habit habit)
|
public void showHabitScreen(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(activity, ShowHabitActivity.class);
|
Intent intent = intentFactory.startShowHabitActivity(activity, habit);
|
||||||
intent.setData(
|
|
||||||
Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId()));
|
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showImportScreen()
|
public void showImportScreen()
|
||||||
{
|
{
|
||||||
if (controller == null) return;
|
File dir = dirFinder.findStorageDir(null);
|
||||||
|
|
||||||
File dir = FileUtils.getFilesDir(null);
|
|
||||||
if (dir == null)
|
if (dir == null)
|
||||||
{
|
{
|
||||||
showMessage(R.string.could_not_import);
|
activity.showMessage(R.string.could_not_import);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePickerDialog picker = new FilePickerDialog(activity, dir);
|
FilePickerDialog picker = dialogFactory.buildFilePicker(activity, dir);
|
||||||
|
if (controller != null)
|
||||||
picker.setListener(file -> controller.onImportData(file));
|
picker.setListener(file -> controller.onImportData(file));
|
||||||
picker.show();
|
activity.showDialog(picker.getDialog());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showIntroScreen()
|
public void showIntroScreen()
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(activity, IntroActivity.class);
|
Intent intent = intentFactory.startIntroActivity(activity);
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showSettingsScreen()
|
public void showSettingsScreen()
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(activity, SettingsActivity.class);
|
Intent intent = intentFactory.startSettingsActivity(activity);
|
||||||
activity.startActivityForResult(intent, 0);
|
activity.startActivityForResult(intent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ public class ListHabitsScreen extends BaseScreen
|
|||||||
private void refreshTheme()
|
private void refreshTheme()
|
||||||
{
|
{
|
||||||
new Handler().postDelayed(() -> {
|
new Handler().postDelayed(() -> {
|
||||||
Intent intent = new Intent(activity, MainActivity.class);
|
Intent intent = new Intent(activity, ListHabitsScreen.class);
|
||||||
|
|
||||||
activity.finish();
|
activity.finish();
|
||||||
activity.overridePendingTransition(android.R.anim.fade_in,
|
activity.overridePendingTransition(android.R.anim.fade_in,
|
||||||
@@ -191,14 +192,4 @@ public class ListHabitsScreen extends BaseScreen
|
|||||||
|
|
||||||
}, 500); // HACK: Let the menu disappear first
|
}, 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.commands.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.tasks.*;
|
import org.isoron.uhabits.tasks.*;
|
||||||
import org.isoron.uhabits.ui.habits.edit.*;
|
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||||
|
|
||||||
import javax.inject.*;
|
import javax.inject.*;
|
||||||
|
|
||||||
|
|||||||
@@ -20,33 +20,38 @@
|
|||||||
package org.isoron.uhabits.ui.habits.show;
|
package org.isoron.uhabits.ui.habits.show;
|
||||||
|
|
||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
import android.support.v4.app.*;
|
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.ui.*;
|
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.edit.*;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
public class ShowHabitScreen extends BaseScreen
|
public class ShowHabitScreen extends BaseScreen
|
||||||
{
|
{
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Habit habit;
|
private final Habit habit;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected DialogFactory dialogFactory;
|
||||||
|
|
||||||
public ShowHabitScreen(@NonNull BaseActivity activity,
|
public ShowHabitScreen(@NonNull BaseActivity activity,
|
||||||
@NonNull Habit habit,
|
@NonNull Habit habit,
|
||||||
ShowHabitRootView view)
|
ShowHabitRootView view)
|
||||||
{
|
{
|
||||||
super(activity);
|
super(activity);
|
||||||
|
HabitsApplication.getComponent().inject(this);
|
||||||
|
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
setRootView(view);
|
setRootView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showEditHabitDialog()
|
public void showEditHabitDialog()
|
||||||
{
|
{
|
||||||
Long id = habit.getId();
|
EditHabitDialog dialog = dialogFactory.buildEditHabitDialog(habit);
|
||||||
if (id == null) throw new RuntimeException("habit not saved");
|
activity.showDialog(dialog, "editHabit");
|
||||||
|
|
||||||
FragmentManager manager = activity.getSupportFragmentManager();
|
|
||||||
EditHabitDialogFragment.newInstance(id).show(manager, "editHabit");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showEditHistoryDialog(
|
public void showEditHistoryDialog(
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.ui.intro;
|
package org.isoron.uhabits.ui.intro;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.content.*;
|
||||||
import android.os.Bundle;
|
import android.graphics.*;
|
||||||
|
import android.os.*;
|
||||||
|
|
||||||
import com.github.paolorotolo.appintro.AppIntro2;
|
import com.github.paolorotolo.appintro.*;
|
||||||
import com.github.paolorotolo.appintro.AppIntroFragment;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,6 @@
|
|||||||
package org.isoron.uhabits.ui.settings;
|
package org.isoron.uhabits.ui.settings;
|
||||||
|
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
import android.support.annotation.*;
|
|
||||||
import android.support.v4.app.*;
|
|
||||||
import android.view.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.ui.*;
|
import org.isoron.uhabits.ui.*;
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ public class CheckmarkWidget extends BaseWidget
|
|||||||
@Override
|
@Override
|
||||||
public PendingIntent getOnClickPendingIntent(Context context)
|
public PendingIntent getOnClickPendingIntent(Context context)
|
||||||
{
|
{
|
||||||
IntentFactory factory = new IntentFactory(context);
|
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||||
return factory.buildToggleCheckmark(habit, null);
|
return factory.toggleCheckmark(habit, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ public class FrequencyWidget extends BaseWidget
|
|||||||
@Override
|
@Override
|
||||||
public PendingIntent getOnClickPendingIntent(Context context)
|
public PendingIntent getOnClickPendingIntent(Context context)
|
||||||
{
|
{
|
||||||
IntentFactory factory = new IntentFactory(context);
|
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||||
return factory.buildViewHabit(habit);
|
return factory.showHabit(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ public class HistoryWidget extends BaseWidget
|
|||||||
@Override
|
@Override
|
||||||
public PendingIntent getOnClickPendingIntent(Context context)
|
public PendingIntent getOnClickPendingIntent(Context context)
|
||||||
{
|
{
|
||||||
IntentFactory factory = new IntentFactory(context);
|
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||||
return factory.buildViewHabit(habit);
|
return factory.showHabit(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ public class ScoreWidget extends BaseWidget
|
|||||||
@Override
|
@Override
|
||||||
public PendingIntent getOnClickPendingIntent(Context context)
|
public PendingIntent getOnClickPendingIntent(Context context)
|
||||||
{
|
{
|
||||||
IntentFactory factory = new IntentFactory(context);
|
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||||
return factory.buildViewHabit(habit);
|
return factory.showHabit(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ public class StreakWidget extends BaseWidget
|
|||||||
@Override
|
@Override
|
||||||
public PendingIntent getOnClickPendingIntent(Context context)
|
public PendingIntent getOnClickPendingIntent(Context context)
|
||||||
{
|
{
|
||||||
IntentFactory factory = new IntentFactory(context);
|
PendingIntentFactory factory = new PendingIntentFactory(context);
|
||||||
return factory.buildViewHabit(habit);
|
return factory.showHabit(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,21 +19,15 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.utils;
|
package org.isoron.uhabits.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.*;
|
||||||
import android.os.Environment;
|
import android.os.*;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.v4.content.*;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.util.*;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.HabitsApplication;
|
import org.isoron.uhabits.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
public abstract class FileUtils
|
public abstract class FileUtils
|
||||||
{
|
{
|
||||||
@@ -60,27 +54,49 @@ public abstract class FileUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static File getSDCardDir(@Nullable String relativePath)
|
private static File getDir(@NonNull File potentialParentDirs[],
|
||||||
|
@Nullable String relativePath)
|
||||||
{
|
{
|
||||||
File parents[] = new File[]{ Environment.getExternalStorageDirectory() };
|
if (relativePath == null) relativePath = "";
|
||||||
return getDir(parents, relativePath);
|
|
||||||
|
File chosenDir = null;
|
||||||
|
for (File dir : potentialParentDirs)
|
||||||
|
{
|
||||||
|
if (dir == null || !dir.canWrite()) continue;
|
||||||
|
chosenDir = dir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chosenDir == null)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
if (!dir.exists() && !dir.mkdirs())
|
||||||
|
{
|
||||||
|
Log.e("DatabaseHelper",
|
||||||
|
"getDir: chosen dir does not exist and cannot be created");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static File getFilesDir(@Nullable String relativePath)
|
public static File getFilesDir(@Nullable String relativePath)
|
||||||
{
|
{
|
||||||
Context context = HabitsApplication.getContext();
|
Context context = HabitsApplication.getContext();
|
||||||
if(context == null)
|
File externalFilesDirs[] =
|
||||||
{
|
ContextCompat.getExternalFilesDirs(context, null);
|
||||||
Log.e("DatabaseHelper", "getFilesDir: no application context available");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
File externalFilesDirs[] = ContextCompat.getExternalFilesDirs(context, null);
|
if (externalFilesDirs == null)
|
||||||
|
|
||||||
if(externalFilesDirs == null)
|
|
||||||
{
|
{
|
||||||
Log.e("DatabaseHelper", "getFilesDir: getExternalFilesDirs returned null");
|
Log.e("DatabaseHelper",
|
||||||
|
"getFilesDir: getExternalFilesDirs returned null");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,32 +104,10 @@ public abstract class FileUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static File getDir(@NonNull File potentialParentDirs[], @Nullable String relativePath)
|
public static File getSDCardDir(@Nullable String relativePath)
|
||||||
{
|
{
|
||||||
if(relativePath == null) relativePath = "";
|
File parents[] =
|
||||||
|
new File[]{ Environment.getExternalStorageDirectory() };
|
||||||
File chosenDir = null;
|
return getDir(parents, relativePath);
|
||||||
for(File dir : potentialParentDirs)
|
|
||||||
{
|
|
||||||
if (dir == null || !dir.canWrite()) continue;
|
|
||||||
chosenDir = dir;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chosenDir == null)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
if (!dir.exists() && !dir.mkdirs())
|
|
||||||
{
|
|
||||||
Log.e("DatabaseHelper", "getDir: chosen dir does not exist and cannot be created");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,16 @@ import android.preference.*;
|
|||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
|
|
||||||
|
import javax.inject.*;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class Preferences
|
public class Preferences
|
||||||
{
|
{
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public Preferences()
|
public Preferences()
|
||||||
{
|
{
|
||||||
this.context = HabitsApplication.getContext();
|
this.context = HabitsApplication.getContext();
|
||||||
|
|||||||
@@ -32,20 +32,21 @@ import javax.inject.*;
|
|||||||
|
|
||||||
import static org.isoron.uhabits.utils.DateUtils.*;
|
import static org.isoron.uhabits.utils.DateUtils.*;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class ReminderScheduler
|
public class ReminderScheduler
|
||||||
{
|
{
|
||||||
private final IntentFactory intentFactory;
|
@Inject
|
||||||
|
protected PendingIntentFactory pendingIntentFactory;
|
||||||
|
|
||||||
private final IntentScheduler intentScheduler;
|
@Inject
|
||||||
|
protected IntentScheduler intentScheduler;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
HabitLogger logger;
|
HabitLogger logger;
|
||||||
|
|
||||||
public ReminderScheduler(IntentFactory intentFactory,
|
@Inject
|
||||||
IntentScheduler intentScheduler)
|
public ReminderScheduler()
|
||||||
{
|
{
|
||||||
this.intentFactory = intentFactory;
|
|
||||||
this.intentScheduler = intentScheduler;
|
|
||||||
HabitsApplication.getComponent().inject(this);
|
HabitsApplication.getComponent().inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ public class ReminderScheduler
|
|||||||
if (reminderTime == null) reminderTime = getReminderTime(reminder);
|
if (reminderTime == null) reminderTime = getReminderTime(reminder);
|
||||||
long timestamp = getStartOfDay(toLocalTime(reminderTime));
|
long timestamp = getStartOfDay(toLocalTime(reminderTime));
|
||||||
|
|
||||||
PendingIntent intent = intentFactory.buildShowReminder(habit,
|
PendingIntent intent = pendingIntentFactory.showReminder(habit,
|
||||||
reminderTime, timestamp);
|
reminderTime, timestamp);
|
||||||
intentScheduler.schedule(reminderTime, intent);
|
intentScheduler.schedule(reminderTime, intent);
|
||||||
logger.logReminderScheduled(habit, reminderTime);
|
logger.logReminderScheduled(habit, reminderTime);
|
||||||
|
|||||||
@@ -22,17 +22,17 @@ package org.isoron.uhabits.utils;
|
|||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.preference.*;
|
import android.preference.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import javax.inject.*;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class WidgetPreferences
|
public class WidgetPreferences
|
||||||
{
|
{
|
||||||
private Context context;
|
|
||||||
|
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
public WidgetPreferences()
|
@Inject
|
||||||
|
public WidgetPreferences(Context context)
|
||||||
{
|
{
|
||||||
this.context = HabitsApplication.getContext();
|
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
style="@style/dialogForm"
|
style="@style/dialogForm"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".ui.habits.edit.BaseDialogFragment"
|
tools:context=".ui.habits.edit.BaseDialog"
|
||||||
tools:ignore="MergeRootFrame">
|
tools:ignore="MergeRootFrame">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -19,7 +19,10 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.intents.*;
|
||||||
|
import org.isoron.uhabits.io.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
@@ -36,21 +39,41 @@ public class BaseUnitTest
|
|||||||
@Inject
|
@Inject
|
||||||
protected ModelFactory modelFactory;
|
protected ModelFactory modelFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected DialogFactory dialogFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected IntentFactory intentFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected HabitList habitList;
|
protected HabitList habitList;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected HabitLogger logger;
|
protected HabitLogger logger;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected PendingIntentFactory pendingIntentFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected IntentScheduler intentScheduler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected DirFinder dirFinder;
|
||||||
|
|
||||||
protected TestComponent testComponent;
|
protected TestComponent testComponent;
|
||||||
|
|
||||||
protected HabitFixtures fixtures;
|
protected HabitFixtures fixtures;
|
||||||
|
|
||||||
|
public void log(String format, Object... args)
|
||||||
|
{
|
||||||
|
System.out.println(String.format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp()
|
public void setUp()
|
||||||
{
|
{
|
||||||
DateUtils.setFixedLocalTime(FIXED_LOCAL_TIME);
|
DateUtils.setFixedLocalTime(FIXED_LOCAL_TIME);
|
||||||
testComponent = DaggerTestComponent.builder().build();
|
testComponent = DaggerTestComponent.create();
|
||||||
HabitsApplication.setComponent(testComponent);
|
HabitsApplication.setComponent(testComponent);
|
||||||
testComponent.inject(this);
|
testComponent.inject(this);
|
||||||
fixtures = new HabitFixtures(habitList);
|
fixtures = new HabitFixtures(habitList);
|
||||||
@@ -63,9 +86,4 @@ public class BaseUnitTest
|
|||||||
fixtures.purgeHabits();
|
fixtures.purgeHabits();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void log(String format, Object... args)
|
|
||||||
{
|
|
||||||
System.out.println(String.format(format, args));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,11 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
import org.isoron.uhabits.commands.*;
|
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.*;
|
||||||
import org.isoron.uhabits.models.memory.*;
|
import org.isoron.uhabits.models.memory.*;
|
||||||
|
import org.isoron.uhabits.ui.common.dialogs.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import javax.inject.*;
|
import javax.inject.*;
|
||||||
@@ -40,6 +43,20 @@ public class TestModule
|
|||||||
return mock(CommandRunner.class);
|
return mock(CommandRunner.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
DialogFactory provideDialogFactory()
|
||||||
|
{
|
||||||
|
return mock(DialogFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
DirFinder provideDirFinder()
|
||||||
|
{
|
||||||
|
return mock(DirFinder.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
Habit provideHabit()
|
Habit provideHabit()
|
||||||
{
|
{
|
||||||
@@ -53,6 +70,27 @@ public class TestModule
|
|||||||
return new MemoryHabitList();
|
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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
ModelFactory provideModelFactory()
|
ModelFactory provideModelFactory()
|
||||||
@@ -60,6 +98,13 @@ public class TestModule
|
|||||||
return new MemoryModelFactory();
|
return new MemoryModelFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
PendingIntentFactory providePendingIntentFactory()
|
||||||
|
{
|
||||||
|
return mock(PendingIntentFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
Preferences providePreferences()
|
Preferences providePreferences()
|
||||||
@@ -67,13 +112,6 @@ public class TestModule
|
|||||||
return mock(Preferences.class);
|
return mock(Preferences.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
WidgetPreferences provideWidgetPreferences()
|
|
||||||
{
|
|
||||||
return mock(WidgetPreferences.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
ReminderScheduler provideReminderScheduler()
|
ReminderScheduler provideReminderScheduler()
|
||||||
@@ -83,8 +121,8 @@ public class TestModule
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@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 android.app.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.intents.*;
|
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
@@ -31,26 +30,19 @@ import static org.mockito.Mockito.*;
|
|||||||
@SuppressWarnings("JavaDoc")
|
@SuppressWarnings("JavaDoc")
|
||||||
public class ReminderSchedulerTest extends BaseUnitTest
|
public class ReminderSchedulerTest extends BaseUnitTest
|
||||||
{
|
{
|
||||||
private IntentFactory intentFactory;
|
|
||||||
|
|
||||||
private IntentScheduler intentScheduler;
|
|
||||||
|
|
||||||
private ReminderScheduler scheduler;
|
|
||||||
|
|
||||||
private Habit habit;
|
private Habit habit;
|
||||||
|
|
||||||
private PendingIntent intent;
|
private PendingIntent intent;
|
||||||
|
|
||||||
|
private ReminderScheduler reminderScheduler;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@Override
|
@Override
|
||||||
public void setUp()
|
public void setUp()
|
||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
intentFactory = mock(IntentFactory.class);
|
|
||||||
intentScheduler = mock(IntentScheduler.class);
|
|
||||||
intent = mock(PendingIntent.class);
|
intent = mock(PendingIntent.class);
|
||||||
|
reminderScheduler = new ReminderScheduler();
|
||||||
scheduler = new ReminderScheduler(intentFactory, intentScheduler);
|
|
||||||
habit = fixtures.createEmptyHabit();
|
habit = fixtures.createEmptyHabit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +86,7 @@ public class ReminderSchedulerTest extends BaseUnitTest
|
|||||||
|
|
||||||
fixtures.createEmptyHabit();
|
fixtures.createEmptyHabit();
|
||||||
|
|
||||||
scheduler.schedule(habitList);
|
reminderScheduler.schedule(habitList);
|
||||||
|
|
||||||
verify(intentScheduler).schedule(1422347400000L, null);
|
verify(intentScheduler).schedule(1422347400000L, null);
|
||||||
verify(intentScheduler).schedule(1422297000000L, null);
|
verify(intentScheduler).schedule(1422297000000L, null);
|
||||||
@@ -117,7 +109,7 @@ public class ReminderSchedulerTest extends BaseUnitTest
|
|||||||
@Test
|
@Test
|
||||||
public void testSchedule_withoutReminder()
|
public void testSchedule_withoutReminder()
|
||||||
{
|
{
|
||||||
scheduler.schedule(habit, null);
|
reminderScheduler.schedule(habit, null);
|
||||||
verifyZeroInteractions(intentScheduler);
|
verifyZeroInteractions(intentScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,14 +117,14 @@ public class ReminderSchedulerTest extends BaseUnitTest
|
|||||||
long expectedCheckmarkTime,
|
long expectedCheckmarkTime,
|
||||||
long expectedReminderTime)
|
long expectedReminderTime)
|
||||||
{
|
{
|
||||||
when(intentFactory.buildShowReminder(habit, expectedReminderTime,
|
when(pendingIntentFactory.showReminder(habit, expectedReminderTime,
|
||||||
expectedCheckmarkTime)).thenReturn(intent);
|
expectedCheckmarkTime)).thenReturn(intent);
|
||||||
|
|
||||||
scheduler.schedule(habit, atTime);
|
reminderScheduler.schedule(habit, atTime);
|
||||||
|
|
||||||
verify(logger).logReminderScheduled(habit, expectedReminderTime);
|
verify(logger).logReminderScheduled(habit, expectedReminderTime);
|
||||||
|
|
||||||
verify(intentFactory).buildShowReminder(habit, expectedReminderTime,
|
verify(pendingIntentFactory).showReminder(habit, expectedReminderTime,
|
||||||
expectedCheckmarkTime);
|
expectedCheckmarkTime);
|
||||||
verify(intentScheduler).schedule(expectedReminderTime, intent);
|
verify(intentScheduler).schedule(expectedReminderTime, intent);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user