mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
Refactor widgets
This commit is contained in:
parent
10268c50dd
commit
7e4c01f078
32 changed files with 704 additions and 862 deletions
|
|
@ -22,6 +22,7 @@ import com.habitrpg.android.habitica.models.user.User
|
|||
import io.reactivex.Flowable
|
||||
import retrofit2.http.*
|
||||
|
||||
@JvmSuppressWildcards
|
||||
interface ApiService {
|
||||
@get:GET("status")
|
||||
val status: Flowable<HabitResponse<Status>>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import java.util.*
|
|||
interface TaskRepository : BaseRepository {
|
||||
fun getTasks(taskType: String, userID: String): Flowable<RealmResults<Task>>
|
||||
fun getTasks(userId: String): Flowable<RealmResults<Task>>
|
||||
fun getCurrentUserTasks(taskType: String): Flowable<RealmResults<Task>>
|
||||
fun getTasksOfType(taskType: String): Flowable<RealmResults<Task>>
|
||||
fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList)
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
|
|||
override fun getTasks(userId: String): Flowable<RealmResults<Task>> =
|
||||
this.localRepository.getTasks(userId)
|
||||
|
||||
override fun getCurrentUserTasks(taskType: String): Flowable<RealmResults<Task>> =
|
||||
this.localRepository.getTasks(taskType, userID)
|
||||
|
||||
override fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList) {
|
||||
localRepository.saveTasks(userId, order, tasks)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.habitrpg.android.habitica.interactors
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
|
@ -12,8 +11,8 @@ import com.habitrpg.android.habitica.helpers.SoundManager
|
|||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.functions.Consumer
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
|
@ -62,13 +61,9 @@ constructor(private val soundManager: SoundManager, threadExecutor: ThreadExecut
|
|||
|
||||
val event = ShareEvent()
|
||||
event.sharedMessage = requestValues.activity.getString(R.string.share_levelup, requestValues.newLevel) + " https://habitica.com/social/level-UP"
|
||||
val avatarView = AvatarView(requestValues.activity, true, true, true)
|
||||
val avatarView = AvatarView(requestValues.activity, showBackground = true, showMount = true, showPet = true)
|
||||
avatarView.setAvatar(requestValues.user)
|
||||
avatarView.onAvatarImageReady(object : AvatarView.Consumer<Bitmap?> {
|
||||
override fun accept(t: Bitmap?) {
|
||||
event.shareImage = t
|
||||
}
|
||||
})
|
||||
avatarView.onAvatarImageReady(Consumer { t -> event.shareImage = t })
|
||||
|
||||
val alert = HabiticaAlertDialog(requestValues.activity)
|
||||
alert.setTitle(requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel))
|
||||
|
|
|
|||
|
|
@ -188,10 +188,8 @@ open class User : RealmObject(), Avatar, VersionedObject {
|
|||
return (this.balance * 4).toInt()
|
||||
}
|
||||
|
||||
override fun getHourglassCount(): Int? {
|
||||
return if (purchased != null) {
|
||||
purchased?.plan?.consecutive?.trinkets
|
||||
} else 0
|
||||
override fun getHourglassCount(): Int {
|
||||
return purchased?.plan?.consecutive?.trinkets ?: 0
|
||||
}
|
||||
|
||||
override fun getCostume(): Outfit? {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.facebook.imagepipeline.image.ImageInfo
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.models.Avatar
|
||||
import io.reactivex.functions.Consumer
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
|
|
@ -518,10 +519,6 @@ class AvatarView : View {
|
|||
PET
|
||||
}
|
||||
|
||||
interface Consumer<in T> {
|
||||
fun accept(t: T)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val IMAGE_URI_ROOT = "https://habitica-assets.s3.amazonaws.com/mobileApp/images/"
|
||||
private const val TAG = "AvatarView"
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
|
||||
public class AddTaskWidgetProvider extends BaseWidgetProvider {
|
||||
|
||||
@Override
|
||||
public int layoutResourceId() {
|
||||
return R.layout.widget_add_task;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
// Get all ids
|
||||
ComponentName thisWidget = new ComponentName(context,
|
||||
AddTaskWidgetProvider.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteViews configureRemoteViews(RemoteViews remoteViews, int widgetId, int columns, int rows) {
|
||||
|
||||
String selectedTaskType = getSelectedTaskType(widgetId);
|
||||
String addText = "";
|
||||
int backgroundResource = R.drawable.widget_add_habit_background;
|
||||
switch (selectedTaskType) {
|
||||
case Task.TYPE_HABIT:
|
||||
addText = this.getContext().getResources().getString(R.string.add_habit);
|
||||
backgroundResource = R.drawable.widget_add_habit_background;
|
||||
break;
|
||||
case Task.TYPE_DAILY:
|
||||
addText = this.getContext().getResources().getString(R.string.add_daily);
|
||||
backgroundResource = R.drawable.widget_add_daily_background;
|
||||
break;
|
||||
case Task.TYPE_TODO:
|
||||
addText = this.getContext().getResources().getString(R.string.add_todo);
|
||||
backgroundResource = R.drawable.widget_add_todo_background;
|
||||
break;
|
||||
case Task.TYPE_REWARD:
|
||||
addText = this.getContext().getResources().getString(R.string.add_reward);
|
||||
backgroundResource = R.drawable.widget_add_reward_background;
|
||||
break;
|
||||
}
|
||||
remoteViews.setTextViewText(R.id.add_task_text, addText);
|
||||
remoteViews.setInt(R.id.add_task_icon, "setBackgroundResource", backgroundResource);
|
||||
return remoteViews;
|
||||
}
|
||||
|
||||
private String getSelectedTaskType(int widgetId) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getContext());
|
||||
return preferences.getString("add_task_widget_" + widgetId, Task.TYPE_HABIT);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.preference.PreferenceManager
|
||||
import android.widget.RemoteViews
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
||||
class AddTaskWidgetProvider : BaseWidgetProvider() {
|
||||
|
||||
override fun layoutResourceId(): Int {
|
||||
return R.layout.widget_add_task
|
||||
}
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
// Get all ids
|
||||
val thisWidget = ComponentName(context,
|
||||
AddTaskWidgetProvider::class.java)
|
||||
val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget)
|
||||
|
||||
for (widgetId in allWidgetIds) {
|
||||
val options = appWidgetManager.getAppWidgetOptions(widgetId)
|
||||
appWidgetManager.partiallyUpdateAppWidget(widgetId,
|
||||
sizeRemoteViews(context, options, widgetId))
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureRemoteViews(remoteViews: RemoteViews, widgetId: Int, columns: Int, rows: Int): RemoteViews {
|
||||
|
||||
val selectedTaskType = getSelectedTaskType(widgetId)
|
||||
var addText: String? = ""
|
||||
var backgroundResource = R.drawable.widget_add_habit_background
|
||||
when (selectedTaskType) {
|
||||
Task.TYPE_HABIT -> {
|
||||
addText = context?.resources?.getString(R.string.add_habit)
|
||||
backgroundResource = R.drawable.widget_add_habit_background
|
||||
}
|
||||
Task.TYPE_DAILY -> {
|
||||
addText = context?.resources?.getString(R.string.add_daily)
|
||||
backgroundResource = R.drawable.widget_add_daily_background
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
addText = context?.resources?.getString(R.string.add_todo)
|
||||
backgroundResource = R.drawable.widget_add_todo_background
|
||||
}
|
||||
Task.TYPE_REWARD -> {
|
||||
addText = context?.resources?.getString(R.string.add_reward)
|
||||
backgroundResource = R.drawable.widget_add_reward_background
|
||||
}
|
||||
}
|
||||
remoteViews.setTextViewText(R.id.add_task_text, addText)
|
||||
remoteViews.setInt(R.id.add_task_icon, "setBackgroundResource", backgroundResource)
|
||||
return remoteViews
|
||||
}
|
||||
|
||||
private fun getSelectedTaskType(widgetId: Int): String {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(this.context)
|
||||
return preferences.getString("add_task_widget_$widgetId", Task.TYPE_HABIT) ?: ""
|
||||
}
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
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.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.HealthFormatter;
|
||||
import com.habitrpg.android.habitica.helpers.NumberAbbreviator;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.user.Stats;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.AvatarView;
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
public class AvatarStatsWidgetProvider extends BaseWidgetProvider {
|
||||
|
||||
private AppWidgetManager appWidgetManager;
|
||||
|
||||
@Override
|
||||
public int layoutResourceId() {
|
||||
return R.layout.widget_avatar_stats;
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
private Boolean showManaBar = true;
|
||||
|
||||
private void setUp() {
|
||||
if (userRepository == null) {
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getUserComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
this.setUp();
|
||||
this.appWidgetManager = appWidgetManager;
|
||||
this.setContext(context);
|
||||
|
||||
userRepository.getUser(userId).firstElement().subscribe(this::updateData, RxErrorHandler.Companion.handleEmptyError());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RemoteViews configureRemoteViews(@NonNull RemoteViews remoteViews, int widgetId, int columns, int rows) {
|
||||
if (columns > 3) {
|
||||
remoteViews.setViewVisibility(R.id.avatar_view, View.VISIBLE);
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.avatar_view, View.GONE);
|
||||
}
|
||||
|
||||
showManaBar = rows > 1;
|
||||
if (rows > 1) {
|
||||
remoteViews.setViewVisibility(R.id.mp_wrapper, View.VISIBLE);
|
||||
remoteViews.setViewVisibility(R.id.detail_info_view, View.VISIBLE);
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.mp_wrapper, View.GONE);
|
||||
remoteViews.setViewVisibility(R.id.detail_info_view, View.GONE);
|
||||
}
|
||||
|
||||
return remoteViews;
|
||||
}
|
||||
|
||||
private void updateData(User user) {
|
||||
if (user == null || user.getStats() == null) {
|
||||
return;
|
||||
}
|
||||
Stats stats = user.getStats();
|
||||
ComponentName thisWidget = new ComponentName(getContext(), AvatarStatsWidgetProvider.class);
|
||||
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||
Double currentHealth = HealthFormatter.format(stats.getHp());
|
||||
String currentHealthString = HealthFormatter.formatToString(stats.getHp());
|
||||
String healthValueString = currentHealthString + "/" + stats.getMaxHealth();
|
||||
String expValueString = "" + stats.getExp().intValue() + "/" + stats.getToNextLevel();
|
||||
String mpValueString = "" + stats.getMp().intValue() + "/" + stats.getMaxMP();
|
||||
|
||||
for (int widgetId : allWidgetIds) {
|
||||
RemoteViews remoteViews = new RemoteViews(getContext().getPackageName(), R.layout.widget_avatar_stats);
|
||||
|
||||
remoteViews.setTextViewText(R.id.TV_hp_value, healthValueString);
|
||||
remoteViews.setTextViewText(R.id.exp_TV_value, expValueString);
|
||||
remoteViews.setTextViewText(R.id.mp_TV_value, mpValueString);
|
||||
|
||||
remoteViews.setImageViewBitmap(R.id.ic_hp_header, HabiticaIconsHelper.imageOfHeartDarkBg());
|
||||
remoteViews.setImageViewBitmap(R.id.ic_exp_header, HabiticaIconsHelper.imageOfExperience());
|
||||
remoteViews.setImageViewBitmap(R.id.ic_mp_header, HabiticaIconsHelper.imageOfMagic());
|
||||
|
||||
remoteViews.setProgressBar(R.id.hp_bar, stats.getMaxHealth(), currentHealth.intValue(), false);
|
||||
remoteViews.setProgressBar(R.id.exp_bar, stats.getToNextLevel(), stats.getExp().intValue(), false);
|
||||
remoteViews.setProgressBar(R.id.mp_bar, stats.getMaxMP(), stats.getMp().intValue(), false);
|
||||
remoteViews.setViewVisibility(R.id.mp_wrapper, showManaBar && ( stats.getHabitClass() == null || stats.getLvl() < 10 || user.getPreferences().getDisableClasses()) ? View.GONE : View.VISIBLE);
|
||||
|
||||
remoteViews.setTextViewText(R.id.gold_tv, NumberAbbreviator.INSTANCE.abbreviate(getContext(), stats.getGp()));
|
||||
remoteViews.setTextViewText(R.id.gems_tv, String.valueOf((int) (user.getBalance() * 4)));
|
||||
int hourGlassCount = user.getHourglassCount();
|
||||
if (hourGlassCount == 0) {
|
||||
remoteViews.setViewVisibility(R.id.hourglass_icon, View.GONE);
|
||||
remoteViews.setViewVisibility(R.id.hourglasses_tv, View.GONE);
|
||||
} else {
|
||||
remoteViews.setImageViewBitmap(R.id.hourglass_icon, HabiticaIconsHelper.imageOfHourglass());
|
||||
remoteViews.setViewVisibility(R.id.hourglass_icon, View.VISIBLE);
|
||||
remoteViews.setTextViewText(R.id.hourglasses_tv, String.valueOf(hourGlassCount));
|
||||
remoteViews.setViewVisibility(R.id.hourglasses_tv, View.VISIBLE);
|
||||
}
|
||||
remoteViews.setImageViewBitmap(R.id.gem_icon, HabiticaIconsHelper.imageOfGem());
|
||||
remoteViews.setImageViewBitmap(R.id.gold_icon, HabiticaIconsHelper.imageOfGold());
|
||||
remoteViews.setTextViewText(R.id.lvl_tv, getContext().getString(R.string.user_level, user.getStats().getLvl()));
|
||||
|
||||
AvatarView avatarView = new AvatarView(getContext(), true, true, true);
|
||||
|
||||
avatarView.setAvatar(user);
|
||||
RemoteViews finalRemoteViews = remoteViews;
|
||||
avatarView.onAvatarImageReady(bitmap -> {
|
||||
finalRemoteViews.setImageViewBitmap(R.id.avatar_view, bitmap);
|
||||
appWidgetManager.partiallyUpdateAppWidget(allWidgetIds, finalRemoteViews);
|
||||
});
|
||||
|
||||
//If user click on life and xp: open the app
|
||||
Intent openAppIntent = new Intent(getContext().getApplicationContext(), MainActivity.class);
|
||||
PendingIntent openApp = PendingIntent.getActivity(getContext(), 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
remoteViews.setOnClickPendingIntent(R.id.widget_main_view, openApp);
|
||||
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);
|
||||
remoteViews = sizeRemoteViews(getContext(), options, widgetId);
|
||||
}
|
||||
|
||||
appWidgetManager.updateAppWidget(widgetId, remoteViews);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
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.view.View
|
||||
import android.widget.RemoteViews
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.helpers.HealthFormatter
|
||||
import com.habitrpg.android.habitica.helpers.NumberAbbreviator
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
||||
|
||||
private var appWidgetManager: AppWidgetManager? = null
|
||||
|
||||
private var showManaBar: Boolean = true
|
||||
|
||||
override fun layoutResourceId(): Int {
|
||||
return R.layout.widget_avatar_stats
|
||||
}
|
||||
|
||||
private fun setUp() {
|
||||
if (!hasInjected) {
|
||||
hasInjected = true
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
this.setUp()
|
||||
this.appWidgetManager = appWidgetManager
|
||||
this.context = context
|
||||
|
||||
userRepository?.getUser()?.firstElement()?.subscribe(Consumer<User> { this.updateData(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
override fun configureRemoteViews(remoteViews: RemoteViews, widgetId: Int, columns: Int, rows: Int): RemoteViews {
|
||||
if (columns > 3) {
|
||||
remoteViews.setViewVisibility(R.id.avatar_view, View.VISIBLE)
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.avatar_view, View.GONE)
|
||||
}
|
||||
|
||||
showManaBar = rows > 1
|
||||
if (rows > 1) {
|
||||
remoteViews.setViewVisibility(R.id.mp_wrapper, View.VISIBLE)
|
||||
remoteViews.setViewVisibility(R.id.detail_info_view, View.VISIBLE)
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.mp_wrapper, View.GONE)
|
||||
remoteViews.setViewVisibility(R.id.detail_info_view, View.GONE)
|
||||
}
|
||||
|
||||
return remoteViews
|
||||
}
|
||||
|
||||
private fun updateData(user: User?) {
|
||||
val context = context
|
||||
val appWidgetManager = appWidgetManager
|
||||
val stats = user?.stats
|
||||
if (user == null || stats == null || context == null || appWidgetManager == null) {
|
||||
return
|
||||
}
|
||||
val thisWidget = ComponentName(context, AvatarStatsWidgetProvider::class.java)
|
||||
val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget)
|
||||
val currentHealth = HealthFormatter.format(stats.hp ?: 0.0)
|
||||
val currentHealthString = HealthFormatter.formatToString(stats.hp ?: 0.0)
|
||||
val healthValueString = currentHealthString + "/" + stats.maxHealth
|
||||
val expValueString = "" + stats.exp?.toInt() + "/" + stats.toNextLevel
|
||||
val mpValueString = "" + stats.mp?.toInt() + "/" + stats.maxMP
|
||||
|
||||
for (widgetId in allWidgetIds) {
|
||||
var remoteViews = RemoteViews(context.packageName, R.layout.widget_avatar_stats)
|
||||
|
||||
remoteViews.setTextViewText(R.id.TV_hp_value, healthValueString)
|
||||
remoteViews.setTextViewText(R.id.exp_TV_value, expValueString)
|
||||
remoteViews.setTextViewText(R.id.mp_TV_value, mpValueString)
|
||||
|
||||
remoteViews.setImageViewBitmap(R.id.ic_hp_header, HabiticaIconsHelper.imageOfHeartDarkBg())
|
||||
remoteViews.setImageViewBitmap(R.id.ic_exp_header, HabiticaIconsHelper.imageOfExperience())
|
||||
remoteViews.setImageViewBitmap(R.id.ic_mp_header, HabiticaIconsHelper.imageOfMagic())
|
||||
|
||||
remoteViews.setProgressBar(R.id.hp_bar, stats.maxHealth ?: 0, currentHealth.toInt(), false)
|
||||
remoteViews.setProgressBar(R.id.exp_bar, stats.toNextLevel ?: 0, stats.exp?.toInt() ?: 0, false)
|
||||
remoteViews.setProgressBar(R.id.mp_bar, stats.maxMP ?: 0, stats.mp?.toInt() ?: 0, false)
|
||||
remoteViews.setViewVisibility(R.id.mp_wrapper, if (showManaBar && (stats.habitClass == null || (stats.lvl ?: 0) < 10 || user.preferences?.disableClasses == true)) View.GONE else View.VISIBLE)
|
||||
|
||||
remoteViews.setTextViewText(R.id.gold_tv, NumberAbbreviator.abbreviate(context, stats.gp ?: 0.0))
|
||||
remoteViews.setTextViewText(R.id.gems_tv, (user.balance * 4).toInt().toString())
|
||||
val hourGlassCount = user.hourglassCount
|
||||
if (hourGlassCount == 0) {
|
||||
remoteViews.setViewVisibility(R.id.hourglass_icon, View.GONE)
|
||||
remoteViews.setViewVisibility(R.id.hourglasses_tv, View.GONE)
|
||||
} else {
|
||||
remoteViews.setImageViewBitmap(R.id.hourglass_icon, HabiticaIconsHelper.imageOfHourglass())
|
||||
remoteViews.setViewVisibility(R.id.hourglass_icon, View.VISIBLE)
|
||||
remoteViews.setTextViewText(R.id.hourglasses_tv, hourGlassCount.toString())
|
||||
remoteViews.setViewVisibility(R.id.hourglasses_tv, View.VISIBLE)
|
||||
}
|
||||
remoteViews.setImageViewBitmap(R.id.gem_icon, HabiticaIconsHelper.imageOfGem())
|
||||
remoteViews.setImageViewBitmap(R.id.gold_icon, HabiticaIconsHelper.imageOfGold())
|
||||
remoteViews.setTextViewText(R.id.lvl_tv, context.getString(R.string.user_level, user.stats?.lvl ?: 0))
|
||||
|
||||
val avatarView = AvatarView(context, showBackground = true, showMount = true, showPet = true)
|
||||
|
||||
avatarView.setAvatar(user)
|
||||
val finalRemoteViews = remoteViews
|
||||
avatarView.onAvatarImageReady(Consumer { bitmap ->
|
||||
finalRemoteViews.setImageViewBitmap(R.id.avatar_view, bitmap)
|
||||
appWidgetManager.partiallyUpdateAppWidget(allWidgetIds, finalRemoteViews)
|
||||
})
|
||||
|
||||
//If user click on life and xp: open the app
|
||||
val openAppIntent = Intent(context.applicationContext, MainActivity::class.java)
|
||||
val openApp = PendingIntent.getActivity(context, 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
remoteViews.setOnClickPendingIntent(R.id.widget_main_view, openApp)
|
||||
|
||||
|
||||
val options = appWidgetManager.getAppWidgetOptions(widgetId)
|
||||
remoteViews = sizeRemoteViews(context, options, widgetId)
|
||||
|
||||
appWidgetManager.updateAppWidget(widgetId, remoteViews)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,8 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
|
|||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
var hasInjected = false
|
||||
|
||||
protected var context: Context? = null
|
||||
|
||||
/**
|
||||
|
|
@ -62,7 +64,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
|
|||
return configureRemoteViews(remoteViews, widgetId, columns, rows)
|
||||
}
|
||||
|
||||
protected fun showToastForTaskDirection(context: Context, data: TaskScoringResult?, userID: String) {
|
||||
protected fun showToastForTaskDirection(context: Context, data: TaskScoringResult?) {
|
||||
if (data != null) {
|
||||
val pair = NotifyUserUseCase.getNotificationAndAddStatsToUserAsText(context, data.experienceDelta!!, data.healthDelta!!, data.goldDelta!!, data.manaDelta!!)
|
||||
val toast = Toast.makeText(context, pair.first, Toast.LENGTH_LONG)
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
|
||||
|
||||
public class DailiesListFactory extends TaskListFactory {
|
||||
public DailiesListFactory(Context context, Intent intent) {
|
||||
super(context, intent, Task.TYPE_DAILY, R.layout.widget_dailies_list_row, R.id.dailies_text);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
||||
|
||||
class DailiesListFactory(context: Context, intent: Intent) : TaskListFactory(context, intent, Task.TYPE_DAILY, R.layout.widget_dailies_list_row, R.id.dailies_text)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.api.HostConfig;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class DailiesWidgetProvider extends TaskListWidgetProvider {
|
||||
|
||||
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
|
||||
ApiClient apiClient;
|
||||
@Inject
|
||||
HostConfig hostConfig;
|
||||
|
||||
private void setUp(Context context) {
|
||||
if (apiClient == null) {
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getUserComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class getServiceClass() {
|
||||
return DailiesWidgetService.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class getProviderClass() {
|
||||
return DailiesWidgetProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleResId() {
|
||||
return R.string.dailies;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
||||
class DailiesWidgetProvider : TaskListWidgetProvider() {
|
||||
override val serviceClass: Class<*>
|
||||
get() = DailiesWidgetService::class.java
|
||||
override val providerClass: Class<*>
|
||||
get() = DailiesWidgetProvider::class.java
|
||||
override val titleResId: Int
|
||||
get() = R.string.dailies
|
||||
}
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.widget.RemoteViewsService;
|
||||
|
||||
|
||||
public class DailiesWidgetService extends RemoteViewsService {
|
||||
|
||||
@Override
|
||||
public RemoteViewsFactory onGetViewFactory(Intent intent) {
|
||||
return new DailiesListFactory(this.getApplicationContext(), intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.content.Intent
|
||||
import android.widget.RemoteViewsService
|
||||
|
||||
|
||||
class DailiesWidgetService : RemoteViewsService() {
|
||||
|
||||
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
|
||||
return DailiesListFactory(this.applicationContext, intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.responses.TaskDirection;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
public class HabitButtonWidgetProvider extends BaseWidgetProvider {
|
||||
|
||||
public static final String HABIT_ACTION = "com.habitrpg.android.habitica.HABIT_ACTION";
|
||||
public static final String TASK_ID = "com.habitrpg.android.habitica.TASK_ID_ITEM";
|
||||
public static final String TASK_DIRECTION = "com.habitrpg.android.habitica.TASK_DIRECTION";
|
||||
@Inject
|
||||
public TaskRepository taskRepository;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
public String userId;
|
||||
|
||||
private void setUp() {
|
||||
if (taskRepository == null) {
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getUserComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int layoutResourceId() {
|
||||
return R.layout.widget_habit_button;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
setUp();
|
||||
ComponentName thisWidget = new ComponentName(context,
|
||||
HabitButtonWidgetProvider.class);
|
||||
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||
|
||||
for (int widgetId : allWidgetIds) {
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);
|
||||
appWidgetManager.partiallyUpdateAppWidget(widgetId,
|
||||
sizeRemoteViews(context, options, widgetId));
|
||||
}
|
||||
|
||||
// Build the intent to call the service
|
||||
Intent intent = new Intent(context.getApplicationContext(), HabitButtonWidgetService.class);
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
|
||||
|
||||
try {
|
||||
context.startService(intent);
|
||||
} catch (IllegalStateException ignore) {
|
||||
//TODO: Make this play more nicely with Android 8
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
setUp();
|
||||
if (intent.getAction().equals(HABIT_ACTION)) {
|
||||
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
|
||||
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||
String taskId = intent.getStringExtra(TASK_ID);
|
||||
String direction = intent.getStringExtra(TASK_DIRECTION);
|
||||
|
||||
int[] ids = {appWidgetId};
|
||||
|
||||
if (taskId != null) {
|
||||
getUserRepository().getUser(userId).firstElement().flatMap(user -> taskRepository.taskChecked(user, taskId, TaskDirection.UP.getText().equals(direction), false, null))
|
||||
.subscribe(taskDirectionData -> showToastForTaskDirection(context, taskDirectionData, userId), RxErrorHandler.Companion.handleEmptyError(), () -> this.onUpdate(context, mgr, ids));
|
||||
}
|
||||
}
|
||||
super.onReceive(context, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteViews configureRemoteViews(RemoteViews remoteViews, int widgetId, int columns, int rows) {
|
||||
return remoteViews;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.RemoteViews
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.responses.TaskDirection
|
||||
import io.reactivex.functions.Action
|
||||
import io.reactivex.functions.Consumer
|
||||
import javax.inject.Inject
|
||||
|
||||
class HabitButtonWidgetProvider : BaseWidgetProvider() {
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
|
||||
private fun setUp() {
|
||||
if (!hasInjected) {
|
||||
hasInjected = true
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun layoutResourceId(): Int {
|
||||
return R.layout.widget_habit_button
|
||||
}
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
setUp()
|
||||
val thisWidget = ComponentName(context,
|
||||
HabitButtonWidgetProvider::class.java)
|
||||
val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget)
|
||||
|
||||
for (widgetId in allWidgetIds) {
|
||||
val options = appWidgetManager.getAppWidgetOptions(widgetId)
|
||||
appWidgetManager.partiallyUpdateAppWidget(widgetId,
|
||||
sizeRemoteViews(context, options, widgetId))
|
||||
}
|
||||
|
||||
// Build the intent to call the service
|
||||
val intent = Intent(context.applicationContext, HabitButtonWidgetService::class.java)
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds)
|
||||
|
||||
try {
|
||||
context.startService(intent)
|
||||
} catch (ignore: IllegalStateException) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
setUp()
|
||||
if (intent.action == HABIT_ACTION) {
|
||||
val mgr = AppWidgetManager.getInstance(context)
|
||||
val appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID)
|
||||
val taskId = intent.getStringExtra(TASK_ID)
|
||||
val direction = intent.getStringExtra(TASK_DIRECTION)
|
||||
|
||||
val ids = intArrayOf(appWidgetId)
|
||||
|
||||
if (taskId != null) {
|
||||
userRepository.getUser().firstElement().flatMap { user -> taskRepository.taskChecked(user, taskId, TaskDirection.UP.text == direction, false, null) }
|
||||
.subscribe(Consumer { taskDirectionData -> showToastForTaskDirection(context, taskDirectionData) }, RxErrorHandler.handleEmptyError(), Action { this.onUpdate(context, mgr, ids) })
|
||||
}
|
||||
}
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
|
||||
override fun configureRemoteViews(remoteViews: RemoteViews, widgetId: Int, columns: Int, rows: Int): RemoteViews {
|
||||
return remoteViews
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val HABIT_ACTION = "com.habitrpg.android.habitica.HABIT_ACTION"
|
||||
const val TASK_ID = "com.habitrpg.android.habitica.TASK_ID_ITEM"
|
||||
const val TASK_DIRECTION = "com.habitrpg.android.habitica.TASK_DIRECTION"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.os.IBinder;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.DynamicDrawableSpan;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.responses.TaskDirection;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
|
||||
|
||||
import net.pherth.android.emoji_library.EmojiHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
public class HabitButtonWidgetService extends Service {
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
public String userId;
|
||||
@Inject
|
||||
public SharedPreferences sharedPreferences;
|
||||
@Inject
|
||||
public Resources resources;
|
||||
@Inject
|
||||
public Context context;
|
||||
@Inject
|
||||
TaskRepository taskRepository;
|
||||
private AppWidgetManager appWidgetManager;
|
||||
|
||||
private Map<String, Integer> taskMapping;
|
||||
private int[] allWidgetIds;
|
||||
|
||||
@Override
|
||||
public int onStartCommand(final Intent intent, int flags, int startId) {
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getUserComponent()).inject(this);
|
||||
this.appWidgetManager = AppWidgetManager.getInstance(this);
|
||||
ComponentName thisWidget = new ComponentName(this, HabitButtonWidgetProvider.class);
|
||||
allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||
makeTaskMapping();
|
||||
|
||||
for (String taskid : this.taskMapping.keySet()) {
|
||||
taskRepository.getUnmanagedTask(taskid).firstElement().subscribe(this::updateData, RxErrorHandler.Companion.handleEmptyError());
|
||||
}
|
||||
|
||||
stopSelf();
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private void updateData(Task task) {
|
||||
RemoteViews remoteViews = new RemoteViews(this.getPackageName(), R.layout.widget_habit_button);
|
||||
if (task != null && task.isValid()) {
|
||||
CharSequence parsedText = MarkdownParser.INSTANCE.parseMarkdown(task.getText());
|
||||
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(parsedText);
|
||||
EmojiHandler.addEmojis(this.context, builder, 16, DynamicDrawableSpan.ALIGN_BASELINE, 16, 0, -1, false);
|
||||
|
||||
remoteViews.setTextViewText(R.id.habit_title, builder);
|
||||
|
||||
if (!task.getUp()) {
|
||||
remoteViews.setViewVisibility(R.id.btnPlusWrapper, View.GONE);
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnPlusWrapper, null);
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.btnPlusWrapper, View.VISIBLE);
|
||||
remoteViews.setInt(R.id.btnPlus, "setBackgroundColor", ContextCompat.getColor(context, task.getLightTaskColor()));
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnPlusWrapper, getPendingIntent(task.getId(), TaskDirection.UP.getText(), taskMapping.get(task.getId())));
|
||||
}
|
||||
if (!task.getDown()) {
|
||||
remoteViews.setViewVisibility(R.id.btnMinusWrapper, View.GONE);
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnMinusWrapper, null);
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.btnMinusWrapper, View.VISIBLE);
|
||||
remoteViews.setInt(R.id.btnMinus, "setBackgroundColor", ContextCompat.getColor(context, task.getMediumTaskColor()));
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnMinusWrapper, getPendingIntent(task.getId(), TaskDirection.DOWN.getText(), taskMapping.get(task.getId())));
|
||||
}
|
||||
if (taskMapping.get(task.getId()) != null && remoteViews != null) {
|
||||
appWidgetManager.updateAppWidget(taskMapping.get(task.getId()), remoteViews);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void makeTaskMapping() {
|
||||
this.taskMapping = new HashMap<>();
|
||||
for (int widgetId : allWidgetIds) {
|
||||
String taskId = getTaskId(widgetId);
|
||||
if (!taskId.equals("")) {
|
||||
this.taskMapping.put(taskId, widgetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getTaskId(int widgetId) {
|
||||
return sharedPreferences.getString("habit_button_widget_" + widgetId, "");
|
||||
}
|
||||
|
||||
private PendingIntent getPendingIntent(String taskId, String direction, int widgetId) {
|
||||
Intent taskIntent = new Intent(context, HabitButtonWidgetProvider.class);
|
||||
taskIntent.setAction(HabitButtonWidgetProvider.HABIT_ACTION);
|
||||
taskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
|
||||
taskIntent.putExtra(HabitButtonWidgetProvider.TASK_ID, taskId);
|
||||
taskIntent.putExtra(HabitButtonWidgetProvider.TASK_DIRECTION, direction);
|
||||
return PendingIntent.getBroadcast(context, widgetId + direction.hashCode(), taskIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.IBinder
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.DynamicDrawableSpan
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.responses.TaskDirection
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiHandler
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class HabitButtonWidgetService : Service() {
|
||||
@Inject
|
||||
lateinit var sharedPreferences: SharedPreferences
|
||||
@Inject
|
||||
lateinit var context: Context
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
private var appWidgetManager: AppWidgetManager? = null
|
||||
|
||||
private var taskMapping = mutableMapOf<String, Int>()
|
||||
private var allWidgetIds: IntArray? = null
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
this.appWidgetManager = AppWidgetManager.getInstance(this)
|
||||
val thisWidget = ComponentName(this, HabitButtonWidgetProvider::class.java)
|
||||
allWidgetIds = appWidgetManager?.getAppWidgetIds(thisWidget)
|
||||
makeTaskMapping()
|
||||
|
||||
for (taskid in this.taskMapping.keys) {
|
||||
taskRepository.getUnmanagedTask(taskid).firstElement().subscribe(Consumer<Task> { this.updateData(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
stopSelf()
|
||||
|
||||
return Service.START_STICKY
|
||||
}
|
||||
|
||||
private fun updateData(task: Task?) {
|
||||
val remoteViews = RemoteViews(this.packageName, R.layout.widget_habit_button)
|
||||
if (task != null && task.isValid) {
|
||||
val parsedText = MarkdownParser.parseMarkdown(task.text)
|
||||
|
||||
val builder = SpannableStringBuilder(parsedText)
|
||||
EmojiHandler.addEmojis(this.context, builder, 16, DynamicDrawableSpan.ALIGN_BASELINE, 16, 0, -1, false)
|
||||
|
||||
remoteViews.setTextViewText(R.id.habit_title, builder)
|
||||
|
||||
if (task.up != true) {
|
||||
remoteViews.setViewVisibility(R.id.btnPlusWrapper, View.GONE)
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnPlusWrapper, null)
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.btnPlusWrapper, View.VISIBLE)
|
||||
remoteViews.setInt(R.id.btnPlus, "setBackgroundColor", ContextCompat.getColor(context, task.lightTaskColor))
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnPlusWrapper, getPendingIntent(task.id, TaskDirection.UP.text, taskMapping[task.id]!!))
|
||||
}
|
||||
if (task.down != true) {
|
||||
remoteViews.setViewVisibility(R.id.btnMinusWrapper, View.GONE)
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnMinusWrapper, null)
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.btnMinusWrapper, View.VISIBLE)
|
||||
remoteViews.setInt(R.id.btnMinus, "setBackgroundColor", ContextCompat.getColor(context, task.mediumTaskColor))
|
||||
remoteViews.setOnClickPendingIntent(R.id.btnMinusWrapper, getPendingIntent(task.id, TaskDirection.DOWN.text, taskMapping[task.id]!!))
|
||||
}
|
||||
if (taskMapping[task.id] != null) {
|
||||
appWidgetManager?.updateAppWidget(taskMapping[task.id]!!, remoteViews)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun makeTaskMapping() {
|
||||
this.taskMapping = HashMap()
|
||||
for (widgetId in allWidgetIds!!) {
|
||||
val taskId = getTaskId(widgetId)
|
||||
if (taskId != "") {
|
||||
this.taskMapping[taskId] = widgetId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTaskId(widgetId: Int): String {
|
||||
return sharedPreferences.getString("habit_button_widget_$widgetId", "") ?: ""
|
||||
}
|
||||
|
||||
private fun getPendingIntent(taskId: String?, direction: String, widgetId: Int): PendingIntent {
|
||||
val taskIntent = Intent(context, HabitButtonWidgetProvider::class.java)
|
||||
taskIntent.action = HabitButtonWidgetProvider.HABIT_ACTION
|
||||
taskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
|
||||
taskIntent.putExtra(HabitButtonWidgetProvider.TASK_ID, taskId)
|
||||
taskIntent.putExtra(HabitButtonWidgetProvider.TASK_DIRECTION, direction)
|
||||
return PendingIntent.getBroadcast(context, widgetId + direction.hashCode(), taskIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.DynamicDrawableSpan;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.RemoteViewsService;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
|
||||
|
||||
import net.pherth.android.emoji_library.EmojiHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
||||
public abstract class TaskListFactory implements RemoteViewsService.RemoteViewsFactory {
|
||||
private final int widgetId;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
public String userID;
|
||||
@Inject
|
||||
TaskRepository taskRepository;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
private int listItemResId;
|
||||
private int listItemTextResId;
|
||||
private String taskType;
|
||||
private List<Task> taskList = new ArrayList<>();
|
||||
private Context context = null;
|
||||
private boolean reloadData;
|
||||
|
||||
TaskListFactory(Context context, Intent intent, String taskType, int listItemResId, int listItemTextResId) {
|
||||
this.context = context;
|
||||
this.widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
|
||||
this.listItemResId = listItemResId;
|
||||
this.listItemTextResId = listItemTextResId;
|
||||
this.reloadData = false;
|
||||
this.taskType = taskType;
|
||||
|
||||
if (userID == null) {
|
||||
Objects.requireNonNull(HabiticaApplication.Companion.getUserComponent()).inject(this);
|
||||
}
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
Handler mainHandler = new Handler(context.getMainLooper());
|
||||
mainHandler.post(() -> taskRepository.getTasks(taskType, userID)
|
||||
.firstElement()
|
||||
.toObservable()
|
||||
.flatMap(Observable::fromIterable)
|
||||
.filter(task -> (task.getType().equals(Task.TYPE_TODO) && !task.getCompleted()) || task.isDisplayedActive())
|
||||
.toList()
|
||||
.flatMapMaybe(tasks -> taskRepository.getTaskCopies(tasks).firstElement())
|
||||
.subscribeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(tasks -> {
|
||||
reloadData = false;
|
||||
taskList = tasks;
|
||||
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(widgetId, R.id.list_view);
|
||||
}, RxErrorHandler.Companion.handleEmptyError()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@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(), listItemResId);
|
||||
if (taskList.size() > position) {
|
||||
Task task = taskList.get(position);
|
||||
|
||||
CharSequence parsedText = MarkdownParser.INSTANCE.parseMarkdown(task.getText());
|
||||
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(parsedText);
|
||||
EmojiHandler.addEmojis(this.context, builder, 16, DynamicDrawableSpan.ALIGN_BASELINE, 16, 0, -1, false);
|
||||
|
||||
remoteView.setTextViewText(listItemTextResId, 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.widget_list_row, fillInIntent);
|
||||
}
|
||||
return remoteView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteViews getLoadingView() {
|
||||
return new RemoteViews(context.getPackageName(), listItemResId);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.DynamicDrawableSpan
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.RemoteViewsService
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiHandler
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class TaskListFactory internal constructor(val context: Context, intent: Intent, private val taskType: String, private val listItemResId: Int, private val listItemTextResId: Int) : RemoteViewsService.RemoteViewsFactory {
|
||||
private val widgetId: Int = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0)
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
private var taskList: List<Task> = ArrayList()
|
||||
private var reloadData: Boolean = false
|
||||
|
||||
init {
|
||||
this.reloadData = false
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
val mainHandler = Handler(context.mainLooper)
|
||||
mainHandler.post {
|
||||
taskRepository.getCurrentUserTasks(taskType)
|
||||
.firstElement()
|
||||
.toObservable()
|
||||
.flatMap { Observable.fromIterable(it) }
|
||||
.filter { task -> task.type == Task.TYPE_TODO && !task.completed || task.isDisplayedActive }
|
||||
.toList()
|
||||
.flatMapMaybe { tasks -> taskRepository.getTaskCopies(tasks).firstElement() }
|
||||
.subscribeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(Consumer { tasks ->
|
||||
reloadData = false
|
||||
taskList = tasks
|
||||
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(widgetId, R.id.list_view)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
this.loadData()
|
||||
}
|
||||
override fun onDestroy() {}
|
||||
|
||||
override fun onDataSetChanged() {
|
||||
if (this.reloadData) {
|
||||
this.loadData()
|
||||
}
|
||||
this.reloadData = true
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return taskList.size
|
||||
}
|
||||
|
||||
override fun getViewAt(position: Int): RemoteViews {
|
||||
val remoteView = RemoteViews(context.packageName, listItemResId)
|
||||
if (taskList.size > position) {
|
||||
val task = taskList[position]
|
||||
|
||||
val parsedText = MarkdownParser.parseMarkdown(task.text)
|
||||
|
||||
val builder = SpannableStringBuilder(parsedText)
|
||||
EmojiHandler.addEmojis(this.context, builder, 16, DynamicDrawableSpan.ALIGN_BASELINE, 16, 0, -1, false)
|
||||
|
||||
remoteView.setTextViewText(listItemTextResId, builder)
|
||||
remoteView.setInt(R.id.checkbox_background, "setBackgroundResource", task.lightTaskColor)
|
||||
val fillInIntent = Intent()
|
||||
fillInIntent.putExtra(TaskListWidgetProvider.TASK_ID_ITEM, task.id)
|
||||
remoteView.setOnClickFillInIntent(R.id.widget_list_row, fillInIntent)
|
||||
}
|
||||
return remoteView
|
||||
}
|
||||
|
||||
override fun getLoadingView(): RemoteViews {
|
||||
return RemoteViews(context.packageName, listItemResId)
|
||||
}
|
||||
|
||||
override fun getViewTypeCount(): Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
if (taskList.size > position) {
|
||||
val task = taskList[position]
|
||||
return task.id.hashCode().toLong()
|
||||
}
|
||||
return position.toLong()
|
||||
}
|
||||
|
||||
override fun hasStableIds(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
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.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
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
|
||||
ApiClient apiClient;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
@Inject
|
||||
TaskRepository taskRepository;
|
||||
|
||||
private void setUp(Context context) {
|
||||
if (apiClient == null) {
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getUserComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Class getServiceClass();
|
||||
|
||||
protected abstract Class getProviderClass();
|
||||
|
||||
protected abstract int getTitleResId();
|
||||
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
setUp(context);
|
||||
if (intent.getAction().equals(DAILY_ACTION)) {
|
||||
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||
String taskId = intent.getStringExtra(TASK_ID_ITEM);
|
||||
|
||||
if (taskId != null) {
|
||||
getUserRepository().getUser(userId).firstElement().flatMap(user -> taskRepository.taskChecked(user, taskId, true, false, null))
|
||||
.subscribe(taskDirectionData -> {
|
||||
taskRepository.markTaskCompleted(taskId, true);
|
||||
showToastForTaskDirection(context, taskDirectionData, userId);
|
||||
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
|
||||
}, RxErrorHandler.Companion.handleEmptyError());
|
||||
}
|
||||
}
|
||||
super.onReceive(context, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
setUp(context);
|
||||
ComponentName thisWidget = new ComponentName(context, getProviderClass());
|
||||
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 appWidgetId : appWidgetIds) {
|
||||
Intent intent = new Intent(context, getServiceClass());
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
|
||||
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_task_list);
|
||||
rv.setRemoteAdapter(appWidgetId, R.id.list_view, intent);
|
||||
rv.setEmptyView(R.id.list_view, R.id.emptyView);
|
||||
rv.setTextViewText(R.id.widget_title, context.getString(getTitleResId()));
|
||||
|
||||
// if the user click on the title: open App
|
||||
Intent openAppIntent = new Intent(context.getApplicationContext(), MainActivity.class);
|
||||
PendingIntent openApp = PendingIntent.getActivity(context, 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
rv.setOnClickPendingIntent(R.id.widget_title, openApp);
|
||||
|
||||
Intent taskIntent = new Intent(context, getProviderClass());
|
||||
taskIntent.setAction(DAILY_ACTION);
|
||||
taskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||
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(appWidgetId, rv);
|
||||
|
||||
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view);
|
||||
}
|
||||
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int layoutResourceId() {
|
||||
return R.layout.widget_task_list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteViews configureRemoteViews(RemoteViews remoteViews, int widgetId, int columns, int rows) {
|
||||
return remoteViews;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
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.widget.RemoteViews
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import io.reactivex.functions.Consumer
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class TaskListWidgetProvider : BaseWidgetProvider() {
|
||||
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
|
||||
protected abstract val serviceClass: Class<*>
|
||||
|
||||
protected abstract val providerClass: Class<*>
|
||||
|
||||
protected abstract val titleResId: Int
|
||||
|
||||
private fun setUp() {
|
||||
if (!hasInjected) {
|
||||
hasInjected = true
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
setUp()
|
||||
if (intent.action == DAILY_ACTION) {
|
||||
val appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID)
|
||||
val taskId = intent.getStringExtra(TASK_ID_ITEM)
|
||||
|
||||
if (taskId != null) {
|
||||
userRepository.getUser().firstElement().flatMap { user -> taskRepository.taskChecked(user, taskId, up = true, force = false, notifyFunc = null) }
|
||||
.subscribe(Consumer { taskDirectionData ->
|
||||
showToastForTaskDirection(context, taskDirectionData)
|
||||
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
setUp()
|
||||
val thisWidget = ComponentName(context, providerClass)
|
||||
val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget)
|
||||
|
||||
for (widgetId in allWidgetIds) {
|
||||
val options = appWidgetManager.getAppWidgetOptions(widgetId)
|
||||
appWidgetManager.partiallyUpdateAppWidget(widgetId,
|
||||
sizeRemoteViews(context, options, widgetId))
|
||||
}
|
||||
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
val intent = Intent(context, serviceClass)
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
intent.data = Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))
|
||||
val rv = RemoteViews(context.packageName, R.layout.widget_task_list)
|
||||
rv.setRemoteAdapter(R.id.list_view, intent)
|
||||
rv.setEmptyView(R.id.list_view, R.id.emptyView)
|
||||
rv.setTextViewText(R.id.widget_title, context.getString(titleResId))
|
||||
|
||||
// if the user click on the title: open App
|
||||
val openAppIntent = Intent(context.applicationContext, MainActivity::class.java)
|
||||
val openApp = PendingIntent.getActivity(context, 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
rv.setOnClickPendingIntent(R.id.widget_title, openApp)
|
||||
|
||||
val taskIntent = Intent(context, providerClass)
|
||||
taskIntent.action = DAILY_ACTION
|
||||
taskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
intent.data = Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))
|
||||
val toastPendingIntent = PendingIntent.getBroadcast(context, 0, taskIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
rv.setPendingIntentTemplate(R.id.list_view, toastPendingIntent)
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, rv)
|
||||
|
||||
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view)
|
||||
}
|
||||
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
}
|
||||
|
||||
override fun layoutResourceId(): Int {
|
||||
return R.layout.widget_task_list
|
||||
}
|
||||
|
||||
override fun configureRemoteViews(remoteViews: RemoteViews, widgetId: Int, columns: Int, rows: Int): RemoteViews {
|
||||
return remoteViews
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DAILY_ACTION = "com.habitrpg.android.habitica.DAILY_ACTION"
|
||||
const val TASK_ID_ITEM = "com.habitrpg.android.habitica.TASK_ID_ITEM"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
|
||||
public class TodoListFactory extends TaskListFactory {
|
||||
public TodoListFactory(Context context, Intent intent) {
|
||||
super(context, intent, Task.TYPE_TODO, R.layout.widget_todo_list_row, R.id.todo_text);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
||||
class TodoListFactory(context: Context, intent: Intent) : TaskListFactory(context, intent, Task.TYPE_TODO, R.layout.widget_todo_list_row, R.id.todo_text)
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package com.habitrpg.android.habitica.widget;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
|
||||
public class TodoListWidgetProvider extends TaskListWidgetProvider {
|
||||
|
||||
@Override
|
||||
protected Class getServiceClass() {
|
||||
return TodosWidgetService.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class getProviderClass() {
|
||||
return TodoListWidgetProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleResId() {
|
||||
return R.string.todos;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
||||
class TodoListWidgetProvider : TaskListWidgetProvider() {
|
||||
override val serviceClass: Class<*>
|
||||
get() = TodosWidgetService::class.java
|
||||
|
||||
override val providerClass: Class<*>
|
||||
get() = TodoListWidgetProvider::class.java
|
||||
|
||||
override val titleResId: Int
|
||||
get() = R.string.todos
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
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 TodoListFactory(this.getApplicationContext(), intent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.habitrpg.android.habitica.widget
|
||||
|
||||
import android.content.Intent
|
||||
import android.widget.RemoteViewsService
|
||||
|
||||
class TodosWidgetService : RemoteViewsService() {
|
||||
|
||||
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
|
||||
return TodoListFactory(this.applicationContext, intent)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,12 +3,12 @@ apply plugin: 'kotlin-multiplatform'
|
|||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue