diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml
index 465a4ae4a..00a950c73 100644
--- a/Habitica/AndroidManifest.xml
+++ b/Habitica/AndroidManifest.xml
@@ -166,12 +166,6 @@
-
-
-
-
-
-
@@ -204,7 +198,15 @@
android:resource="@xml/avatar_widget_info" />
+ android:label="@string/widget_dailies">
+
+
+
+
+
+
@@ -223,6 +225,9 @@
+
diff --git a/Habitica/res/layout/widget_configure_task_list.xml b/Habitica/res/layout/widget_configure_task_list.xml
deleted file mode 100644
index 52a5f6d8e..000000000
--- a/Habitica/res/layout/widget_configure_task_list.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/Habitica/res/layout/widget_configure_task_list_item.xml b/Habitica/res/layout/widget_configure_task_list_item.xml
deleted file mode 100644
index 2de284224..000000000
--- a/Habitica/res/layout/widget_configure_task_list_item.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 32c9b402c..8bbe7d42e 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -416,7 +416,8 @@ To start, which parts of your life do you want to improve?
Add Reward
You completed all your dailies. Well done!
Habitica Do Habit
- Habitica Task List
+ Habitica Dailies
+ Habitica Todo List
Habitica Add Task
Google play services could not be found.
Purchase
diff --git a/Habitica/res/xml/task_list_widget_info.xml b/Habitica/res/xml/task_list_widget_info.xml
index ba50c211a..db0b85187 100644
--- a/Habitica/res/xml/task_list_widget_info.xml
+++ b/Habitica/res/xml/task_list_widget_info.xml
@@ -4,7 +4,6 @@
android:minHeight="120dp"
android:minWidth="120dp"
android:updatePeriodMillis="1800000"
- android:resizeMode="horizontal|vertical"
- android:configure="com.habitrpg.android.habitica.ui.activities.TaskListWidgetActivity">
+ android:resizeMode="horizontal|vertical">
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java
index f40aa70f7..e819a04da 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java
@@ -21,7 +21,6 @@ import com.habitrpg.android.habitica.ui.activities.SetupActivity;
import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity;
import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity;
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
-import com.habitrpg.android.habitica.ui.activities.TaskListWidgetActivity;
import com.habitrpg.android.habitica.ui.fragments.GemsPurchaseFragment;
import com.habitrpg.android.habitica.ui.fragments.NewsFragment;
import com.habitrpg.android.habitica.ui.fragments.faq.FAQDetailFragment;
@@ -61,6 +60,7 @@ import com.habitrpg.android.habitica.widget.AvatarStatsWidgetProvider;
import com.habitrpg.android.habitica.widget.DailiesWidgetProvider;
import com.habitrpg.android.habitica.widget.HabitButtonWidgetProvider;
import com.habitrpg.android.habitica.widget.HabitButtonWidgetService;
+import com.habitrpg.android.habitica.widget.TaskListWidgetProvider;
import javax.inject.Singleton;
@@ -186,5 +186,5 @@ public interface AppComponent {
void inject(SoundManager soundManager);
- void inject(TaskListWidgetActivity taskListWidgetActivity);
+ void inject(TaskListWidgetProvider taskListWidgetProvider);
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskListWidgetActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskListWidgetActivity.java
deleted file mode 100644
index 38bc88165..000000000
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskListWidgetActivity.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.habitrpg.android.habitica.ui.activities;
-
-import android.appwidget.AppWidgetManager;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.support.v7.preference.PreferenceManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import com.habitrpg.android.habitica.R;
-import com.habitrpg.android.habitica.components.AppComponent;
-import com.habitrpg.android.habitica.widget.HabitButtonWidgetProvider;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-
-public class TaskListWidgetActivity extends BaseActivity implements TaskTypeSelected {
-
- @BindView(R.id.recyclerView)
- RecyclerView recyclerView;
- private int widgetId;
-
- @Override
- protected int getLayoutResId() {
- return R.layout.widget_configure_task_list;
- }
-
- @Override
- protected void injectActivity(AppComponent component) {
- component.inject(this);
- }
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Intent intent = getIntent();
- Bundle extras = intent.getExtras();
- if (extras != null) {
- widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
- }
-
- // If this activity was started with an intent without an app widget ID,
- // finish with an error.
- if (widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
- finish();
- }
-
- LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
-
- if (layoutManager == null) {
- layoutManager = new LinearLayoutManager(this);
-
- recyclerView.setLayoutManager(layoutManager);
- }
-
- HashMap taskTypesMap = new HashMap<>();
- taskTypesMap.put(getString(R.string.dailies),"dailies");
- taskTypesMap.put(getString(R.string.todos),"todos");
-
- recyclerView.setAdapter(new TaskTypeSelectionViewAdapter(taskTypesMap, this));
- }
-
- @Override
- public void taskTypeSelected(String selectedType) {
- finishWithSelection(selectedType);
- }
-
-
-
- public class TaskTypeSelectionViewAdapter extends RecyclerView.Adapter
- {
- private HashMap taskTypes;
- private TaskTypeSelected taskTypeSelected;
-
- public TaskTypeSelectionViewAdapter(HashMap taskTypes, TaskTypeSelected taskTypeSelected) {
-
- this.taskTypes = taskTypes;
- this.taskTypeSelected = taskTypeSelected;
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.widget_configure_task_list_item, parent, false);
- return new ViewHolder(view);
- }
-
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- ArrayList keys = new ArrayList<>(taskTypes.keySet());
-
- String label = keys.get(position);
- String value = taskTypes.get(label);
-
- holder.bind(label, value);
- }
-
- @Override
- public int getItemCount() {
- return taskTypes.size();
- }
-
- public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
- @BindView(R.id.text)
- TextView textView;
-
- public ViewHolder(View itemView) {
- super(itemView);
-
- itemView.setOnClickListener(this);
- itemView.setClickable(true);
-
- ButterKnife.bind(this, itemView);
- }
-
- private String key;
-
- public void bind(String label, String key){
- textView.setText(label);
- this.key = key;
- }
-
- @Override
- public void onClick(View view) {
- taskTypeSelected.taskTypeSelected(key);
- }
- }
- }
-
- private void finishWithSelection(String selectedTaskType) {
- storeSelectedTaskType(selectedTaskType);
-
- Intent resultValue = new Intent();
- resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
- setResult(RESULT_OK, resultValue);
- finish();
-
- Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, HabitButtonWidgetProvider.class);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {widgetId});
- sendBroadcast(intent);
- }
-
- private void storeSelectedTaskType(String selectedTaskType) {
- SharedPreferences.Editor preferences = PreferenceManager.getDefaultSharedPreferences(this).edit();
- preferences.putString("habit_list_widget_" + widgetId, selectedTaskType);
- preferences.apply();
- }
-}
-
-interface TaskTypeSelected
-{
- void taskTypeSelected(String selectedType);
-}
-
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesListProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesListProvider.java
index 3123002e5..44bbde43d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesListProvider.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesListProvider.java
@@ -1,129 +1,13 @@
package com.habitrpg.android.habitica.widget;
-import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
-import android.content.res.TypedArray;
-import android.text.SpannableStringBuilder;
-import android.text.style.DynamicDrawableSpan;
-import android.widget.RemoteViews;
-import android.widget.RemoteViewsService;
-import com.habitrpg.android.habitica.R;
-import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
-import com.raizlabs.android.dbflow.sql.builder.Condition;
-import com.raizlabs.android.dbflow.sql.language.OrderBy;
-import com.raizlabs.android.dbflow.sql.language.Select;
-
-import net.pherth.android.emoji_library.EmojiHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import rx.Observable;
-import rx.android.schedulers.AndroidSchedulers;
-import rx.schedulers.Schedulers;
-
-public class DailiesListProvider implements RemoteViewsService.RemoteViewsFactory {
- private final int widgetId;
- private List taskList = new ArrayList<>();
- private Context context = null;
- private boolean reloadData;
+public class DailiesListProvider extends TaskListProvider {
public DailiesListProvider(Context context, Intent intent) {
- this.context = context;
- this.widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
- this.reloadData = false;
- this.loadData();
+ super(context, intent, Task.TYPE_DAILY);
}
+}
- private void loadData() {
- Observable.defer(() -> Observable.from(new Select()
- .from(Task.class)
- .where(Condition.column("type").eq(Task.TYPE_DAILY))
- .and(Condition.column("completed").eq(false))
- .orderBy(OrderBy.columns("position", "dateCreated").descending())
- .queryList()))
- .filter(task -> task.isDisplayedActive(0))
- .toList()
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(tasks -> {
- taskList = tasks;
- this.reloadData = false;
- AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(widgetId, R.id.list_view);
- }, throwable -> {
- this.reloadData = false;
- });
- }
-
-
- @Override
- public void onCreate() {
- }
-
- @Override
- public void onDataSetChanged() {
- if (this.reloadData) {
- this.loadData();
- }
- this.reloadData = true;
- }
-
- @Override
- public void onDestroy() {
- }
-
- @Override
- public int getCount() {
- return taskList.size();
- }
-
- @Override
- public RemoteViews getViewAt(int position) {
- final RemoteViews remoteView = new RemoteViews(
- context.getPackageName(), R.layout.widget_dailies_list_row);
- if (taskList.size() > position) {
- Task task = taskList.get(position);
-
- CharSequence parsedText = MarkdownParser.parseMarkdown(task.text);
-
- SpannableStringBuilder builder = new SpannableStringBuilder(parsedText);
- EmojiHandler.addEmojis(this.context, builder, 16, DynamicDrawableSpan.ALIGN_BASELINE, 16, 0, -1, false);
-
- remoteView.setTextViewText(R.id.dailies_text, builder);
- remoteView.setInt(R.id.checkbox_background, "setBackgroundResource", task.getLightTaskColor());
- Intent fillInIntent = new Intent();
- fillInIntent.putExtra(DailiesWidgetProvider.TASK_ID_ITEM, task.getId());
- remoteView.setOnClickFillInIntent(R.id.dailies_list_row, fillInIntent);
- }
- return remoteView;
- }
-
- @Override
- public RemoteViews getLoadingView() {
- return new RemoteViews(
- context.getPackageName(), R.layout.widget_dailies_list_row);
- }
-
- @Override
- public int getViewTypeCount() {
- return 1;
- }
-
- @Override
- public long getItemId(int position) {
- if (taskList.size() > position) {
- Task task = taskList.get(position);
- return task.getId().hashCode();
- }
- return position;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
-}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetProvider.java
index c486a3bf7..3f416ea9c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetProvider.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetProvider.java
@@ -1,113 +1,10 @@
package com.habitrpg.android.habitica.widget;
-import android.app.PendingIntent;
-import android.appwidget.AppWidgetManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.widget.RemoteViews;
-
-import com.habitrpg.android.habitica.APIHelper;
-import com.habitrpg.android.habitica.HabiticaApplication;
-import com.habitrpg.android.habitica.HostConfig;
-import com.habitrpg.android.habitica.R;
-import com.magicmicky.habitrpgwrapper.lib.models.TaskDirection;
-import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
-import com.raizlabs.android.dbflow.sql.builder.Condition;
-import com.raizlabs.android.dbflow.sql.language.Select;
-
-import javax.inject.Inject;
-
-public class DailiesWidgetProvider extends BaseWidgetProvider {
- public static final String DAILY_ACTION = "com.habitrpg.android.habitica.DAILY_ACTION";
- public static final String TASK_ID_ITEM = "com.habitrpg.android.habitica.TASK_ID_ITEM";
-
- @Inject
- APIHelper apiHelper;
- @Inject
- HostConfig hostConfig;
-
- private void setUp(Context context) {
- if (apiHelper == null) {
- HabiticaApplication application = HabiticaApplication.getInstance(context);
- application.getComponent().inject(this);
- }
- }
+public class DailiesWidgetProvider extends TaskListWidgetProvider{
@Override
- public void onReceive(Context context, Intent intent) {
- setUp(context);
- if (intent.getAction().equals(DAILY_ACTION)) {
- AppWidgetManager mgr = AppWidgetManager.getInstance(context);
- int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
- AppWidgetManager.INVALID_APPWIDGET_ID);
- String taskId = intent.getStringExtra(TASK_ID_ITEM);
-
- if (taskId != null) {
- apiHelper.apiService.postTaskDirection(taskId, TaskDirection.up.toString())
- .compose(apiHelper.configureApiCallObserver())
- .subscribe(taskDirectionData -> {
- Task task = new Select().from(Task.class).where(Condition.column("id").eq(taskId)).querySingle();
- task.completed = true;
- task.save();
- showToastForTaskDirection(context, taskDirectionData, hostConfig.getUser());
- AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
- }, throwable -> {
- AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
- });
- }
- }
- super.onReceive(context, intent);
+ protected Class getServiceClass() {
+ return DailiesWidgetService.class;
}
+}
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- setUp(context);
- ComponentName thisWidget = new ComponentName(context,
- DailiesWidgetProvider.class);
- int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
-
- if (Build.VERSION.SDK_INT >= 16) {
- for (int widgetId : allWidgetIds) {
- Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);
- appWidgetManager.partiallyUpdateAppWidget(widgetId,
- sizeRemoteViews(context, options, widgetId));
- }
- }
-
- for (int i = 0; i < appWidgetIds.length; ++i) {
- Intent intent = new Intent(context, DailiesWidgetService.class);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
- intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
- RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_dailies);
- rv.setRemoteAdapter(appWidgetIds[i], R.id.list_view, intent);
- rv.setEmptyView(R.id.list, R.id.empty_view);
-
- Intent taskIntent = new Intent(context, DailiesWidgetProvider.class);
- taskIntent.setAction(DAILY_ACTION);
- taskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
- intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
- PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, taskIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- rv.setPendingIntentTemplate(R.id.list_view, toastPendingIntent);
-
- appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
-
- AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.list_view);
- }
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- }
-
- @Override
- public int layoutResourceId() {
- return R.layout.widget_dailies;
- }
-
- @Override
- public RemoteViews configureRemoteViews(RemoteViews remoteViews, int widgetId, int columns, int rows) {
- return remoteViews;
- }
-}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetService.java
index 03f081f5f..094448126 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetService.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/DailiesWidgetService.java
@@ -10,3 +10,4 @@ public class DailiesWidgetService extends RemoteViewsService {
return new DailiesListProvider(this.getApplicationContext(), intent);
}
}
+
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListProvider.java
new file mode 100644
index 000000000..8bc17e635
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListProvider.java
@@ -0,0 +1,129 @@
+package com.habitrpg.android.habitica.widget;
+
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.text.SpannableStringBuilder;
+import android.text.style.DynamicDrawableSpan;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
+import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
+import com.raizlabs.android.dbflow.sql.builder.Condition;
+import com.raizlabs.android.dbflow.sql.language.OrderBy;
+import com.raizlabs.android.dbflow.sql.language.Select;
+
+import net.pherth.android.emoji_library.EmojiHandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+public abstract class TaskListProvider implements RemoteViewsService.RemoteViewsFactory {
+ private final int widgetId;
+ private String taskType;
+ private List taskList = new ArrayList<>();
+ private Context context = null;
+ private boolean reloadData;
+
+ public TaskListProvider(Context context, Intent intent, String taskType) {
+ this.context = context;
+ this.widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
+ this.reloadData = false;
+ this.taskType = taskType;
+
+ this.loadData();
+ }
+
+ private void loadData() {
+ Observable.defer(() -> Observable.from(new Select()
+ .from(Task.class)
+ .where(Condition.column("type").eq(taskType))
+ .and(Condition.column("completed").eq(false))
+ .orderBy(OrderBy.columns("position", "dateCreated").descending())
+ .queryList()))
+ .filter(task -> task.type.equals(Task.TYPE_TODO) || task.isDisplayedActive(0))
+ .toList()
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(tasks -> {
+ taskList = tasks;
+ this.reloadData = false;
+ AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(widgetId, R.id.list_view);
+ }, throwable -> {
+ this.reloadData = false;
+ });
+ }
+
+
+ @Override
+ public void onCreate() {
+ }
+
+ @Override
+ public void onDataSetChanged() {
+ if (this.reloadData) {
+ this.loadData();
+ }
+ this.reloadData = true;
+ }
+
+ @Override
+ public void onDestroy() {
+ }
+
+ @Override
+ public int getCount() {
+ return taskList.size();
+ }
+
+ @Override
+ public RemoteViews getViewAt(int position) {
+ final RemoteViews remoteView = new RemoteViews(
+ context.getPackageName(), R.layout.widget_dailies_list_row);
+ if (taskList.size() > position) {
+ Task task = taskList.get(position);
+
+ CharSequence parsedText = MarkdownParser.parseMarkdown(task.text);
+
+ SpannableStringBuilder builder = new SpannableStringBuilder(parsedText);
+ EmojiHandler.addEmojis(this.context, builder, 16, DynamicDrawableSpan.ALIGN_BASELINE, 16, 0, -1, false);
+
+ remoteView.setTextViewText(R.id.dailies_text, builder);
+ remoteView.setInt(R.id.checkbox_background, "setBackgroundResource", task.getLightTaskColor());
+ Intent fillInIntent = new Intent();
+ fillInIntent.putExtra(TaskListWidgetProvider.TASK_ID_ITEM, task.getId());
+ remoteView.setOnClickFillInIntent(R.id.dailies_list_row, fillInIntent);
+ }
+ return remoteView;
+ }
+
+ @Override
+ public RemoteViews getLoadingView() {
+ return new RemoteViews(context.getPackageName(), R.layout.widget_dailies_list_row);
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ if (taskList.size() > position) {
+ Task task = taskList.get(position);
+ return task.getId().hashCode();
+ }
+ return position;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java
new file mode 100644
index 000000000..98a84ee5c
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java
@@ -0,0 +1,125 @@
+package com.habitrpg.android.habitica.widget;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.widget.RemoteViews;
+
+import com.habitrpg.android.habitica.APIHelper;
+import com.habitrpg.android.habitica.HabiticaApplication;
+import com.habitrpg.android.habitica.HostConfig;
+import com.habitrpg.android.habitica.R;
+import com.magicmicky.habitrpgwrapper.lib.models.TaskDirection;
+import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
+import com.raizlabs.android.dbflow.sql.builder.Condition;
+import com.raizlabs.android.dbflow.sql.language.Select;
+
+import javax.inject.Inject;
+
+public abstract class TaskListWidgetProvider extends BaseWidgetProvider {
+ public static final String DAILY_ACTION = "com.habitrpg.android.habitica.DAILY_ACTION";
+ public static final String TASK_ID_ITEM = "com.habitrpg.android.habitica.TASK_ID_ITEM";
+
+ @Inject
+ APIHelper apiHelper;
+ @Inject
+ HostConfig hostConfig;
+ @Inject
+ public SharedPreferences sharedPreferences;
+
+ private void setUp(Context context) {
+ if (apiHelper == null) {
+ HabiticaApplication application = HabiticaApplication.getInstance(context);
+ application.getComponent().inject(this);
+ }
+ }
+
+ protected abstract Class getServiceClass();
+
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ setUp(context);
+ if (intent.getAction().equals(DAILY_ACTION)) {
+ AppWidgetManager mgr = AppWidgetManager.getInstance(context);
+ int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
+ AppWidgetManager.INVALID_APPWIDGET_ID);
+ String taskId = intent.getStringExtra(TASK_ID_ITEM);
+
+ if (taskId != null) {
+ apiHelper.apiService.postTaskDirection(taskId, TaskDirection.up.toString())
+ .compose(apiHelper.configureApiCallObserver())
+ .subscribe(taskDirectionData -> {
+ Task task = new Select().from(Task.class).where(Condition.column("id").eq(taskId)).querySingle();
+ task.completed = true;
+ task.save();
+ showToastForTaskDirection(context, taskDirectionData, hostConfig.getUser());
+ AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
+ }, throwable -> {
+ AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
+ });
+ }
+ }
+ super.onReceive(context, intent);
+ }
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ setUp(context);
+ ComponentName thisWidget = new ComponentName(context,
+ DailiesWidgetProvider.class);
+ int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
+
+ if (Build.VERSION.SDK_INT >= 16) {
+ for (int widgetId : allWidgetIds) {
+ Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);
+ appWidgetManager.partiallyUpdateAppWidget(widgetId,
+ sizeRemoteViews(context, options, widgetId));
+ }
+ }
+
+ for (int i = 0; i < appWidgetIds.length; ++i) {
+ Intent intent = new Intent(context, getServiceClass());
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
+ intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
+ RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_dailies);
+ rv.setRemoteAdapter(appWidgetIds[i], R.id.list_view, intent);
+ rv.setEmptyView(R.id.list, R.id.empty_view);
+
+ Intent taskIntent = new Intent(context, DailiesWidgetProvider.class);
+ taskIntent.setAction(DAILY_ACTION);
+ taskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
+ intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
+ PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, taskIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ rv.setPendingIntentTemplate(R.id.list_view, toastPendingIntent);
+
+ appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
+
+ AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.list_view);
+ }
+
+ super.onUpdate(context, appWidgetManager, appWidgetIds);
+ }
+
+ @Override
+ public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
+ super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
+ }
+
+ @Override
+ public int layoutResourceId() {
+ return R.layout.widget_dailies;
+ }
+
+ @Override
+ public RemoteViews configureRemoteViews(RemoteViews remoteViews, int widgetId, int columns, int rows) {
+ return remoteViews;
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodoListProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodoListProvider.java
new file mode 100644
index 000000000..0f24c7edc
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodoListProvider.java
@@ -0,0 +1,12 @@
+package com.habitrpg.android.habitica.widget;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
+
+public class TodoListProvider extends TaskListProvider {
+ public TodoListProvider(Context context, Intent intent) {
+ super(context, intent, Task.TYPE_TODO);
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodoListWidgetProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodoListWidgetProvider.java
new file mode 100644
index 000000000..185a14da0
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodoListWidgetProvider.java
@@ -0,0 +1,9 @@
+package com.habitrpg.android.habitica.widget;
+
+public class TodoListWidgetProvider extends TaskListWidgetProvider{
+
+ @Override
+ protected Class getServiceClass() {
+ return TodosWidgetService.class;
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodosWidgetService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodosWidgetService.java
new file mode 100644
index 000000000..e84a6a5db
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TodosWidgetService.java
@@ -0,0 +1,12 @@
+package com.habitrpg.android.habitica.widget;
+
+import android.content.Intent;
+import android.widget.RemoteViewsService;
+
+public class TodosWidgetService extends RemoteViewsService {
+
+ @Override
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ return new TodoListProvider(this.getApplicationContext(), intent);
+ }
+}