mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-15 12:16:31 +00:00
Refactor activities and remove Butterknife
This commit is contained in:
parent
b52b4563e9
commit
b366686764
102 changed files with 7291 additions and 8266 deletions
|
|
@ -55,9 +55,6 @@ dependencies {
|
|||
releaseImplementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') {
|
||||
transitive = true
|
||||
}
|
||||
// View Elements Binding :)
|
||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||
kapt 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||
//Dependency Injection
|
||||
implementation 'com.google.dagger:dagger:2.16'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.16'
|
||||
|
|
|
|||
|
|
@ -1,265 +0,0 @@
|
|||
package com.habitrpg.android.habitica;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.DatabaseErrorHandler;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
import android.util.Log;
|
||||
|
||||
import com.amplitude.api.Amplitude;
|
||||
import com.amplitude.api.Identify;
|
||||
import com.facebook.FacebookSdk;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.core.ImagePipelineConfig;
|
||||
import com.habitrpg.android.habitica.api.HostConfig;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy;
|
||||
import com.habitrpg.android.habitica.ui.activities.IntroActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.LoginActivity;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
import com.squareup.leakcanary.RefWatcher;
|
||||
|
||||
import org.solovyev.android.checkout.Billing;
|
||||
import org.solovyev.android.checkout.Cache;
|
||||
import org.solovyev.android.checkout.Checkout;
|
||||
import org.solovyev.android.checkout.PurchaseVerifier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.realm.Realm;
|
||||
import io.realm.RealmConfiguration;
|
||||
|
||||
//contains all HabiticaApplicationLogic except dagger componentInitialisation
|
||||
public abstract class HabiticaBaseApplication extends Application {
|
||||
|
||||
private static AppComponent component;
|
||||
public RefWatcher refWatcher;
|
||||
@Inject
|
||||
ApiClient lazyApiHelper;
|
||||
@Inject
|
||||
InventoryRepository inventoryRepository;
|
||||
@Inject
|
||||
SharedPreferences sharedPrefs;
|
||||
@Inject
|
||||
CrashlyticsProxy crashlyticsProxy;
|
||||
/**
|
||||
* For better performance billing class should be used as singleton
|
||||
*/
|
||||
private Billing billing;
|
||||
/**
|
||||
* Application wide {@link Checkout} instance (can be used
|
||||
* anywhere in the app).
|
||||
* This instance contains all available products in the app.
|
||||
*/
|
||||
private Checkout checkout;
|
||||
|
||||
public static HabiticaBaseApplication getInstance(Context context) {
|
||||
return (HabiticaBaseApplication) context.getApplicationContext();
|
||||
}
|
||||
|
||||
public static void logout(Context context) {
|
||||
Realm realm = Realm.getDefaultInstance();
|
||||
getInstance(context).deleteDatabase(realm.getPath());
|
||||
realm.close();
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean use_reminder = preferences.getBoolean("use_reminder", false);
|
||||
String reminder_time = preferences.getString("reminder_time", "19:00");
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.clear();
|
||||
editor.putBoolean("use_reminder", use_reminder);
|
||||
editor.putString("reminder_time", reminder_time);
|
||||
editor.apply();
|
||||
getInstance(context).lazyApiHelper.updateAuthenticationCredentials(null, null);
|
||||
startActivity(LoginActivity.class, context);
|
||||
}
|
||||
|
||||
public static boolean checkUserAuthentication(Context context, HostConfig hostConfig) {
|
||||
if (hostConfig == null || hostConfig.getApi() == null || hostConfig.getApi().equals("") || hostConfig.getUser() == null || hostConfig.getUser().equals("")) {
|
||||
startActivity(IntroActivity.class, context);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void startActivity(Class activityClass, Context context) {
|
||||
Intent intent = new Intent(context, activityClass);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static AppComponent getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return;
|
||||
}
|
||||
setupRealm();
|
||||
setupDagger();
|
||||
setupLeakCanary();
|
||||
setupFacebookSdk();
|
||||
createBillingAndCheckout();
|
||||
HabiticaIconsHelper.init(this);
|
||||
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||
|
||||
if (!BuildConfig.DEBUG) {
|
||||
try {
|
||||
Amplitude.getInstance().initialize(this, getString(R.string.amplitude_app_id)).enableForegroundTracking(this);
|
||||
Identify identify = new Identify().setOnce("androidStore", BuildConfig.STORE);
|
||||
Amplitude.getInstance().identify(identify);
|
||||
} catch (Resources.NotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
|
||||
.setDownsampleEnabled(true)
|
||||
.build();
|
||||
Fresco.initialize(this, config);
|
||||
|
||||
RxErrorHandler.init(crashlyticsProxy);
|
||||
|
||||
checkIfNewVersion();
|
||||
}
|
||||
|
||||
protected void setupRealm() {
|
||||
Realm.init(this);
|
||||
RealmConfiguration.Builder builder = new RealmConfiguration.Builder()
|
||||
.schemaVersion(1)
|
||||
.deleteRealmIfMigrationNeeded();
|
||||
try {
|
||||
Realm.setDefaultConfiguration(builder.build());
|
||||
} catch (UnsatisfiedLinkError ignored) {
|
||||
//Catch crash in tests
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfNewVersion() {
|
||||
PackageInfo info = null;
|
||||
try {
|
||||
info = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e("MyApplication", "couldn't get package info!");
|
||||
}
|
||||
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int lastInstalledVersion = sharedPrefs.getInt("last_installed_version", 0);
|
||||
if (lastInstalledVersion < info.versionCode) {
|
||||
sharedPrefs.edit().putInt("last_installed_version", info.versionCode).apply();
|
||||
inventoryRepository.retrieveContent().subscribe(contentResult -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
private void setupDagger() {
|
||||
component = initDagger();
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
protected abstract AppComponent initDagger();
|
||||
|
||||
private void setupLeakCanary() {
|
||||
refWatcher = LeakCanary.install(this);
|
||||
}
|
||||
|
||||
private void setupFacebookSdk() {
|
||||
String fbApiKey = null;
|
||||
try {
|
||||
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
|
||||
Bundle bundle = ai.metaData;
|
||||
fbApiKey = bundle.getString(FacebookSdk.APPLICATION_ID_PROPERTY);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e("FB Error", "Failed to load meta-data, NameNotFound: " + e.getMessage());
|
||||
} catch (NullPointerException e) {
|
||||
Log.e("FB Error", "Failed to load meta-data, NullPointer: " + e.getMessage());
|
||||
}
|
||||
if (fbApiKey != null) {
|
||||
FacebookSdk.sdkInitialize(getApplicationContext());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLiteDatabase openOrCreateDatabase(String name,
|
||||
int mode, SQLiteDatabase.CursorFactory factory) {
|
||||
return super.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(), mode, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLiteDatabase openOrCreateDatabase(String name,
|
||||
int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
|
||||
return super.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(), mode, factory, errorHandler);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region IAP - Specific
|
||||
|
||||
@Override
|
||||
public boolean deleteDatabase(String name) {
|
||||
Realm realm = Realm.getDefaultInstance();
|
||||
realm.executeTransaction(realm1 -> {
|
||||
realm1.deleteAll();
|
||||
realm1.close();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createBillingAndCheckout() {
|
||||
billing = new Billing(this, new Billing.DefaultConfiguration() {
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicKey() {
|
||||
return "DONT-NEED-IT";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Cache getCache() {
|
||||
return Billing.newCache();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PurchaseVerifier getPurchaseVerifier() {
|
||||
return new HabiticaPurchaseVerifier(HabiticaBaseApplication.this, lazyApiHelper);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
checkout = Checkout.forApplication(billing);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Checkout getCheckout() {
|
||||
return checkout;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
public Billing getBilling() {
|
||||
return billing;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
package com.habitrpg.android.habitica
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import android.database.DatabaseErrorHandler
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
import android.util.Log
|
||||
|
||||
import com.amplitude.api.Amplitude
|
||||
import com.amplitude.api.Identify
|
||||
import com.facebook.FacebookSdk
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.imagepipeline.core.ImagePipelineConfig
|
||||
import com.habitrpg.android.habitica.api.HostConfig
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
|
||||
import com.habitrpg.android.habitica.ui.activities.IntroActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.LoginActivity
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.squareup.leakcanary.LeakCanary
|
||||
import com.squareup.leakcanary.RefWatcher
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
import org.solovyev.android.checkout.Billing
|
||||
import org.solovyev.android.checkout.Cache
|
||||
import org.solovyev.android.checkout.Checkout
|
||||
import org.solovyev.android.checkout.PurchaseVerifier
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
|
||||
//contains all HabiticaApplicationLogic except dagger componentInitialisation
|
||||
abstract class HabiticaBaseApplication : Application() {
|
||||
var refWatcher: RefWatcher? = null
|
||||
@Inject
|
||||
internal lateinit var lazyApiHelper: ApiClient
|
||||
@Inject
|
||||
internal lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
internal lateinit var sharedPrefs: SharedPreferences
|
||||
@Inject
|
||||
internal lateinit var crashlyticsProxy: CrashlyticsProxy
|
||||
/**
|
||||
* For better performance billing class should be used as singleton
|
||||
*/
|
||||
// endregion
|
||||
|
||||
var billing: Billing? = null
|
||||
private set
|
||||
/**
|
||||
* Application wide [Checkout] instance (can be used
|
||||
* anywhere in the app).
|
||||
* This instance contains all available products in the app.
|
||||
*/
|
||||
var checkout: Checkout? = null
|
||||
private set
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return
|
||||
}
|
||||
setupRealm()
|
||||
setupDagger()
|
||||
refWatcher = LeakCanary.install(this)
|
||||
setupFacebookSdk()
|
||||
createBillingAndCheckout()
|
||||
HabiticaIconsHelper.init(this)
|
||||
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||
|
||||
if (!BuildConfig.DEBUG) {
|
||||
try {
|
||||
Amplitude.getInstance().initialize(this, getString(R.string.amplitude_app_id)).enableForegroundTracking(this)
|
||||
val identify = Identify().setOnce("androidStore", BuildConfig.STORE)
|
||||
Amplitude.getInstance().identify(identify)
|
||||
} catch (ignored: Resources.NotFoundException) {
|
||||
}
|
||||
|
||||
}
|
||||
val config = ImagePipelineConfig.newBuilder(this)
|
||||
.setDownsampleEnabled(true)
|
||||
.build()
|
||||
Fresco.initialize(this, config)
|
||||
|
||||
RxErrorHandler.init(crashlyticsProxy)
|
||||
|
||||
checkIfNewVersion()
|
||||
}
|
||||
|
||||
protected open fun setupRealm() {
|
||||
Realm.init(this)
|
||||
val builder = RealmConfiguration.Builder()
|
||||
.schemaVersion(1)
|
||||
.deleteRealmIfMigrationNeeded()
|
||||
try {
|
||||
Realm.setDefaultConfiguration(builder.build())
|
||||
} catch (ignored: UnsatisfiedLinkError) {
|
||||
//Catch crash in tests
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun checkIfNewVersion() {
|
||||
var info: PackageInfo? = null
|
||||
try {
|
||||
info = packageManager.getPackageInfo(packageName, 0)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
Log.e("MyApplication", "couldn't get package info!")
|
||||
}
|
||||
|
||||
if (info == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val lastInstalledVersion = sharedPrefs.getInt("last_installed_version", 0)
|
||||
if (lastInstalledVersion < info.versionCode) {
|
||||
sharedPrefs.edit().putInt("last_installed_version", info.versionCode).apply()
|
||||
inventoryRepository.retrieveContent().subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDagger() {
|
||||
component = initDagger()
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
protected abstract fun initDagger(): AppComponent
|
||||
|
||||
private fun setupFacebookSdk() {
|
||||
var fbApiKey: String? = null
|
||||
try {
|
||||
val ai = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
|
||||
val bundle = ai.metaData
|
||||
fbApiKey = bundle.getString(FacebookSdk.APPLICATION_ID_PROPERTY)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
Log.e("FB Error", "Failed to load meta-data, NameNotFound: " + e.message)
|
||||
} catch (e: NullPointerException) {
|
||||
Log.e("FB Error", "Failed to load meta-data, NullPointer: " + e.message)
|
||||
}
|
||||
|
||||
if (fbApiKey != null) {
|
||||
FacebookSdk.sdkInitialize(applicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
override fun openOrCreateDatabase(name: String,
|
||||
mode: Int, factory: SQLiteDatabase.CursorFactory): SQLiteDatabase {
|
||||
return super.openOrCreateDatabase(getDatabasePath(name).absolutePath, mode, factory)
|
||||
}
|
||||
|
||||
override fun openOrCreateDatabase(name: String,
|
||||
mode: Int, factory: SQLiteDatabase.CursorFactory, errorHandler: DatabaseErrorHandler?): SQLiteDatabase {
|
||||
return super.openOrCreateDatabase(getDatabasePath(name).absolutePath, mode, factory, errorHandler)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region IAP - Specific
|
||||
|
||||
override fun deleteDatabase(name: String): Boolean {
|
||||
val realm = Realm.getDefaultInstance()
|
||||
realm.executeTransaction { realm1 ->
|
||||
realm1.deleteAll()
|
||||
realm1.close()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun createBillingAndCheckout() {
|
||||
billing = Billing(this, object : Billing.DefaultConfiguration() {
|
||||
override fun getPublicKey(): String {
|
||||
return "DONT-NEED-IT"
|
||||
}
|
||||
|
||||
override fun getCache(): Cache? {
|
||||
return Billing.newCache()
|
||||
}
|
||||
|
||||
override fun getPurchaseVerifier(): PurchaseVerifier {
|
||||
return HabiticaPurchaseVerifier(this@HabiticaBaseApplication, lazyApiHelper)
|
||||
}
|
||||
})
|
||||
|
||||
billing.notNull { checkout = Checkout.forApplication(it) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var component: AppComponent? = null
|
||||
private set
|
||||
|
||||
fun getInstance(context: Context): HabiticaBaseApplication {
|
||||
return context.applicationContext as HabiticaBaseApplication
|
||||
}
|
||||
|
||||
fun logout(context: Context) {
|
||||
val realm = Realm.getDefaultInstance()
|
||||
getInstance(context).deleteDatabase(realm.path)
|
||||
realm.close()
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val useReminder = preferences.getBoolean("use_reminder", false)
|
||||
val reminderTime = preferences.getString("reminder_time", "19:00")
|
||||
val editor = preferences.edit()
|
||||
editor.clear()
|
||||
editor.putBoolean("use_reminder", useReminder)
|
||||
editor.putString("reminder_time", reminderTime)
|
||||
editor.apply()
|
||||
getInstance(context).lazyApiHelper.updateAuthenticationCredentials(null, null)
|
||||
startActivity(LoginActivity::class.java, context)
|
||||
}
|
||||
|
||||
fun checkUserAuthentication(context: Context, hostConfig: HostConfig?): Boolean {
|
||||
if (hostConfig == null || hostConfig.api == null || hostConfig.api == "" || hostConfig.user == null || hostConfig.user == "") {
|
||||
startActivity(IntroActivity::class.java, context)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun startActivity(activityClass: Class<*>, context: Context) {
|
||||
val intent = Intent(context, activityClass)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener;
|
|||
init {
|
||||
this.popupNotificationsManager.setApiClient(this)
|
||||
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
crashlyticsProxy.setUserIdentifier(this.hostConfig.user)
|
||||
crashlyticsProxy.setUserName(this.hostConfig.user)
|
||||
Amplitude.getInstance().userId = this.hostConfig.user
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import java.util.Calendar;
|
|||
public class FirstDayOfTheWeekHelper {
|
||||
|
||||
private int firstDayOfTheWeek;
|
||||
private int dailyTaskFormOffset;
|
||||
public int dailyTaskFormOffset;
|
||||
|
||||
private FirstDayOfTheWeekHelper(int dailyTaskFormOffset, int firstDayOfTheWeek) {
|
||||
this.dailyTaskFormOffset = dailyTaskFormOffset;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.text.DateFormat;
|
|||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ public class RemindersManager {
|
|||
private DateFormat dateFormater;
|
||||
|
||||
public RemindersManager(String taskType) {
|
||||
HabiticaBaseApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
if (taskType.equals("todo")) {
|
||||
dateFormater = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import com.habitrpg.android.habitica.HabiticaApplication
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
|
@ -21,7 +22,7 @@ class SoundFileLoader(private val context: Context) {
|
|||
|
||||
private val externalCacheDir: String?
|
||||
get() {
|
||||
val cacheDir = HabiticaApplication.getInstance(context).getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS)
|
||||
val cacheDir = HabiticaBaseApplication.getInstance(context).getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS)
|
||||
return cacheDir?.path
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class SoundManager {
|
|||
private val loadedSoundFiles: MutableMap<String, SoundFile> = HashMap()
|
||||
|
||||
init {
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
}
|
||||
|
||||
fun preloadAllFiles(): Maybe<List<SoundFile>> {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.google.firebase.iid.FirebaseInstanceId;
|
|||
import com.google.firebase.iid.FirebaseInstanceIdService;
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
|
|
@ -16,7 +18,7 @@ public class HabiticaFirebaseInstanceIDService extends FirebaseInstanceIdService
|
|||
|
||||
@Override
|
||||
public void onTokenRefresh() {
|
||||
HabiticaApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaApplication.Companion.getComponent()).inject(this);
|
||||
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
|
||||
pushNotificationManager.setRefreshedToken(refreshedToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.google.firebase.messaging.FirebaseMessagingService;
|
|||
import com.google.firebase.messaging.RemoteMessage;
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
|
|
@ -16,7 +18,7 @@ public class HabiticaFirebaseMessagingService extends FirebaseMessagingService {
|
|||
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
HabiticaApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaApplication.Companion.getComponent()).inject(this);
|
||||
pushNotificationManager.displayNotification(remoteMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import com.habitrpg.android.habitica.data.UserRepository;
|
|||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class LocalNotificationActionReceiver extends BroadcastReceiver {
|
||||
|
|
@ -33,7 +35,7 @@ public class LocalNotificationActionReceiver extends BroadcastReceiver {
|
|||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
HabiticaBaseApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
this.resources = context.getResources();
|
||||
|
||||
this.action = intent.getAction();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.support.v4.content.ContextCompat;
|
|||
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
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;
|
||||
|
|
@ -19,6 +20,8 @@ import com.habitrpg.android.habitica.models.tasks.Task;
|
|||
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;
|
||||
|
||||
|
|
@ -39,7 +42,7 @@ public class NotificationPublisher extends WakefulBroadcastReceiver {
|
|||
public void onReceive(Context context, Intent intent) {
|
||||
this.context = context;
|
||||
if (taskRepository == null) {
|
||||
HabiticaApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
}
|
||||
|
||||
boolean check_dailies = intent.getBooleanExtra(CHECK_DAILIES, false);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import android.content.Intent;
|
|||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class TaskAlarmBootReceiver extends BroadcastReceiver {
|
||||
|
|
@ -16,7 +18,7 @@ public class TaskAlarmBootReceiver extends BroadcastReceiver {
|
|||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent arg1) {
|
||||
HabiticaApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaApplication.Companion.getComponent()).inject(this);
|
||||
taskAlarmManager.scheduleAllSavedAlarms();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import android.media.RingtoneManager
|
|||
import android.os.Build
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import com.habitrpg.android.habitica.HabiticaApplication
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
|
|
@ -22,7 +23,7 @@ class TaskReceiver : BroadcastReceiver() {
|
|||
lateinit var taskAlarmManager: TaskAlarmManager
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
HabiticaApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
val extras = intent.extras
|
||||
if (extras != null) {
|
||||
val taskTitle = extras.getString(TaskAlarmManager.TASK_NAME_INTENT_KEY)
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ class AboutActivity : BaseActivity() {
|
|||
tabLayout.setupWithViewPager(pager)
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent) {
|
||||
component.inject(this)
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
|
|
|||
|
|
@ -1,79 +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.app.AppCompatActivity;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.widget.AddTaskWidgetProvider;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class AddTaskWidgetActivity extends AppCompatActivity {
|
||||
|
||||
private int widgetId;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setResult(RESULT_CANCELED);
|
||||
setContentView(R.layout.widget_configure_add_task);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.add_habit_button)
|
||||
public void addHabitSelected() {
|
||||
finishWithSelection(Task.TYPE_HABIT);
|
||||
}
|
||||
|
||||
@OnClick(R.id.add_daily_button)
|
||||
public void addDailySelected() {
|
||||
finishWithSelection(Task.TYPE_DAILY);
|
||||
}
|
||||
|
||||
@OnClick(R.id.add_todo_button)
|
||||
public void addToDoSelected() {
|
||||
finishWithSelection(Task.TYPE_TODO);
|
||||
}
|
||||
|
||||
@OnClick(R.id.add_reward_button)
|
||||
public void addRewardSelected() {
|
||||
finishWithSelection(Task.TYPE_REWARD);
|
||||
}
|
||||
|
||||
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, AddTaskWidgetProvider.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("add_task_widget_" + widgetId, selectedTaskType);
|
||||
preferences.apply();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.preference.PreferenceManager
|
||||
import android.widget.Button
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.widget.AddTaskWidgetProvider
|
||||
|
||||
class AddTaskWidgetActivity : AppCompatActivity() {
|
||||
|
||||
private var widgetId: Int = 0
|
||||
|
||||
private val addHabitButton: Button by bindView(R.id.add_habit_button)
|
||||
private val addDailyButton: Button by bindView(R.id.add_daily_button)
|
||||
private val addToDoButton: Button by bindView(R.id.add_todo_button)
|
||||
private val addRewardButton: Button by bindView(R.id.add_reward_button)
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
setContentView(R.layout.widget_configure_add_task)
|
||||
|
||||
val intent = intent
|
||||
val extras = intent.extras
|
||||
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()
|
||||
}
|
||||
|
||||
addHabitButton.setOnClickListener { addHabitSelected() }
|
||||
addDailyButton.setOnClickListener { addDailySelected() }
|
||||
addToDoButton.setOnClickListener { addToDoSelected() }
|
||||
addRewardButton.setOnClickListener { addRewardSelected() }
|
||||
}
|
||||
|
||||
private fun addHabitSelected() {
|
||||
finishWithSelection(Task.TYPE_HABIT)
|
||||
}
|
||||
|
||||
private fun addDailySelected() {
|
||||
finishWithSelection(Task.TYPE_DAILY)
|
||||
}
|
||||
|
||||
private fun addToDoSelected() {
|
||||
finishWithSelection(Task.TYPE_TODO)
|
||||
}
|
||||
|
||||
private fun addRewardSelected() {
|
||||
finishWithSelection(Task.TYPE_REWARD)
|
||||
}
|
||||
|
||||
private fun finishWithSelection(selectedTaskType: String) {
|
||||
storeSelectedTaskType(selectedTaskType)
|
||||
|
||||
val resultValue = Intent()
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
|
||||
setResult(Activity.RESULT_OK, resultValue)
|
||||
finish()
|
||||
|
||||
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, AddTaskWidgetProvider::class.java)
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(widgetId))
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
private fun storeSelectedTaskType(selectedTaskType: String) {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(this).edit()
|
||||
preferences.putString("add_task_widget_$widgetId", selectedTaskType)
|
||||
preferences.apply()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
||||
public abstract class BaseActivity extends AppCompatActivity {
|
||||
|
||||
private boolean destroyed;
|
||||
|
||||
protected abstract int getLayoutResId();
|
||||
|
||||
public boolean isDestroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
protected CompositeDisposable compositeSubscription;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getHabiticaApplication();
|
||||
injectActivity(HabiticaBaseApplication.getComponent());
|
||||
setContentView(getLayoutResId());
|
||||
ButterKnife.bind(this);
|
||||
compositeSubscription = new CompositeDisposable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
if (EventBus.getDefault().isRegistered(this)) {
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
protected abstract void injectActivity(AppComponent component);
|
||||
|
||||
protected void setupToolbar(Toolbar toolbar) {
|
||||
if (toolbar != null) {
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
actionBar.setDisplayShowTitleEnabled(true);
|
||||
actionBar.setDisplayUseLogoEnabled(false);
|
||||
actionBar.setHomeButtonEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
destroyed = true;
|
||||
|
||||
if (compositeSubscription != null && !compositeSubscription.isDisposed()) {
|
||||
compositeSubscription.dispose();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public HabiticaApplication getHabiticaApplication() {
|
||||
return (HabiticaApplication) getApplication();
|
||||
}
|
||||
|
||||
//Check for "Don't keep Activities" Developer setting
|
||||
//TODO: Make this check obsolete.
|
||||
boolean isAlwaysFinishActivitiesOptionEnabled() {
|
||||
int alwaysFinishActivitiesInt = 0;
|
||||
if (Build.VERSION.SDK_INT >= 17) {
|
||||
alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0);
|
||||
} else {
|
||||
alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0);
|
||||
}
|
||||
|
||||
return alwaysFinishActivitiesInt == 1;
|
||||
}
|
||||
|
||||
void showDeveloperOptionsScreen() {
|
||||
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(ShowConnectionProblemEvent event) {
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setTitle(event.title)
|
||||
.setMessage(event.message)
|
||||
.setNeutralButton(android.R.string.ok, (dialog, which) -> {
|
||||
});
|
||||
|
||||
if (!event.title.isEmpty()) {
|
||||
builder.setIcon(R.drawable.ic_warning_black);
|
||||
}
|
||||
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import com.habitrpg.android.habitica.HabiticaApplication
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
|
||||
private var destroyed: Boolean = false
|
||||
|
||||
protected abstract fun getLayoutResId(): Int
|
||||
|
||||
protected var compositeSubscription = CompositeDisposable()
|
||||
|
||||
private val habiticaApplication: HabiticaApplication
|
||||
get() = application as HabiticaApplication
|
||||
|
||||
//Check for "Don't keep Activities" Developer setting
|
||||
//TODO: Make this check obsolete.
|
||||
internal val isAlwaysFinishActivitiesOptionEnabled: Boolean
|
||||
get() {
|
||||
var alwaysFinishActivitiesInt = 0
|
||||
alwaysFinishActivitiesInt = if (Build.VERSION.SDK_INT >= 17) {
|
||||
Settings.System.getInt(applicationContext.contentResolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0)
|
||||
} else {
|
||||
Settings.System.getInt(applicationContext.contentResolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0)
|
||||
}
|
||||
|
||||
return alwaysFinishActivitiesInt == 1
|
||||
}
|
||||
|
||||
override fun isDestroyed(): Boolean {
|
||||
return destroyed
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
habiticaApplication
|
||||
injectActivity(HabiticaBaseApplication.component)
|
||||
setContentView(getLayoutResId())
|
||||
compositeSubscription = CompositeDisposable()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
if (EventBus.getDefault().isRegistered(this)) {
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
protected abstract fun injectActivity(component: AppComponent?)
|
||||
|
||||
protected fun setupToolbar(toolbar: Toolbar?) {
|
||||
if (toolbar != null) {
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
val actionBar = supportActionBar
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||
actionBar.setDisplayShowHomeEnabled(true)
|
||||
actionBar.setDisplayShowTitleEnabled(true)
|
||||
actionBar.setDisplayUseLogoEnabled(false)
|
||||
actionBar.setHomeButtonEnabled(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
destroyed = true
|
||||
|
||||
if (compositeSubscription != null && !compositeSubscription!!.isDisposed) {
|
||||
compositeSubscription!!.dispose()
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
internal fun showDeveloperOptionsScreen() {
|
||||
val intent = Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: ShowConnectionProblemEvent) {
|
||||
val builder = AlertDialog.Builder(this)
|
||||
.setTitle(event.title)
|
||||
.setMessage(event.message)
|
||||
.setNeutralButton(android.R.string.ok) { _, _ -> }
|
||||
|
||||
if (!event.title.isEmpty()) {
|
||||
builder.setIcon(R.drawable.ic_warning_black)
|
||||
}
|
||||
|
||||
builder.show()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,433 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.events.HabitScoreEvent;
|
||||
import com.habitrpg.android.habitica.events.TaskUpdatedEvent;
|
||||
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand;
|
||||
import com.habitrpg.android.habitica.events.commands.ChecklistCheckedCommand;
|
||||
import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.interactors.BuyRewardUseCase;
|
||||
import com.habitrpg.android.habitica.interactors.ChecklistCheckUseCase;
|
||||
import com.habitrpg.android.habitica.interactors.DailyCheckUseCase;
|
||||
import com.habitrpg.android.habitica.interactors.DisplayItemDropUseCase;
|
||||
import com.habitrpg.android.habitica.interactors.HabitScoreUseCase;
|
||||
import com.habitrpg.android.habitica.interactors.NotifyUserUseCase;
|
||||
import com.habitrpg.android.habitica.interactors.TodoCheckUseCase;
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody;
|
||||
import com.habitrpg.android.habitica.models.responses.TaskScoringResult;
|
||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDetailDialogHolder;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar;
|
||||
import com.habitrpg.android.habitica.utils.Action1;
|
||||
|
||||
import net.pherth.android.emoji_library.EmojiParser;
|
||||
import net.pherth.android.emoji_library.EmojiTextView;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
|
||||
public class ChallengeDetailActivity extends BaseActivity {
|
||||
|
||||
public static String CHALLENGE_ID = "CHALLENGE_ID";
|
||||
|
||||
@BindView(R.id.detail_tabs)
|
||||
TabLayout detail_tabs;
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
|
||||
@Inject
|
||||
ChallengeRepository challengeRepository;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
|
||||
@BindView(R.id.floating_menu_wrapper)
|
||||
FrameLayout floatingMenuWrapper;
|
||||
|
||||
// region UseCases
|
||||
|
||||
@Inject
|
||||
HabitScoreUseCase habitScoreUseCase;
|
||||
|
||||
@Inject
|
||||
DailyCheckUseCase dailyCheckUseCase;
|
||||
|
||||
@Inject
|
||||
TodoCheckUseCase todoCheckUseCase;
|
||||
|
||||
@Inject
|
||||
BuyRewardUseCase buyRewardUseCase;
|
||||
|
||||
@Inject
|
||||
ChecklistCheckUseCase checklistCheckUseCase;
|
||||
|
||||
@Inject
|
||||
DisplayItemDropUseCase displayItemDropUseCase;
|
||||
|
||||
@Inject
|
||||
NotifyUserUseCase notifyUserUseCase;
|
||||
|
||||
// endregion
|
||||
|
||||
@Nullable
|
||||
private Challenge challenge;
|
||||
private User user;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_challenge_detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_challenge_details, menu);
|
||||
|
||||
if(challenge != null && challenge.leaderId != null && !challenge.leaderId.equals(userId)){
|
||||
menu.setGroupVisible(R.id.challenge_edit_action_group, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setupToolbar(toolbar);
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setTitle(R.string.challenge_details);
|
||||
}
|
||||
detail_tabs.setVisibility(View.GONE);
|
||||
|
||||
Bundle extras = getIntent().getExtras();
|
||||
|
||||
String challengeId = extras.getString(CHALLENGE_ID);
|
||||
|
||||
List<Task> fullList = new ArrayList<>();
|
||||
|
||||
userRepository.getUser(userId).firstElement().subscribe(user -> {
|
||||
ChallengeDetailActivity.this.user = user;
|
||||
createTaskRecyclerFragment(fullList);
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
|
||||
if (challengeId != null) {
|
||||
challengeRepository.getChallengeTasks(challengeId)
|
||||
.firstElement()
|
||||
.subscribe(taskList -> {
|
||||
ArrayList<Task> resultList = new ArrayList<>();
|
||||
|
||||
ArrayList<Task> todos = new ArrayList<>();
|
||||
ArrayList<Task> habits = new ArrayList<>();
|
||||
ArrayList<Task> dailies = new ArrayList<>();
|
||||
ArrayList<Task> rewards = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, Task> entry : taskList.tasks.entrySet()) {
|
||||
switch (entry.getValue().getType()) {
|
||||
case Task.TYPE_TODO:
|
||||
todos.add(entry.getValue());
|
||||
break;
|
||||
case Task.TYPE_HABIT:
|
||||
|
||||
habits.add(entry.getValue());
|
||||
break;
|
||||
case Task.TYPE_DAILY:
|
||||
|
||||
dailies.add(entry.getValue());
|
||||
break;
|
||||
case Task.TYPE_REWARD:
|
||||
|
||||
rewards.add(entry.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!habits.isEmpty()) {
|
||||
Task dividerTask = new Task();
|
||||
dividerTask.setId("divhabits");
|
||||
dividerTask.setType("divider");
|
||||
dividerTask.setText("Challenge Habits");
|
||||
|
||||
resultList.add(dividerTask);
|
||||
resultList.addAll(habits);
|
||||
}
|
||||
|
||||
|
||||
if (!dailies.isEmpty()) {
|
||||
Task dividerTask = new Task();
|
||||
dividerTask.setId("divdailies");
|
||||
dividerTask.setType("divider");
|
||||
dividerTask.setText("Challenge Dailies");
|
||||
|
||||
resultList.add(dividerTask);
|
||||
resultList.addAll(dailies);
|
||||
}
|
||||
|
||||
|
||||
if (!todos.isEmpty()) {
|
||||
Task dividerTask = new Task();
|
||||
dividerTask.setId("divtodos");
|
||||
dividerTask.setType("divider");
|
||||
dividerTask.setText("Challenge To-Dos");
|
||||
|
||||
resultList.add(dividerTask);
|
||||
resultList.addAll(todos);
|
||||
}
|
||||
|
||||
if (!rewards.isEmpty()) {
|
||||
Task dividerTask = new Task();
|
||||
dividerTask.setId("divrewards");
|
||||
dividerTask.setType("divider");
|
||||
dividerTask.setText("Challenge Rewards");
|
||||
|
||||
resultList.add(dividerTask);
|
||||
resultList.addAll(rewards);
|
||||
}
|
||||
|
||||
|
||||
fullList.addAll(resultList);
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
if (challengeId != null) {
|
||||
challengeRepository.getChallenge(challengeId).subscribe(challenge -> {
|
||||
ChallengeDetailActivity.this.challenge = challenge;
|
||||
ChallengeViewHolder challengeViewHolder = new ChallengeViewHolder(findViewById(R.id.challenge_header));
|
||||
challengeViewHolder.bind(challenge);
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
private void createTaskRecyclerFragment(List<Task> fullList) {
|
||||
ChallengeTasksRecyclerViewFragment fragment = ChallengeTasksRecyclerViewFragment.newInstance(user, fullList);
|
||||
|
||||
if (getSupportFragmentManager().getFragments() == null) {
|
||||
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, fragment).commitAllowingStateLoss();
|
||||
} else {
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
transaction.replace(R.id.fragment_container, fragment).addToBackStack(null).commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
challengeRepository.close();
|
||||
userRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_edit:
|
||||
openChallengeEditActivity();
|
||||
return true;
|
||||
case R.id.action_leave:
|
||||
showChallengeLeaveDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void openChallengeEditActivity(){
|
||||
Intent intent = new Intent(this, CreateChallengeActivity.class);
|
||||
if (challenge != null) {
|
||||
intent.putExtra(CreateChallengeActivity.CHALLENGE_ID_KEY, challenge.id);
|
||||
}
|
||||
|
||||
startActivity(intent);
|
||||
|
||||
}
|
||||
|
||||
private void showChallengeLeaveDialog(){
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(this.getString(R.string.challenge_leave_title))
|
||||
.setMessage(this.getString(R.string.challenge_leave_text, challenge != null ? challenge.name : ""))
|
||||
.setPositiveButton(this.getString(R.string.yes), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
|
||||
showRemoveTasksDialog(keepTasks -> this.challengeRepository.leaveChallenge(challenge, new LeaveChallengeBody(keepTasks))
|
||||
.subscribe(aVoid -> finish(), RxErrorHandler.handleEmptyError()));
|
||||
})
|
||||
.setNegativeButton(this.getString(R.string.no), (dialog, which) -> dialog.dismiss()).show();
|
||||
}
|
||||
|
||||
// refactor as an UseCase later - see ChallengeDetailDialogHolder
|
||||
private void showRemoveTasksDialog(Action1<String> callback){
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(this.getString(R.string.challenge_remove_tasks_title))
|
||||
.setMessage(this.getString(R.string.challenge_remove_tasks_text))
|
||||
.setPositiveButton(this.getString(R.string.remove_tasks), (dialog, which) -> {
|
||||
callback.call("remove-all");
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(this.getString(R.string.keep_tasks), (dialog, which) -> {
|
||||
callback.call("keep-all");
|
||||
dialog.dismiss();
|
||||
}).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
finish();
|
||||
}
|
||||
|
||||
class ChallengeViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.challenge_name)
|
||||
EmojiTextView challengeName;
|
||||
|
||||
@BindView(R.id.challenge_description)
|
||||
EmojiTextView challengeDescription;
|
||||
|
||||
@BindView(R.id.challenge_member_count)
|
||||
TextView memberCountTextView;
|
||||
|
||||
@BindView(R.id.gem_amount)
|
||||
TextView gemPrizeTextView;
|
||||
|
||||
private Challenge challenge;
|
||||
|
||||
ChallengeViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
ButterKnife.bind(this, itemView);
|
||||
|
||||
Drawable gemDrawable = new BitmapDrawable(itemView.getResources(), HabiticaIconsHelper.imageOfGem());
|
||||
gemPrizeTextView.setCompoundDrawablesWithIntrinsicBounds(gemDrawable, null, null, null);
|
||||
}
|
||||
|
||||
public void bind(Challenge challenge) {
|
||||
this.challenge = challenge;
|
||||
|
||||
if (challengeName != null) {
|
||||
challengeName.setText(EmojiParser.parseEmojis(challenge.name));
|
||||
}
|
||||
challengeDescription.setText(MarkdownParser.INSTANCE.parseMarkdown(challenge.description));
|
||||
|
||||
memberCountTextView.setText(String.valueOf(challenge.memberCount));
|
||||
|
||||
if (challenge.prize == 0) {
|
||||
gemPrizeTextView.setVisibility(View.GONE);
|
||||
} else {
|
||||
gemPrizeTextView.setVisibility(View.VISIBLE);
|
||||
gemPrizeTextView.setText(String.valueOf(challenge.prize));
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_show_more)
|
||||
void onShowMore() {
|
||||
ChallengeDetailDialogHolder.Companion.showDialog(ChallengeDetailActivity.this,
|
||||
ChallengeDetailActivity.this.challengeRepository,
|
||||
challenge,
|
||||
challenge1 -> ChallengeDetailActivity.this.onBackPressed());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(TaskCheckedCommand event) {
|
||||
switch (event.Task.getType()) {
|
||||
case Task.TYPE_DAILY: {
|
||||
dailyCheckUseCase.observable(new DailyCheckUseCase.RequestValues(user, event.Task, !event.Task.getCompleted()))
|
||||
.subscribe(this::onTaskDataReceived, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
break;
|
||||
case Task.TYPE_TODO: {
|
||||
todoCheckUseCase.observable(new TodoCheckUseCase.RequestValues(user, event.Task, !event.Task.getCompleted()))
|
||||
.subscribe(this::onTaskDataReceived, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(ChecklistCheckedCommand event) {
|
||||
checklistCheckUseCase.observable(new ChecklistCheckUseCase.RequestValues(event.task.getId(), event.item.getId()))
|
||||
.subscribe(res -> EventBus.getDefault().post(new TaskUpdatedEvent(event.task)), RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(HabitScoreEvent event) {
|
||||
habitScoreUseCase.observable(new HabitScoreUseCase.RequestValues(user, event.habit, event.Up))
|
||||
.subscribe(this::onTaskDataReceived, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final BuyRewardCommand event) {
|
||||
if (user.getStats().getGp() < event.Reward.getValue()) {
|
||||
HabiticaSnackbar.Companion.showSnackbar(floatingMenuWrapper, getString(R.string.no_gold), HabiticaSnackbar.SnackbarDisplayType.FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (event.Reward.getSpecialTag() == null || !event.Reward.getSpecialTag().equals("item")) {
|
||||
|
||||
buyRewardUseCase.observable(new BuyRewardUseCase.RequestValues(user, event.Reward))
|
||||
.subscribe(res -> HabiticaSnackbar.Companion.showSnackbar(floatingMenuWrapper, getString(R.string.notification_purchase_reward), HabiticaSnackbar.SnackbarDisplayType.NORMAL), RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onTaskDataReceived(TaskScoringResult data) {
|
||||
if (user != null) {
|
||||
notifyUserUseCase.observable(new NotifyUserUseCase.RequestValues(this, floatingMenuWrapper,
|
||||
user, data.getExperienceDelta(), data.getHealthDelta(), data.getGoldDelta(), data.getManaDelta(), data.getQuestDamage(), data.getHasLeveledUp()));
|
||||
}
|
||||
|
||||
displayItemDropUseCase.observable(new DisplayItemDropUseCase.RequestValues(data, this, floatingMenuWrapper))
|
||||
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,397 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.events.HabitScoreEvent
|
||||
import com.habitrpg.android.habitica.events.TaskUpdatedEvent
|
||||
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand
|
||||
import com.habitrpg.android.habitica.events.commands.ChecklistCheckedCommand
|
||||
import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.interactors.*
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody
|
||||
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDetailDialogHolder
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.utils.Action1
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiParser
|
||||
import net.pherth.android.emoji_library.EmojiTextView
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
|
||||
class ChallengeDetailActivity : BaseActivity() {
|
||||
|
||||
|
||||
@Inject
|
||||
internal lateinit var challengeRepository: ChallengeRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
internal lateinit var userId: String
|
||||
@Inject
|
||||
internal lateinit var userRepository: UserRepository
|
||||
|
||||
private val floatingMenuWrapper: FrameLayout by bindView(R.id.floating_menu_wrapper)
|
||||
private val detailTabs: TabLayout by bindView(R.id.detail_tabs)
|
||||
private val toolbar: Toolbar by bindView(R.id.toolbar)
|
||||
// region UseCases
|
||||
|
||||
@Inject
|
||||
internal lateinit var habitScoreUseCase: HabitScoreUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var dailyCheckUseCase: DailyCheckUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var todoCheckUseCase: TodoCheckUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var buyRewardUseCase: BuyRewardUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var checklistCheckUseCase: ChecklistCheckUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var displayItemDropUseCase: DisplayItemDropUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var notifyUserUseCase: NotifyUserUseCase
|
||||
|
||||
// endregion
|
||||
|
||||
private var challenge: Challenge? = null
|
||||
private var user: User? = null
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_challenge_detail
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
val inflater = menuInflater
|
||||
inflater.inflate(R.menu.menu_challenge_details, menu)
|
||||
|
||||
if (challenge?.leaderId != userId) {
|
||||
menu.setGroupVisible(R.id.challenge_edit_action_group, false)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setupToolbar(toolbar)
|
||||
|
||||
supportActionBar?.setTitle(R.string.challenge_details)
|
||||
detailTabs.visibility = View.GONE
|
||||
|
||||
val extras = intent.extras
|
||||
|
||||
val challengeId = extras.getString(CHALLENGE_ID)
|
||||
|
||||
val fullList = ArrayList<Task>()
|
||||
|
||||
userRepository.getUser(userId).firstElement().subscribe(Consumer { user ->
|
||||
this@ChallengeDetailActivity.user = user
|
||||
createTaskRecyclerFragment(fullList)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
||||
if (challengeId != null) {
|
||||
challengeRepository.getChallengeTasks(challengeId)
|
||||
.firstElement()
|
||||
.subscribe(Consumer { taskList ->
|
||||
val resultList = ArrayList<Task>()
|
||||
|
||||
val todos = ArrayList<Task>()
|
||||
val habits = ArrayList<Task>()
|
||||
val dailies = ArrayList<Task>()
|
||||
val rewards = ArrayList<Task>()
|
||||
|
||||
for (entry in taskList.tasks.entries) {
|
||||
when (entry.value.type) {
|
||||
Task.TYPE_TODO -> todos.add(entry.value)
|
||||
Task.TYPE_HABIT ->
|
||||
|
||||
habits.add(entry.value)
|
||||
Task.TYPE_DAILY ->
|
||||
|
||||
dailies.add(entry.value)
|
||||
Task.TYPE_REWARD ->
|
||||
|
||||
rewards.add(entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!habits.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divhabits"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge Habits"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(habits)
|
||||
}
|
||||
|
||||
|
||||
if (!dailies.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divdailies"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge Dailies"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(dailies)
|
||||
}
|
||||
|
||||
|
||||
if (!todos.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divtodos"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge To-Dos"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(todos)
|
||||
}
|
||||
|
||||
if (!rewards.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divrewards"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge Rewards"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(rewards)
|
||||
}
|
||||
|
||||
|
||||
fullList.addAll(resultList)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
if (challengeId != null) {
|
||||
challengeRepository.getChallenge(challengeId).subscribe(Consumer { challenge ->
|
||||
this@ChallengeDetailActivity.challenge = challenge
|
||||
val challengeViewHolder = ChallengeViewHolder(findViewById(R.id.challenge_header))
|
||||
challengeViewHolder.bind(challenge)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTaskRecyclerFragment(fullList: List<Task>) {
|
||||
val fragment = ChallengeTasksRecyclerViewFragment.newInstance(user, fullList)
|
||||
|
||||
if (supportFragmentManager.fragments == null) {
|
||||
supportFragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commitAllowingStateLoss()
|
||||
} else {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
transaction.replace(R.id.fragment_container, fragment).addToBackStack(null).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
challengeRepository.close()
|
||||
userRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_edit -> {
|
||||
openChallengeEditActivity()
|
||||
return true
|
||||
}
|
||||
R.id.action_leave -> {
|
||||
showChallengeLeaveDialog()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun openChallengeEditActivity() {
|
||||
val intent = Intent(this, CreateChallengeActivity::class.java)
|
||||
intent.putExtra(CreateChallengeActivity.CHALLENGE_ID_KEY, challenge?.id)
|
||||
|
||||
startActivity(intent)
|
||||
|
||||
}
|
||||
|
||||
private fun showChallengeLeaveDialog() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(this.getString(R.string.challenge_leave_title))
|
||||
.setMessage(this.getString(R.string.challenge_leave_text, challenge?.name ?: ""))
|
||||
.setPositiveButton(this.getString(R.string.yes)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
|
||||
showRemoveTasksDialog(object: Action1<String> {
|
||||
override fun call(t: String) {
|
||||
challengeRepository.leaveChallenge(challenge, LeaveChallengeBody(t))
|
||||
.subscribe(Consumer { finish() }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
})
|
||||
}
|
||||
.setNegativeButton(this.getString(R.string.no)) { dialog, _ -> dialog.dismiss() }.show()
|
||||
}
|
||||
|
||||
// refactor as an UseCase later - see ChallengeDetailDialogHolder
|
||||
private fun showRemoveTasksDialog(callback: Action1<String>) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(this.getString(R.string.challenge_remove_tasks_title))
|
||||
.setMessage(this.getString(R.string.challenge_remove_tasks_text))
|
||||
.setPositiveButton(this.getString(R.string.remove_tasks)) { dialog, _ ->
|
||||
callback.call("remove-all")
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(this.getString(R.string.keep_tasks)) { dialog, _ ->
|
||||
callback.call("keep-all")
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finish()
|
||||
}
|
||||
|
||||
internal inner class ChallengeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val challengeName: EmojiTextView by bindView(itemView, R.id.challenge_name)
|
||||
private val challengeDescription: EmojiTextView by bindView(itemView, R.id.challenge_description)
|
||||
private val memberCountTextView: TextView by bindView(itemView, R.id.challenge_member_count)
|
||||
private val gemPrizeTextView: TextView by bindView(itemView, R.id.gem_amount)
|
||||
private val showMoreButton: Button by bindView(itemView, R.id.btn_show_more)
|
||||
|
||||
private var challenge: Challenge? = null
|
||||
|
||||
init {
|
||||
showMoreButton.setOnClickListener { onShowMore() }
|
||||
|
||||
val gemDrawable = BitmapDrawable(itemView.resources, HabiticaIconsHelper.imageOfGem())
|
||||
gemPrizeTextView.setCompoundDrawablesWithIntrinsicBounds(gemDrawable, null, null, null)
|
||||
}
|
||||
|
||||
fun bind(challenge: Challenge) {
|
||||
this.challenge = challenge
|
||||
|
||||
challengeName.text = EmojiParser.parseEmojis(challenge.name)
|
||||
challengeDescription.text = MarkdownParser.parseMarkdown(challenge.description)
|
||||
|
||||
memberCountTextView.text = challenge.memberCount.toString()
|
||||
|
||||
if (challenge.prize == 0) {
|
||||
gemPrizeTextView.visibility = View.GONE
|
||||
} else {
|
||||
gemPrizeTextView.visibility = View.VISIBLE
|
||||
gemPrizeTextView.text = challenge.prize.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun onShowMore() {
|
||||
challenge.notNull {
|
||||
ChallengeDetailDialogHolder.showDialog(this@ChallengeDetailActivity,
|
||||
this@ChallengeDetailActivity.challengeRepository,
|
||||
it,
|
||||
object: Action1<Challenge> {
|
||||
override fun call(t: Challenge) {
|
||||
onBackPressed()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: TaskCheckedCommand) {
|
||||
when (event.Task.type) {
|
||||
Task.TYPE_DAILY -> {
|
||||
dailyCheckUseCase.observable(DailyCheckUseCase.RequestValues(user, event.Task, !event.Task.completed))
|
||||
.subscribe(Consumer { this.onTaskDataReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
todoCheckUseCase.observable(TodoCheckUseCase.RequestValues(user, event.Task, !event.Task.completed))
|
||||
.subscribe(Consumer { this.onTaskDataReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: ChecklistCheckedCommand) {
|
||||
checklistCheckUseCase.observable(ChecklistCheckUseCase.RequestValues(event.task.id, event.item.id))
|
||||
.subscribe(Consumer { EventBus.getDefault().post(TaskUpdatedEvent(event.task)) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: HabitScoreEvent) {
|
||||
habitScoreUseCase.observable(HabitScoreUseCase.RequestValues(user, event.habit, event.Up))
|
||||
.subscribe(Consumer { this.onTaskDataReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: BuyRewardCommand) {
|
||||
if ((user?.stats?.gp ?: 0.toDouble()) < event.Reward.value) {
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.no_gold), HabiticaSnackbar.SnackbarDisplayType.FAILURE)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (event.Reward.specialTag == null || event.Reward.specialTag != "item") {
|
||||
|
||||
buyRewardUseCase.observable(BuyRewardUseCase.RequestValues(user, event.Reward))
|
||||
.subscribe(Consumer { HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.notification_purchase_reward), HabiticaSnackbar.SnackbarDisplayType.NORMAL) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun onTaskDataReceived(data: TaskScoringResult) {
|
||||
if (user != null) {
|
||||
notifyUserUseCase.observable(NotifyUserUseCase.RequestValues(this, floatingMenuWrapper,
|
||||
user, data.experienceDelta, data.healthDelta, data.goldDelta, data.manaDelta, data.questDamage, data.hasLeveledUp))
|
||||
}
|
||||
|
||||
displayItemDropUseCase.observable(DisplayItemDropUseCase.RequestValues(data, this, floatingMenuWrapper))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var CHALLENGE_ID = "CHALLENGE_ID"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.user.Gear;
|
||||
import com.habitrpg.android.habitica.models.user.Hair;
|
||||
import com.habitrpg.android.habitica.models.user.Items;
|
||||
import com.habitrpg.android.habitica.models.user.Outfit;
|
||||
import com.habitrpg.android.habitica.models.user.Preferences;
|
||||
import com.habitrpg.android.habitica.models.user.Stats;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.ui.AvatarView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.functions.Consumer;
|
||||
|
||||
public class ClassSelectionActivity extends BaseActivity implements Consumer<User> {
|
||||
|
||||
String currentClass;
|
||||
Boolean isInitialSelection;
|
||||
Boolean classWasUnset = false;
|
||||
Boolean shouldFinish = false;
|
||||
|
||||
@BindView(R.id.healerAvatarView)
|
||||
AvatarView healerAvatarView;
|
||||
@BindView(R.id.mageAvatarView)
|
||||
AvatarView mageAvatarView;
|
||||
@BindView(R.id.rogueAvatarView)
|
||||
AvatarView rogueAvatarView;
|
||||
@BindView(R.id.warriorAvatarView)
|
||||
AvatarView warriorAvatarView;
|
||||
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
|
||||
ProgressDialog progressDialog;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_class_selection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
Bundle bundle = intent.getExtras();
|
||||
isInitialSelection = bundle.getBoolean("isInitialSelection");
|
||||
currentClass = bundle.getString("currentClass");
|
||||
|
||||
Preferences preferences = new Preferences();
|
||||
preferences.setHair(new Hair());
|
||||
preferences.setCostume(false);
|
||||
preferences.setSize(bundle.getString("size"));
|
||||
preferences.setSkin(bundle.getString("skin"));
|
||||
preferences.setShirt(bundle.getString("shirt"));
|
||||
preferences.getHair().setBangs(bundle.getInt("hairBangs"));
|
||||
preferences.getHair().setBase(bundle.getInt("hairBase"));
|
||||
preferences.getHair().setColor(bundle.getString("hairColor"));
|
||||
preferences.getHair().setMustache(bundle.getInt("hairMustache"));
|
||||
preferences.getHair().setBeard(bundle.getInt("hairBeard"));
|
||||
|
||||
|
||||
Outfit healerOutfit = new Outfit();
|
||||
healerOutfit.setArmor("armor_healer_5");
|
||||
healerOutfit.setHead("head_healer_5");
|
||||
healerOutfit.setShield("shield_healer_5");
|
||||
healerOutfit.setWeapon("weapon_healer_6");
|
||||
User healer = this.makeUser(preferences, healerOutfit);
|
||||
healerAvatarView.setAvatar(healer);
|
||||
|
||||
Outfit mageOutfit = new Outfit();
|
||||
mageOutfit.setArmor("armor_wizard_5");
|
||||
mageOutfit.setHead("head_wizard_5");
|
||||
mageOutfit.setWeapon("weapon_wizard_6");
|
||||
User mage = this.makeUser(preferences, mageOutfit);
|
||||
mageAvatarView.setAvatar(mage);
|
||||
|
||||
Outfit rogueOutfit = new Outfit();
|
||||
rogueOutfit.setArmor("armor_rogue_5");
|
||||
rogueOutfit.setHead("head_rogue_5");
|
||||
rogueOutfit.setShield("shield_rogue_6");
|
||||
rogueOutfit.setWeapon("weapon_rogue_6");
|
||||
User rogue = this.makeUser(preferences, rogueOutfit);
|
||||
rogueAvatarView.setAvatar(rogue);
|
||||
|
||||
Outfit warriorOutfit = new Outfit();
|
||||
warriorOutfit.setArmor("armor_warrior_5");
|
||||
warriorOutfit.setHead("head_warrior_5");
|
||||
warriorOutfit.setShield("shield_warrior_5");
|
||||
warriorOutfit.setWeapon("weapon_warrior_6");
|
||||
User warrior = this.makeUser(preferences, warriorOutfit);
|
||||
warriorAvatarView.setAvatar(warrior);
|
||||
|
||||
if (!isInitialSelection) {
|
||||
userRepository.changeClass()
|
||||
.subscribe(user -> classWasUnset = true, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public User makeUser(Preferences preferences, Outfit outfit) {
|
||||
User user = new User();
|
||||
user.setPreferences(preferences);
|
||||
user.setItems(new Items());
|
||||
user.getItems().setGear(new Gear());
|
||||
user.getItems().getGear().setEquipped(outfit);
|
||||
return user;
|
||||
}
|
||||
|
||||
@OnClick(R.id.healerWrapper)
|
||||
public void healerSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.healer), Stats.HEALER);
|
||||
}
|
||||
|
||||
@OnClick(R.id.mageWrapper)
|
||||
public void mageSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.mage), Stats.MAGE);
|
||||
}
|
||||
|
||||
@OnClick(R.id.rogueWrapper)
|
||||
public void rogueSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.rogue), Stats.ROGUE);
|
||||
}
|
||||
|
||||
@OnClick(R.id.warriorWrapper)
|
||||
public void warriorSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.warrior), Stats.WARRIOR);
|
||||
}
|
||||
|
||||
@OnClick(R.id.optOutWrapper)
|
||||
public void optOutSelected() {
|
||||
if (!this.isInitialSelection && !this.classWasUnset) {
|
||||
return;
|
||||
}
|
||||
AlertDialog alert = new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.opt_out_confirmation))
|
||||
.setNegativeButton(getString(R.string.dialog_go_back), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setPositiveButton(getString(R.string.opt_out_class), (dialog, which) -> {
|
||||
optOutOfClasses();
|
||||
}).create();
|
||||
alert.show();
|
||||
}
|
||||
|
||||
private void displayConfirmationDialogForClass(String className, String classIdentifier) {
|
||||
|
||||
if (!this.isInitialSelection && !this.classWasUnset) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.change_class_confirmation))
|
||||
.setMessage(getString(R.string.change_class_equipment_warning, currentClass))
|
||||
.setNegativeButton(getString(R.string.dialog_go_back), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setPositiveButton(getString(R.string.choose_class), (dialog, which) -> {
|
||||
selectClass(classIdentifier);
|
||||
displayClassChanged(className);
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.class_confirmation, className))
|
||||
.setNegativeButton(getString(R.string.dialog_go_back), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setPositiveButton(getString(R.string.choose_class), (dialog, which) -> {
|
||||
selectClass(classIdentifier);
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void displayClassChanged(String newClassName) {
|
||||
AlertDialog.Builder changeConfirmedBuilder = new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.class_changed, newClassName))
|
||||
.setMessage(getString(R.string.class_changed_description))
|
||||
.setPositiveButton(getString(R.string.complete_tutorial), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
AlertDialog changeDoneAlert = changeConfirmedBuilder.create();
|
||||
changeDoneAlert.show();
|
||||
}
|
||||
|
||||
private void optOutOfClasses() {
|
||||
shouldFinish = true;
|
||||
this.displayProgressDialog();
|
||||
userRepository.disableClasses().subscribe(this, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
private void selectClass(String selectedClass) {
|
||||
shouldFinish = true;
|
||||
this.displayProgressDialog();
|
||||
userRepository.changeClass(selectedClass).subscribe(this, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
private void displayProgressDialog() {
|
||||
progressDialog = ProgressDialog.show(this, getString(R.string.changing_class_progress), null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(User user) {
|
||||
if (shouldFinish) {
|
||||
if (progressDialog != null) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
setResult(MainActivity.SELECT_CLASS_RESULT);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.View
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.user.*
|
||||
import com.habitrpg.android.habitica.ui.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.functions.Consumer
|
||||
import javax.inject.Inject
|
||||
|
||||
class ClassSelectionActivity : BaseActivity(), Consumer<User> {
|
||||
|
||||
private var currentClass: String? = null
|
||||
private var isInitialSelection: Boolean = false
|
||||
private var classWasUnset: Boolean? = false
|
||||
private var shouldFinish: Boolean? = false
|
||||
|
||||
internal val healerAvatarView: AvatarView by bindView(R.id.healerAvatarView)
|
||||
private val healerWrapper: View by bindView(R.id.healerWrapper)
|
||||
internal val mageAvatarView: AvatarView by bindView(R.id.mageAvatarView)
|
||||
private val mageWrapper: View by bindView(R.id.mageWrapper)
|
||||
internal val rogueAvatarView: AvatarView by bindView(R.id.rogueAvatarView)
|
||||
private val rogueWrapper: View by bindView(R.id.rogueWrapper)
|
||||
internal val warriorAvatarView: AvatarView by bindView(R.id.warriorAvatarView)
|
||||
private val warriorWrapper: View by bindView(R.id.warriorWrapper)
|
||||
private val optOutWrapper: View by bindView(R.id.optOutWrapper)
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
private var progressDialog: ProgressDialog? = null
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_class_selection
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = intent
|
||||
val bundle = intent.extras
|
||||
isInitialSelection = bundle?.getBoolean("isInitialSelection") ?: false
|
||||
currentClass = bundle.getString("currentClass")
|
||||
|
||||
val preferences = Preferences()
|
||||
preferences.setHair(Hair())
|
||||
preferences.costume = false
|
||||
preferences.setSize(bundle.getString("size")!!)
|
||||
preferences.setSkin(bundle.getString("skin")!!)
|
||||
preferences.setShirt(bundle.getString("shirt")!!)
|
||||
preferences.hair?.bangs = bundle.getInt("hairBangs")
|
||||
preferences.hair?.base = bundle.getInt("hairBase")
|
||||
preferences.hair?.color = bundle.getString("hairColor")
|
||||
preferences.hair?.mustache = bundle.getInt("hairMustache")
|
||||
preferences.hair?.beard = bundle.getInt("hairBeard")
|
||||
|
||||
|
||||
val healerOutfit = Outfit()
|
||||
healerOutfit.armor = "armor_healer_5"
|
||||
healerOutfit.head = "head_healer_5"
|
||||
healerOutfit.shield = "shield_healer_5"
|
||||
healerOutfit.weapon = "weapon_healer_6"
|
||||
val healer = this.makeUser(preferences, healerOutfit)
|
||||
healerAvatarView.setAvatar(healer)
|
||||
|
||||
val mageOutfit = Outfit()
|
||||
mageOutfit.armor = "armor_wizard_5"
|
||||
mageOutfit.head = "head_wizard_5"
|
||||
mageOutfit.weapon = "weapon_wizard_6"
|
||||
val mage = this.makeUser(preferences, mageOutfit)
|
||||
mageAvatarView.setAvatar(mage)
|
||||
|
||||
val rogueOutfit = Outfit()
|
||||
rogueOutfit.armor = "armor_rogue_5"
|
||||
rogueOutfit.head = "head_rogue_5"
|
||||
rogueOutfit.shield = "shield_rogue_6"
|
||||
rogueOutfit.weapon = "weapon_rogue_6"
|
||||
val rogue = this.makeUser(preferences, rogueOutfit)
|
||||
rogueAvatarView.setAvatar(rogue)
|
||||
|
||||
val warriorOutfit = Outfit()
|
||||
warriorOutfit.armor = "armor_warrior_5"
|
||||
warriorOutfit.head = "head_warrior_5"
|
||||
warriorOutfit.shield = "shield_warrior_5"
|
||||
warriorOutfit.weapon = "weapon_warrior_6"
|
||||
val warrior = this.makeUser(preferences, warriorOutfit)
|
||||
warriorAvatarView.setAvatar(warrior)
|
||||
|
||||
if (!isInitialSelection) {
|
||||
userRepository.changeClass()
|
||||
.subscribe(Consumer { classWasUnset = true }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
healerWrapper.setOnClickListener { healerSelected() }
|
||||
mageWrapper.setOnClickListener { mageSelected() }
|
||||
rogueWrapper.setOnClickListener { rogueSelected() }
|
||||
warriorWrapper.setOnClickListener { warriorSelected() }
|
||||
optOutWrapper.setOnClickListener { optOutSelected() }
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
private fun makeUser(preferences: Preferences, outfit: Outfit): User {
|
||||
val user = User()
|
||||
user.preferences = preferences
|
||||
user.items = Items()
|
||||
user.items.gear = Gear()
|
||||
user.items.gear.equipped = outfit
|
||||
return user
|
||||
}
|
||||
|
||||
fun healerSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.healer), Stats.HEALER)
|
||||
}
|
||||
|
||||
fun mageSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.mage), Stats.MAGE)
|
||||
}
|
||||
|
||||
fun rogueSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.rogue), Stats.ROGUE)
|
||||
}
|
||||
|
||||
fun warriorSelected() {
|
||||
displayConfirmationDialogForClass(getString(R.string.warrior), Stats.WARRIOR)
|
||||
}
|
||||
|
||||
fun optOutSelected() {
|
||||
if (!this.isInitialSelection && this.classWasUnset == false) {
|
||||
return
|
||||
}
|
||||
val alert = AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.opt_out_confirmation))
|
||||
.setNegativeButton(getString(R.string.dialog_go_back)) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(getString(R.string.opt_out_class)) { _, _ -> optOutOfClasses() }.create()
|
||||
alert.show()
|
||||
}
|
||||
|
||||
private fun displayConfirmationDialogForClass(className: String, classIdentifier: String) {
|
||||
|
||||
if (!this.isInitialSelection && this.classWasUnset == false) {
|
||||
val builder = AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.change_class_confirmation))
|
||||
.setMessage(getString(R.string.change_class_equipment_warning, currentClass))
|
||||
.setNegativeButton(getString(R.string.dialog_go_back)) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(getString(R.string.choose_class)) { _, _ ->
|
||||
selectClass(classIdentifier)
|
||||
displayClassChanged(className)
|
||||
}
|
||||
val alert = builder.create()
|
||||
alert.show()
|
||||
} else {
|
||||
val builder = AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.class_confirmation, className))
|
||||
.setNegativeButton(getString(R.string.dialog_go_back)) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(getString(R.string.choose_class)) { _, _ -> selectClass(classIdentifier) }
|
||||
val alert = builder.create()
|
||||
alert.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayClassChanged(newClassName: String) {
|
||||
val changeConfirmedBuilder = AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.class_changed, newClassName))
|
||||
.setMessage(getString(R.string.class_changed_description))
|
||||
.setPositiveButton(getString(R.string.complete_tutorial)) { dialog, _ -> dialog.dismiss() }
|
||||
val changeDoneAlert = changeConfirmedBuilder.create()
|
||||
changeDoneAlert.show()
|
||||
}
|
||||
|
||||
private fun optOutOfClasses() {
|
||||
shouldFinish = true
|
||||
this.displayProgressDialog()
|
||||
userRepository.disableClasses().subscribe(this, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun selectClass(selectedClass: String) {
|
||||
shouldFinish = true
|
||||
this.displayProgressDialog()
|
||||
userRepository.changeClass(selectedClass).subscribe(this, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun displayProgressDialog() {
|
||||
progressDialog = ProgressDialog.show(this, getString(R.string.changing_class_progress), null, true)
|
||||
}
|
||||
|
||||
override fun accept(user: User) {
|
||||
if (shouldFinish == true) {
|
||||
progressDialog?.dismiss()
|
||||
setResult(MainActivity.SELECT_CLASS_RESULT)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,589 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.AppCompatCheckedTextView;
|
||||
import android.support.v7.widget.AppCompatTextView;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.underscore.U;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository;
|
||||
import com.habitrpg.android.habitica.data.SocialRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.events.TaskTappedEvent;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||
import com.habitrpg.android.habitica.models.social.Group;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.Flowable;
|
||||
|
||||
public class CreateChallengeActivity extends BaseActivity {
|
||||
public static final String CHALLENGE_ID_KEY = "challengeId";
|
||||
|
||||
@BindView(R.id.create_challenge_title_input_layout)
|
||||
TextInputLayout createChallengeTitleInputLayout;
|
||||
|
||||
@BindView(R.id.create_challenge_title)
|
||||
EditText createChallengeTitle;
|
||||
|
||||
@BindView(R.id.create_challenge_description_input_layout)
|
||||
TextInputLayout createChallengeDescriptionInputLayout;
|
||||
|
||||
@BindView(R.id.create_challenge_description)
|
||||
EditText createChallengeDescription;
|
||||
|
||||
@BindView(R.id.create_challenge_prize)
|
||||
EditText createChallengePrize;
|
||||
|
||||
|
||||
@BindView(R.id.create_challenge_tag_input_layout)
|
||||
TextInputLayout createChallengeTagInputLayout;
|
||||
|
||||
@BindView(R.id.create_challenge_tag)
|
||||
EditText createChallengeTag;
|
||||
|
||||
@BindView(R.id.create_challenge_gem_error)
|
||||
TextView createChallengeGemError;
|
||||
|
||||
@BindView(R.id.create_challenge_task_error)
|
||||
TextView createChallengeTaskError;
|
||||
|
||||
@BindView(R.id.challenge_location_spinner)
|
||||
Spinner challengeLocationSpinner;
|
||||
|
||||
@BindView(R.id.challenge_add_gem_btn)
|
||||
Button challengeAddGemBtn;
|
||||
|
||||
@BindView(R.id.challenge_remove_gem_btn)
|
||||
Button challengeRemoveGemBtn;
|
||||
|
||||
@BindView(R.id.create_challenge_task_list)
|
||||
RecyclerView createChallengeTaskList;
|
||||
|
||||
@BindView(R.id.gem_icon)
|
||||
ImageView gemIconView;
|
||||
|
||||
@Inject
|
||||
ChallengeRepository challengeRepository;
|
||||
@Inject
|
||||
SocialRepository socialRepository;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
|
||||
private ChallengeTasksRecyclerViewAdapter challengeTasks;
|
||||
|
||||
private GroupArrayAdapter locationAdapter;
|
||||
private String challengeId;
|
||||
private boolean editMode;
|
||||
|
||||
private HashMap<String, Task> addedTasks = new HashMap<>();
|
||||
private HashMap<String, Task> updatedTasks = new HashMap<>();
|
||||
private HashMap<String, Task> removedTasks = new HashMap<>();
|
||||
|
||||
// Add {*} Items
|
||||
Task addHabit;
|
||||
Task addDaily;
|
||||
Task addTodo;
|
||||
Task addReward;
|
||||
@Nullable
|
||||
private User user;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_create_challenge;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_create_challenge, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean savingInProgress = false;
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_save && !savingInProgress && validateAllFields()) {
|
||||
savingInProgress = true;
|
||||
ProgressDialog dialog = ProgressDialog.show(this, "", "Saving challenge data. Please wait...", true, false);
|
||||
|
||||
Flowable<Challenge> observable;
|
||||
|
||||
if (editMode) {
|
||||
observable = updateChallenge();
|
||||
} else {
|
||||
observable = createChallenge();
|
||||
}
|
||||
|
||||
observable.subscribe(challenge -> {
|
||||
dialog.dismiss();
|
||||
savingInProgress = false;
|
||||
finish();
|
||||
}, throwable -> {
|
||||
dialog.dismiss();
|
||||
savingInProgress = false;
|
||||
RxErrorHandler.reportError(throwable);
|
||||
});
|
||||
} else if(item.getItemId() == android.R.id.home){
|
||||
finish();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private boolean validateAllFields() {
|
||||
ArrayList<String> errorMessages = new ArrayList<>();
|
||||
|
||||
if (getEditTextString(createChallengeTitle).isEmpty()) {
|
||||
String titleEmptyError = getString(R.string.challenge_create_error_title);
|
||||
createChallengeTitleInputLayout.setError(titleEmptyError);
|
||||
errorMessages.add(titleEmptyError);
|
||||
} else {
|
||||
createChallengeTitleInputLayout.setErrorEnabled(false);
|
||||
}
|
||||
|
||||
if (getEditTextString(createChallengeTag).isEmpty()) {
|
||||
String tagEmptyError = getString(R.string.challenge_create_error_tag);
|
||||
|
||||
createChallengeTagInputLayout.setError(tagEmptyError);
|
||||
errorMessages.add(tagEmptyError);
|
||||
} else {
|
||||
createChallengeTagInputLayout.setErrorEnabled(false);
|
||||
}
|
||||
|
||||
String prizeError = checkPrizeAndMinimumForTavern();
|
||||
|
||||
if(!prizeError.isEmpty()){
|
||||
errorMessages.add(prizeError);
|
||||
}
|
||||
|
||||
// all "Add {*}"-Buttons are one task itself, so we need atleast more than 4
|
||||
if (challengeTasks.getTaskList().size() <= 4) {
|
||||
createChallengeTaskError.setVisibility(View.VISIBLE);
|
||||
errorMessages.add(getString(R.string.challenge_create_error_no_tasks));
|
||||
} else {
|
||||
createChallengeTaskError.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setMessage(U.join(errorMessages, "\n"));
|
||||
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
|
||||
return errorMessages.size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
Bundle bundle = intent.getExtras();
|
||||
|
||||
if (bundle != null) {
|
||||
challengeId = bundle.getString(CHALLENGE_ID_KEY, null);
|
||||
}
|
||||
|
||||
fillControls();
|
||||
|
||||
if (challengeId != null) {
|
||||
fillControlsByChallenge();
|
||||
}
|
||||
|
||||
userRepository.getUser(userId).subscribe(user1 -> this.user = user1, RxErrorHandler.handleEmptyError());
|
||||
gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
socialRepository.close();
|
||||
challengeRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(TaskTappedEvent tappedEvent) {
|
||||
openNewTaskActivity(null, tappedEvent.Task);
|
||||
}
|
||||
|
||||
@OnClick(R.id.challenge_add_gem_btn)
|
||||
public void onAddGem() {
|
||||
String stringValue = createChallengePrize.getText().toString();
|
||||
if (stringValue.length() == 0) {
|
||||
stringValue = "0";
|
||||
}
|
||||
int currentVal = Integer.parseInt(stringValue);
|
||||
currentVal++;
|
||||
|
||||
createChallengePrize.setText(String.valueOf(currentVal));
|
||||
|
||||
checkPrizeAndMinimumForTavern();
|
||||
}
|
||||
|
||||
@OnClick(R.id.challenge_remove_gem_btn)
|
||||
public void onRemoveGem() {
|
||||
String stringValue = createChallengePrize.getText().toString();
|
||||
if (stringValue.length() == 0) {
|
||||
stringValue = "0";
|
||||
}
|
||||
int currentVal = Integer.parseInt(stringValue);
|
||||
currentVal--;
|
||||
|
||||
createChallengePrize.setText(String.valueOf(currentVal));
|
||||
|
||||
checkPrizeAndMinimumForTavern();
|
||||
}
|
||||
|
||||
private String checkPrizeAndMinimumForTavern() {
|
||||
String errorResult = "";
|
||||
|
||||
String inputValue = createChallengePrize.getText().toString();
|
||||
|
||||
if (inputValue.isEmpty()) {
|
||||
inputValue = "0";
|
||||
}
|
||||
|
||||
int currentVal = Integer.parseInt(inputValue);
|
||||
|
||||
// 0 is Tavern
|
||||
int selectedLocation = challengeLocationSpinner.getSelectedItemPosition();
|
||||
|
||||
double gemCount = 0;
|
||||
if (user != null) {
|
||||
gemCount = user.getGemCount();
|
||||
}
|
||||
|
||||
if (selectedLocation == 0 && currentVal == 0) {
|
||||
createChallengeGemError.setVisibility(View.VISIBLE);
|
||||
String error = getString(R.string.challenge_create_error_tavern_one_gem);
|
||||
createChallengeGemError.setText(error);
|
||||
errorResult = error;
|
||||
} else if (currentVal > gemCount) {
|
||||
createChallengeGemError.setVisibility(View.VISIBLE);
|
||||
String error = getString(R.string.challenge_create_error_enough_gems);
|
||||
createChallengeGemError.setText(error);
|
||||
errorResult = error;
|
||||
} else {
|
||||
createChallengeGemError.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
challengeRemoveGemBtn.setEnabled(currentVal != 0);
|
||||
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
private void fillControls() {
|
||||
Resources resources = getResources();
|
||||
|
||||
ActionBar supportActionBar = getSupportActionBar();
|
||||
if (supportActionBar != null) {
|
||||
supportActionBar.setDisplayShowHomeEnabled(true);
|
||||
supportActionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
|
||||
|
||||
supportActionBar.setTitle("");
|
||||
supportActionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.brand_200)));
|
||||
supportActionBar.setElevation(0);
|
||||
}
|
||||
|
||||
locationAdapter = new GroupArrayAdapter(this);
|
||||
locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
socialRepository.getGroups("guild").subscribe(groups -> {
|
||||
Group tavern = new Group();
|
||||
tavern.setId("00000000-0000-4000-A000-000000000000");
|
||||
tavern.setName(getString(R.string.sidebar_tavern));
|
||||
|
||||
locationAdapter.add(tavern);
|
||||
|
||||
for (Group group : groups) {
|
||||
locationAdapter.add(group);
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
|
||||
challengeLocationSpinner.setAdapter(locationAdapter);
|
||||
challengeLocationSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
checkPrizeAndMinimumForTavern();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
|
||||
}
|
||||
});
|
||||
createChallengePrize.setOnKeyListener((view, i, keyEvent) -> {
|
||||
checkPrizeAndMinimumForTavern();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
addHabit = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_habit));
|
||||
addDaily = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_daily));
|
||||
addTodo = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_todo));
|
||||
addReward = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_reward));
|
||||
|
||||
|
||||
ArrayList<Task> taskList = new ArrayList<>();
|
||||
taskList.add(addHabit);
|
||||
taskList.add(addDaily);
|
||||
taskList.add(addTodo);
|
||||
taskList.add(addReward);
|
||||
|
||||
challengeTasks = new ChallengeTasksRecyclerViewAdapter(null, 0, this, "", null, false, true);
|
||||
challengeTasks.setTasks(taskList);
|
||||
challengeTasks.addItemObservable().subscribe(t -> {
|
||||
if (t.equals(addHabit)) {
|
||||
openNewTaskActivity(Task.TYPE_HABIT, null);
|
||||
} else if (t.equals(addDaily)) {
|
||||
openNewTaskActivity(Task.TYPE_DAILY, null);
|
||||
} else if (t.equals(addTodo)) {
|
||||
openNewTaskActivity(Task.TYPE_TODO, null);
|
||||
} else if (t.equals(addReward)) {
|
||||
openNewTaskActivity(Task.TYPE_REWARD, null);
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
|
||||
createChallengeTaskList.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
// Stop only scrolling.
|
||||
return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
|
||||
}
|
||||
});
|
||||
createChallengeTaskList.setAdapter(challengeTasks);
|
||||
createChallengeTaskList.setLayoutManager(new LinearLayoutManager(this));
|
||||
}
|
||||
|
||||
private static Task createTask(String taskType, String taskName) {
|
||||
Task t = new Task();
|
||||
|
||||
t.setId(UUID.randomUUID().toString());
|
||||
t.setType(taskType);
|
||||
t.setText(taskName);
|
||||
|
||||
if (taskType.equals(Task.TYPE_HABIT)) {
|
||||
t.setUp(true);
|
||||
t.setDown(false);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
private void fillControlsByChallenge() {
|
||||
challengeRepository.getChallenge(challengeId).subscribe(challenge -> {
|
||||
|
||||
createChallengeTitle.setText(challenge.name);
|
||||
createChallengeDescription.setText(challenge.description);
|
||||
createChallengeTag.setText(challenge.shortName);
|
||||
createChallengePrize.setText(String.valueOf(challenge.prize));
|
||||
|
||||
for (int i = 0; i < locationAdapter.getCount(); i++) {
|
||||
Group group = locationAdapter.getItem(i);
|
||||
|
||||
if (group != null && challenge.groupId.equals(group.getId())) {
|
||||
challengeLocationSpinner.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
checkPrizeAndMinimumForTavern();
|
||||
|
||||
challengeRepository.getChallengeTasks(challengeId).subscribe(tasks -> {
|
||||
for (Task task : tasks.tasks.values()) {
|
||||
addOrUpdateTaskInList(task);
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError(), () -> {
|
||||
// activate editMode to track taskChanges
|
||||
editMode = true;
|
||||
});
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
private void openNewTaskActivity(String type, Task task) {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
if (task == null) {
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type);
|
||||
} else {
|
||||
bundle.putParcelable(TaskFormActivity.PARCELABLE_TASK, task);
|
||||
}
|
||||
|
||||
bundle.putBoolean(TaskFormActivity.SAVE_TO_DB, false);
|
||||
bundle.putBoolean(TaskFormActivity.SET_IGNORE_FLAG, true);
|
||||
bundle.putBoolean(TaskFormActivity.SHOW_TAG_SELECTION, false);
|
||||
bundle.putBoolean(TaskFormActivity.SHOW_CHECKLIST, false);
|
||||
|
||||
if (user != null && user.getPreferences() != null) {
|
||||
boolean allocationMode = user.getPreferences().hasTaskBasedAllocation();
|
||||
|
||||
bundle.putString(TaskFormActivity.USER_ID_KEY, user.getId());
|
||||
bundle.putBoolean(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(this, TaskFormActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
|
||||
startActivityForResult(intent, 1);
|
||||
}
|
||||
|
||||
private Challenge getChallengeData() {
|
||||
Challenge c = new Challenge();
|
||||
|
||||
int locationPos = challengeLocationSpinner.getSelectedItemPosition();
|
||||
Group locationGroup = locationAdapter.getItem(locationPos);
|
||||
|
||||
if (challengeId != null) {
|
||||
c.id = challengeId;
|
||||
}
|
||||
|
||||
if (locationGroup != null) {
|
||||
c.groupId = locationGroup.getId();
|
||||
}
|
||||
c.name = createChallengeTitle.getText().toString();
|
||||
c.description = createChallengeDescription.getText().toString();
|
||||
c.shortName = createChallengeTag.getText().toString();
|
||||
c.prize = Integer.parseInt(createChallengePrize.getText().toString());
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private Flowable<Challenge> createChallenge() {
|
||||
Challenge c = getChallengeData();
|
||||
|
||||
List<Task> taskList = challengeTasks.getTaskList();
|
||||
taskList.remove(addHabit);
|
||||
taskList.remove(addDaily);
|
||||
taskList.remove(addTodo);
|
||||
taskList.remove(addReward);
|
||||
|
||||
return challengeRepository.createChallenge(c, taskList);
|
||||
}
|
||||
|
||||
private Flowable<Challenge> updateChallenge() {
|
||||
Challenge c = getChallengeData();
|
||||
|
||||
List<Task> taskList = challengeTasks.getTaskList();
|
||||
taskList.remove(addHabit);
|
||||
taskList.remove(addDaily);
|
||||
taskList.remove(addTodo);
|
||||
taskList.remove(addReward);
|
||||
|
||||
return challengeRepository.updateChallenge(c, taskList, new ArrayList<>(addedTasks.values()),
|
||||
new ArrayList<>(updatedTasks.values()),
|
||||
new ArrayList<>(removedTasks.keySet())
|
||||
);
|
||||
}
|
||||
|
||||
private void addOrUpdateTaskInList(Task task) {
|
||||
if (!challengeTasks.replaceTask(task)) {
|
||||
Task taskAbove;
|
||||
|
||||
switch (task.getType()) {
|
||||
case Task.TYPE_HABIT:
|
||||
taskAbove = addHabit;
|
||||
break;
|
||||
case Task.TYPE_DAILY:
|
||||
taskAbove = addDaily;
|
||||
break;
|
||||
case Task.TYPE_TODO:
|
||||
taskAbove = addTodo;
|
||||
break;
|
||||
default:
|
||||
taskAbove = addReward;
|
||||
break;
|
||||
}
|
||||
|
||||
challengeTasks.addTaskUnder(task, taskAbove);
|
||||
|
||||
if (editMode) {
|
||||
addedTasks.put(task.getId(), task);
|
||||
}
|
||||
} else {
|
||||
// don't need to add the task to updatedTasks if its already been added right now
|
||||
if (editMode && !addedTasks.containsKey(task.getId())) {
|
||||
updatedTasks.put(task.getId(), task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getEditTextString(EditText editText) {
|
||||
return editText.getText().toString();
|
||||
}
|
||||
|
||||
private class GroupArrayAdapter extends ArrayAdapter<Group> {
|
||||
GroupArrayAdapter(@NonNull Context context) {
|
||||
super(context, android.R.layout.simple_spinner_item);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
AppCompatTextView checkedTextView = (AppCompatTextView) super.getView(position, convertView, parent);
|
||||
checkedTextView.setText(getItem(position).getName());
|
||||
return checkedTextView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
AppCompatCheckedTextView checkedTextView = (AppCompatCheckedTextView) super.getDropDownView(position, convertView, parent);
|
||||
checkedTextView.setText(getItem(position).getName());
|
||||
return checkedTextView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,500 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TextInputLayout
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.widget.AppCompatCheckedTextView
|
||||
import android.support.v7.widget.AppCompatTextView
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
import com.github.underscore.U
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.events.TaskTappedEvent
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.functions.Consumer
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class CreateChallengeActivity : BaseActivity() {
|
||||
|
||||
private val createChallengeTitleInputLayout: TextInputLayout by bindView(R.id.create_challenge_title_input_layout)
|
||||
private val createChallengeTitle: EditText by bindView(R.id.create_challenge_title)
|
||||
private val createChallengeDescription: EditText by bindView(R.id.create_challenge_description)
|
||||
private val createChallengePrize: EditText by bindView(R.id.create_challenge_prize)
|
||||
private val createChallengeTagInputLayout: TextInputLayout by bindView(R.id.create_challenge_tag_input_layout)
|
||||
private val createChallengeTag: EditText by bindView(R.id.create_challenge_tag)
|
||||
private val createChallengeGemError: TextView by bindView(R.id.create_challenge_gem_error)
|
||||
private val createChallengeTaskError: TextView by bindView(R.id.create_challenge_task_error)
|
||||
private val challengeLocationSpinner: Spinner by bindView(R.id.challenge_location_spinner)
|
||||
private val challengeAddGemBtn: Button by bindView(R.id.challenge_add_gem_btn)
|
||||
private val challengeRemoveGemBtn: Button by bindView(R.id.challenge_remove_gem_btn)
|
||||
private val createChallengeTaskList: RecyclerView by bindView(R.id.create_challenge_task_list)
|
||||
private val gemIconView: ImageView by bindView(R.id.gem_icon)
|
||||
|
||||
@Inject
|
||||
internal lateinit var challengeRepository: ChallengeRepository
|
||||
@Inject
|
||||
internal lateinit var socialRepository: SocialRepository
|
||||
@Inject
|
||||
internal lateinit var userRepository: UserRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
internal lateinit var userId: String
|
||||
|
||||
private var challengeTasks = ChallengeTasksRecyclerViewAdapter(null, 0, this, "", null, false, true)
|
||||
|
||||
private var locationAdapter = GroupArrayAdapter(this)
|
||||
private var challengeId: String? = null
|
||||
private var editMode: Boolean = false
|
||||
|
||||
private val addedTasks = HashMap<String, Task>()
|
||||
private val updatedTasks = HashMap<String, Task>()
|
||||
private val removedTasks = HashMap<String, Task>()
|
||||
|
||||
// Add {*} Items
|
||||
private var addHabit: Task? = null
|
||||
private var addDaily: Task? = null
|
||||
private var addTodo: Task? = null
|
||||
private var addReward: Task? = null
|
||||
private var user: User? = null
|
||||
|
||||
private var savingInProgress = false
|
||||
|
||||
private val challengeData: Challenge
|
||||
get() {
|
||||
val c = Challenge()
|
||||
|
||||
val locationPos = challengeLocationSpinner.selectedItemPosition
|
||||
val locationGroup = locationAdapter.getItem(locationPos)
|
||||
|
||||
if (challengeId != null) {
|
||||
c.id = challengeId
|
||||
}
|
||||
|
||||
if (locationGroup != null) {
|
||||
c.groupId = locationGroup.id
|
||||
}
|
||||
c.name = createChallengeTitle.text.toString()
|
||||
c.description = createChallengeDescription.text.toString()
|
||||
c.shortName = createChallengeTag.text.toString()
|
||||
c.prize = Integer.parseInt(createChallengePrize.text.toString())
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_create_challenge
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
val inflater = menuInflater
|
||||
inflater.inflate(R.menu.menu_create_challenge, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == R.id.action_save && !savingInProgress && validateAllFields()) {
|
||||
savingInProgress = true
|
||||
val dialog = ProgressDialog.show(this, "", "Saving challenge data. Please wait...", true, false)
|
||||
|
||||
val observable: Flowable<Challenge> = if (editMode) {
|
||||
updateChallenge()
|
||||
} else {
|
||||
createChallenge()
|
||||
}
|
||||
|
||||
observable.subscribe({
|
||||
dialog.dismiss()
|
||||
savingInProgress = false
|
||||
finish()
|
||||
}, { throwable ->
|
||||
dialog.dismiss()
|
||||
savingInProgress = false
|
||||
RxErrorHandler.reportError(throwable)
|
||||
})
|
||||
} else if (item.itemId == android.R.id.home) {
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun validateAllFields(): Boolean {
|
||||
val errorMessages = ArrayList<String>()
|
||||
|
||||
if (getEditTextString(createChallengeTitle).isEmpty()) {
|
||||
val titleEmptyError = getString(R.string.challenge_create_error_title)
|
||||
createChallengeTitleInputLayout.error = titleEmptyError
|
||||
errorMessages.add(titleEmptyError)
|
||||
} else {
|
||||
createChallengeTitleInputLayout.isErrorEnabled = false
|
||||
}
|
||||
|
||||
if (getEditTextString(createChallengeTag).isEmpty()) {
|
||||
val tagEmptyError = getString(R.string.challenge_create_error_tag)
|
||||
|
||||
createChallengeTagInputLayout.error = tagEmptyError
|
||||
errorMessages.add(tagEmptyError)
|
||||
} else {
|
||||
createChallengeTagInputLayout.isErrorEnabled = false
|
||||
}
|
||||
|
||||
val prizeError = checkPrizeAndMinimumForTavern()
|
||||
|
||||
if (!prizeError.isEmpty()) {
|
||||
errorMessages.add(prizeError)
|
||||
}
|
||||
|
||||
// all "Add {*}"-Buttons are one task itself, so we need atleast more than 4
|
||||
if (challengeTasks.taskList?.size ?: 0 <= 4) {
|
||||
createChallengeTaskError.visibility = View.VISIBLE
|
||||
errorMessages.add(getString(R.string.challenge_create_error_no_tasks))
|
||||
} else {
|
||||
createChallengeTaskError.visibility = View.GONE
|
||||
}
|
||||
|
||||
val builder = AlertDialog.Builder(this)
|
||||
.setMessage(U.join(errorMessages, "\n"))
|
||||
|
||||
val alert = builder.create()
|
||||
alert.show()
|
||||
|
||||
return errorMessages.size == 0
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = intent
|
||||
val bundle = intent.extras
|
||||
|
||||
if (bundle != null) {
|
||||
challengeId = bundle.getString(CHALLENGE_ID_KEY, null)
|
||||
}
|
||||
|
||||
fillControls()
|
||||
|
||||
if (challengeId != null) {
|
||||
fillControlsByChallenge()
|
||||
}
|
||||
|
||||
userRepository.getUser(userId).subscribe(Consumer { this.user = it }, RxErrorHandler.handleEmptyError())
|
||||
gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem())
|
||||
|
||||
challengeAddGemBtn.setOnClickListener { onAddGem() }
|
||||
challengeRemoveGemBtn.setOnClickListener { onRemoveGem() }
|
||||
}
|
||||
|
||||
|
||||
public override fun onDestroy() {
|
||||
socialRepository.close()
|
||||
challengeRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(tappedEvent: TaskTappedEvent) {
|
||||
openNewTaskActivity(null, tappedEvent.Task)
|
||||
}
|
||||
|
||||
fun onAddGem() {
|
||||
var stringValue = createChallengePrize.text.toString()
|
||||
if (stringValue.isEmpty()) {
|
||||
stringValue = "0"
|
||||
}
|
||||
var currentVal = Integer.parseInt(stringValue)
|
||||
currentVal++
|
||||
|
||||
createChallengePrize.setText(currentVal.toString())
|
||||
|
||||
checkPrizeAndMinimumForTavern()
|
||||
}
|
||||
|
||||
fun onRemoveGem() {
|
||||
var stringValue = createChallengePrize.text.toString()
|
||||
if (stringValue.isEmpty()) {
|
||||
stringValue = "0"
|
||||
}
|
||||
var currentVal = Integer.parseInt(stringValue)
|
||||
currentVal--
|
||||
|
||||
createChallengePrize.setText(currentVal.toString())
|
||||
|
||||
checkPrizeAndMinimumForTavern()
|
||||
}
|
||||
|
||||
private fun checkPrizeAndMinimumForTavern(): String {
|
||||
var errorResult = ""
|
||||
|
||||
var inputValue = createChallengePrize.text.toString()
|
||||
|
||||
if (inputValue.isEmpty()) {
|
||||
inputValue = "0"
|
||||
}
|
||||
|
||||
val currentVal = Integer.parseInt(inputValue)
|
||||
|
||||
// 0 is Tavern
|
||||
val selectedLocation = challengeLocationSpinner.selectedItemPosition
|
||||
|
||||
val gemCount = user?.gemCount?.toDouble() ?: 0.toDouble()
|
||||
|
||||
if (selectedLocation == 0 && currentVal == 0) {
|
||||
createChallengeGemError.visibility = View.VISIBLE
|
||||
val error = getString(R.string.challenge_create_error_tavern_one_gem)
|
||||
createChallengeGemError.text = error
|
||||
errorResult = error
|
||||
} else if (currentVal > gemCount) {
|
||||
createChallengeGemError.visibility = View.VISIBLE
|
||||
val error = getString(R.string.challenge_create_error_enough_gems)
|
||||
createChallengeGemError.text = error
|
||||
errorResult = error
|
||||
} else {
|
||||
createChallengeGemError.visibility = View.GONE
|
||||
}
|
||||
|
||||
challengeRemoveGemBtn.isEnabled = currentVal != 0
|
||||
|
||||
return errorResult
|
||||
}
|
||||
|
||||
private fun fillControls() {
|
||||
val resources = resources
|
||||
|
||||
val supportActionBar = supportActionBar
|
||||
if (supportActionBar != null) {
|
||||
supportActionBar.setDisplayShowHomeEnabled(true)
|
||||
supportActionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp)
|
||||
|
||||
supportActionBar.title = ""
|
||||
supportActionBar.setBackgroundDrawable(ColorDrawable(ContextCompat.getColor(this, R.color.brand_200)))
|
||||
supportActionBar.elevation = 0f
|
||||
}
|
||||
|
||||
locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
socialRepository.getGroups("guild").subscribe(Consumer { groups ->
|
||||
val tavern = Group()
|
||||
tavern.id = "00000000-0000-4000-A000-000000000000"
|
||||
tavern.name = getString(R.string.sidebar_tavern)
|
||||
|
||||
locationAdapter.add(tavern)
|
||||
|
||||
for (group in groups) {
|
||||
locationAdapter.add(group)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
||||
challengeLocationSpinner.adapter = locationAdapter
|
||||
challengeLocationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) {
|
||||
checkPrizeAndMinimumForTavern()
|
||||
}
|
||||
|
||||
override fun onNothingSelected(adapterView: AdapterView<*>) {
|
||||
|
||||
}
|
||||
}
|
||||
createChallengePrize.setOnKeyListener { _, _, _ ->
|
||||
checkPrizeAndMinimumForTavern()
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
addHabit = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_habit))
|
||||
addDaily = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_daily))
|
||||
addTodo = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_todo))
|
||||
addReward = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_reward))
|
||||
|
||||
|
||||
val taskList = ArrayList<Task>()
|
||||
addHabit.notNull { taskList.add(it) }
|
||||
addDaily.notNull { taskList.add(it) }
|
||||
addTodo.notNull { taskList.add(it) }
|
||||
addReward.notNull { taskList.add(it) }
|
||||
|
||||
challengeTasks.setTasks(taskList)
|
||||
challengeTasks.addItemObservable().subscribe(Consumer { t ->
|
||||
when (t) {
|
||||
addHabit -> openNewTaskActivity(Task.TYPE_HABIT, null)
|
||||
addDaily -> openNewTaskActivity(Task.TYPE_DAILY, null)
|
||||
addTodo -> openNewTaskActivity(Task.TYPE_TODO, null)
|
||||
addReward -> openNewTaskActivity(Task.TYPE_REWARD, null)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
||||
createChallengeTaskList.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
|
||||
override fun onInterceptTouchEvent(rv: RecyclerView?, e: MotionEvent?): Boolean {
|
||||
// Stop only scrolling.
|
||||
return rv?.scrollState == RecyclerView.SCROLL_STATE_DRAGGING
|
||||
}
|
||||
})
|
||||
createChallengeTaskList.adapter = challengeTasks
|
||||
createChallengeTaskList.layoutManager = LinearLayoutManager(this)
|
||||
}
|
||||
|
||||
private fun fillControlsByChallenge() {
|
||||
challengeRepository.getChallenge(challengeId).subscribe(Consumer { challenge ->
|
||||
|
||||
createChallengeTitle.setText(challenge.name)
|
||||
createChallengeDescription.setText(challenge.description)
|
||||
createChallengeTag.setText(challenge.shortName)
|
||||
createChallengePrize.setText(challenge.prize.toString())
|
||||
|
||||
for (i in 0 until locationAdapter.count) {
|
||||
val group = locationAdapter.getItem(i)
|
||||
|
||||
if (group != null && challenge.groupId == group.id) {
|
||||
challengeLocationSpinner.setSelection(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
checkPrizeAndMinimumForTavern()
|
||||
|
||||
challengeRepository.getChallengeTasks(challengeId).doOnComplete { editMode = true }.subscribe(Consumer { tasks ->
|
||||
for (task in tasks.tasks.values) {
|
||||
addOrUpdateTaskInList(task)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun openNewTaskActivity(type: String?, task: Task?) {
|
||||
val bundle = Bundle()
|
||||
|
||||
if (task == null) {
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type)
|
||||
} else {
|
||||
bundle.putParcelable(TaskFormActivity.PARCELABLE_TASK, task)
|
||||
}
|
||||
|
||||
bundle.putBoolean(TaskFormActivity.SAVE_TO_DB, false)
|
||||
bundle.putBoolean(TaskFormActivity.SET_IGNORE_FLAG, true)
|
||||
bundle.putBoolean(TaskFormActivity.SHOW_TAG_SELECTION, false)
|
||||
bundle.putBoolean(TaskFormActivity.SHOW_CHECKLIST, false)
|
||||
|
||||
val allocationMode = user?.preferences?.hasTaskBasedAllocation()
|
||||
|
||||
bundle.putString(TaskFormActivity.USER_ID_KEY, user?.id)
|
||||
bundle.putBoolean(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode ?: false)
|
||||
|
||||
val intent = Intent(this, TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
|
||||
startActivityForResult(intent, 1)
|
||||
}
|
||||
|
||||
private fun createChallenge(): Flowable<Challenge> {
|
||||
val c = challengeData
|
||||
|
||||
val taskList = challengeTasks.taskList
|
||||
taskList.remove(addHabit)
|
||||
taskList.remove(addDaily)
|
||||
taskList.remove(addTodo)
|
||||
taskList.remove(addReward)
|
||||
|
||||
return challengeRepository.createChallenge(c, taskList)
|
||||
}
|
||||
|
||||
private fun updateChallenge(): Flowable<Challenge> {
|
||||
val c = challengeData
|
||||
|
||||
val taskList = challengeTasks.taskList
|
||||
taskList.remove(addHabit)
|
||||
taskList.remove(addDaily)
|
||||
taskList.remove(addTodo)
|
||||
taskList.remove(addReward)
|
||||
|
||||
return challengeRepository.updateChallenge(c, taskList, ArrayList(addedTasks.values),
|
||||
ArrayList(updatedTasks.values),
|
||||
ArrayList(removedTasks.keys)
|
||||
)
|
||||
}
|
||||
|
||||
private fun addOrUpdateTaskInList(task: Task) {
|
||||
if (!challengeTasks.replaceTask(task)) {
|
||||
val taskAbove: Task? = when (task.type) {
|
||||
Task.TYPE_HABIT -> addHabit
|
||||
Task.TYPE_DAILY -> addDaily
|
||||
Task.TYPE_TODO -> addTodo
|
||||
else -> addReward
|
||||
}
|
||||
|
||||
challengeTasks.addTaskUnder(task, taskAbove)
|
||||
|
||||
if (editMode) {
|
||||
addedTasks[task.id ?: ""] = task
|
||||
}
|
||||
} else {
|
||||
// don't need to add the task to updatedTasks if its already been added right now
|
||||
if (editMode && !addedTasks.containsKey(task.id)) {
|
||||
updatedTasks[task.id ?: ""] = task
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEditTextString(editText: EditText): String {
|
||||
return editText.text.toString()
|
||||
}
|
||||
|
||||
private inner class GroupArrayAdapter internal constructor(context: Context) : ArrayAdapter<Group>(context, android.R.layout.simple_spinner_item) {
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val checkedTextView = super.getView(position, convertView, parent) as AppCompatTextView
|
||||
checkedTextView.text = getItem(position).name
|
||||
return checkedTextView
|
||||
}
|
||||
|
||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val checkedTextView = super.getDropDownView(position, convertView, parent) as AppCompatCheckedTextView
|
||||
checkedTextView.text = getItem(position).name
|
||||
return checkedTextView
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CHALLENGE_ID_KEY = "challengeId"
|
||||
|
||||
private fun createTask(taskType: String, taskName: String): Task {
|
||||
val t = Task()
|
||||
|
||||
t.id = UUID.randomUUID().toString()
|
||||
t.type = taskType
|
||||
t.text = taskName
|
||||
|
||||
if (taskType == Task.TYPE_HABIT) {
|
||||
t.up = true
|
||||
t.down = false
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,506 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.AppCompatImageView;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.controller.BaseControllerListener;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.facebook.imagepipeline.image.ImageInfo;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository;
|
||||
import com.habitrpg.android.habitica.data.SocialRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.helpers.UserStatComputer;
|
||||
import com.habitrpg.android.habitica.models.Achievement;
|
||||
import com.habitrpg.android.habitica.models.AchievementGroup;
|
||||
import com.habitrpg.android.habitica.models.AchievementResult;
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment;
|
||||
import com.habitrpg.android.habitica.models.members.Member;
|
||||
import com.habitrpg.android.habitica.models.user.Buffs;
|
||||
import com.habitrpg.android.habitica.models.user.Outfit;
|
||||
import com.habitrpg.android.habitica.models.user.Profile;
|
||||
import com.habitrpg.android.habitica.models.user.Stats;
|
||||
import com.habitrpg.android.habitica.ui.AvatarView;
|
||||
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.AchievementAdapter;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
|
||||
import com.habitrpg.android.habitica.ui.helpers.UiUtils;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar;
|
||||
|
||||
import net.pherth.android.emoji_library.EmojiEditText;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import io.reactivex.Flowable;
|
||||
import io.realm.RealmResults;
|
||||
|
||||
import static com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType;
|
||||
|
||||
public class FullProfileActivity extends BaseActivity {
|
||||
@Inject
|
||||
InventoryRepository inventoryRepository;
|
||||
@Inject
|
||||
ApiClient apiClient;
|
||||
@Inject
|
||||
SocialRepository socialRepository;
|
||||
@BindView(R.id.profile_image)
|
||||
SimpleDraweeView profile_image;
|
||||
@BindView(R.id.profile_blurb)
|
||||
TextView blurbTextView;
|
||||
@BindView(R.id.avatarView)
|
||||
AvatarView avatarView;
|
||||
@BindView(R.id.copy_userid)
|
||||
Button copyUserIdButton;
|
||||
@BindView(R.id.userid)
|
||||
TextView userIdText;
|
||||
@BindView(R.id.profile_attributes_card)
|
||||
CardView attributesCardView;
|
||||
@BindView(R.id.attributes_table)
|
||||
TableLayout attributesTableLayout;
|
||||
@BindView(R.id.attributes_collapse_icon)
|
||||
AppCompatImageView attributesCollapseIcon;
|
||||
@BindView(R.id.equipment_table)
|
||||
TableLayout equipmentTableLayout;
|
||||
@BindView(R.id.costume_table)
|
||||
TableLayout costumeTableLayout;
|
||||
@BindView(R.id.profile_costume_card)
|
||||
CardView costumeCard;
|
||||
@BindView(R.id.avatar_with_bars)
|
||||
View avatar_with_bars;
|
||||
@BindView(R.id.fullprofile_scrollview)
|
||||
ScrollView fullprofile_scrollview;
|
||||
@BindView(R.id.profile_pets_found_count)
|
||||
TextView petsFoundCount;
|
||||
@BindView(R.id.profile_mounts_tamed_count)
|
||||
TextView mountsTamedCount;
|
||||
@BindView(R.id.profile_achievements_card)
|
||||
CardView achievementCard;
|
||||
@BindView(R.id.avatar_achievements_progress)
|
||||
ProgressBar achievementProgress;
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView achievementGroupList;
|
||||
private String userId;
|
||||
private String userName;
|
||||
private AvatarWithBarsViewModel avatarWithBars;
|
||||
private float attributeStrSum = 0;
|
||||
private float attributeIntSum = 0;
|
||||
private float attributeConSum = 0;
|
||||
private float attributePerSum = 0;
|
||||
private boolean attributeDetailsHidden = true;
|
||||
private ArrayList<TableRow> attributeRows = new ArrayList<>();
|
||||
|
||||
public static void open(Context context, String userId) {
|
||||
if (userId.equals("system")) {
|
||||
return;
|
||||
}
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("userId", userId);
|
||||
|
||||
Intent intent = new Intent(context, FullProfileActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
Bundle bundle = intent.getExtras();
|
||||
this.userId = bundle.getString("userId");
|
||||
|
||||
setTitle(R.string.profile_loading_data);
|
||||
|
||||
socialRepository.getMember(this.userId).subscribe(this::updateView, RxErrorHandler.handleEmptyError());
|
||||
|
||||
avatarWithBars = new AvatarWithBarsViewModel(this, avatar_with_bars);
|
||||
avatarWithBars.valueBarLabelsToBlack();
|
||||
|
||||
avatar_with_bars.setBackgroundColor(ContextCompat.getColor(this, R.color.transparent));
|
||||
|
||||
attributeRows.clear();
|
||||
attributesCardView.setOnClickListener(view -> toggleAttributeDetails());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
inventoryRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if (id == R.id.private_message) {
|
||||
showSendMessageToUserDialog();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == android.R.id.home) {
|
||||
// app icon in action bar clicked; goto parent activity.
|
||||
this.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void showSendMessageToUserDialog() {
|
||||
LayoutInflater factory = LayoutInflater.from(this);
|
||||
final View newMessageView = factory.inflate(R.layout.profile_new_message_dialog, null);
|
||||
|
||||
EmojiEditText emojiEditText = (EmojiEditText) newMessageView.findViewById(R.id.edit_new_message_text);
|
||||
|
||||
TextView newMessageTitle = (TextView) newMessageView.findViewById(R.id.new_message_title);
|
||||
newMessageTitle.setText(String.format(getString(R.string.profile_send_message_to), userName));
|
||||
|
||||
final AlertDialog addMessageDialog = new AlertDialog.Builder(this)
|
||||
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||
socialRepository.postPrivateMessage(userId, emojiEditText.getText().toString())
|
||||
.subscribe(postChatMessageResult -> HabiticaSnackbar.Companion.showSnackbar((ViewGroup) FullProfileActivity.this.fullprofile_scrollview.getChildAt(0),
|
||||
String.format(getString(R.string.profile_message_sent_to), userName), SnackbarDisplayType.NORMAL), RxErrorHandler.handleEmptyError());
|
||||
|
||||
UiUtils.dismissKeyboard(this);
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> UiUtils.dismissKeyboard(this))
|
||||
|
||||
.create();
|
||||
|
||||
addMessageDialog.setView(newMessageView);
|
||||
|
||||
addMessageDialog.show();
|
||||
}
|
||||
|
||||
private void updateView(Member user) {
|
||||
Profile profile = user.getProfile();
|
||||
Stats stats = user.getStats();
|
||||
|
||||
userName = profile.getName();
|
||||
|
||||
setTitle(profile.getName());
|
||||
|
||||
String imageUrl = profile.getImageUrl();
|
||||
if (imageUrl == null || imageUrl.isEmpty()) {
|
||||
profile_image.setVisibility(View.GONE);
|
||||
} else {
|
||||
profile_image.setController(Fresco.newDraweeControllerBuilder()
|
||||
.setUri(imageUrl)
|
||||
.setControllerListener(new BaseControllerListener<ImageInfo>() {
|
||||
@Override
|
||||
public void onFailure(String id, Throwable throwable) {
|
||||
profile_image.setVisibility(View.GONE);
|
||||
}
|
||||
})
|
||||
.build());
|
||||
}
|
||||
|
||||
String blurbText = profile.getBlurb();
|
||||
if (blurbText != null && !blurbText.isEmpty()) {
|
||||
blurbTextView.setText(MarkdownParser.INSTANCE.parseMarkdown(blurbText));
|
||||
}
|
||||
userIdText.setText(userId);
|
||||
copyUserIdButton.setVisibility(View.VISIBLE);
|
||||
copyUserIdButton.setOnClickListener(view -> {
|
||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) view.getContext()
|
||||
.getSystemService(CLIPBOARD_SERVICE);
|
||||
android.content.ClipData clip = android.content.ClipData.newPlainText(userId, userId);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
});
|
||||
|
||||
|
||||
avatarView.setAvatar(user);
|
||||
avatarWithBars.updateData(user);
|
||||
|
||||
loadItemDataByOutfit(user.getEquipped()).subscribe(gear -> this.gotGear(gear, user), RxErrorHandler.handleEmptyError());
|
||||
|
||||
if (user.getPreferences().getCostume()) {
|
||||
loadItemDataByOutfit(user.getCostume()).subscribe(this::gotCostume, RxErrorHandler.handleEmptyError());
|
||||
} else {
|
||||
costumeCard.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//petsFoundCount.setText(String.valueOf(user.getPetsFoundCount()));
|
||||
//mountsTamedCount.setText(String.valueOf(user.getMountsTamedCount()));
|
||||
|
||||
// Load the members achievements now
|
||||
socialRepository.getMemberAchievements(this.userId).subscribe(this::fillAchievements, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Attributes
|
||||
|
||||
private void fillAchievements(AchievementResult achievements) {
|
||||
if (achievements == null) {
|
||||
return;
|
||||
}
|
||||
List<Object> items = new ArrayList<>();
|
||||
|
||||
fillAchievements(achievements.basic, items);
|
||||
fillAchievements(achievements.seasonal, items);
|
||||
fillAchievements(achievements.special, items);
|
||||
|
||||
AchievementAdapter adapter = new AchievementAdapter();
|
||||
adapter.setItemList(items);
|
||||
|
||||
GridLayoutManager layoutManager = new GridLayoutManager(this, 3);
|
||||
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
|
||||
@Override
|
||||
public int getSpanSize(int position) {
|
||||
if (adapter.getItemViewType(position) == 0) {
|
||||
return layoutManager.getSpanCount();
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
achievementGroupList.setLayoutManager(layoutManager);
|
||||
achievementGroupList.setAdapter(adapter);
|
||||
|
||||
stopAndHideProgress(achievementProgress);
|
||||
}
|
||||
|
||||
private void fillAchievements(AchievementGroup achievementGroup, List<Object> targetList) {
|
||||
// Order by ID first
|
||||
ArrayList<Achievement> achievementList = new ArrayList<>(achievementGroup.achievements.values());
|
||||
Collections.sort(achievementList, (achievement, t1) -> Double.compare(achievement.index, t1.index));
|
||||
|
||||
targetList.add(achievementGroup.label);
|
||||
targetList.addAll(achievementList);
|
||||
}
|
||||
|
||||
private void stopAndHideProgress(ProgressBar bar) {
|
||||
bar.setIndeterminate(false);
|
||||
bar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private String getFloorValueString(float val, boolean roundDown) {
|
||||
if (roundDown) {
|
||||
return String.valueOf(Math.floor(val));
|
||||
} else {
|
||||
if (val == 0.0) {
|
||||
return "0";
|
||||
} else {
|
||||
return String.valueOf(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float getFloorValue(float val, boolean roundDown) {
|
||||
return roundDown
|
||||
? ((int) Math.floor(val))
|
||||
: val;
|
||||
}
|
||||
|
||||
private TableRow addEquipmentRow(TableLayout table, String gearKey, String text, String stats) {
|
||||
TableRow gearRow = (TableRow) getLayoutInflater().inflate(R.layout.profile_gear_tablerow, table, false);
|
||||
|
||||
SimpleDraweeView draweeView = (SimpleDraweeView) gearRow.findViewById(R.id.gear_drawee);
|
||||
|
||||
draweeView.setController(Fresco.newDraweeControllerBuilder()
|
||||
.setUri(AvatarView.IMAGE_URI_ROOT + "shop_" + gearKey + ".png")
|
||||
.setControllerListener(new BaseControllerListener<ImageInfo>() {
|
||||
@Override
|
||||
public void onFailure(String id, Throwable throwable) {
|
||||
draweeView.setVisibility(View.GONE);
|
||||
}
|
||||
})
|
||||
.build());
|
||||
|
||||
TextView keyTextView = (TextView) gearRow.findViewById(R.id.tableRowTextView1);
|
||||
keyTextView.setText(text);
|
||||
|
||||
TextView valueTextView = (TextView) gearRow.findViewById(R.id.tableRowTextView2);
|
||||
|
||||
if (!stats.isEmpty()) {
|
||||
valueTextView.setText(stats);
|
||||
} else {
|
||||
valueTextView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
table.addView(gearRow);
|
||||
|
||||
return gearRow;
|
||||
}
|
||||
|
||||
private void addLevelAttributes(Member user) {
|
||||
float byLevelStat = Math.min(user.getStats().getLvl() / 2.0f, 50f);
|
||||
|
||||
addAttributeRow(getString(R.string.profile_level), byLevelStat, byLevelStat, byLevelStat, byLevelStat, true, false);
|
||||
}
|
||||
|
||||
private Flowable<RealmResults<Equipment>> loadItemDataByOutfit(Outfit outfit) {
|
||||
ArrayList<String> outfitList = new ArrayList<>();
|
||||
outfitList.add(outfit.getArmor());
|
||||
outfitList.add(outfit.getBack());
|
||||
outfitList.add(outfit.getBody());
|
||||
outfitList.add(outfit.getEyeWear());
|
||||
outfitList.add(outfit.getHead());
|
||||
outfitList.add(outfit.getHeadAccessory());
|
||||
outfitList.add(outfit.getShield());
|
||||
outfitList.add(outfit.getWeapon());
|
||||
|
||||
return inventoryRepository.getItems(outfitList);
|
||||
}
|
||||
|
||||
public void gotGear(List<Equipment> equipmentList, Member user) {
|
||||
UserStatComputer userStatComputer = new UserStatComputer();
|
||||
List<UserStatComputer.StatsRow> statsRows = userStatComputer.computeClassBonus(equipmentList, user);
|
||||
|
||||
equipmentTableLayout.removeAllViews();
|
||||
for (int index = 1 ; index < attributesTableLayout.getChildCount() ; index++) {
|
||||
attributesTableLayout.removeViewAt(index);
|
||||
}
|
||||
|
||||
addLevelAttributes(user);
|
||||
|
||||
for (UserStatComputer.StatsRow row : statsRows) {
|
||||
if (row.getClass().equals(UserStatComputer.EquipmentRow.class)) {
|
||||
UserStatComputer.EquipmentRow equipmentRow = (UserStatComputer.EquipmentRow) row;
|
||||
addEquipmentRow(equipmentTableLayout, equipmentRow.gearKey, equipmentRow.text, equipmentRow.stats);
|
||||
} else if (row.getClass().equals(UserStatComputer.AttributeRow.class)) {
|
||||
UserStatComputer.AttributeRow attributeRow2 = (UserStatComputer.AttributeRow) row;
|
||||
addAttributeRow(getString(attributeRow2.labelId), attributeRow2.strVal, attributeRow2.intVal, attributeRow2.conVal, attributeRow2.perVal, attributeRow2.roundDown, attributeRow2.isSummary);
|
||||
}
|
||||
}
|
||||
|
||||
addNormalAddBuffAttributes(user.getStats());
|
||||
}
|
||||
|
||||
public void gotCostume(List<Equipment> obj) {
|
||||
// fill costume table
|
||||
costumeTableLayout.removeAllViews();
|
||||
for (Equipment i : obj) {
|
||||
addEquipmentRow(costumeTableLayout, i.getKey(), i.getText(), "");
|
||||
}
|
||||
}
|
||||
|
||||
private void addNormalAddBuffAttributes(Stats stats) {
|
||||
Buffs buffs = stats.getBuffs();
|
||||
|
||||
addAttributeRow(getString(R.string.profile_allocated), stats.getStr(), stats.get_int(), stats.getCon(), stats.getPer(), true, false);
|
||||
addAttributeRow(getString(R.string.profile_boosts), buffs.getStr(), buffs.get_int(), buffs.getCon(), buffs.getPer(), true, false);
|
||||
|
||||
// Summary row
|
||||
addAttributeRow("", attributeStrSum, attributeIntSum, attributeConSum, attributePerSum, false, true);
|
||||
}
|
||||
|
||||
private TableRow addAttributeRow(String label, float strVal, float intVal, float conVal, float perVal, boolean roundDown, boolean isSummary) {
|
||||
TableRow tableRow = (TableRow) getLayoutInflater().inflate(R.layout.profile_attributetablerow, attributesTableLayout, false);
|
||||
TextView keyTextView = (TextView) tableRow.findViewById(R.id.tv_attribute_type);
|
||||
keyTextView.setText(label);
|
||||
|
||||
TextView strTextView = (TextView) tableRow.findViewById(R.id.tv_attribute_str);
|
||||
strTextView.setText(getFloorValueString(strVal, roundDown));
|
||||
|
||||
TextView intTextView = (TextView) tableRow.findViewById(R.id.tv_attribute_int);
|
||||
intTextView.setText(getFloorValueString(intVal, roundDown));
|
||||
|
||||
TextView conTextView = (TextView) tableRow.findViewById(R.id.tv_attribute_con);
|
||||
conTextView.setText(getFloorValueString(conVal, roundDown));
|
||||
|
||||
TextView perTextView = (TextView) tableRow.findViewById(R.id.tv_attribute_per);
|
||||
perTextView.setText(getFloorValueString(perVal, roundDown));
|
||||
|
||||
|
||||
if (isSummary) {
|
||||
strTextView.setTypeface(null, Typeface.BOLD);
|
||||
intTextView.setTypeface(null, Typeface.BOLD);
|
||||
conTextView.setTypeface(null, Typeface.BOLD);
|
||||
perTextView.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
attributeStrSum += getFloorValue(strVal, roundDown);
|
||||
attributeIntSum += getFloorValue(intVal, roundDown);
|
||||
attributeConSum += getFloorValue(conVal, roundDown);
|
||||
attributePerSum += getFloorValue(perVal, roundDown);
|
||||
|
||||
attributeRows.add(tableRow);
|
||||
tableRow.setVisibility(attributeDetailsHidden ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
attributesTableLayout.addView(tableRow);
|
||||
|
||||
return tableRow;
|
||||
}
|
||||
|
||||
private void toggleAttributeDetails() {
|
||||
attributeDetailsHidden = !attributeDetailsHidden;
|
||||
|
||||
attributesCollapseIcon.setImageDrawable(ContextCompat.getDrawable(this, attributeDetailsHidden
|
||||
? R.drawable.ic_keyboard_arrow_right_black_24dp
|
||||
: R.drawable.ic_keyboard_arrow_down_black_24dp));
|
||||
|
||||
for (TableRow row : attributeRows) {
|
||||
row.setVisibility(attributeDetailsHidden ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// endregion
|
||||
|
||||
// region Navigation
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
finish();
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region BaseActivity-Overrides
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_full_profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_full_profile, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,465 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.widget.AppCompatImageView
|
||||
import android.support.v7.widget.CardView
|
||||
import android.support.v7.widget.GridLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.drawee.controller.BaseControllerListener
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.UserStatComputer
|
||||
import com.habitrpg.android.habitica.models.AchievementGroup
|
||||
import com.habitrpg.android.habitica.models.AchievementResult
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.models.user.Outfit
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.ui.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.AchievementAdapter
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.UiUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.functions.Consumer
|
||||
import io.realm.RealmResults
|
||||
import net.pherth.android.emoji_library.EmojiEditText
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class FullProfileActivity : BaseActivity() {
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
|
||||
private val profileImage: SimpleDraweeView by bindView(R.id.profile_image)
|
||||
private val blurbTextView: TextView by bindView(R.id.profile_blurb)
|
||||
private val avatarView: AvatarView by bindView(R.id.avatarView)
|
||||
private val copyUserIdButton: Button by bindView(R.id.copy_userid)
|
||||
private val userIdText: TextView by bindView(R.id.userid)
|
||||
private val attributesCardView: CardView by bindView(R.id.profile_attributes_card)
|
||||
private val attributesTableLayout: TableLayout by bindView(R.id.attributes_table)
|
||||
private val attributesCollapseIcon: AppCompatImageView by bindView(R.id.attributes_collapse_icon)
|
||||
private val equipmentTableLayout: TableLayout by bindView(R.id.equipment_table)
|
||||
private val costumeTableLayout: TableLayout by bindView(R.id.costume_table)
|
||||
private val costumeCard: CardView by bindView(R.id.profile_costume_card)
|
||||
private val avatar_with_bars: View by bindView(R.id.avatar_with_bars)
|
||||
private val fullprofile_scrollview: ScrollView by bindView(R.id.fullprofile_scrollview)
|
||||
private val petsFoundCount: TextView by bindView(R.id.profile_pets_found_count)
|
||||
private val mountsTamedCount: TextView by bindView(R.id.profile_mounts_tamed_count)
|
||||
private val achievementCard: CardView by bindView(R.id.profile_achievements_card)
|
||||
private val achievementProgress: ProgressBar by bindView(R.id.avatar_achievements_progress)
|
||||
private val achievementGroupList: RecyclerView by bindView(R.id.recyclerView)
|
||||
|
||||
private var userId = ""
|
||||
private var userName: String? = null
|
||||
private var avatarWithBars = AvatarWithBarsViewModel(this, avatar_with_bars)
|
||||
private var attributeStrSum = 0f
|
||||
private var attributeIntSum = 0f
|
||||
private var attributeConSum = 0f
|
||||
private var attributePerSum = 0f
|
||||
private var attributeDetailsHidden = true
|
||||
private val attributeRows = ArrayList<TableRow>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = intent
|
||||
val bundle = intent.extras
|
||||
this.userId = bundle?.getString("userId") ?: ""
|
||||
|
||||
setTitle(R.string.profile_loading_data)
|
||||
|
||||
socialRepository.getMember(this.userId).subscribe(Consumer { this.updateView(it) }, RxErrorHandler.handleEmptyError())
|
||||
|
||||
avatarWithBars.valueBarLabelsToBlack()
|
||||
|
||||
avatar_with_bars.setBackgroundColor(ContextCompat.getColor(this, R.color.transparent))
|
||||
|
||||
attributeRows.clear()
|
||||
attributesCardView.setOnClickListener { toggleAttributeDetails() }
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
inventoryRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val id = item.itemId
|
||||
|
||||
if (id == R.id.private_message) {
|
||||
showSendMessageToUserDialog()
|
||||
return true
|
||||
}
|
||||
|
||||
if (id == android.R.id.home) {
|
||||
// app icon in action bar clicked; goto parent activity.
|
||||
this.finish()
|
||||
return true
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun showSendMessageToUserDialog() {
|
||||
val factory = LayoutInflater.from(this)
|
||||
val newMessageView = factory.inflate(R.layout.profile_new_message_dialog, null)
|
||||
|
||||
val emojiEditText = newMessageView.findViewById<EmojiEditText>(R.id.edit_new_message_text)
|
||||
|
||||
val newMessageTitle = newMessageView.findViewById<TextView>(R.id.new_message_title)
|
||||
newMessageTitle.text = String.format(getString(R.string.profile_send_message_to), userName)
|
||||
|
||||
val addMessageDialog = AlertDialog.Builder(this)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
socialRepository.postPrivateMessage(userId, emojiEditText.text.toString())
|
||||
.subscribe(Consumer {
|
||||
HabiticaSnackbar.showSnackbar(this@FullProfileActivity.fullprofile_scrollview.getChildAt(0) as ViewGroup,
|
||||
String.format(getString(R.string.profile_message_sent_to), userName), SnackbarDisplayType.NORMAL)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
||||
UiUtils.dismissKeyboard(this)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> UiUtils.dismissKeyboard(this) }
|
||||
|
||||
.create()
|
||||
|
||||
addMessageDialog.setView(newMessageView)
|
||||
|
||||
addMessageDialog.show()
|
||||
}
|
||||
|
||||
private fun updateView(user: Member) {
|
||||
val profile = user.profile
|
||||
|
||||
userName = profile.name
|
||||
|
||||
title = profile.name
|
||||
|
||||
val imageUrl = profile.imageUrl
|
||||
if (imageUrl == null || imageUrl.isEmpty()) {
|
||||
profileImage.visibility = View.GONE
|
||||
} else {
|
||||
profileImage.controller = Fresco.newDraweeControllerBuilder()
|
||||
.setUri(imageUrl)
|
||||
.setControllerListener(object : BaseControllerListener<ImageInfo>() {
|
||||
override fun onFailure(id: String?, throwable: Throwable?) {
|
||||
profileImage.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
val blurbText = profile.blurb
|
||||
if (blurbText != null && !blurbText.isEmpty()) {
|
||||
blurbTextView.text = MarkdownParser.parseMarkdown(blurbText)
|
||||
}
|
||||
userIdText.text = userId
|
||||
copyUserIdButton.visibility = View.VISIBLE
|
||||
copyUserIdButton.setOnClickListener { view ->
|
||||
val clipboard = view.context
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
|
||||
val clip = android.content.ClipData.newPlainText(userId, userId)
|
||||
clipboard.primaryClip = clip
|
||||
}
|
||||
|
||||
|
||||
avatarView.setAvatar(user)
|
||||
avatarWithBars.updateData(user)
|
||||
|
||||
loadItemDataByOutfit(user.equipped).subscribe(Consumer { gear -> this.gotGear(gear, user) }, RxErrorHandler.handleEmptyError())
|
||||
|
||||
if (user.preferences.costume) {
|
||||
loadItemDataByOutfit(user.costume).subscribe(Consumer<RealmResults<Equipment>> { this.gotCostume(it) }, RxErrorHandler.handleEmptyError())
|
||||
} else {
|
||||
costumeCard.visibility = View.GONE
|
||||
}
|
||||
|
||||
//petsFoundCount.setText(String.valueOf(user.getPetsFoundCount()));
|
||||
//mountsTamedCount.setText(String.valueOf(user.getMountsTamedCount()));
|
||||
|
||||
// Load the members achievements now
|
||||
socialRepository.getMemberAchievements(this.userId).subscribe(Consumer<AchievementResult> { this.fillAchievements(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Attributes
|
||||
|
||||
private fun fillAchievements(achievements: AchievementResult?) {
|
||||
if (achievements == null) {
|
||||
return
|
||||
}
|
||||
val items = ArrayList<Any>()
|
||||
|
||||
fillAchievements(achievements.basic, items)
|
||||
fillAchievements(achievements.seasonal, items)
|
||||
fillAchievements(achievements.special, items)
|
||||
|
||||
val adapter = AchievementAdapter()
|
||||
adapter.setItemList(items)
|
||||
|
||||
val layoutManager = GridLayoutManager(this, 3)
|
||||
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (adapter.getItemViewType(position) == 0) {
|
||||
layoutManager.spanCount
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
achievementGroupList.layoutManager = layoutManager
|
||||
achievementGroupList.adapter = adapter
|
||||
|
||||
stopAndHideProgress(achievementProgress)
|
||||
}
|
||||
|
||||
private fun fillAchievements(achievementGroup: AchievementGroup, targetList: MutableList<Any>) {
|
||||
// Order by ID first
|
||||
val achievementList = ArrayList(achievementGroup.achievements.values)
|
||||
achievementList.sortWith(Comparator { achievement, t1 -> java.lang.Double.compare(achievement.index.toDouble(), t1.index.toDouble()) })
|
||||
|
||||
targetList.add(achievementGroup.label)
|
||||
targetList.addAll(achievementList)
|
||||
}
|
||||
|
||||
private fun stopAndHideProgress(bar: ProgressBar) {
|
||||
bar.isIndeterminate = false
|
||||
bar.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun getFloorValueString(`val`: Float, roundDown: Boolean): String {
|
||||
return if (roundDown) {
|
||||
Math.floor(`val`.toDouble()).toString()
|
||||
} else {
|
||||
if (`val`.toDouble() == 0.0) {
|
||||
"0"
|
||||
} else {
|
||||
`val`.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFloorValue(value: Float, roundDown: Boolean): Float {
|
||||
return if (roundDown) {
|
||||
Math.floor(value.toDouble()).toFloat()
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEquipmentRow(table: TableLayout, gearKey: String?, text: String, stats: String) {
|
||||
val gearRow = layoutInflater.inflate(R.layout.profile_gear_tablerow, table, false) as TableRow
|
||||
|
||||
val draweeView = gearRow.findViewById<SimpleDraweeView>(R.id.gear_drawee)
|
||||
|
||||
draweeView.controller = Fresco.newDraweeControllerBuilder()
|
||||
.setUri(AvatarView.IMAGE_URI_ROOT + "shop_" + gearKey + ".png")
|
||||
.setControllerListener(object : BaseControllerListener<ImageInfo>() {
|
||||
override fun onFailure(id: String?, throwable: Throwable?) {
|
||||
draweeView.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
.build()
|
||||
|
||||
val keyTextView = gearRow.findViewById<TextView>(R.id.tableRowTextView1)
|
||||
keyTextView.text = text
|
||||
|
||||
val valueTextView = gearRow.findViewById<TextView>(R.id.tableRowTextView2)
|
||||
|
||||
if (!stats.isEmpty()) {
|
||||
valueTextView.text = stats
|
||||
} else {
|
||||
valueTextView.visibility = View.GONE
|
||||
}
|
||||
|
||||
table.addView(gearRow)
|
||||
|
||||
}
|
||||
|
||||
private fun addLevelAttributes(user: Member) {
|
||||
val byLevelStat = Math.min(user.stats.getLvl() / 2.0f, 50f)
|
||||
|
||||
addAttributeRow(getString(R.string.profile_level), byLevelStat, byLevelStat, byLevelStat, byLevelStat, true, false)
|
||||
}
|
||||
|
||||
private fun loadItemDataByOutfit(outfit: Outfit?): Flowable<RealmResults<Equipment>> {
|
||||
val outfitList = ArrayList<String>()
|
||||
if (outfit != null) {
|
||||
outfitList.add(outfit.armor)
|
||||
outfitList.add(outfit.back)
|
||||
outfitList.add(outfit.body)
|
||||
outfitList.add(outfit.eyeWear)
|
||||
outfitList.add(outfit.head)
|
||||
outfitList.add(outfit.headAccessory)
|
||||
outfitList.add(outfit.shield)
|
||||
outfitList.add(outfit.weapon)
|
||||
}
|
||||
return inventoryRepository.getItems(outfitList)
|
||||
}
|
||||
|
||||
private fun gotGear(equipmentList: List<Equipment>, user: Member) {
|
||||
val userStatComputer = UserStatComputer()
|
||||
val statsRows = userStatComputer.computeClassBonus(equipmentList, user)
|
||||
|
||||
equipmentTableLayout.removeAllViews()
|
||||
for (index in 1 until attributesTableLayout.childCount) {
|
||||
attributesTableLayout.removeViewAt(index)
|
||||
}
|
||||
|
||||
addLevelAttributes(user)
|
||||
|
||||
for (row in statsRows) {
|
||||
if (row.javaClass == UserStatComputer.EquipmentRow::class.java) {
|
||||
val equipmentRow = row as UserStatComputer.EquipmentRow
|
||||
addEquipmentRow(equipmentTableLayout, equipmentRow.gearKey, equipmentRow.text, equipmentRow.stats)
|
||||
} else if (row.javaClass == UserStatComputer.AttributeRow::class.java) {
|
||||
val attributeRow2 = row as UserStatComputer.AttributeRow
|
||||
addAttributeRow(getString(attributeRow2.labelId), attributeRow2.strVal, attributeRow2.intVal, attributeRow2.conVal, attributeRow2.perVal, attributeRow2.roundDown, attributeRow2.isSummary)
|
||||
}
|
||||
}
|
||||
|
||||
addNormalAddBuffAttributes(user.stats)
|
||||
}
|
||||
|
||||
private fun gotCostume(obj: List<Equipment>) {
|
||||
// fill costume table
|
||||
costumeTableLayout.removeAllViews()
|
||||
for (i in obj) {
|
||||
addEquipmentRow(costumeTableLayout, i.key, i.text, "")
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNormalAddBuffAttributes(stats: Stats) {
|
||||
val buffs = stats.getBuffs()
|
||||
|
||||
addAttributeRow(getString(R.string.profile_allocated), stats.getStr().toFloat(), stats.get_int().toFloat(), stats.getCon().toFloat(), stats.getPer().toFloat(), true, false)
|
||||
addAttributeRow(getString(R.string.profile_boosts), buffs.getStr(), buffs.get_int(), buffs.getCon(), buffs.getPer(), true, false)
|
||||
|
||||
// Summary row
|
||||
addAttributeRow("", attributeStrSum, attributeIntSum, attributeConSum, attributePerSum, false, true)
|
||||
}
|
||||
|
||||
private fun addAttributeRow(label: String, strVal: Float, intVal: Float, conVal: Float, perVal: Float, roundDown: Boolean, isSummary: Boolean) {
|
||||
val tableRow = layoutInflater.inflate(R.layout.profile_attributetablerow, attributesTableLayout, false) as TableRow
|
||||
val keyTextView = tableRow.findViewById<TextView>(R.id.tv_attribute_type)
|
||||
keyTextView.text = label
|
||||
|
||||
val strTextView = tableRow.findViewById<TextView>(R.id.tv_attribute_str)
|
||||
strTextView.text = getFloorValueString(strVal, roundDown)
|
||||
|
||||
val intTextView = tableRow.findViewById<TextView>(R.id.tv_attribute_int)
|
||||
intTextView.text = getFloorValueString(intVal, roundDown)
|
||||
|
||||
val conTextView = tableRow.findViewById<TextView>(R.id.tv_attribute_con)
|
||||
conTextView.text = getFloorValueString(conVal, roundDown)
|
||||
|
||||
val perTextView = tableRow.findViewById<TextView>(R.id.tv_attribute_per)
|
||||
perTextView.text = getFloorValueString(perVal, roundDown)
|
||||
|
||||
|
||||
if (isSummary) {
|
||||
strTextView.setTypeface(null, Typeface.BOLD)
|
||||
intTextView.setTypeface(null, Typeface.BOLD)
|
||||
conTextView.setTypeface(null, Typeface.BOLD)
|
||||
perTextView.setTypeface(null, Typeface.BOLD)
|
||||
} else {
|
||||
attributeStrSum += getFloorValue(strVal, roundDown)
|
||||
attributeIntSum += getFloorValue(intVal, roundDown)
|
||||
attributeConSum += getFloorValue(conVal, roundDown)
|
||||
attributePerSum += getFloorValue(perVal, roundDown)
|
||||
|
||||
attributeRows.add(tableRow)
|
||||
tableRow.visibility = if (attributeDetailsHidden) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
attributesTableLayout.addView(tableRow)
|
||||
|
||||
}
|
||||
|
||||
private fun toggleAttributeDetails() {
|
||||
attributeDetailsHidden = !attributeDetailsHidden
|
||||
|
||||
attributesCollapseIcon.setImageDrawable(ContextCompat.getDrawable(this, if (attributeDetailsHidden)
|
||||
R.drawable.ic_keyboard_arrow_right_black_24dp
|
||||
else
|
||||
R.drawable.ic_keyboard_arrow_down_black_24dp))
|
||||
|
||||
for (row in attributeRows) {
|
||||
row.visibility = if (attributeDetailsHidden) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// endregion
|
||||
|
||||
// region Navigation
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finish()
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region BaseActivity-Overrides
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_full_profile
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_full_profile, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun open(context: Context, userId: String) {
|
||||
if (userId == "system") {
|
||||
return
|
||||
}
|
||||
val bundle = Bundle()
|
||||
bundle.putString("userId", userId)
|
||||
|
||||
val intent = Intent(context, FullProfileActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
|
|
@ -1,300 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
|
||||
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy;
|
||||
import com.habitrpg.android.habitica.ui.fragments.GemsPurchaseFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.SubscriptionFragment;
|
||||
import com.playseeds.android.sdk.Seeds;
|
||||
import com.playseeds.android.sdk.inappmessaging.InAppMessageListener;
|
||||
|
||||
import org.solovyev.android.checkout.ActivityCheckout;
|
||||
import org.solovyev.android.checkout.BillingRequests;
|
||||
import org.solovyev.android.checkout.Checkout;
|
||||
import org.solovyev.android.checkout.ProductTypes;
|
||||
import org.solovyev.android.checkout.Purchase;
|
||||
import org.solovyev.android.checkout.Purchases;
|
||||
import org.solovyev.android.checkout.RequestListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class GemPurchaseActivity extends BaseActivity implements InAppMessageListener {
|
||||
|
||||
@Inject
|
||||
CrashlyticsProxy crashlyticsProxy;
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.viewPager)
|
||||
ViewPager viewPager;
|
||||
List<CheckoutFragment> fragments = new ArrayList<>();
|
||||
private ActivityCheckout checkout;
|
||||
private BillingRequests billingRequests;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_gem_purchase;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
checkout.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setupCheckout();
|
||||
|
||||
Seeds.sharedInstance()
|
||||
.simpleInit(this, this, "https://dash.playseeds.com", getString(R.string.seeds_app_key))
|
||||
.setLoggingEnabled(true);
|
||||
Seeds.sharedInstance().requestInAppMessage(getString(R.string.seeds_interstitial_gems));
|
||||
Seeds.sharedInstance().requestInAppMessage(getString(R.string.seeds_interstitial_sharing));
|
||||
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setTitle(R.string.gem_purchase_toolbartitle);
|
||||
}
|
||||
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
setViewPagerAdapter();
|
||||
|
||||
checkout.destroyPurchaseFlow();
|
||||
|
||||
checkout.createPurchaseFlow(new RequestListener<Purchase>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Purchase purchase) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Object o) {
|
||||
//EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
|
||||
if (purchase.sku.equals(PurchaseTypes.Purchase84Gems)) {
|
||||
GemPurchaseActivity.this.showSeedsPromo(getString(R.string.seeds_interstitial_sharing), "store");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Consume", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Error", e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
checkout.whenReady(new Checkout.Listener() {
|
||||
@Override
|
||||
public void onReady(@NonNull final BillingRequests billingRequests) {
|
||||
GemPurchaseActivity.this.billingRequests = billingRequests;
|
||||
|
||||
for (CheckoutFragment fragment : fragments) {
|
||||
fragment.setBillingRequests(billingRequests);
|
||||
}
|
||||
|
||||
checkIfPendingPurchases();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady(@NonNull BillingRequests billingRequests, @NonNull String s, boolean b) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (checkout != null) {
|
||||
checkout.stop();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void setupCheckout() {
|
||||
checkout = Checkout.forActivity(this, HabiticaApplication.getInstance(this).getBilling());
|
||||
checkout.start();
|
||||
}
|
||||
|
||||
public ActivityCheckout getActivityCheckout() {
|
||||
return checkout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inAppMessageClicked(String messageId) {
|
||||
for (CheckoutFragment fragment : fragments) {
|
||||
if (fragment.getClass().isAssignableFrom(GemsPurchaseFragment.class)) {
|
||||
((GemsPurchaseFragment)fragment).purchaseGems(PurchaseTypes.Purchase84Gems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inAppMessageDismissed(String messageId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inAppMessageLoadSucceeded(String messageId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inAppMessageShown(String messageId, boolean succeeded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noInAppMessageFound(String messageId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inAppMessageClickedWithDynamicPrice(String messageId, Double price) {
|
||||
|
||||
}
|
||||
|
||||
public void showSeedsPromo(final String messageId, final String context) {
|
||||
try {
|
||||
runOnUiThread(() -> {
|
||||
if (Seeds.sharedInstance().isInAppMessageLoaded(messageId)) {
|
||||
Seeds.sharedInstance().showInAppMessage(messageId, context);
|
||||
} else {
|
||||
// Skip the interstitial showing this time and try to reload the interstitial
|
||||
Seeds.sharedInstance().requestInAppMessage(messageId);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
CheckoutFragment fragment;
|
||||
if (position == 0) {
|
||||
fragment = new GemsPurchaseFragment();
|
||||
} else {
|
||||
fragment = new SubscriptionFragment();
|
||||
}
|
||||
if (fragments.size() > position) {
|
||||
fragments.set(position, fragment);
|
||||
} else {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
fragment.setListener(GemPurchaseActivity.this);
|
||||
fragment.setupCheckout();
|
||||
if (billingRequests != null) {
|
||||
fragment.setBillingRequests(billingRequests);
|
||||
}
|
||||
return (Fragment) fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getString(R.string.gems);
|
||||
case 1:
|
||||
return getString(R.string.subscriptions);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfPendingPurchases() {
|
||||
billingRequests.getAllPurchases(ProductTypes.IN_APP, new RequestListener<Purchases>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Purchases purchases) {
|
||||
for (Purchase purchase : purchases.list) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Object o) {
|
||||
//EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Consume", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "getAllPurchases", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface CheckoutFragment {
|
||||
|
||||
void setupCheckout();
|
||||
|
||||
void setListener(GemPurchaseActivity listener);
|
||||
|
||||
void setBillingRequests(BillingRequests billingRequests);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.MenuItem
|
||||
import com.habitrpg.android.habitica.HabiticaApplication
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes
|
||||
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
|
||||
import com.habitrpg.android.habitica.ui.fragments.GemsPurchaseFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.SubscriptionFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.playseeds.android.sdk.Seeds
|
||||
import com.playseeds.android.sdk.inappmessaging.InAppMessageListener
|
||||
import org.solovyev.android.checkout.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
|
||||
|
||||
@Inject
|
||||
lateinit var crashlyticsProxy: CrashlyticsProxy
|
||||
|
||||
internal val tabLayout: TabLayout by bindView(R.id.tab_layout)
|
||||
internal val viewPager: ViewPager by bindView(R.id.viewPager)
|
||||
|
||||
internal var fragments: MutableList<CheckoutFragment> = ArrayList()
|
||||
var activityCheckout: ActivityCheckout? = null
|
||||
private set
|
||||
private var billingRequests: BillingRequests? = null
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_gem_purchase
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
activityCheckout?.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setupCheckout()
|
||||
|
||||
Seeds.sharedInstance()
|
||||
.simpleInit(this, this, "https://dash.playseeds.com", getString(R.string.seeds_app_key)).isLoggingEnabled = true
|
||||
Seeds.sharedInstance().requestInAppMessage(getString(R.string.seeds_interstitial_gems))
|
||||
Seeds.sharedInstance().requestInAppMessage(getString(R.string.seeds_interstitial_sharing))
|
||||
|
||||
val toolbar = findViewById<Toolbar>(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
supportActionBar?.setTitle(R.string.gem_purchase_toolbartitle)
|
||||
|
||||
viewPager.currentItem = 0
|
||||
|
||||
setViewPagerAdapter()
|
||||
|
||||
activityCheckout?.destroyPurchaseFlow()
|
||||
|
||||
activityCheckout?.createPurchaseFlow(object : RequestListener<Purchase> {
|
||||
override fun onSuccess(purchase: Purchase) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
|
||||
override fun onSuccess(o: Any) {
|
||||
//EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
|
||||
if (purchase.sku == PurchaseTypes.Purchase84Gems) {
|
||||
this@GemPurchaseActivity.showSeedsPromo(getString(R.string.seeds_interstitial_sharing), "store")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Consume", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Error", e)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
activityCheckout?.whenReady(object : Checkout.Listener {
|
||||
override fun onReady(billingRequests: BillingRequests) {
|
||||
this@GemPurchaseActivity.billingRequests = billingRequests
|
||||
|
||||
for (fragment in fragments) {
|
||||
fragment.setBillingRequests(billingRequests)
|
||||
}
|
||||
|
||||
checkIfPendingPurchases()
|
||||
}
|
||||
|
||||
override fun onReady(billingRequests: BillingRequests, s: String, b: Boolean) {}
|
||||
})
|
||||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
activityCheckout?.stop()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
finish()
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun setupCheckout() {
|
||||
HabiticaBaseApplication.getInstance(this).billing.notNull {
|
||||
activityCheckout = Checkout.forActivity(this, it)
|
||||
activityCheckout?.start()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun inAppMessageClicked(messageId: String) {
|
||||
for (fragment in fragments) {
|
||||
if (fragment.javaClass.isAssignableFrom(GemsPurchaseFragment::class.java)) {
|
||||
(fragment as GemsPurchaseFragment).purchaseGems(PurchaseTypes.Purchase84Gems)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun inAppMessageDismissed(messageId: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun inAppMessageLoadSucceeded(messageId: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun inAppMessageShown(messageId: String, succeeded: Boolean) {
|
||||
|
||||
}
|
||||
|
||||
override fun noInAppMessageFound(messageId: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun inAppMessageClickedWithDynamicPrice(messageId: String, price: Double?) {
|
||||
|
||||
}
|
||||
|
||||
fun showSeedsPromo(messageId: String, context: String) {
|
||||
try {
|
||||
runOnUiThread {
|
||||
if (Seeds.sharedInstance().isInAppMessageLoaded(messageId)) {
|
||||
Seeds.sharedInstance().showInAppMessage(messageId, context)
|
||||
} else {
|
||||
// Skip the interstitial showing this time and try to reload the interstitial
|
||||
Seeds.sharedInstance().requestInAppMessage(messageId)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("Exception: $e")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = supportFragmentManager
|
||||
|
||||
viewPager.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val fragment: CheckoutFragment = if (position == 0) {
|
||||
GemsPurchaseFragment()
|
||||
} else {
|
||||
SubscriptionFragment()
|
||||
}
|
||||
if (fragments.size > position) {
|
||||
fragments[position] = fragment
|
||||
} else {
|
||||
fragments.add(fragment)
|
||||
}
|
||||
fragment.setListener(this@GemPurchaseActivity)
|
||||
fragment.setupCheckout()
|
||||
if (billingRequests != null) {
|
||||
fragment.setBillingRequests(billingRequests)
|
||||
}
|
||||
return fragment as Fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
when (position) {
|
||||
0 -> return getString(R.string.gems)
|
||||
1 -> return getString(R.string.subscriptions)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
tabLayout.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
private fun checkIfPendingPurchases() {
|
||||
billingRequests?.getAllPurchases(ProductTypes.IN_APP, object : RequestListener<Purchases> {
|
||||
override fun onSuccess(purchases: Purchases) {
|
||||
for (purchase in purchases.list) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
|
||||
override fun onSuccess(o: Any) {
|
||||
//EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Consume", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "getAllPurchases", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
interface CheckoutFragment {
|
||||
|
||||
fun setupCheckout()
|
||||
|
||||
fun setListener(listener: GemPurchaseActivity)
|
||||
|
||||
fun setBillingRequests(billingRequests: BillingRequests?)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
|
||||
import com.habitrpg.android.habitica.ui.helpers.UiUtils;
|
||||
|
||||
import net.pherth.android.emoji_library.EmojiEditText;
|
||||
import net.pherth.android.emoji_library.EmojiPopup;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class GroupFormActivity extends BaseActivity {
|
||||
|
||||
public static final int GROUP_FORM_ACTIVITY = 11;
|
||||
|
||||
String groupID;
|
||||
String groupName;
|
||||
String groupDescription;
|
||||
String groupPrivacy;
|
||||
String groupLeader;
|
||||
|
||||
@BindView(R.id.group_name_edittext)
|
||||
EditText groupNameEditText;
|
||||
|
||||
@BindView(R.id.group_description_edittext)
|
||||
EmojiEditText groupDescriptionEditText;
|
||||
|
||||
@BindView(R.id.emoji_toggle_btn)
|
||||
ImageButton emojiButton;
|
||||
|
||||
@BindView(R.id.privacyWrapper)
|
||||
LinearLayout privacyWrapper;
|
||||
|
||||
@BindView(R.id.privacySpinner)
|
||||
Spinner privacySpinner;
|
||||
|
||||
EmojiPopup popup;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_group_form;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
Bundle bundle = intent.getExtras();
|
||||
this.groupID = bundle.getString("groupID");
|
||||
this.groupName = bundle.getString("name");
|
||||
this.groupDescription = bundle.getString("description");
|
||||
this.groupPrivacy = bundle.getString("privacy");
|
||||
this.groupLeader = bundle.getString("leader");
|
||||
|
||||
// Emoji keyboard stuff
|
||||
|
||||
popup = new EmojiPopup(emojiButton.getRootView(), this, ContextCompat.getColor(this, R.color.brand));
|
||||
|
||||
popup.setSizeForSoftKeyboard();
|
||||
popup.setOnDismissListener(() -> changeEmojiKeyboardIcon(false));
|
||||
popup.setOnSoftKeyboardOpenCloseListener(new EmojiPopup.OnSoftKeyboardOpenCloseListener() {
|
||||
|
||||
@Override
|
||||
public void onKeyboardOpen(int keyBoardHeight) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardClose() {
|
||||
if (popup.isShowing())
|
||||
popup.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
popup.setOnEmojiconClickedListener(emojicon -> {
|
||||
EmojiEditText emojiEditText = null;
|
||||
if (getCurrentFocus() == null || !isEmojiEditText(getCurrentFocus()) || emojicon == null) {
|
||||
return;
|
||||
} else {
|
||||
emojiEditText = (EmojiEditText) getCurrentFocus();
|
||||
}
|
||||
int start = emojiEditText.getSelectionStart();
|
||||
int end = emojiEditText.getSelectionEnd();
|
||||
if (start < 0) {
|
||||
emojiEditText.append(emojicon.getEmoji());
|
||||
} else {
|
||||
emojiEditText.getText().replace(Math.min(start, end),
|
||||
Math.max(start, end), emojicon.getEmoji(), 0,
|
||||
emojicon.getEmoji().length());
|
||||
}
|
||||
});
|
||||
|
||||
popup.setOnEmojiconBackspaceClickedListener(v -> {
|
||||
if (isEmojiEditText(getCurrentFocus())) {
|
||||
KeyEvent event = new KeyEvent(
|
||||
0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL);
|
||||
getCurrentFocus().dispatchKeyEvent(event);
|
||||
}
|
||||
});
|
||||
|
||||
emojiButton.setOnClickListener(new emojiClickListener(groupDescriptionEditText));
|
||||
|
||||
if (this.groupID != null) {
|
||||
this.fillForm();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void fillForm() {
|
||||
this.groupNameEditText.setText(this.groupName);
|
||||
this.groupDescriptionEditText.setText(this.groupDescription);
|
||||
this.privacyWrapper.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_save, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_save_changes) {
|
||||
finishActivitySuccessfuly();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private boolean isEmojiEditText(View view) {
|
||||
return view instanceof EmojiEditText;
|
||||
}
|
||||
|
||||
private void changeEmojiKeyboardIcon(Boolean keyboardOpened) {
|
||||
|
||||
if (keyboardOpened) {
|
||||
emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_keyboard_grey600_24dp));
|
||||
} else {
|
||||
emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_emoticon_grey600_24dp));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
finish();
|
||||
UiUtils.dismissKeyboard(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
finish();
|
||||
UiUtils.dismissKeyboard(this);
|
||||
}
|
||||
|
||||
private void finishActivitySuccessfuly() {
|
||||
Intent resultIntent = new Intent();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("name", this.groupNameEditText.getText().toString());
|
||||
bundle.putString("description", MarkdownParser.INSTANCE.parseCompiled(this.groupDescriptionEditText.getText()));
|
||||
bundle.putString("leader", this.groupLeader);
|
||||
resultIntent.putExtras(bundle);
|
||||
setResult(Activity.RESULT_OK, resultIntent);
|
||||
finish();
|
||||
UiUtils.dismissKeyboard(this);
|
||||
}
|
||||
|
||||
private class emojiClickListener implements View.OnClickListener {
|
||||
|
||||
EmojiEditText view;
|
||||
|
||||
public emojiClickListener(EmojiEditText view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!popup.isShowing()) {
|
||||
|
||||
if (popup.isKeyBoardOpen()) {
|
||||
popup.showAtBottom();
|
||||
changeEmojiKeyboardIcon(true);
|
||||
} else {
|
||||
view.setFocusableInTouchMode(true);
|
||||
view.requestFocus();
|
||||
popup.showAtBottomPending();
|
||||
final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
|
||||
changeEmojiKeyboardIcon(true);
|
||||
}
|
||||
} else {
|
||||
popup.dismiss();
|
||||
changeEmojiKeyboardIcon(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.UiUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import net.pherth.android.emoji_library.EmojiEditText
|
||||
import net.pherth.android.emoji_library.EmojiPopup
|
||||
|
||||
class GroupFormActivity : BaseActivity() {
|
||||
|
||||
private var groupID: String? = null
|
||||
private var groupName: String? = null
|
||||
private var groupDescription: String? = null
|
||||
private var groupPrivacy: String? = null
|
||||
private var groupLeader: String? = null
|
||||
|
||||
private val groupNameEditText: EditText by bindView(R.id.group_name_edittext)
|
||||
private val groupDescriptionEditText: EmojiEditText by bindView(R.id.group_description_edittext)
|
||||
internal val emojiButton: ImageButton by bindView(R.id.emoji_toggle_btn)
|
||||
internal val privacyWrapper: LinearLayout by bindView(R.id.privacyWrapper)
|
||||
internal val privacySpinner: Spinner by bindView(R.id.privacySpinner)
|
||||
|
||||
private val popup: EmojiPopup by lazy {
|
||||
EmojiPopup(emojiButton.rootView, this, ContextCompat.getColor(this, R.color.brand))
|
||||
}
|
||||
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_group_form
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = intent
|
||||
val bundle = intent.extras
|
||||
this.groupID = bundle!!.getString("groupID")
|
||||
this.groupName = bundle.getString("name")
|
||||
this.groupDescription = bundle.getString("description")
|
||||
this.groupPrivacy = bundle.getString("privacy")
|
||||
this.groupLeader = bundle.getString("leader")
|
||||
|
||||
// Emoji keyboard stuff
|
||||
|
||||
popup
|
||||
|
||||
popup.setSizeForSoftKeyboard()
|
||||
popup.setOnDismissListener { changeEmojiKeyboardIcon(false) }
|
||||
popup.setOnSoftKeyboardOpenCloseListener(object : EmojiPopup.OnSoftKeyboardOpenCloseListener {
|
||||
|
||||
override fun onKeyboardOpen(keyBoardHeight: Int) {
|
||||
}
|
||||
|
||||
override fun onKeyboardClose() {
|
||||
if (popup.isShowing) {
|
||||
popup.dismiss()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
popup.setOnEmojiconClickedListener { emojicon ->
|
||||
if (currentFocus == null || !isEmojiEditText(currentFocus) || emojicon == null) {
|
||||
return@setOnEmojiconClickedListener
|
||||
}
|
||||
val emojiEditText = currentFocus as EmojiEditText
|
||||
val start = emojiEditText.selectionStart
|
||||
val end = emojiEditText.selectionEnd
|
||||
if (start < 0) {
|
||||
emojiEditText.append(emojicon.emoji)
|
||||
} else {
|
||||
emojiEditText.text.replace(Math.min(start, end),
|
||||
Math.max(start, end), emojicon.emoji, 0,
|
||||
emojicon.emoji.length)
|
||||
}
|
||||
}
|
||||
|
||||
popup.setOnEmojiconBackspaceClickedListener { v ->
|
||||
if (isEmojiEditText(currentFocus)) {
|
||||
val event = KeyEvent(
|
||||
0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL)
|
||||
currentFocus!!.dispatchKeyEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
emojiButton.setOnClickListener(EmojiClickListener(groupDescriptionEditText))
|
||||
|
||||
if (this.groupID != null) {
|
||||
this.fillForm()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
private fun fillForm() {
|
||||
this.groupNameEditText.setText(this.groupName)
|
||||
this.groupDescriptionEditText.setText(this.groupDescription)
|
||||
this.privacyWrapper.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_save, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
val id = item.itemId
|
||||
|
||||
|
||||
if (id == R.id.action_save_changes) {
|
||||
finishActivitySuccessfuly()
|
||||
return true
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun isEmojiEditText(view: View?): Boolean {
|
||||
return view is EmojiEditText
|
||||
}
|
||||
|
||||
private fun changeEmojiKeyboardIcon(keyboardOpened: Boolean) {
|
||||
|
||||
if (keyboardOpened) {
|
||||
emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_keyboard_grey600_24dp))
|
||||
} else {
|
||||
emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_emoticon_grey600_24dp))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
finish()
|
||||
UiUtils.dismissKeyboard(this)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finish()
|
||||
UiUtils.dismissKeyboard(this)
|
||||
}
|
||||
|
||||
private fun finishActivitySuccessfuly() {
|
||||
val resultIntent = Intent()
|
||||
val bundle = Bundle()
|
||||
bundle.putString("name", this.groupNameEditText.text.toString())
|
||||
bundle.putString("description", MarkdownParser.parseCompiled(this.groupDescriptionEditText.text))
|
||||
bundle.putString("leader", this.groupLeader)
|
||||
resultIntent.putExtras(bundle)
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
finish()
|
||||
UiUtils.dismissKeyboard(this)
|
||||
}
|
||||
|
||||
private inner class EmojiClickListener(internal var view: EmojiEditText) : View.OnClickListener {
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (!popup.isShowing) {
|
||||
if (popup.isKeyBoardOpen == true) {
|
||||
popup.showAtBottom()
|
||||
changeEmojiKeyboardIcon(true)
|
||||
} else {
|
||||
view.isFocusableInTouchMode = true
|
||||
view.requestFocus()
|
||||
popup.showAtBottomPending()
|
||||
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
|
||||
changeEmojiKeyboardIcon(true)
|
||||
}
|
||||
} else {
|
||||
popup.dismiss()
|
||||
changeEmojiKeyboardIcon(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val GROUP_FORM_ACTIVITY = 11
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +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 com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
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.adapter.SkillTasksRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.widget.HabitButtonWidgetProvider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class HabitButtonWidgetActivity extends BaseActivity {
|
||||
|
||||
@Inject
|
||||
TaskRepository taskRepository;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView recyclerView;
|
||||
private int widgetId;
|
||||
private SkillTasksRecyclerViewAdapter adapter;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.widget_configure_habit_button;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
adapter = new SkillTasksRecyclerViewAdapter(null, true);
|
||||
compositeSubscription.add(adapter.getTaskSelectionEvents().subscribe(task -> taskSelected(task.getId()), RxErrorHandler.handleEmptyError()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
taskRepository.getTasks(Task.TYPE_HABIT, userId).firstElement().subscribe(adapter::updateData, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
public void taskSelected(String taskId) {
|
||||
finishWithSelection(taskId);
|
||||
}
|
||||
|
||||
private void finishWithSelection(String selectedTaskId) {
|
||||
storeSelectedTaskId(selectedTaskId);
|
||||
|
||||
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 storeSelectedTaskId(String selectedTaskId) {
|
||||
SharedPreferences.Editor preferences = PreferenceManager.getDefaultSharedPreferences(this).edit();
|
||||
preferences.putString("habit_button_widget_" + widgetId, selectedTaskId);
|
||||
preferences.apply();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v7.preference.PreferenceManager
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
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.adapter.SkillTasksRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.widget.HabitButtonWidgetProvider
|
||||
import io.reactivex.functions.Consumer
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class HabitButtonWidgetActivity : BaseActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userId: String
|
||||
|
||||
internal val recyclerView: RecyclerView by bindView(R.id.recyclerView)
|
||||
private var widgetId: Int = 0
|
||||
private var adapter: SkillTasksRecyclerViewAdapter? = null
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.widget_configure_habit_button
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = intent
|
||||
val extras = intent.extras
|
||||
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()
|
||||
}
|
||||
|
||||
var layoutManager: LinearLayoutManager? = recyclerView.layoutManager as LinearLayoutManager?
|
||||
|
||||
if (layoutManager == null) {
|
||||
layoutManager = LinearLayoutManager(this)
|
||||
|
||||
recyclerView.layoutManager = layoutManager
|
||||
}
|
||||
|
||||
adapter = SkillTasksRecyclerViewAdapter(null, true)
|
||||
adapter?.getTaskSelectionEvents()?.subscribe(Consumer { task -> taskSelected(task.id) }, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription?.add(it) }
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
taskRepository.getTasks(Task.TYPE_HABIT, userId).firstElement().subscribe(Consumer { adapter?.updateData(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun taskSelected(taskId: String?) {
|
||||
finishWithSelection(taskId)
|
||||
}
|
||||
|
||||
private fun finishWithSelection(selectedTaskId: String?) {
|
||||
storeSelectedTaskId(selectedTaskId)
|
||||
|
||||
val resultValue = Intent()
|
||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
|
||||
setResult(Activity.RESULT_OK, resultValue)
|
||||
finish()
|
||||
|
||||
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, HabitButtonWidgetProvider::class.java)
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(widgetId))
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
private fun storeSelectedTaskId(selectedTaskId: String?) {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(this).edit()
|
||||
preferences.putString("habit_button_widget_$widgetId", selectedTaskId)
|
||||
preferences.apply()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.IntroFragment;
|
||||
import com.viewpagerindicator.IconPageIndicator;
|
||||
import com.viewpagerindicator.IconPagerAdapter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class IntroActivity extends BaseActivity implements View.OnClickListener, ViewPager.OnPageChangeListener {
|
||||
|
||||
@Inject
|
||||
public ApiClient apiClient;
|
||||
@BindView(R.id.viewPager)
|
||||
ViewPager pager;
|
||||
@BindView(R.id.view_pager_indicator)
|
||||
IconPageIndicator indicator;
|
||||
@BindView(R.id.skipButton)
|
||||
Button skipButton;
|
||||
@BindView(R.id.finishButton)
|
||||
Button finishButton;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_intro;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
HabiticaBaseApplication.getComponent().inject(this);
|
||||
|
||||
setupIntro();
|
||||
indicator.setViewPager(pager);
|
||||
|
||||
this.skipButton.setOnClickListener(this);
|
||||
this.finishButton.setOnClickListener(this);
|
||||
|
||||
apiClient.getContent()
|
||||
.subscribe(contentResult -> {}, RxErrorHandler.handleEmptyError());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
Window window = getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.setStatusBarColor(ContextCompat.getColor(this, R.color.black_20_alpha));
|
||||
}
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void setupIntro() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
pager.setAdapter(new PagerAdapter(fragmentManager));
|
||||
|
||||
pager.addOnPageChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finishIntro();
|
||||
}
|
||||
|
||||
private void finishIntro() {
|
||||
Intent intent = new Intent(this, LoginActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
this.startActivity(intent);
|
||||
overridePendingTransition(0, R.anim.activity_fade_out);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (position == 2) {
|
||||
this.finishButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
this.finishButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
|
||||
private class PagerAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
|
||||
public PagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
IntroFragment fragment = new IntroFragment();
|
||||
|
||||
switch (position) {
|
||||
case 0: {
|
||||
fragment.setImage(ResourcesCompat.getDrawable(getResources(), R.drawable.intro_1, null));
|
||||
fragment.setSubtitle(getString(R.string.intro_1_subtitle));
|
||||
fragment.setTitleImage(ResourcesCompat.getDrawable(getResources(), R.drawable.intro_1_title, null));
|
||||
fragment.setDescription(getString(R.string.intro_1_description, getString(R.string.habitica_user_count)));
|
||||
fragment.setBackgroundColor(ContextCompat.getColor(IntroActivity.this, R.color.brand_300));
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
fragment.setImage(ResourcesCompat.getDrawable(getResources(), R.drawable.intro_2, null));
|
||||
fragment.setSubtitle(getString(R.string.intro_2_subtitle));
|
||||
fragment.setTitle(getString(R.string.intro_2_title));
|
||||
fragment.setDescription(getString(R.string.intro_2_description));
|
||||
fragment.setBackgroundColor(ContextCompat.getColor(IntroActivity.this, R.color.blue_10));
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
fragment.setImage(ResourcesCompat.getDrawable(getResources(), R.drawable.intro_3, null));
|
||||
fragment.setSubtitle(getString(R.string.intro_3_subtitle));
|
||||
fragment.setTitle(getString(R.string.intro_3_title));
|
||||
fragment.setDescription(getString(R.string.intro_3_description));
|
||||
fragment.setBackgroundColor(ContextCompat.getColor(IntroActivity.this, R.color.red_100));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconResId(int index) {
|
||||
return R.drawable.indicator_diamond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.content.res.ResourcesCompat
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.Button
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ContentRepository
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.IntroFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.viewpagerindicator.IconPageIndicator
|
||||
import com.viewpagerindicator.IconPagerAdapter
|
||||
import io.reactivex.functions.Consumer
|
||||
import javax.inject.Inject
|
||||
|
||||
class IntroActivity : BaseActivity(), View.OnClickListener, ViewPager.OnPageChangeListener {
|
||||
|
||||
@Inject
|
||||
lateinit var contentRepository: InventoryRepository
|
||||
|
||||
private val pager: ViewPager by bindView(R.id.viewPager)
|
||||
private val indicator: IconPageIndicator by bindView(R.id.view_pager_indicator)
|
||||
private val skipButton: Button by bindView(R.id.skipButton)
|
||||
private val finishButton: Button by bindView(R.id.finishButton)
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_intro
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setupIntro()
|
||||
indicator.setViewPager(pager)
|
||||
|
||||
this.skipButton.setOnClickListener(this)
|
||||
this.finishButton.setOnClickListener(this)
|
||||
|
||||
contentRepository.retrieveContent().subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val window = window
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.statusBarColor = ContextCompat.getColor(this, R.color.black_20_alpha)
|
||||
}
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
private fun setupIntro() {
|
||||
val fragmentManager = supportFragmentManager
|
||||
|
||||
pager.adapter = PagerAdapter(fragmentManager)
|
||||
|
||||
pager.addOnPageChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
finishIntro()
|
||||
}
|
||||
|
||||
private fun finishIntro() {
|
||||
val intent = Intent(this, LoginActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
|
||||
this.startActivity(intent)
|
||||
overridePendingTransition(0, R.anim.activity_fade_out)
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
if (position == 2) {
|
||||
this.finishButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
this.finishButton.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
|
||||
private inner class PagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm), IconPagerAdapter {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val fragment = IntroFragment()
|
||||
|
||||
when (position) {
|
||||
0 -> {
|
||||
fragment.setImage(ResourcesCompat.getDrawable(resources, R.drawable.intro_1, null))
|
||||
fragment.setSubtitle(getString(R.string.intro_1_subtitle))
|
||||
fragment.setTitleImage(ResourcesCompat.getDrawable(resources, R.drawable.intro_1_title, null))
|
||||
fragment.setDescription(getString(R.string.intro_1_description, getString(R.string.habitica_user_count)))
|
||||
fragment.setBackgroundColor(ContextCompat.getColor(this@IntroActivity, R.color.brand_300))
|
||||
}
|
||||
1 -> {
|
||||
fragment.setImage(ResourcesCompat.getDrawable(resources, R.drawable.intro_2, null))
|
||||
fragment.setSubtitle(getString(R.string.intro_2_subtitle))
|
||||
fragment.setTitle(getString(R.string.intro_2_title))
|
||||
fragment.setDescription(getString(R.string.intro_2_description))
|
||||
fragment.setBackgroundColor(ContextCompat.getColor(this@IntroActivity, R.color.blue_10))
|
||||
}
|
||||
2 -> {
|
||||
fragment.setImage(ResourcesCompat.getDrawable(resources, R.drawable.intro_3, null))
|
||||
fragment.setSubtitle(getString(R.string.intro_3_subtitle))
|
||||
fragment.setTitle(getString(R.string.intro_3_title))
|
||||
fragment.setDescription(getString(R.string.intro_3_description))
|
||||
fragment.setBackgroundColor(ContextCompat.getColor(this@IntroActivity, R.color.red_100))
|
||||
}
|
||||
}
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getIconResId(index: Int): Int {
|
||||
return R.drawable.indicator_diamond
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,677 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Dialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.text.InputType;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import com.facebook.AccessToken;
|
||||
import com.facebook.CallbackManager;
|
||||
import com.facebook.FacebookCallback;
|
||||
import com.facebook.FacebookException;
|
||||
import com.facebook.FacebookSdk;
|
||||
import com.facebook.login.LoginManager;
|
||||
import com.facebook.login.LoginResult;
|
||||
import com.google.android.gms.auth.GoogleAuthException;
|
||||
import com.google.android.gms.auth.GoogleAuthUtil;
|
||||
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
|
||||
import com.google.android.gms.auth.UserRecoverableAuthException;
|
||||
import com.google.android.gms.common.AccountPicker;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.gms.common.Scopes;
|
||||
import com.habitrpg.android.habitica.BuildConfig;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.api.HostConfig;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.auth.UserAuthResponse;
|
||||
import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator;
|
||||
import com.habitrpg.android.habitica.prefs.scanner.IntentResult;
|
||||
import com.habitrpg.android.habitica.ui.helpers.UiUtils;
|
||||
import com.habitrpg.android.habitica.ui.views.login.LockableScrollView;
|
||||
import com.habitrpg.android.habitica.ui.views.login.LoginBackgroundView;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.exceptions.Exceptions;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static com.habitrpg.android.habitica.R.id.password;
|
||||
|
||||
/**
|
||||
* @author Mickael Goubin
|
||||
*/
|
||||
public class LoginActivity extends BaseActivity
|
||||
implements Consumer<UserAuthResponse> {
|
||||
static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
|
||||
private final static String TAG_ADDRESS = "address";
|
||||
private final static String TAG_USERID = "user";
|
||||
private final static String TAG_APIKEY = "key";
|
||||
private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001;
|
||||
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
|
||||
|
||||
@Inject
|
||||
public ApiClient apiClient;
|
||||
@Inject
|
||||
public SharedPreferences sharedPrefs;
|
||||
@Inject
|
||||
public HostConfig hostConfig;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
public String mTmpUserToken;
|
||||
public String mTmpApiToken;
|
||||
public Boolean isRegistering;
|
||||
Boolean isShowingForm = false;
|
||||
|
||||
@BindView(R.id.background_container)
|
||||
LockableScrollView backgroundContainer;
|
||||
@BindView(R.id.background_view)
|
||||
LoginBackgroundView backgroundView;
|
||||
@BindView(R.id.new_game_button)
|
||||
Button newGameButton;
|
||||
@BindView(R.id.show_login_button)
|
||||
Button showLoginButton;
|
||||
@BindView(R.id.login_scrollview)
|
||||
ScrollView scrollView;
|
||||
@BindView(R.id.login_linear_layout)
|
||||
LinearLayout formWrapper;
|
||||
@BindView(R.id.back_button)
|
||||
Button backButton;
|
||||
@BindView(R.id.logo_view)
|
||||
ImageView logoView;
|
||||
|
||||
@BindView(R.id.login_btn)
|
||||
Button mLoginNormalBtn;
|
||||
@BindView(R.id.PB_AsyncTask)
|
||||
ProgressBar mProgressBar;
|
||||
@BindView(R.id.username)
|
||||
EditText mUsernameET;
|
||||
@BindView(password)
|
||||
EditText mPasswordET;
|
||||
@BindView(R.id.email)
|
||||
EditText mEmail;
|
||||
@BindView(R.id.confirm_password)
|
||||
EditText mConfirmPassword;
|
||||
@BindView(R.id.forgot_password)
|
||||
Button forgotPasswordButton;
|
||||
private CallbackManager callbackManager;
|
||||
private String googleEmail;
|
||||
private LoginManager loginManager;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
|
||||
return R.layout.activity_login;
|
||||
}
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().hide();
|
||||
}
|
||||
//Set default values to avoid null-responses when requesting unedited settings
|
||||
PreferenceManager.setDefaultValues(this, R.xml.preferences_fragment, false);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setupFacebookLogin();
|
||||
|
||||
mLoginNormalBtn.setOnClickListener(mLoginNormalClick);
|
||||
|
||||
SpannableString content = new SpannableString(forgotPasswordButton.getText());
|
||||
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
|
||||
forgotPasswordButton.setText(content);
|
||||
|
||||
callbackManager = CallbackManager.Factory.create();
|
||||
|
||||
|
||||
this.isRegistering = true;
|
||||
|
||||
Map<String, Object> additionalData = new HashMap<>();
|
||||
additionalData.put("page", this.getClass().getSimpleName());
|
||||
AmplitudeManager.sendEvent("navigate", AmplitudeManager.EVENT_CATEGORY_NAVIGATION, AmplitudeManager.EVENT_HITTYPE_PAGEVIEW, additionalData);
|
||||
|
||||
backgroundContainer.post(() -> backgroundContainer.scrollTo(0, backgroundContainer.getBottom()));
|
||||
backgroundContainer.setScrollingEnabled(false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
Window window = getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.setStatusBarColor(ContextCompat.getColor(this, R.color.black_20_alpha));
|
||||
}
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupFacebookLogin() {
|
||||
callbackManager = CallbackManager.Factory.create();
|
||||
loginManager = LoginManager.getInstance();
|
||||
loginManager.registerCallback(callbackManager,
|
||||
new FacebookCallback<LoginResult>() {
|
||||
@Override
|
||||
public void onSuccess(LoginResult loginResult) {
|
||||
Log.e("Login", "SUCCESS");
|
||||
AccessToken accessToken = AccessToken.getCurrentAccessToken();
|
||||
apiClient.connectSocial("facebook", accessToken.getUserId(), accessToken.getToken())
|
||||
.subscribe(LoginActivity.this, throwable -> hideProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Log.e("Login", "CANCEL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(FacebookException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (isShowingForm) {
|
||||
hideForm();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void resetLayout() {
|
||||
if (this.isRegistering) {
|
||||
if (this.mEmail.getVisibility() == View.GONE) {
|
||||
show(this.mEmail);
|
||||
}
|
||||
if (this.mConfirmPassword.getVisibility() == View.GONE) {
|
||||
show(this.mConfirmPassword);
|
||||
}
|
||||
} else {
|
||||
if (this.mEmail.getVisibility() == View.VISIBLE) {
|
||||
hide(this.mEmail);
|
||||
}
|
||||
if (this.mConfirmPassword.getVisibility() == View.VISIBLE) {
|
||||
hide(this.mConfirmPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener mLoginNormalClick = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
if (isRegistering) {
|
||||
String username, email, password, cpassword;
|
||||
username = String.valueOf(mUsernameET.getText()).trim();
|
||||
email = String.valueOf(mEmail.getText()).trim();
|
||||
password = String.valueOf(mPasswordET.getText());
|
||||
cpassword = String.valueOf(mConfirmPassword.getText());
|
||||
if (username.length() == 0 || password.length() == 0 || email.length() == 0 || cpassword.length() == 0) {
|
||||
showValidationError(R.string.login_validation_error_fieldsmissing);
|
||||
return;
|
||||
}
|
||||
apiClient.registerUser(username, email, password, cpassword)
|
||||
.subscribe(LoginActivity.this, throwable -> hideProgress());
|
||||
} else {
|
||||
String username, password;
|
||||
username = String.valueOf(mUsernameET.getText()).trim();
|
||||
password = String.valueOf(mPasswordET.getText());
|
||||
if (username.length() == 0 || password.length() == 0) {
|
||||
showValidationError(R.string.login_validation_error_fieldsmissing);
|
||||
return;
|
||||
}
|
||||
apiClient.connectUser(username, password)
|
||||
.subscribe(LoginActivity.this, throwable -> hideProgress());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private View.OnClickListener mForgotPWClick = v -> {
|
||||
String url = BuildConfig.BASE_URL;
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
startActivity(i);
|
||||
};
|
||||
|
||||
|
||||
public static void show(final View v) {
|
||||
v.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public static void hide(final View v) {
|
||||
v.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void startMainActivity() {
|
||||
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void startSetupActivity() {
|
||||
Intent intent = new Intent(LoginActivity.this, SetupActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void toggleRegistering() {
|
||||
this.isRegistering = !this.isRegistering;
|
||||
this.setRegistering();
|
||||
}
|
||||
|
||||
private void setRegistering() {
|
||||
if (this.isRegistering) {
|
||||
this.mLoginNormalBtn.setText(getString(R.string.register_btn));
|
||||
mUsernameET.setHint(R.string.username);
|
||||
mPasswordET.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
} else {
|
||||
this.mLoginNormalBtn.setText(getString(R.string.login_btn));
|
||||
mUsernameET.setHint(R.string.email_username);
|
||||
mPasswordET.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
}
|
||||
this.resetLayout();
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
callbackManager.onActivityResult(requestCode, resultCode, intent);
|
||||
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
|
||||
if (scanResult != null) {
|
||||
try {
|
||||
Log.d("scanresult", scanResult.getContents());
|
||||
this.parse(scanResult.getContents());
|
||||
} catch (Exception e) {
|
||||
Log.e("scanresult", "Could not parse scanResult", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
googleEmail = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
|
||||
handleGoogleLoginResult();
|
||||
}
|
||||
}
|
||||
if (requestCode == REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR) {
|
||||
handleGoogleLoginResult();
|
||||
}
|
||||
|
||||
if (requestCode == FacebookSdk.getCallbackRequestCodeOffset()) {
|
||||
//This is necessary because the regular login callback is not called for some reason
|
||||
AccessToken accessToken = AccessToken.getCurrentAccessToken();
|
||||
if (accessToken != null && accessToken.getToken() != null) {
|
||||
apiClient.connectSocial("facebook", accessToken.getUserId(), accessToken.getToken())
|
||||
.subscribe(LoginActivity.this, throwable -> hideProgress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String contents) {
|
||||
String adr, user, key;
|
||||
try {
|
||||
JSONObject obj;
|
||||
|
||||
obj = new JSONObject(contents);
|
||||
adr = obj.getString(TAG_ADDRESS);
|
||||
user = obj.getString(TAG_USERID);
|
||||
key = obj.getString(TAG_APIKEY);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
boolean ans = editor.putString(getString(R.string.SP_address), adr)
|
||||
.putString(getString(R.string.SP_APIToken), key)
|
||||
.putString(getString(R.string.SP_userID), user)
|
||||
.commit();
|
||||
if (!ans) {
|
||||
throw new Exception("PB_string_commit");
|
||||
}
|
||||
startMainActivity();
|
||||
} catch (JSONException e) {
|
||||
showSnackbar(getString(R.string.ERR_pb_barcode));
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
if ("PB_string_commit".equals(e.getMessage())) {
|
||||
showSnackbar(getString(R.string.ERR_pb_barcode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showSnackbar(String content) {
|
||||
Snackbar snackbar = Snackbar
|
||||
.make(this.findViewById(R.id.login_linear_layout), content, Snackbar.LENGTH_LONG);
|
||||
|
||||
View snackbarView = snackbar.getView();
|
||||
snackbarView.setBackgroundColor(Color.RED);//change Snackbar's background color;
|
||||
snackbar.show(); // Don’t forget to show!
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_toggleRegistering:
|
||||
toggleRegistering();
|
||||
break;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void saveTokens(String api, String user) throws Exception {
|
||||
this.apiClient.updateAuthenticationCredentials(user, api);
|
||||
SharedPreferences.Editor editor = sharedPrefs.edit();
|
||||
boolean ans = editor.putString(getString(R.string.SP_APIToken), api)
|
||||
.putString(getString(R.string.SP_userID), user)
|
||||
.commit();
|
||||
if (!ans) {
|
||||
throw new Exception("PB_string_commit");
|
||||
}
|
||||
}
|
||||
|
||||
private void hideProgress() {
|
||||
runOnUiThread(() -> {
|
||||
if (mProgressBar != null) {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showValidationError(int resourceMessageString) {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
new android.support.v7.app.AlertDialog.Builder(this)
|
||||
.setTitle(R.string.login_validation_error_title)
|
||||
.setMessage(resourceMessageString)
|
||||
.setNeutralButton(android.R.string.ok, (dialog, which) -> {
|
||||
})
|
||||
.setIcon(R.drawable.ic_warning_black)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(UserAuthResponse userAuthResponse) {
|
||||
try {
|
||||
saveTokens(userAuthResponse.getToken(), userAuthResponse.getId());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
userRepository.retrieveUser(true)
|
||||
.subscribe(user -> {
|
||||
if (userAuthResponse.getNewUser()) {
|
||||
this.startSetupActivity();
|
||||
} else {
|
||||
AmplitudeManager.sendEvent("login", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT);
|
||||
this.startMainActivity();
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@OnClick(R.id.fb_login_button)
|
||||
public void handleFacebookLogin() {
|
||||
loginManager.logInWithReadPermissions(this, Collections.singletonList("user_friends"));
|
||||
}
|
||||
|
||||
@OnClick(R.id.google_login_button)
|
||||
public void handleGoogleLogin() {
|
||||
if (!checkPlayServices()) {
|
||||
return;
|
||||
}
|
||||
String[] accountTypes = new String[]{"com.google"};
|
||||
Intent intent = AccountPicker.newChooseAccountIntent(null, null,
|
||||
accountTypes, false, null, null, null, null);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Dialog dialog = new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.authentication_error_title)
|
||||
.setMessage(R.string.google_services_missing)
|
||||
.setNegativeButton(R.string.close, (dialogInterface, i) -> dialogInterface.dismiss())
|
||||
.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGoogleLoginResult() {
|
||||
String scopesString = Scopes.PROFILE + " " + Scopes.EMAIL;
|
||||
String scopes = "oauth2:" + scopesString;
|
||||
Flowable.defer(() -> {
|
||||
try {
|
||||
return Flowable.just(GoogleAuthUtil.getToken(LoginActivity.this, googleEmail, scopes));
|
||||
} catch (IOException | GoogleAuthException e) {
|
||||
throw Exceptions.propagate(e);
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMap(token -> apiClient.connectSocial("google", googleEmail, token))
|
||||
.subscribe(LoginActivity.this, throwable -> {
|
||||
throwable.printStackTrace();
|
||||
hideProgress();
|
||||
if (throwable.getCause() != null && GoogleAuthException.class.isAssignableFrom(throwable.getCause().getClass())) {
|
||||
handleGoogleAuthException((GoogleAuthException) throwable.getCause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleGoogleAuthException(final Exception e) {
|
||||
if (e instanceof GooglePlayServicesAvailabilityException) {
|
||||
// The Google Play services APK is old, disabled, or not present.
|
||||
// Show a dialog created by Google Play services that allows
|
||||
// the user to update the APK
|
||||
int statusCode = ((GooglePlayServicesAvailabilityException) e)
|
||||
.getConnectionStatusCode();
|
||||
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
|
||||
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(statusCode,
|
||||
LoginActivity.this,
|
||||
REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
|
||||
dialog.show();
|
||||
} else if (e instanceof UserRecoverableAuthException) {
|
||||
// Unable to authenticate, such as when the user has not yet granted
|
||||
// the app access to the account, but the user can fix this.
|
||||
// Forward the user to an activity in Google Play services.
|
||||
Intent intent = ((UserRecoverableAuthException) e).getIntent();
|
||||
startActivityForResult(intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPlayServices() {
|
||||
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
|
||||
int result = googleAPI.isGooglePlayServicesAvailable(this);
|
||||
if(result != ConnectionResult.SUCCESS) {
|
||||
if(googleAPI.isUserResolvableError(result)) {
|
||||
googleAPI.getErrorDialog(this, result, PLAY_SERVICES_RESOLUTION_REQUEST).show();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@OnClick(R.id.new_game_button)
|
||||
void newGameButtonClicked() {
|
||||
isRegistering = true;
|
||||
showForm();
|
||||
setRegistering();
|
||||
}
|
||||
|
||||
@OnClick(R.id.show_login_button)
|
||||
void showLoginButtonClicked() {
|
||||
isRegistering = false;
|
||||
showForm();
|
||||
setRegistering();
|
||||
}
|
||||
|
||||
@OnClick(R.id.back_button)
|
||||
void backButtonClicked() {
|
||||
if (isShowingForm) {
|
||||
hideForm();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void showForm() {
|
||||
isShowingForm = true;
|
||||
ValueAnimator panAnimation = ObjectAnimator.ofInt(backgroundContainer, "scrollY", 0).setDuration(1000);
|
||||
ValueAnimator newGameAlphaAnimation = ObjectAnimator.ofFloat(newGameButton, View.ALPHA, 0);
|
||||
ValueAnimator showLoginAlphaAnimation = ObjectAnimator.ofFloat(showLoginButton, View.ALPHA, 0);
|
||||
ValueAnimator scaleLogoAnimation = ValueAnimator.ofInt(logoView.getMeasuredHeight(), (int)(logoView.getMeasuredHeight()*0.75));
|
||||
scaleLogoAnimation.addUpdateListener(valueAnimator -> {
|
||||
int val = (Integer) valueAnimator.getAnimatedValue();
|
||||
ViewGroup.LayoutParams layoutParams = logoView.getLayoutParams();
|
||||
layoutParams.height = val;
|
||||
logoView.setLayoutParams(layoutParams);
|
||||
});
|
||||
if (isRegistering) {
|
||||
newGameAlphaAnimation.setStartDelay(600);
|
||||
newGameAlphaAnimation.setDuration(400);
|
||||
showLoginAlphaAnimation.setDuration(400);
|
||||
newGameAlphaAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
newGameButton.setVisibility(View.GONE);
|
||||
showLoginButton.setVisibility(View.GONE);
|
||||
scrollView.setVisibility(View.VISIBLE);
|
||||
scrollView.setAlpha(1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showLoginAlphaAnimation.setStartDelay(600);
|
||||
showLoginAlphaAnimation.setDuration(400);
|
||||
newGameAlphaAnimation.setDuration(400);
|
||||
showLoginAlphaAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
newGameButton.setVisibility(View.GONE);
|
||||
showLoginButton.setVisibility(View.GONE);
|
||||
scrollView.setVisibility(View.VISIBLE);
|
||||
scrollView.setAlpha(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
ValueAnimator backAlphaAnimation = ObjectAnimator.ofFloat(backButton, View.ALPHA, 1).setDuration(800);
|
||||
AnimatorSet showAnimation = new AnimatorSet();
|
||||
showAnimation.playTogether(panAnimation, newGameAlphaAnimation, showLoginAlphaAnimation, scaleLogoAnimation);
|
||||
showAnimation.play(backAlphaAnimation).after(panAnimation);
|
||||
for (int i = 0; i < formWrapper.getChildCount(); i++) {
|
||||
View view = formWrapper.getChildAt(i);
|
||||
view.setAlpha(0);
|
||||
ValueAnimator animator = ObjectAnimator.ofFloat(view, View.ALPHA, 1).setDuration(400);
|
||||
animator.setStartDelay(100 * i);
|
||||
showAnimation.play(animator).after(panAnimation);
|
||||
}
|
||||
|
||||
showAnimation.start();
|
||||
}
|
||||
|
||||
private void hideForm() {
|
||||
isShowingForm = false;
|
||||
ValueAnimator panAnimation = ObjectAnimator.ofInt(backgroundContainer, "scrollY", backgroundContainer.getBottom()).setDuration(1000);
|
||||
ValueAnimator newGameAlphaAnimation = ObjectAnimator.ofFloat(newGameButton, View.ALPHA, 1).setDuration(700);
|
||||
ValueAnimator showLoginAlphaAnimation = ObjectAnimator.ofFloat(showLoginButton, View.ALPHA, 1).setDuration(700);
|
||||
ValueAnimator scaleLogoAnimation = ValueAnimator.ofInt(logoView.getMeasuredHeight(), (int)(logoView.getMeasuredHeight()*1.333333));
|
||||
scaleLogoAnimation.addUpdateListener(valueAnimator -> {
|
||||
int val = (Integer) valueAnimator.getAnimatedValue();
|
||||
ViewGroup.LayoutParams layoutParams = logoView.getLayoutParams();
|
||||
layoutParams.height = val;
|
||||
logoView.setLayoutParams(layoutParams);
|
||||
});
|
||||
showLoginAlphaAnimation.setStartDelay(300);
|
||||
ValueAnimator scrollViewAlphaAnimation = ObjectAnimator.ofFloat(scrollView, View.ALPHA, 0).setDuration(800);
|
||||
scrollViewAlphaAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
newGameButton.setVisibility(View.VISIBLE);
|
||||
showLoginButton.setVisibility(View.VISIBLE);
|
||||
scrollView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
ValueAnimator backAlphaAnimation = ObjectAnimator.ofFloat(backButton, View.ALPHA, 0).setDuration(800);
|
||||
AnimatorSet showAnimation = new AnimatorSet();
|
||||
showAnimation.playTogether(panAnimation, scrollViewAlphaAnimation, backAlphaAnimation, scaleLogoAnimation);
|
||||
showAnimation.play(newGameAlphaAnimation).after(scrollViewAlphaAnimation);
|
||||
showAnimation.play(showLoginAlphaAnimation).after(scrollViewAlphaAnimation);
|
||||
showAnimation.start();
|
||||
UiUtils.dismissKeyboard(this);
|
||||
}
|
||||
|
||||
@OnClick(R.id.forgot_password)
|
||||
public void onForgotPasswordClicked() {
|
||||
final EditText input = new EditText(this);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
input.setAutofillHints(EditText.AUTOFILL_HINT_EMAIL_ADDRESS);
|
||||
}
|
||||
input.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
input.setLayoutParams(lp);
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.forgot_password_title)
|
||||
.setMessage(R.string.forgot_password_description)
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.send, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
userRepository.sendPasswordResetEmail(input.getText().toString()).subscribe(aVoid -> {
|
||||
showPasswordEmailConfirmation();
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}).setNegativeButton(R.string.action_cancel, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
private void showPasswordEmailConfirmation() {
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(R.string.forgot_password_confirmation)
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,608 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.accounts.AccountManager
|
||||
import android.animation.*
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.preference.PreferenceManager
|
||||
import android.text.InputType
|
||||
import android.text.SpannableString
|
||||
import android.text.style.UnderlineSpan
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.*
|
||||
import com.facebook.*
|
||||
import com.facebook.login.LoginManager
|
||||
import com.facebook.login.LoginResult
|
||||
import com.google.android.gms.auth.GoogleAuthException
|
||||
import com.google.android.gms.auth.GoogleAuthUtil
|
||||
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException
|
||||
import com.google.android.gms.auth.UserRecoverableAuthException
|
||||
import com.google.android.gms.common.*
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.api.HostConfig
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.auth.UserAuthResponse
|
||||
import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator
|
||||
import com.habitrpg.android.habitica.ui.helpers.UiUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.login.LockableScrollView
|
||||
import com.habitrpg.android.habitica.ui.views.login.LoginBackgroundView
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.exceptions.Exceptions
|
||||
import io.reactivex.functions.Consumer
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* @author Mickael Goubin
|
||||
*/
|
||||
class LoginActivity : BaseActivity(), Consumer<UserAuthResponse> {
|
||||
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
@Inject
|
||||
lateinit var sharedPrefs: SharedPreferences
|
||||
@Inject
|
||||
lateinit var hostConfig: HostConfig
|
||||
@Inject
|
||||
internal lateinit var userRepository: UserRepository
|
||||
|
||||
private var isRegistering: Boolean = false
|
||||
private var isShowingForm: Boolean = false
|
||||
|
||||
private val backgroundContainer: LockableScrollView by bindView(R.id.background_container)
|
||||
internal val backgroundView: LoginBackgroundView by bindView(R.id.background_view)
|
||||
internal val newGameButton: Button by bindView(R.id.new_game_button)
|
||||
internal val showLoginButton: Button by bindView(R.id.show_login_button)
|
||||
internal val scrollView: ScrollView by bindView(R.id.login_scrollview)
|
||||
private val formWrapper: LinearLayout by bindView(R.id.login_linear_layout)
|
||||
private val backButton: Button by bindView(R.id.back_button)
|
||||
private val logoView: ImageView by bindView(R.id.logo_view)
|
||||
private val mLoginNormalBtn: Button by bindView(R.id.login_btn)
|
||||
private val mProgressBar: ProgressBar by bindView(R.id.PB_AsyncTask)
|
||||
private val mUsernameET: EditText by bindView(R.id.username)
|
||||
private val mPasswordET: EditText by bindView(R.id.password)
|
||||
private val mEmail: EditText by bindView(R.id.email)
|
||||
private val mConfirmPassword: EditText by bindView(R.id.confirm_password)
|
||||
private val forgotPasswordButton: Button by bindView(R.id.forgot_password)
|
||||
private val facebookLoginButton: Button by bindView(R.id.fb_login_button)
|
||||
private val googleLoginButton: Button by bindView(R.id.google_login_button)
|
||||
|
||||
private var callbackManager = CallbackManager.Factory.create()
|
||||
private var googleEmail: String? = null
|
||||
private var loginManager = LoginManager.getInstance()
|
||||
|
||||
private val mLoginNormalClick = View.OnClickListener {
|
||||
mProgressBar.visibility = View.VISIBLE
|
||||
if (isRegistering) {
|
||||
val username: String = mUsernameET.text.toString().trim { it <= ' ' }
|
||||
val email: String = mEmail.text.toString().trim { it <= ' ' }
|
||||
val password: String = mPasswordET.text.toString()
|
||||
val confirmPassword: String = mConfirmPassword.text.toString()
|
||||
if (username.isEmpty() || password.isEmpty() || email.isEmpty() || confirmPassword.isEmpty()) {
|
||||
showValidationError(R.string.login_validation_error_fieldsmissing)
|
||||
return@OnClickListener
|
||||
}
|
||||
apiClient.registerUser(username, email, password, confirmPassword)
|
||||
.subscribe(this@LoginActivity, Consumer { hideProgress() })
|
||||
} else {
|
||||
val username: String = mUsernameET.text.toString().trim { it <= ' ' }
|
||||
val password: String = mPasswordET.text.toString()
|
||||
if (username.isEmpty() || password.isEmpty()) {
|
||||
showValidationError(R.string.login_validation_error_fieldsmissing)
|
||||
return@OnClickListener
|
||||
}
|
||||
apiClient.connectUser(username, password)
|
||||
.subscribe(this@LoginActivity, Consumer { hideProgress() })
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
window.requestFeature(Window.FEATURE_ACTION_BAR)
|
||||
return R.layout.activity_login
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar?.hide()
|
||||
//Set default values to avoid null-responses when requesting unedited settings
|
||||
PreferenceManager.setDefaultValues(this, R.xml.preferences_fragment, false)
|
||||
|
||||
setupFacebookLogin()
|
||||
|
||||
mLoginNormalBtn.setOnClickListener(mLoginNormalClick)
|
||||
|
||||
val content = SpannableString(forgotPasswordButton.text)
|
||||
content.setSpan(UnderlineSpan(), 0, content.length, 0)
|
||||
forgotPasswordButton.text = content
|
||||
|
||||
this.isRegistering = true
|
||||
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["page"] = this.javaClass.simpleName
|
||||
AmplitudeManager.sendEvent("navigate", AmplitudeManager.EVENT_CATEGORY_NAVIGATION, AmplitudeManager.EVENT_HITTYPE_PAGEVIEW, additionalData)
|
||||
|
||||
backgroundContainer.post { backgroundContainer.scrollTo(0, backgroundContainer.bottom) }
|
||||
backgroundContainer.setScrollingEnabled(false)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val window = window
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.statusBarColor = ContextCompat.getColor(this, R.color.black_20_alpha)
|
||||
}
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||
}
|
||||
|
||||
newGameButton.setOnClickListener { newGameButtonClicked() }
|
||||
showLoginButton.setOnClickListener { showLoginButtonClicked() }
|
||||
backButton.setOnClickListener { backButtonClicked() }
|
||||
forgotPasswordButton.setOnClickListener { onForgotPasswordClicked() }
|
||||
facebookLoginButton.setOnClickListener { handleFacebookLogin() }
|
||||
googleLoginButton.setOnClickListener { handleGoogleLogin() }
|
||||
}
|
||||
|
||||
private fun setupFacebookLogin() {
|
||||
callbackManager = CallbackManager.Factory.create()
|
||||
loginManager.registerCallback(callbackManager,
|
||||
object : FacebookCallback<LoginResult> {
|
||||
override fun onSuccess(loginResult: LoginResult) {
|
||||
Log.e("Login", "SUCCESS")
|
||||
val accessToken = AccessToken.getCurrentAccessToken()
|
||||
apiClient.connectSocial("facebook", accessToken.userId, accessToken.token)
|
||||
.subscribe(this@LoginActivity, Consumer { hideProgress() })
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
Log.e("Login", "CANCEL")
|
||||
}
|
||||
|
||||
override fun onError(exception: FacebookException) {
|
||||
exception.printStackTrace()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (isShowingForm) {
|
||||
hideForm()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
private fun resetLayout() {
|
||||
if (this.isRegistering) {
|
||||
if (this.mEmail.visibility == View.GONE) {
|
||||
show(this.mEmail)
|
||||
}
|
||||
if (this.mConfirmPassword.visibility == View.GONE) {
|
||||
show(this.mConfirmPassword)
|
||||
}
|
||||
} else {
|
||||
if (this.mEmail.visibility == View.VISIBLE) {
|
||||
hide(this.mEmail)
|
||||
}
|
||||
if (this.mConfirmPassword.visibility == View.VISIBLE) {
|
||||
hide(this.mConfirmPassword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startMainActivity() {
|
||||
val intent = Intent(this@LoginActivity, MainActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun startSetupActivity() {
|
||||
val intent = Intent(this@LoginActivity, SetupActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun toggleRegistering() {
|
||||
this.isRegistering = (!this.isRegistering)
|
||||
this.setRegistering()
|
||||
}
|
||||
|
||||
private fun setRegistering() {
|
||||
if (this.isRegistering) {
|
||||
this.mLoginNormalBtn.text = getString(R.string.register_btn)
|
||||
mUsernameET.setHint(R.string.username)
|
||||
mPasswordET.imeOptions = EditorInfo.IME_ACTION_NEXT
|
||||
} else {
|
||||
this.mLoginNormalBtn.text = getString(R.string.login_btn)
|
||||
mUsernameET.setHint(R.string.email_username)
|
||||
mPasswordET.imeOptions = EditorInfo.IME_ACTION_DONE
|
||||
}
|
||||
this.resetLayout()
|
||||
}
|
||||
|
||||
public override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent)
|
||||
callbackManager.onActivityResult(requestCode, resultCode, intent)
|
||||
val scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent)
|
||||
if (scanResult != null) {
|
||||
try {
|
||||
Log.d("scanresult", scanResult.contents)
|
||||
this.parse(scanResult.contents)
|
||||
} catch (e: Exception) {
|
||||
Log.e("scanresult", "Could not parse scanResult", e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
googleEmail = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME)
|
||||
handleGoogleLoginResult()
|
||||
}
|
||||
}
|
||||
if (requestCode == REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR) {
|
||||
handleGoogleLoginResult()
|
||||
}
|
||||
|
||||
if (requestCode == FacebookSdk.getCallbackRequestCodeOffset()) {
|
||||
//This is necessary because the regular login callback is not called for some reason
|
||||
val accessToken = AccessToken.getCurrentAccessToken()
|
||||
if (accessToken != null && accessToken.token != null) {
|
||||
apiClient.connectSocial("facebook", accessToken.userId, accessToken.token)
|
||||
.subscribe(this@LoginActivity, Consumer { hideProgress() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parse(contents: String) {
|
||||
val adr: String
|
||||
val user: String
|
||||
val key: String
|
||||
try {
|
||||
val obj = JSONObject(contents)
|
||||
|
||||
adr = obj.getString(TAG_ADDRESS)
|
||||
user = obj.getString(TAG_USERID)
|
||||
key = obj.getString(TAG_APIKEY)
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val editor = prefs.edit()
|
||||
val ans = editor.putString(getString(R.string.SP_address), adr)
|
||||
.putString(getString(R.string.SP_APIToken), key)
|
||||
.putString(getString(R.string.SP_userID), user)
|
||||
.commit()
|
||||
if (!ans) {
|
||||
throw Exception("PB_string_commit")
|
||||
}
|
||||
startMainActivity()
|
||||
} catch (e: JSONException) {
|
||||
showSnackbar(getString(R.string.ERR_pb_barcode))
|
||||
e.printStackTrace()
|
||||
} catch (e: Exception) {
|
||||
if ("PB_string_commit" == e.message) {
|
||||
showSnackbar(getString(R.string.ERR_pb_barcode))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun showSnackbar(content: String) {
|
||||
val snackbar = Snackbar
|
||||
.make(this.findViewById(R.id.login_linear_layout), content, Snackbar.LENGTH_LONG)
|
||||
|
||||
val snackbarView = snackbar.view
|
||||
snackbarView.setBackgroundColor(Color.RED)//change Snackbar's background color;
|
||||
snackbar.show() // Don’t forget to show!
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_toggleRegistering -> toggleRegistering()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun saveTokens(api: String, user: String) {
|
||||
this.apiClient.updateAuthenticationCredentials(user, api)
|
||||
val editor = sharedPrefs.edit()
|
||||
val ans = editor.putString(getString(R.string.SP_APIToken), api)
|
||||
.putString(getString(R.string.SP_userID), user)
|
||||
.commit()
|
||||
if (!ans) {
|
||||
throw Exception("PB_string_commit")
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideProgress() {
|
||||
runOnUiThread {
|
||||
mProgressBar.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun showValidationError(resourceMessageString: Int) {
|
||||
mProgressBar.visibility = View.GONE
|
||||
android.support.v7.app.AlertDialog.Builder(this)
|
||||
.setTitle(R.string.login_validation_error_title)
|
||||
.setMessage(resourceMessageString)
|
||||
.setNeutralButton(android.R.string.ok) { _, _ -> }
|
||||
.setIcon(R.drawable.ic_warning_black)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun accept(userAuthResponse: UserAuthResponse) {
|
||||
try {
|
||||
saveTokens(userAuthResponse.token, userAuthResponse.id)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
userRepository.retrieveUser(true)
|
||||
.subscribe(Consumer {
|
||||
if (userAuthResponse.newUser) {
|
||||
this.startSetupActivity()
|
||||
} else {
|
||||
AmplitudeManager.sendEvent("login", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT)
|
||||
this.startMainActivity()
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
fun handleFacebookLogin() {
|
||||
loginManager.logInWithReadPermissions(this, listOf("user_friends"))
|
||||
}
|
||||
|
||||
fun handleGoogleLogin() {
|
||||
if (!checkPlayServices()) {
|
||||
return
|
||||
}
|
||||
val accountTypes = arrayOf("com.google")
|
||||
val intent = AccountPicker.newChooseAccountIntent(null, null,
|
||||
accountTypes, false, null, null, null, null)
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
val dialog = AlertDialog.Builder(this)
|
||||
.setTitle(R.string.authentication_error_title)
|
||||
.setMessage(R.string.google_services_missing)
|
||||
.setNegativeButton(R.string.close) { dialogInterface, _ -> dialogInterface.dismiss() }
|
||||
.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun handleGoogleLoginResult() {
|
||||
val scopesString = Scopes.PROFILE + " " + Scopes.EMAIL
|
||||
val scopes = "oauth2:$scopesString"
|
||||
Flowable.defer<String> {
|
||||
try {
|
||||
return@defer Flowable.just(GoogleAuthUtil.getToken(this, googleEmail, scopes))
|
||||
} catch (e: IOException) {
|
||||
throw Exceptions.propagate(e)
|
||||
} catch (e: GoogleAuthException) {
|
||||
throw Exceptions.propagate(e)
|
||||
}
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMap { token -> apiClient.connectSocial("google", googleEmail ?: "", token) }
|
||||
.subscribe(this@LoginActivity, Consumer { throwable ->
|
||||
throwable.printStackTrace()
|
||||
hideProgress()
|
||||
throwable.cause.notNull {
|
||||
if (GoogleAuthException::class.java.isAssignableFrom(it.javaClass)) {
|
||||
handleGoogleAuthException(throwable.cause as GoogleAuthException)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
private fun handleGoogleAuthException(e: Exception) {
|
||||
if (e is GooglePlayServicesAvailabilityException) {
|
||||
// The Google Play services APK is old, disabled, or not present.
|
||||
// Show a dialog created by Google Play services that allows
|
||||
// the user to update the APK
|
||||
val statusCode = e
|
||||
.connectionStatusCode
|
||||
GoogleApiAvailability.getInstance()
|
||||
val dialog = GooglePlayServicesUtil.getErrorDialog(statusCode,
|
||||
this@LoginActivity,
|
||||
REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR)
|
||||
dialog.show()
|
||||
} else if (e is UserRecoverableAuthException) {
|
||||
// Unable to authenticate, such as when the user has not yet granted
|
||||
// the app access to the account, but the user can fix this.
|
||||
// Forward the user to an activity in Google Play services.
|
||||
val intent = e.intent
|
||||
startActivityForResult(intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPlayServices(): Boolean {
|
||||
val googleAPI = GoogleApiAvailability.getInstance()
|
||||
val result = googleAPI.isGooglePlayServicesAvailable(this)
|
||||
if (result != ConnectionResult.SUCCESS) {
|
||||
if (googleAPI.isUserResolvableError(result)) {
|
||||
googleAPI.getErrorDialog(this, result, PLAY_SERVICES_RESOLUTION_REQUEST).show()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun newGameButtonClicked() {
|
||||
isRegistering = true
|
||||
showForm()
|
||||
setRegistering()
|
||||
}
|
||||
|
||||
private fun showLoginButtonClicked() {
|
||||
isRegistering = false
|
||||
showForm()
|
||||
setRegistering()
|
||||
}
|
||||
|
||||
private fun backButtonClicked() {
|
||||
if (isShowingForm) {
|
||||
hideForm()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun showForm() {
|
||||
isShowingForm = true
|
||||
val panAnimation = ObjectAnimator.ofInt(backgroundContainer, "scrollY", 0).setDuration(1000)
|
||||
val newGameAlphaAnimation = ObjectAnimator.ofFloat<View>(newGameButton, View.ALPHA, 0.toFloat())
|
||||
val showLoginAlphaAnimation = ObjectAnimator.ofFloat<View>(showLoginButton, View.ALPHA, 0.toFloat())
|
||||
val scaleLogoAnimation = ValueAnimator.ofInt(logoView.measuredHeight, (logoView.measuredHeight * 0.75).toInt())
|
||||
scaleLogoAnimation.addUpdateListener { valueAnimator ->
|
||||
val `val` = valueAnimator.animatedValue as Int
|
||||
val layoutParams = logoView.layoutParams
|
||||
layoutParams.height = `val`
|
||||
logoView.layoutParams = layoutParams
|
||||
}
|
||||
if (isRegistering) {
|
||||
newGameAlphaAnimation.startDelay = 600
|
||||
newGameAlphaAnimation.duration = 400
|
||||
showLoginAlphaAnimation.duration = 400
|
||||
newGameAlphaAnimation.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
newGameButton.visibility = View.GONE
|
||||
showLoginButton.visibility = View.GONE
|
||||
scrollView.visibility = View.VISIBLE
|
||||
scrollView.alpha = 1f
|
||||
}
|
||||
})
|
||||
} else {
|
||||
showLoginAlphaAnimation.startDelay = 600
|
||||
showLoginAlphaAnimation.duration = 400
|
||||
newGameAlphaAnimation.duration = 400
|
||||
showLoginAlphaAnimation.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
newGameButton.visibility = View.GONE
|
||||
showLoginButton.visibility = View.GONE
|
||||
scrollView.visibility = View.VISIBLE
|
||||
scrollView.alpha = 1f
|
||||
}
|
||||
})
|
||||
}
|
||||
val backAlphaAnimation = ObjectAnimator.ofFloat<View>(backButton, View.ALPHA, 1.toFloat()).setDuration(800)
|
||||
val showAnimation = AnimatorSet()
|
||||
showAnimation.playTogether(panAnimation, newGameAlphaAnimation, showLoginAlphaAnimation, scaleLogoAnimation)
|
||||
showAnimation.play(backAlphaAnimation).after(panAnimation)
|
||||
for (i in 0 until formWrapper.childCount) {
|
||||
val view = formWrapper.getChildAt(i)
|
||||
view.alpha = 0f
|
||||
val animator = ObjectAnimator.ofFloat<View>(view, View.ALPHA, 1.toFloat()).setDuration(400)
|
||||
animator.startDelay = (100 * i).toLong()
|
||||
showAnimation.play(animator).after(panAnimation)
|
||||
}
|
||||
|
||||
showAnimation.start()
|
||||
}
|
||||
|
||||
private fun hideForm() {
|
||||
isShowingForm = false
|
||||
val panAnimation = ObjectAnimator.ofInt(backgroundContainer, "scrollY", backgroundContainer.bottom).setDuration(1000)
|
||||
val newGameAlphaAnimation = ObjectAnimator.ofFloat<View>(newGameButton, View.ALPHA, 1.toFloat()).setDuration(700)
|
||||
val showLoginAlphaAnimation = ObjectAnimator.ofFloat<View>(showLoginButton, View.ALPHA, 1.toFloat()).setDuration(700)
|
||||
val scaleLogoAnimation = ValueAnimator.ofInt(logoView.measuredHeight, (logoView.measuredHeight * 1.333333).toInt())
|
||||
scaleLogoAnimation.addUpdateListener { valueAnimator ->
|
||||
val value = valueAnimator.animatedValue as Int
|
||||
val layoutParams = logoView.layoutParams
|
||||
layoutParams.height = value
|
||||
logoView.layoutParams = layoutParams
|
||||
}
|
||||
showLoginAlphaAnimation.startDelay = 300
|
||||
val scrollViewAlphaAnimation = ObjectAnimator.ofFloat<View>(scrollView, View.ALPHA, 0.toFloat()).setDuration(800)
|
||||
scrollViewAlphaAnimation.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
newGameButton.visibility = View.VISIBLE
|
||||
showLoginButton.visibility = View.VISIBLE
|
||||
scrollView.visibility = View.INVISIBLE
|
||||
}
|
||||
})
|
||||
val backAlphaAnimation = ObjectAnimator.ofFloat<View>(backButton, View.ALPHA, 0.toFloat()).setDuration(800)
|
||||
val showAnimation = AnimatorSet()
|
||||
showAnimation.playTogether(panAnimation, scrollViewAlphaAnimation, backAlphaAnimation, scaleLogoAnimation)
|
||||
showAnimation.play(newGameAlphaAnimation).after(scrollViewAlphaAnimation)
|
||||
showAnimation.play(showLoginAlphaAnimation).after(scrollViewAlphaAnimation)
|
||||
showAnimation.start()
|
||||
UiUtils.dismissKeyboard(this)
|
||||
}
|
||||
|
||||
fun onForgotPasswordClicked() {
|
||||
val input = EditText(this)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
input.setAutofillHints(EditText.AUTOFILL_HINT_EMAIL_ADDRESS)
|
||||
}
|
||||
input.inputType = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
val lp = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT)
|
||||
input.layoutParams = lp
|
||||
val alertDialog = AlertDialog.Builder(this)
|
||||
.setTitle(R.string.forgot_password_title)
|
||||
.setMessage(R.string.forgot_password_description)
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.send) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
userRepository.sendPasswordResetEmail(input.text.toString()).subscribe(Consumer { showPasswordEmailConfirmation() }, RxErrorHandler.handleEmptyError())
|
||||
}.setNegativeButton(R.string.action_cancel) { dialog, _ -> dialog.dismiss() }
|
||||
|
||||
alertDialog.show()
|
||||
}
|
||||
|
||||
private fun showPasswordEmailConfirmation() {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage(R.string.forgot_password_confirmation)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal const val REQUEST_CODE_PICK_ACCOUNT = 1000
|
||||
private const val TAG_ADDRESS = "address"
|
||||
private const val TAG_USERID = "user"
|
||||
private const val TAG_APIKEY = "key"
|
||||
private const val REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001
|
||||
private const val PLAY_SERVICES_RESOLUTION_REQUEST = 9000
|
||||
|
||||
|
||||
fun show(v: View) {
|
||||
v.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
fun hide(v: View) {
|
||||
v.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,906 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.design.widget.AppBarLayout
|
||||
import android.support.design.widget.CollapsingToolbarLayout
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.content.FileProvider
|
||||
import android.support.v4.widget.DrawerLayout
|
||||
import android.support.v7.app.ActionBarDrawerToggle
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
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.api.MaintenanceApiService
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.*
|
||||
import com.habitrpg.android.habitica.events.*
|
||||
import com.habitrpg.android.habitica.events.commands.*
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.*
|
||||
import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager
|
||||
import com.habitrpg.android.habitica.interactors.*
|
||||
import com.habitrpg.android.habitica.models.TutorialStep
|
||||
import com.habitrpg.android.habitica.models.responses.MaintenanceResponse
|
||||
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
|
||||
import com.habitrpg.android.habitica.ui.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel
|
||||
import com.habitrpg.android.habitica.ui.TutorialView
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
|
||||
import com.habitrpg.android.habitica.ui.views.ValueBar
|
||||
import com.habitrpg.android.habitica.ui.views.yesterdailies.YesterdailyDialog
|
||||
import com.habitrpg.android.habitica.userpicture.BitmapUtils
|
||||
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.TodoListWidgetProvider
|
||||
import com.roughike.bottombar.BottomBar
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.functions.Action
|
||||
import io.reactivex.functions.Consumer
|
||||
import io.realm.Realm
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
|
||||
@Inject
|
||||
internal lateinit var apiClient: ApiClient
|
||||
@Inject
|
||||
internal lateinit var soundManager: SoundManager
|
||||
@Inject
|
||||
internal lateinit var maintenanceService: MaintenanceApiService
|
||||
@Inject
|
||||
internal lateinit var hostConfig: HostConfig
|
||||
@Inject
|
||||
internal lateinit var sharedPreferences: SharedPreferences
|
||||
@Inject
|
||||
internal lateinit var crashlyticsProxy: CrashlyticsProxy
|
||||
@Inject
|
||||
internal lateinit var pushNotificationManager: PushNotificationManager
|
||||
@Inject
|
||||
internal lateinit var habitScoreUseCase: HabitScoreUseCase
|
||||
@Inject
|
||||
internal lateinit var dailyCheckUseCase: DailyCheckUseCase
|
||||
@Inject
|
||||
internal lateinit var todoCheckUseCase: TodoCheckUseCase
|
||||
@Inject
|
||||
internal lateinit var buyRewardUseCase: BuyRewardUseCase
|
||||
@Inject
|
||||
internal lateinit var checklistCheckUseCase: ChecklistCheckUseCase
|
||||
@Inject
|
||||
internal lateinit var checkClassSelectionUseCase: CheckClassSelectionUseCase
|
||||
@Inject
|
||||
internal lateinit var displayItemDropUseCase: DisplayItemDropUseCase
|
||||
@Inject
|
||||
internal lateinit var notifyUserUseCase: NotifyUserUseCase
|
||||
@Inject
|
||||
internal lateinit var taskRepository: TaskRepository
|
||||
@Inject
|
||||
internal lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
internal lateinit var tagRepository: TagRepository
|
||||
@Inject
|
||||
internal lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
internal lateinit var taskAlarmManager: TaskAlarmManager
|
||||
@Inject
|
||||
internal lateinit var remoteConfigManager: RemoteConfigManager
|
||||
|
||||
val floatingMenuWrapper: ViewGroup by bindView(R.id.floating_menu_wrapper)
|
||||
private val bottomNavigation: BottomBar by bindView(R.id.bottom_navigation)
|
||||
|
||||
private val appBar: AppBarLayout by bindView(R.id.appbar)
|
||||
private val toolbar: Toolbar by bindView(R.id.toolbar)
|
||||
private val toolbarAccessoryContainer: FrameLayout by bindView(R.id.toolbar_accessory_container)
|
||||
private val toolbarTitleTextView: TextView by bindView(R.id.toolbar_title)
|
||||
private val collapsingToolbar: CollapsingToolbarLayout by bindView(R.id.collapsing_toolbar)
|
||||
private val detailTabs: TabLayout by bindView(R.id.detail_tabs)
|
||||
val avatarWithBars: View by bindView(R.id.avatar_with_bars)
|
||||
private val overlayLayout: ViewGroup by bindView(R.id.overlayFrameLayout)
|
||||
|
||||
var user: User? = null
|
||||
|
||||
private var activeFragment: WeakReference<BaseMainFragment>? = null
|
||||
private var avatarInHeader: AvatarWithBarsViewModel? = null
|
||||
private var faintDialog: AlertDialog? = null
|
||||
private var sideAvatarView: AvatarView? = null
|
||||
private var activeTutorialView: TutorialView? = null
|
||||
private var drawerFragment: NavigationDrawerFragment? = null
|
||||
private var drawerToggle: ActionBarDrawerToggle? = null
|
||||
private var keyboardUtil: KeyboardUtil? = null
|
||||
|
||||
private val statusBarHeight: Int
|
||||
get() {
|
||||
var result = 0
|
||||
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
|
||||
if (resourceId > 0) {
|
||||
result = resources.getDimensionPixelSize(resourceId)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
val userID: String
|
||||
get() = user?.id ?: ""
|
||||
|
||||
val isAppBarExpanded: Boolean
|
||||
get() = appBar.height - appBar.bottom == 0
|
||||
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_main
|
||||
}
|
||||
|
||||
@SuppressLint("ObsoleteSdkInt")
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val languageHelper = LanguageHelper(sharedPreferences.getString("language", "en"))
|
||||
Locale.setDefault(languageHelper.locale)
|
||||
val configuration = Configuration()
|
||||
if (SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
configuration.locale = languageHelper.locale
|
||||
} else {
|
||||
configuration.setLocale(languageHelper.locale)
|
||||
}
|
||||
resources.updateConfiguration(configuration,
|
||||
resources.displayMetrics)
|
||||
|
||||
|
||||
if (!HabiticaBaseApplication.checkUserAuthentication(this, hostConfig)) {
|
||||
return
|
||||
}
|
||||
|
||||
setupToolbar(toolbar)
|
||||
|
||||
avatarInHeader = AvatarWithBarsViewModel(this, avatarWithBars)
|
||||
sideAvatarView = AvatarView(this, true, false, false)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val window = window
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.statusBarColor = ContextCompat.getColor(this, R.color.black_10_alpha)
|
||||
}
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||
toolbar.setPadding(0, statusBarHeight, 0, 0)
|
||||
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics)
|
||||
avatarWithBars.setPadding(px.toInt(), statusBarHeight, px.toInt(), 0)
|
||||
}
|
||||
|
||||
userRepository.getUser(hostConfig.user)
|
||||
.subscribe(Consumer { newUser ->
|
||||
this@MainActivity.user = newUser
|
||||
this@MainActivity.setUserData()
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
||||
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
|
||||
|
||||
drawerFragment = supportFragmentManager.findFragmentById(R.id.navigation_drawer) as NavigationDrawerFragment
|
||||
|
||||
drawerFragment?.setUp(R.id.navigation_drawer, drawerLayout)
|
||||
drawerFragment?.setSelection(NavigationDrawerFragment.SIDEBAR_TASKS, true)
|
||||
|
||||
drawerToggle = object : ActionBarDrawerToggle(
|
||||
this, /* host Activity */
|
||||
findViewById(R.id.drawer_layout), /* DrawerLayout object */
|
||||
R.string.navigation_drawer_open, /* "open drawer" description */
|
||||
R.string.navigation_drawer_close /* "close drawer" description */
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
// Set the drawer toggle as the DrawerListener
|
||||
drawerToggle.notNull { drawerLayout.addDrawerListener(it) }
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setHomeButtonEnabled(true)
|
||||
|
||||
keyboardUtil = KeyboardUtil(this, this.findViewById(android.R.id.content))
|
||||
this.keyboardUtil?.enable()
|
||||
}
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
// Sync the toggle state after onRestoreInstanceState has occurred.
|
||||
drawerToggle?.syncState()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
drawerToggle?.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return if (drawerToggle?.onOptionsItemSelected(item) == true) {
|
||||
true
|
||||
} else super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
retrieveUser()
|
||||
this.checkMaintenance()
|
||||
|
||||
if (this.sharedPreferences.getLong("lastReminderSchedule", 0) < Date().time - 86400000) {
|
||||
try {
|
||||
taskAlarmManager.scheduleAllSavedAlarms()
|
||||
} catch (e: Exception) {
|
||||
crashlyticsProxy.logException(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//after the activity has been stopped and is thereafter resumed,
|
||||
//a state can arise in which the active fragment no longer has a
|
||||
//reference to the tabLayout (and all its adapters are null).
|
||||
//Recreate the fragment as a result.
|
||||
if (activeFragment?.get()?.tabLayout == null) {
|
||||
activeFragment = null
|
||||
var selection: String? = NavigationDrawerFragment.SIDEBAR_TASKS
|
||||
try {
|
||||
selection = this.sharedPreferences.getString("lastActivePosition", NavigationDrawerFragment.SIDEBAR_TASKS)
|
||||
} catch (ignored: java.lang.RuntimeException) {
|
||||
}
|
||||
|
||||
drawerFragment?.setSelection(selection, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
updateWidgets()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
private fun updateWidgets() {
|
||||
updateWidget(AvatarStatsWidgetProvider::class.java)
|
||||
updateWidget(TodoListWidgetProvider::class.java)
|
||||
updateWidget(DailiesWidgetProvider::class.java)
|
||||
updateWidget(HabitButtonWidgetProvider::class.java)
|
||||
}
|
||||
|
||||
private fun updateWidget(widgetClass: Class<*>) {
|
||||
val intent = Intent(this, widgetClass)
|
||||
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
val ids = AppWidgetManager.getInstance(application).getAppWidgetIds(ComponentName(application, widgetClass))
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
@SuppressLint("ObsoleteSdkInt")
|
||||
fun displayFragment(fragment: BaseMainFragment) {
|
||||
if (fragment.javaClass == this.activeFragment?.get()?.javaClass) {
|
||||
return
|
||||
}
|
||||
if (SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && this.isDestroyed) {
|
||||
return
|
||||
}
|
||||
this.activeFragment = WeakReference(fragment)
|
||||
fragment.arguments = intent.extras
|
||||
fragment.user = user
|
||||
fragment.activity = this
|
||||
fragment.tabLayout = detailTabs
|
||||
fragment.toolbarAccessoryContainer = toolbarAccessoryContainer
|
||||
fragment.collapsingToolbar = collapsingToolbar
|
||||
fragment.bottomNavigation = bottomNavigation
|
||||
fragment.floatingMenuWrapper = floatingMenuWrapper
|
||||
|
||||
|
||||
if (supportFragmentManager.fragments == null) {
|
||||
supportFragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commitAllowingStateLoss()
|
||||
} else {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
transaction.replace(R.id.fragment_container, fragment)
|
||||
if (fragment.addToBackStack()) {
|
||||
transaction.addToBackStack(null)
|
||||
}
|
||||
transaction.commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUserData() {
|
||||
if (user != null) {
|
||||
|
||||
val preferences = user?.preferences
|
||||
|
||||
preferences?.language.notNull { apiClient.setLanguageCode(it) }
|
||||
preferences?.language.notNull { soundManager.soundTheme = it }
|
||||
runOnUiThread {
|
||||
updateHeader()
|
||||
updateSidebar()
|
||||
if (activeFragment != null && activeFragment?.get() != null) {
|
||||
activeFragment?.get()?.updateUserData(user)
|
||||
} else {
|
||||
drawerFragment?.setSelection(NavigationDrawerFragment.SIDEBAR_TASKS, true)
|
||||
}
|
||||
}
|
||||
|
||||
displayDeathDialogIfNeeded()
|
||||
YesterdailyDialog.showDialogIfNeeded(this, user?.id, userRepository, taskRepository)
|
||||
|
||||
displayNewInboxMessagesBadge()
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayNewInboxMessagesBadge() {
|
||||
/*int numberOfUnreadPms = this.user.getInbox().getNewMessages();
|
||||
IDrawerItem newInboxItem;
|
||||
|
||||
if (numberOfUnreadPms <= 0) {
|
||||
newInboxItem = new PrimaryDrawerItem()
|
||||
.withName(this.getString(R.string.sidebar_inbox))
|
||||
.withIdentifier(MainDrawerBuilder.INSTANCE.getSIDEBAR_INBOX());
|
||||
} else {
|
||||
String numberOfUnreadPmsLabel = String.valueOf(numberOfUnreadPms);
|
||||
BadgeStyle badgeStyle = new BadgeStyle()
|
||||
.withTextColor(Color.WHITE)
|
||||
.withColorRes(R.color.md_red_700);
|
||||
|
||||
newInboxItem = new PrimaryDrawerItem()
|
||||
.withName(this.getString(R.string.sidebar_inbox))
|
||||
.withIdentifier(MainDrawerBuilder.INSTANCE.getSIDEBAR_INBOX())
|
||||
.withBadge(numberOfUnreadPmsLabel)
|
||||
.withBadgeStyle(badgeStyle);
|
||||
}
|
||||
if (this.drawerFragment != null) {
|
||||
this.drawer.updateItemAtPosition(newInboxItem, this.drawer.getPosition(MainDrawerBuilder.INSTANCE.getSIDEBAR_INBOX()));
|
||||
}*/
|
||||
}
|
||||
|
||||
private fun updateHeader() {
|
||||
user.notNull { avatarInHeader?.updateData(it) }
|
||||
if (activeFragment != null) {
|
||||
setTranslatedFragmentTitle(activeFragment?.get())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSidebar() {
|
||||
drawerFragment?.setUsername(user?.profile?.name)
|
||||
|
||||
if (user?.preferences == null || user?.flags == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val specialItems = user?.items?.special
|
||||
var hasSpecialItems = false
|
||||
if (specialItems != null) {
|
||||
hasSpecialItems = specialItems.hasSpecialItems()
|
||||
}
|
||||
val item = drawerFragment?.getItemWithIdentifier(NavigationDrawerFragment.SIDEBAR_SKILLS)
|
||||
if (item != null) {
|
||||
if (user?.hasClass() == false && (!hasSpecialItems)) {
|
||||
item.isVisible = false
|
||||
} else {
|
||||
if (user?.stats?.getLvl() ?: 0 < HabiticaSnackbar.MIN_LEVEL_FOR_SKILLS && (!hasSpecialItems)) {
|
||||
item.additionalInfo = getString(R.string.unlock_lvl_11)
|
||||
} else {
|
||||
item.additionalInfo = null
|
||||
}
|
||||
item.isVisible = true
|
||||
}
|
||||
drawerFragment?.updateItem(item)
|
||||
}
|
||||
val statsItem = drawerFragment?.getItemWithIdentifier(NavigationDrawerFragment.SIDEBAR_STATS)
|
||||
if (statsItem != null) {
|
||||
if (user?.stats?.lvl ?: 0 >= 0 && user?.stats?.points ?: 0 > 0) {
|
||||
statsItem.additionalInfo = user?.stats?.points.toString()
|
||||
} else {
|
||||
statsItem.additionalInfo = null
|
||||
}
|
||||
drawerFragment?.updateItem(statsItem)
|
||||
}
|
||||
}
|
||||
|
||||
fun setActiveFragment(fragment: BaseMainFragment?) {
|
||||
this.activeFragment = WeakReference<BaseMainFragment>(fragment)
|
||||
setTranslatedFragmentTitle(fragment)
|
||||
if (activeFragment?.get() != null) {
|
||||
this.drawerFragment?.setSelection(this.activeFragment?.get()?.fragmentSidebarIdentifier, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setTranslatedFragmentTitle(fragment: BaseMainFragment?) {
|
||||
if (supportActionBar == null) {
|
||||
return
|
||||
}
|
||||
if (fragment?.customTitle() != null) {
|
||||
toolbarTitleTextView.text = fragment.customTitle()
|
||||
} else if (user?.profile != null) {
|
||||
toolbarTitleTextView.text = user?.profile?.name
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (this.activeTutorialView != null) {
|
||||
this.removeActiveTutorialView()
|
||||
}
|
||||
if (drawerFragment?.isDrawerOpen == true) {
|
||||
drawerFragment?.closeDrawer()
|
||||
} else {
|
||||
try {
|
||||
super.onBackPressed()
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
this.activeFragment?.get()?.updateUserData(user)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
|
||||
if (resultCode == SELECT_CLASS_RESULT) {
|
||||
retrieveUser()
|
||||
} else if (requestCode == GEM_PURCHASE_REQUEST) {
|
||||
retrieveUser()
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
// region Events
|
||||
|
||||
public override fun onDestroy() {
|
||||
userRepository.close()
|
||||
tagRepository.close()
|
||||
inventoryRepository.close()
|
||||
keyboardUtil?.disable()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: OpenMenuItemCommand) {
|
||||
drawerFragment?.setSelection(event.identifier, true)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: BuyRewardCommand) {
|
||||
val rewardKey = event.Reward.id
|
||||
|
||||
if (user?.stats?.getGp() ?: 0.toDouble() < event.Reward.value) {
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.no_gold), SnackbarDisplayType.FAILURE)
|
||||
return
|
||||
}
|
||||
|
||||
if ("potion" == rewardKey) {
|
||||
val currentHp = user?.stats?.getHp()?.toInt()
|
||||
val maxHp = user?.stats?.maxHealth
|
||||
|
||||
if (currentHp == maxHp) {
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.no_potion), SnackbarDisplayType.FAILURE_BLUE)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (event.Reward.specialTag != null && event.Reward.specialTag == "item") {
|
||||
inventoryRepository.buyItem(user, event.Reward.id, event.Reward.value)
|
||||
.subscribe(Consumer { buyResponse ->
|
||||
var snackbarMessage = getString(R.string.successful_purchase, event.Reward.text)
|
||||
if (event.Reward.id == "armoire") {
|
||||
snackbarMessage = when {
|
||||
buyResponse.armoire["type"] == "gear" -> applicationContext.getString(R.string.armoireEquipment, buyResponse.armoire["dropText"])
|
||||
buyResponse.armoire["type"] == "food" -> applicationContext.getString(R.string.armoireFood, buyResponse.armoire["dropArticle"], buyResponse.armoire["dropText"])
|
||||
else -> applicationContext.getString(R.string.armoireExp)
|
||||
}
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop)
|
||||
}
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, null, snackbarMessage, BitmapDrawable(resources, HabiticaIconsHelper.imageOfGold()), ContextCompat.getColor(this, R.color.yellow_10), "-" + event.Reward.value, SnackbarDisplayType.NORMAL)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
} else {
|
||||
buyRewardUseCase.observable(BuyRewardUseCase.RequestValues(user, event.Reward))
|
||||
.subscribe(Consumer {
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, null, getString(R.string.notification_purchase_reward),
|
||||
BitmapDrawable(resources, HabiticaIconsHelper.imageOfGold()),
|
||||
ContextCompat.getColor(this, R.color.yellow_10),
|
||||
"-" + event.Reward.value.toInt(),
|
||||
SnackbarDisplayType.DROP)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun openMysteryItem(event: OpenMysteryItemEvent) {
|
||||
inventoryRepository.openMysteryItem(user)
|
||||
.flatMap { userRepository.retrieveUser(false) }
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun openGemPurchaseFragment(cmd: OpenGemPurchaseFragmentCommand?) {
|
||||
drawerFragment?.setSelection(NavigationDrawerFragment.SIDEBAR_PURCHASE, true)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(tutorialEvent: DisplayTutorialEvent) {
|
||||
if (tutorialEvent.tutorialText != null) {
|
||||
this.displayTutorialStep(tutorialEvent.step, tutorialEvent.tutorialText, tutorialEvent.canBeDeferred)
|
||||
} else {
|
||||
this.displayTutorialStep(tutorialEvent.step, tutorialEvent.tutorialTexts, tutorialEvent.canBeDeferred)
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: DisplayFragmentEvent) {
|
||||
this.displayFragment(event.fragment)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: HatchingCommand) {
|
||||
if (event.usingEgg == null || event.usingHatchingPotion == null) {
|
||||
return
|
||||
}
|
||||
this.inventoryRepository.hatchPet(event.usingEgg, event.usingHatchingPotion)
|
||||
.subscribe(Consumer {
|
||||
val petWrapper = View.inflate(this, R.layout.pet_imageview, null) as FrameLayout
|
||||
val petImageView = petWrapper.findViewById<View>(R.id.pet_imageview) as SimpleDraweeView
|
||||
|
||||
DataBindingUtils.loadImage(petImageView, "Pet-" + event.usingEgg.key + "-" + event.usingHatchingPotion.key)
|
||||
val potionName = event.usingHatchingPotion.text
|
||||
val eggName = event.usingEgg.text
|
||||
val dialog = AlertDialog.Builder(this@MainActivity)
|
||||
.setTitle(getString(R.string.hatched_pet_title, potionName, eggName))
|
||||
.setView(petWrapper)
|
||||
.setPositiveButton(R.string.close) { hatchingDialog, _ -> hatchingDialog.dismiss() }
|
||||
.setNeutralButton(R.string.share) { hatchingDialog, _ ->
|
||||
val event1 = ShareEvent()
|
||||
event1.sharedMessage = getString(R.string.share_hatched, potionName, eggName) + " https://habitica.com/social/hatch-pet"
|
||||
val sharedImage = Bitmap.createBitmap(140, 140, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(sharedImage)
|
||||
canvas.drawColor(ContextCompat.getColor(this, R.color.brand_300))
|
||||
petImageView.drawable.draw(canvas)
|
||||
event1.shareImage = sharedImage
|
||||
EventBus.getDefault().post(event1)
|
||||
hatchingDialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
dialog.show()
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: FeedCommand) {
|
||||
if (event.usingFood == null || event.usingPet == null) {
|
||||
return
|
||||
}
|
||||
val pet = event.usingPet
|
||||
this.inventoryRepository.feedPet(event.usingPet, event.usingFood)
|
||||
.subscribe(Consumer { feedResponse ->
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.notification_pet_fed, pet.colorText, pet.animalText), SnackbarDisplayType.NORMAL)
|
||||
if (feedResponse.value == -1) {
|
||||
val mountWrapper = View.inflate(this, R.layout.pet_imageview, null) as FrameLayout
|
||||
val mountImageView = mountWrapper.findViewById<View>(R.id.pet_imageview) as SimpleDraweeView
|
||||
|
||||
DataBindingUtils.loadImage(mountImageView, "Mount_Icon_" + event.usingPet.key)
|
||||
val colorName = event.usingPet.colorText
|
||||
val animalName = event.usingPet.animalText
|
||||
val dialog = AlertDialog.Builder(this@MainActivity)
|
||||
.setTitle(getString(R.string.evolved_pet_title, colorName, animalName))
|
||||
.setView(mountWrapper)
|
||||
.setPositiveButton(R.string.close) { hatchingDialog, _ -> hatchingDialog.dismiss() }
|
||||
.setNeutralButton(R.string.share) { hatchingDialog, _ ->
|
||||
val event1 = ShareEvent()
|
||||
event1.sharedMessage = getString(R.string.share_raised, colorName, animalName) + " https://habitica.com/social/raise-pet"
|
||||
val sharedImage = Bitmap.createBitmap(99, 99, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(sharedImage)
|
||||
canvas.drawColor(ContextCompat.getColor(this, R.color.brand_300))
|
||||
mountImageView.drawable.draw(canvas)
|
||||
event1.shareImage = sharedImage
|
||||
EventBus.getDefault().post(event1)
|
||||
hatchingDialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
dialog.show()
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
private fun displayTaskScoringResponse(data: TaskScoringResult?) {
|
||||
if (user != null && data != null) {
|
||||
notifyUserUseCase.observable(NotifyUserUseCase.RequestValues(this, floatingMenuWrapper,
|
||||
user, data.experienceDelta, data.healthDelta, data.goldDelta, data.manaDelta, data.questDamage, data.hasLeveledUp))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
displayItemDropUseCase.observable(DisplayItemDropUseCase.RequestValues(data, this, floatingMenuWrapper))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
|
||||
private fun displayDeathDialogIfNeeded() {
|
||||
|
||||
if (user?.stats?.getHp() == null || user?.stats?.getHp() ?: 0.toDouble() > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.faintDialog == null && !this.isFinishing) {
|
||||
|
||||
val customView = View.inflate(this, R.layout.dialog_faint, null)
|
||||
if (customView != null) {
|
||||
val hpBarView = customView.findViewById<View>(R.id.hpBar) as ValueBar
|
||||
|
||||
hpBarView.setLightBackground(true)
|
||||
hpBarView.setIcon(HabiticaIconsHelper.imageOfHeartLightBg())
|
||||
|
||||
val dialogAvatarView = customView.findViewById<View>(R.id.avatarView) as AvatarView
|
||||
user.notNull { dialogAvatarView.setAvatar(it) }
|
||||
}
|
||||
|
||||
this.faintDialog = AlertDialog.Builder(this)
|
||||
.setTitle(R.string.faint_header)
|
||||
.setView(customView)
|
||||
.setPositiveButton(R.string.faint_button) { _, _ ->
|
||||
faintDialog = null
|
||||
user.notNull {
|
||||
userRepository.revive(it).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
.create()
|
||||
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundDeath)
|
||||
this.faintDialog?.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
drawerFragment?.openDrawer()
|
||||
return true
|
||||
}
|
||||
|
||||
return super.onKeyUp(keyCode, event)
|
||||
}
|
||||
|
||||
protected fun retrieveUser() {
|
||||
if (hostConfig.hasAuthentication()) {
|
||||
this.userRepository.retrieveUser(true)
|
||||
.doOnNext { user1 ->
|
||||
pushNotificationManager.setUser(user1)
|
||||
pushNotificationManager.addPushDeviceUsingStoredToken()
|
||||
}
|
||||
.flatMap { userRepository.retrieveInboxMessages() }
|
||||
.flatMap { inventoryRepository.retrieveContent(false) }
|
||||
.flatMap { inventoryRepository.retrieveWorldState() }
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun displayClassSelectionActivity(event: SelectClassEvent) {
|
||||
checkClassSelectionUseCase.observable(CheckClassSelectionUseCase.RequestValues(user, event, this))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun displayTutorialStep(step: TutorialStep, text: String, canBeDeferred: Boolean) {
|
||||
val view = TutorialView(this, step, this)
|
||||
this.activeTutorialView = view
|
||||
view.setTutorialText(text)
|
||||
view.onReaction = this
|
||||
view.setCanBeDeferred(canBeDeferred)
|
||||
this.overlayLayout.addView(view)
|
||||
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["eventLabel"] = step.identifier + "-android"
|
||||
additionalData["eventValue"] = step.identifier ?: ""
|
||||
additionalData["complete"] = false
|
||||
AmplitudeManager.sendEvent("tutorial", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
|
||||
}
|
||||
|
||||
private fun displayTutorialStep(step: TutorialStep, texts: List<String>, canBeDeferred: Boolean) {
|
||||
val view = TutorialView(this, step, this)
|
||||
this.activeTutorialView = view
|
||||
view.setTutorialTexts(texts)
|
||||
view.onReaction = this
|
||||
view.setCanBeDeferred(canBeDeferred)
|
||||
this.overlayLayout.addView(view)
|
||||
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["eventLabel"] = step.identifier + "-android"
|
||||
additionalData["eventValue"] = step.identifier ?: ""
|
||||
additionalData["complete"] = false
|
||||
AmplitudeManager.sendEvent("tutorial", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
|
||||
}
|
||||
|
||||
override fun onTutorialCompleted(step: TutorialStep) {
|
||||
val path = "flags.tutorial." + step.tutorialGroup + "." + step.identifier
|
||||
val updateData = HashMap<String, Any>()
|
||||
updateData[path] = true
|
||||
userRepository.updateUser(user, updateData)
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
this.overlayLayout.removeView(this.activeTutorialView)
|
||||
this.removeActiveTutorialView()
|
||||
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["eventLabel"] = step.identifier + "-android"
|
||||
additionalData["eventValue"] = step.identifier ?: ""
|
||||
additionalData["complete"] = true
|
||||
AmplitudeManager.sendEvent("tutorial", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
|
||||
}
|
||||
|
||||
override fun onTutorialDeferred(step: TutorialStep) {
|
||||
taskRepository.executeTransaction(Realm.Transaction { step.displayedOn = Date() })
|
||||
|
||||
this.removeActiveTutorialView()
|
||||
}
|
||||
|
||||
private fun removeActiveTutorialView() {
|
||||
if (this.activeTutorialView != null) {
|
||||
this.overlayLayout.removeView(this.activeTutorialView)
|
||||
this.activeTutorialView = null
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun shareEvent(event: ShareEvent) {
|
||||
val sharingIntent = Intent(Intent.ACTION_SEND)
|
||||
sharingIntent.type = "*/*"
|
||||
sharingIntent.putExtra(Intent.EXTRA_TEXT, event.sharedMessage)
|
||||
val f = BitmapUtils.saveToShareableFile(filesDir.toString() + "/shared_images", "share.png", event.shareImage)
|
||||
val fileUri = FileProvider.getUriForFile(this, getString(R.string.content_provider), f)
|
||||
sharingIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
|
||||
val resInfoList = this.packageManager.queryIntentActivities(sharingIntent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||
for (resolveInfo in resInfoList) {
|
||||
val packageName = resolveInfo.activityInfo.packageName
|
||||
this.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
startActivity(Intent.createChooser(sharingIntent, getString(R.string.share_using)))
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: TaskCheckedCommand) {
|
||||
when (event.Task.type) {
|
||||
Task.TYPE_DAILY -> {
|
||||
dailyCheckUseCase.observable(DailyCheckUseCase.RequestValues(user, event.Task, !event.Task.completed))
|
||||
.subscribe(Consumer<TaskScoringResult> { this.displayTaskScoringResponse(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
todoCheckUseCase.observable(TodoCheckUseCase.RequestValues(user, event.Task, !event.Task.completed))
|
||||
.subscribe(Consumer<TaskScoringResult> { this.displayTaskScoringResponse(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: ChecklistCheckedCommand) {
|
||||
checklistCheckUseCase.observable(ChecklistCheckUseCase.RequestValues(event.task.id, event.item.id)).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: HabitScoreEvent) {
|
||||
habitScoreUseCase.observable(HabitScoreUseCase.RequestValues(user, event.habit, event.Up))
|
||||
.subscribe(Consumer<TaskScoringResult> { this.displayTaskScoringResponse(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun checkMaintenance() {
|
||||
this.maintenanceService.maintenanceStatus
|
||||
.compose(apiClient.configureApiCallObserver())
|
||||
.subscribe(Consumer { maintenanceResponse ->
|
||||
if (maintenanceResponse == null) {
|
||||
return@Consumer
|
||||
}
|
||||
if (maintenanceResponse.activeMaintenance) {
|
||||
val intent = createMaintenanceIntent(maintenanceResponse, false)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
if (maintenanceResponse.minBuild != null) {
|
||||
try {
|
||||
val packageInfo = packageManager.getPackageInfo(packageName, 0)
|
||||
if (packageInfo.versionCode < maintenanceResponse.minBuild) {
|
||||
val intent = createMaintenanceIntent(maintenanceResponse, true)
|
||||
startActivity(intent)
|
||||
}
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun createMaintenanceIntent(maintenanceResponse: MaintenanceResponse, isDeprecationNotice: Boolean): Intent {
|
||||
val intent = Intent(this, MaintenanceActivity::class.java)
|
||||
val data = Bundle()
|
||||
data.putString("title", maintenanceResponse.title)
|
||||
data.putString("imageUrl", maintenanceResponse.imageUrl)
|
||||
data.putString("description", maintenanceResponse.description)
|
||||
data.putBoolean("deprecationNotice", isDeprecationNotice)
|
||||
intent.putExtras(data)
|
||||
return intent
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showSnackBarEvent(event: ShowSnackbarEvent) {
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, event.leftImage, event.title, event.text, event.specialView, event.rightIcon, event.rightTextColor, event.rightText, event.type)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showCheckinDialog(event: ShowCheckinDialog) {
|
||||
val title = event.notification.data.message
|
||||
|
||||
val factory = LayoutInflater.from(this)
|
||||
val view = factory.inflate(R.layout.dialog_login_incentive, null)
|
||||
|
||||
val imageView = view.findViewById<View>(R.id.imageView) as SimpleDraweeView
|
||||
val imageKey = event.notification.data.rewardKey[0]
|
||||
DataBindingUtils.loadImage(imageView, imageKey)
|
||||
|
||||
val youEarnedMessage = this.getString(R.string.checkInRewardEarned, event.notification.data.rewardText)
|
||||
|
||||
val titleTextView = TextView(this)
|
||||
titleTextView.setBackgroundResource(R.color.blue_100)
|
||||
titleTextView.setTextColor(ContextCompat.getColor(this, R.color.white))
|
||||
val density = this.resources.displayMetrics.density
|
||||
val paddingDp = (16 * density).toInt()
|
||||
titleTextView.setPadding(paddingDp, paddingDp, paddingDp, paddingDp)
|
||||
titleTextView.textSize = 18f
|
||||
titleTextView.gravity = Gravity.CENTER_HORIZONTAL
|
||||
titleTextView.text = title
|
||||
|
||||
val youEarnedTexView = view.findViewById<View>(R.id.you_earned_message) as TextView
|
||||
youEarnedTexView.text = youEarnedMessage
|
||||
|
||||
val nextUnlockTextView = view.findViewById<View>(R.id.next_unlock_message) as TextView
|
||||
nextUnlockTextView.text = event.nextUnlockText
|
||||
|
||||
val builder = AlertDialog.Builder(this, R.style.AlertDialogTheme)
|
||||
.setView(view)
|
||||
.setCustomTitle(titleTextView)
|
||||
.setPositiveButton(R.string.start_day) { _, _ ->
|
||||
apiClient.readNotification(event.notification.id)
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
.setMessage("")
|
||||
|
||||
Completable.complete()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(Action {
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val SELECT_CLASS_RESULT = 11
|
||||
const val GEM_PURCHASE_REQUEST = 111
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.api.MaintenanceApiService;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
|
||||
|
||||
import net.pherth.android.emoji_library.EmojiTextView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class MaintenanceActivity extends BaseActivity {
|
||||
|
||||
@Inject
|
||||
public MaintenanceApiService maintenanceService;
|
||||
|
||||
@Inject
|
||||
public ApiClient apiClient;
|
||||
|
||||
@BindView(R.id.titleTextView)
|
||||
TextView titleTextView;
|
||||
@BindView(R.id.imageView)
|
||||
SimpleDraweeView imageView;
|
||||
@BindView(R.id.descriptionTextView)
|
||||
EmojiTextView descriptionTextView;
|
||||
@BindView(R.id.playStoreButton)
|
||||
Button playStoreButton;
|
||||
private Boolean isDeprecationNotice;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_maintenance;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Bundle data = getIntent().getExtras();
|
||||
|
||||
this.titleTextView.setText(data.getString("title"));
|
||||
|
||||
imageView.setImageURI(Uri.parse(data.getString("imageUrl")));
|
||||
this.descriptionTextView.setText(MarkdownParser.INSTANCE.parseMarkdown(data.getString("description")));
|
||||
this.descriptionTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
isDeprecationNotice = data.getBoolean("deprecationNotice");
|
||||
if (isDeprecationNotice) {
|
||||
this.playStoreButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
this.playStoreButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (!isDeprecationNotice) {
|
||||
this.maintenanceService.getMaintenanceStatus()
|
||||
.compose(apiClient.configureApiCallObserver())
|
||||
.subscribe(maintenanceResponse -> {
|
||||
if (!maintenanceResponse.activeMaintenance) {
|
||||
finish();
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.playStoreButton)
|
||||
public void openInPlayStore() {
|
||||
final String appPackageName = getPackageName();
|
||||
try {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
|
||||
} catch (android.content.ActivityNotFoundException anfe) {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.api.MaintenanceApiService
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiTextView
|
||||
import javax.inject.Inject
|
||||
|
||||
class MaintenanceActivity : BaseActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var maintenanceService: MaintenanceApiService
|
||||
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
|
||||
internal val titleTextView: TextView by bindView(R.id.titleTextView)
|
||||
internal val imageView: SimpleDraweeView by bindView(R.id.imageView)
|
||||
internal val descriptionTextView: EmojiTextView by bindView(R.id.descriptionTextView)
|
||||
internal val playStoreButton: Button by bindView(R.id.playStoreButton)
|
||||
private var isDeprecationNotice: Boolean = false
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_maintenance
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val data = intent.extras
|
||||
|
||||
this.titleTextView.text = data?.getString("title")
|
||||
|
||||
imageView.setImageURI(Uri.parse(data.getString("imageUrl")))
|
||||
this.descriptionTextView.text = MarkdownParser.parseMarkdown(data.getString("description"))
|
||||
this.descriptionTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
isDeprecationNotice = data.getBoolean("deprecationNotice")
|
||||
if (isDeprecationNotice) {
|
||||
this.playStoreButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
this.playStoreButton.visibility = View.GONE
|
||||
}
|
||||
|
||||
playStoreButton.setOnClickListener { openInPlayStore() }
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!isDeprecationNotice) {
|
||||
this.maintenanceService.maintenanceStatus
|
||||
.compose(apiClient.configureApiCallObserver())
|
||||
.subscribe(Consumer { maintenanceResponse ->
|
||||
if (!maintenanceResponse.activeMaintenance) {
|
||||
finish()
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
fun openInPlayStore() {
|
||||
val appPackageName = packageName
|
||||
try {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$appPackageName")))
|
||||
} catch (anfe: android.content.ActivityNotFoundException) {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$appPackageName")))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.SocialRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator;
|
||||
import com.habitrpg.android.habitica.prefs.scanner.IntentResult;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyInviteFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class PartyInviteActivity extends BaseActivity {
|
||||
|
||||
public static final int RESULT_SEND_INVITES = 100;
|
||||
public static final String USER_IDS_KEY = "userIDs";
|
||||
public static final String IS_EMAIL_KEY = "isEmail";
|
||||
public static final String EMAILS_KEY = "emails";
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
protected String userId;
|
||||
@Inject
|
||||
SocialRepository socialRepository;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.viewPager)
|
||||
ViewPager viewPager;
|
||||
List<PartyInviteFragment> fragments = new ArrayList<>();
|
||||
private String userIdToInvite;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_party_invite;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
setViewPagerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_party_invite, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_send_invites) {
|
||||
setResult(Activity.RESULT_OK, createResultIntent());
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private Intent createResultIntent() {
|
||||
Intent intent = new Intent();
|
||||
PartyInviteFragment fragment = fragments.get(viewPager.getCurrentItem());
|
||||
if (viewPager.getCurrentItem() == 0) {
|
||||
intent.putExtra(PartyInviteActivity.IS_EMAIL_KEY, true);
|
||||
intent.putExtra(PartyInviteActivity.EMAILS_KEY, fragment.getValues());
|
||||
} else {
|
||||
intent.putExtra(PartyInviteActivity.IS_EMAIL_KEY, false);
|
||||
intent.putExtra(PartyInviteActivity.USER_IDS_KEY, fragment.getValues());
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
|
||||
PartyInviteFragment fragment = new PartyInviteFragment();
|
||||
fragment.setEmailInvite(position == 0);
|
||||
if (fragments.size() > position) {
|
||||
fragments.set(position, fragment);
|
||||
} else {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getString(R.string.by_email);
|
||||
case 1:
|
||||
return getString(R.string.invite_existing_users);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (scanningResult != null && scanningResult.getContents() != null) {
|
||||
String qrCodeUrl = scanningResult.getContents();
|
||||
Uri uri = Uri.parse(qrCodeUrl);
|
||||
if (uri == null || uri.getPathSegments().size() < 3) {
|
||||
return;
|
||||
}
|
||||
userIdToInvite = uri.getPathSegments().get(2);
|
||||
|
||||
userRepository.getUser(userId).subscribe(this::handleUserRecieved, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
public void handleUserRecieved(User user) {
|
||||
|
||||
if (this.userIdToInvite == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Toast toast = Toast.makeText(getApplicationContext(),
|
||||
"Invited: " + userIdToInvite, Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
|
||||
Map<String, Object> inviteData = new HashMap<>();
|
||||
List<String> invites = new ArrayList<>();
|
||||
invites.add(userIdToInvite);
|
||||
inviteData.put("uuids", invites);
|
||||
|
||||
this.socialRepository.inviteToGroup(user.getParty().getId(), inviteData)
|
||||
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyInviteFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.functions.Consumer
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class PartyInviteActivity : BaseActivity() {
|
||||
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userId: String
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
internal val tabLayout: TabLayout by bindView(R.id.tab_layout)
|
||||
internal val viewPager: ViewPager by bindView(R.id.viewPager)
|
||||
|
||||
internal var fragments: MutableList<PartyInviteFragment> = ArrayList()
|
||||
private var userIdToInvite: String? = null
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_party_invite
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
viewPager.currentItem = 0
|
||||
|
||||
setViewPagerAdapter()
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_party_invite, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
val id = item.itemId
|
||||
|
||||
|
||||
if (id == R.id.action_send_invites) {
|
||||
setResult(Activity.RESULT_OK, createResultIntent())
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun createResultIntent(): Intent {
|
||||
val intent = Intent()
|
||||
val fragment = fragments[viewPager.currentItem]
|
||||
if (viewPager.currentItem == 0) {
|
||||
intent.putExtra(PartyInviteActivity.IS_EMAIL_KEY, true)
|
||||
intent.putExtra(PartyInviteActivity.EMAILS_KEY, fragment.values)
|
||||
} else {
|
||||
intent.putExtra(PartyInviteActivity.IS_EMAIL_KEY, false)
|
||||
intent.putExtra(PartyInviteActivity.USER_IDS_KEY, fragment.values)
|
||||
}
|
||||
return intent
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = supportFragmentManager
|
||||
|
||||
viewPager.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
|
||||
val fragment = PartyInviteFragment()
|
||||
fragment.isEmailInvite = position == 0
|
||||
if (fragments.size > position) {
|
||||
fragments[position] = fragment
|
||||
} else {
|
||||
fragments.add(fragment)
|
||||
}
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
when (position) {
|
||||
0 -> return getString(R.string.by_email)
|
||||
1 -> return getString(R.string.invite_existing_users)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
tabLayout.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
val scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
|
||||
|
||||
if (scanningResult != null && scanningResult.contents != null) {
|
||||
val qrCodeUrl = scanningResult.contents
|
||||
val uri = Uri.parse(qrCodeUrl)
|
||||
if (uri == null || uri.pathSegments.size < 3) {
|
||||
return
|
||||
}
|
||||
userIdToInvite = uri.pathSegments[2]
|
||||
|
||||
userRepository.getUser(userId).subscribe(Consumer<User> { this.handleUserReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUserReceived(user: User) {
|
||||
if (this.userIdToInvite == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val toast = Toast.makeText(applicationContext,
|
||||
"Invited: " + userIdToInvite!!, Toast.LENGTH_LONG)
|
||||
toast.show()
|
||||
|
||||
val inviteData = HashMap<String, Any>()
|
||||
val invites = ArrayList<String>()
|
||||
userIdToInvite.notNull {
|
||||
invites.add(it)
|
||||
}
|
||||
inviteData["uuids"] = invites
|
||||
|
||||
this.socialRepository.inviteToGroup(user.party.getId(), inviteData)
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val RESULT_SEND_INVITES = 100
|
||||
const val USER_IDS_KEY = "userIDs"
|
||||
const val IS_EMAIL_KEY = "isEmail"
|
||||
const val EMAILS_KEY = "emails"
|
||||
}
|
||||
}
|
||||
|
|
@ -26,8 +26,8 @@ class PrefsActivity : BaseActivity(), PreferenceFragmentCompat.OnPreferenceStart
|
|||
.commit()
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent) {
|
||||
component.inject(this)
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
|
|
|
|||
|
|
@ -1,293 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.content.res.AppCompatResources;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.api.HostConfig;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.events.commands.EquipCommand;
|
||||
import com.habitrpg.android.habitica.events.commands.UpdateUserCommand;
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.AvatarSetupFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.TaskSetupFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.WelcomeFragment;
|
||||
import com.habitrpg.android.habitica.ui.views.FadingViewPager;
|
||||
import com.viewpagerindicator.IconPageIndicator;
|
||||
import com.viewpagerindicator.IconPagerAdapter;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.Flowable;
|
||||
|
||||
public class SetupActivity extends BaseActivity implements ViewPager.OnPageChangeListener {
|
||||
|
||||
@Inject
|
||||
public ApiClient apiClient;
|
||||
@Inject
|
||||
protected HostConfig hostConfig;
|
||||
@Inject
|
||||
protected UserRepository userRepository;
|
||||
@Inject
|
||||
protected TaskRepository taskRepository;
|
||||
@BindView(R.id.viewPager)
|
||||
FadingViewPager pager;
|
||||
@BindView(R.id.nextButton)
|
||||
Button nextButton;
|
||||
@BindView(R.id.previousButton)
|
||||
Button previousButton;
|
||||
@BindView(R.id.view_pager_indicator)
|
||||
IconPageIndicator indicator;
|
||||
AvatarSetupFragment avatarSetupFragment;
|
||||
TaskSetupFragment taskSetupFragment;
|
||||
@Nullable
|
||||
User user;
|
||||
boolean completedSetup = false;
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_setup;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
compositeSubscription.add(userRepository.getUser(hostConfig.getUser())
|
||||
.flatMap(user -> {
|
||||
if (user == null) {
|
||||
return userRepository.retrieveUser(true);
|
||||
} else {
|
||||
return Flowable.just(user);
|
||||
}
|
||||
})
|
||||
.subscribe(this::onUserReceived, RxErrorHandler.handleEmptyError()));
|
||||
|
||||
Map<String, Object> additionalData = new HashMap<>();
|
||||
additionalData.put("status", "displayed");
|
||||
AmplitudeManager.sendEvent("setup", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData);
|
||||
|
||||
String currentDeviceLanguage = Locale.getDefault().getLanguage();
|
||||
for (String language : getResources().getStringArray(R.array.LanguageValues)) {
|
||||
if (language.equals(currentDeviceLanguage)) {
|
||||
apiClient.registrationLanguage(currentDeviceLanguage)
|
||||
.subscribe(habitRPGUser -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
View decor = getWindow().getDecorView();
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
window.setStatusBarColor(ContextCompat.getColor(this, R.color.light_gray_bg));
|
||||
} else {
|
||||
window.setStatusBarColor(ContextCompat.getColor(this, R.color.days_gray));
|
||||
}
|
||||
}
|
||||
|
||||
pager.disableFading = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
userRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void setupViewpager() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
pager.setAdapter(new ViewPageAdapter(fragmentManager));
|
||||
|
||||
pager.addOnPageChangeListener(this);
|
||||
indicator.setViewPager(pager);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(UpdateUserCommand event) {
|
||||
this.userRepository.updateUser(user, event.updateData)
|
||||
.subscribe(this::onUserReceived, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(EquipCommand event) {
|
||||
this.apiClient.equipItem(event.type, event.key)
|
||||
.subscribe(items -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@OnClick(R.id.nextButton)
|
||||
public void nextClicked(View v) {
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString("FirstDayOfTheWeek",
|
||||
Integer.toString(Calendar.getInstance().getFirstDayOfWeek()));
|
||||
editor.apply();
|
||||
if (isLastPage()) {
|
||||
if (this.taskSetupFragment == null) {
|
||||
return;
|
||||
}
|
||||
List<Task> newTasks = this.taskSetupFragment.createSampleTasks();
|
||||
this.completedSetup = true;
|
||||
this.taskRepository.createTasks(newTasks)
|
||||
.subscribe(tasks -> onUserReceived(user), RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
this.pager.setCurrentItem(this.pager.getCurrentItem() + 1);
|
||||
}
|
||||
|
||||
@OnClick(R.id.previousButton)
|
||||
public void previousClicked() {
|
||||
this.pager.setCurrentItem(this.pager.getCurrentItem() - 1);
|
||||
}
|
||||
|
||||
private void setPreviousButtonEnabled(boolean enabled) {
|
||||
Drawable leftDrawable;
|
||||
if (enabled) {
|
||||
previousButton.setText(R.string.action_back);
|
||||
leftDrawable = AppCompatResources.getDrawable(this, R.drawable.back_arrow_enabled);
|
||||
} else {
|
||||
previousButton.setText(null);
|
||||
leftDrawable = AppCompatResources.getDrawable(this, R.drawable.back_arrow_disabled);
|
||||
}
|
||||
previousButton.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (position == 0) {
|
||||
this.setPreviousButtonEnabled(false);
|
||||
this.nextButton.setText(this.getString(R.string.next_button));
|
||||
} else if (isLastPage()) {
|
||||
this.setPreviousButtonEnabled(true);
|
||||
this.nextButton.setText(this.getString(R.string.intro_finish_button));
|
||||
} else {
|
||||
this.setPreviousButtonEnabled(true);
|
||||
this.nextButton.setText(this.getString(R.string.next_button));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
|
||||
public void onUserReceived(User user) {
|
||||
if (completedSetup) {
|
||||
if (compositeSubscription != null && !compositeSubscription.isDisposed()) {
|
||||
compositeSubscription.dispose();
|
||||
}
|
||||
this.startMainActivity();
|
||||
return;
|
||||
}
|
||||
this.user = user;
|
||||
if (this.pager.getAdapter() == null) {
|
||||
this.setupViewpager();
|
||||
} else {
|
||||
if (this.avatarSetupFragment != null) {
|
||||
this.avatarSetupFragment.setUser(user);
|
||||
}
|
||||
if (this.taskSetupFragment != null) {
|
||||
this.taskSetupFragment.setUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> additionalData = new HashMap<>();
|
||||
additionalData.put("status", "completed");
|
||||
AmplitudeManager.sendEvent("setup", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData);
|
||||
}
|
||||
|
||||
private void startMainActivity() {
|
||||
Intent intent = new Intent(SetupActivity.this, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private class ViewPageAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
|
||||
|
||||
public ViewPageAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
Fragment fragment;
|
||||
|
||||
switch (position) {
|
||||
case 1: {
|
||||
avatarSetupFragment = new AvatarSetupFragment();
|
||||
avatarSetupFragment.setActivity(SetupActivity.this);
|
||||
avatarSetupFragment.setUser(user);
|
||||
avatarSetupFragment.setWidth(pager.getWidth());
|
||||
fragment = avatarSetupFragment;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
taskSetupFragment = new TaskSetupFragment();
|
||||
taskSetupFragment.setUser(user);
|
||||
fragment = taskSetupFragment;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
fragment = new WelcomeFragment();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconResId(int index) {
|
||||
return R.drawable.indicator_diamond;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLastPage() {
|
||||
return this.pager == null || this.pager.getAdapter() == null || this.pager.getCurrentItem() == this.pager.getAdapter().getCount() - 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.support.v7.content.res.AppCompatResources
|
||||
import android.support.v7.preference.PreferenceManager
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.api.HostConfig
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.events.commands.EquipCommand
|
||||
import com.habitrpg.android.habitica.events.commands.UpdateUserCommand
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.AvatarSetupFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.TaskSetupFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.WelcomeFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.FadingViewPager
|
||||
import com.viewpagerindicator.IconPageIndicator
|
||||
import com.viewpagerindicator.IconPagerAdapter
|
||||
import io.reactivex.functions.Consumer
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
|
||||
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
@Inject
|
||||
lateinit var hostConfig: HostConfig
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
|
||||
private val pager: FadingViewPager by bindView(R.id.viewPager)
|
||||
private val nextButton: Button by bindView(R.id.nextButton)
|
||||
private val previousButton: Button by bindView(R.id.previousButton)
|
||||
private val indicator: IconPageIndicator by bindView(R.id.view_pager_indicator)
|
||||
|
||||
internal var avatarSetupFragment: AvatarSetupFragment? = null
|
||||
internal var taskSetupFragment: TaskSetupFragment? = null
|
||||
internal var user: User? = null
|
||||
private var completedSetup = false
|
||||
|
||||
private val isLastPage: Boolean
|
||||
get() = this.pager.adapter == null || this.pager.currentItem == this.pager.adapter?.count ?: 0 - 1
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_setup
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
compositeSubscription?.add(userRepository.getUser(hostConfig.user)
|
||||
.subscribe(Consumer { this.onUserReceived(it) }, RxErrorHandler.handleEmptyError()))
|
||||
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["status"] = "displayed"
|
||||
AmplitudeManager.sendEvent("setup", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
|
||||
|
||||
val currentDeviceLanguage = Locale.getDefault().language
|
||||
for (language in resources.getStringArray(R.array.LanguageValues)) {
|
||||
if (language == currentDeviceLanguage) {
|
||||
apiClient.registrationLanguage(currentDeviceLanguage)
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
val window = window
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val decor = getWindow().decorView
|
||||
decor.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
window.statusBarColor = ContextCompat.getColor(this, R.color.light_gray_bg)
|
||||
} else {
|
||||
window.statusBarColor = ContextCompat.getColor(this, R.color.days_gray)
|
||||
}
|
||||
}
|
||||
|
||||
pager.disableFading = true
|
||||
|
||||
previousButton.setOnClickListener { previousClicked() }
|
||||
nextButton.setOnClickListener { nextClicked() }
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
userRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun setupViewpager() {
|
||||
val fragmentManager = supportFragmentManager
|
||||
|
||||
pager.adapter = ViewPageAdapter(fragmentManager)
|
||||
|
||||
pager.addOnPageChangeListener(this)
|
||||
indicator.setViewPager(pager)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: UpdateUserCommand) {
|
||||
this.userRepository.updateUser(user, event.updateData)
|
||||
.subscribe(Consumer<User> { this.onUserReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: EquipCommand) {
|
||||
this.apiClient.equipItem(event.type, event.key)
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun nextClicked() {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val editor = sharedPreferences.edit()
|
||||
editor.putString("FirstDayOfTheWeek", Integer.toString(Calendar.getInstance().firstDayOfWeek))
|
||||
editor.apply()
|
||||
if (isLastPage) {
|
||||
if (this.taskSetupFragment == null) {
|
||||
return
|
||||
}
|
||||
val newTasks = this.taskSetupFragment?.createSampleTasks()
|
||||
this.completedSetup = true
|
||||
newTasks.notNull {
|
||||
this.taskRepository.createTasks(it).subscribe(Consumer { onUserReceived(user) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
this.pager.currentItem = this.pager.currentItem + 1
|
||||
}
|
||||
|
||||
private fun previousClicked() {
|
||||
this.pager.currentItem = this.pager.currentItem - 1
|
||||
}
|
||||
|
||||
private fun setPreviousButtonEnabled(enabled: Boolean) {
|
||||
val leftDrawable: Drawable?
|
||||
if (enabled) {
|
||||
previousButton.setText(R.string.action_back)
|
||||
leftDrawable = AppCompatResources.getDrawable(this, R.drawable.back_arrow_enabled)
|
||||
} else {
|
||||
previousButton.text = null
|
||||
leftDrawable = AppCompatResources.getDrawable(this, R.drawable.back_arrow_disabled)
|
||||
}
|
||||
previousButton.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null)
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
when {
|
||||
position == 0 -> {
|
||||
this.setPreviousButtonEnabled(false)
|
||||
this.nextButton.text = this.getString(R.string.next_button)
|
||||
}
|
||||
isLastPage -> {
|
||||
this.setPreviousButtonEnabled(true)
|
||||
this.nextButton.text = this.getString(R.string.intro_finish_button)
|
||||
}
|
||||
else -> {
|
||||
this.setPreviousButtonEnabled(true)
|
||||
this.nextButton.text = this.getString(R.string.next_button)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
|
||||
private fun onUserReceived(user: User?) {
|
||||
if (completedSetup) {
|
||||
if (!compositeSubscription.isDisposed) {
|
||||
compositeSubscription.dispose()
|
||||
}
|
||||
this.startMainActivity()
|
||||
return
|
||||
}
|
||||
this.user = user
|
||||
if (this.pager.adapter == null) {
|
||||
this.setupViewpager()
|
||||
} else {
|
||||
this.avatarSetupFragment?.setUser(user)
|
||||
this.taskSetupFragment?.setUser(user)
|
||||
}
|
||||
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["status"] = "completed"
|
||||
AmplitudeManager.sendEvent("setup", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
|
||||
}
|
||||
|
||||
private fun startMainActivity() {
|
||||
val intent = Intent(this@SetupActivity, MainActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private inner class ViewPageAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm), IconPagerAdapter {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
return when (position) {
|
||||
1 -> {
|
||||
val fragment = AvatarSetupFragment()
|
||||
fragment.activity = this@SetupActivity
|
||||
fragment.setUser(user)
|
||||
fragment.width = pager.width
|
||||
avatarSetupFragment = fragment
|
||||
fragment
|
||||
}
|
||||
2 -> {
|
||||
val fragment = TaskSetupFragment()
|
||||
fragment.setUser(user)
|
||||
taskSetupFragment = fragment
|
||||
fragment
|
||||
}
|
||||
else -> { WelcomeFragment() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 3
|
||||
}
|
||||
|
||||
override fun getIconResId(index: Int): Int {
|
||||
return R.drawable.indicator_diamond
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,8 +29,8 @@ class SkillMemberActivity : BaseActivity() {
|
|||
return R.layout.activity_skill_members
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent) {
|
||||
component.inject(this)
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
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.fragments.skills.SkillTasksRecyclerViewFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SkillTasksActivity extends BaseActivity {
|
||||
|
||||
@Inject
|
||||
TaskRepository taskRepository;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
|
||||
@BindView(R.id.viewpager)
|
||||
public ViewPager viewPager;
|
||||
|
||||
@BindView(R.id.tab_layout)
|
||||
public TabLayout tabLayout;
|
||||
SparseArray<SkillTasksRecyclerViewFragment> viewFragmentsDictionary = new SparseArray<>();
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_skill_tasks;
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
loadTaskLists();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectActivity(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public void loadTaskLists() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
SkillTasksRecyclerViewFragment fragment = new SkillTasksRecyclerViewFragment();
|
||||
switch (position) {
|
||||
case 0:
|
||||
fragment.setTaskType(Task.TYPE_HABIT);
|
||||
break;
|
||||
case 1:
|
||||
fragment.setTaskType(Task.TYPE_DAILY);
|
||||
break;
|
||||
default:
|
||||
fragment.setTaskType(Task.TYPE_TODO);
|
||||
}
|
||||
|
||||
compositeSubscription.add(fragment.getTaskSelectionEvents().subscribe(task -> taskSelected(task), RxErrorHandler.handleEmptyError()));
|
||||
|
||||
viewFragmentsDictionary.put(position, fragment);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getString(R.string.habits);
|
||||
case 1:
|
||||
return getString(R.string.dailies);
|
||||
case 2:
|
||||
return getString(R.string.todos);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
|
||||
public void taskSelected(Task task) {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra("task_id", task.getId());
|
||||
setResult(Activity.RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.util.SparseArray
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
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.fragments.skills.SkillTasksRecyclerViewFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.functions.Consumer
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class SkillTasksActivity : BaseActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userId: String
|
||||
|
||||
private val viewPager: ViewPager by bindView(R.id.viewPager)
|
||||
private val tabLayout: TabLayout by bindView(R.id.tab_layout)
|
||||
|
||||
internal var viewFragmentsDictionary = SparseArray<SkillTasksRecyclerViewFragment>()
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_skill_tasks
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
loadTaskLists()
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
private fun loadTaskLists() {
|
||||
val fragmentManager = supportFragmentManager
|
||||
|
||||
viewPager.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val fragment = SkillTasksRecyclerViewFragment()
|
||||
when (position) {
|
||||
0 -> fragment.taskType = Task.TYPE_HABIT
|
||||
1 -> fragment.taskType = Task.TYPE_DAILY
|
||||
else -> fragment.taskType = Task.TYPE_TODO
|
||||
}
|
||||
|
||||
compositeSubscription.add(fragment.taskSelectionEvents.subscribe(Consumer { task -> taskSelected(task) }, RxErrorHandler.handleEmptyError()))
|
||||
|
||||
viewFragmentsDictionary.put(position, fragment)
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 3
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
when (position) {
|
||||
0 -> return getString(R.string.habits)
|
||||
1 -> return getString(R.string.dailies)
|
||||
2 -> return getString(R.string.todos)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tabLayout.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
fun taskSelected(task: Task) {
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra("task_id", task.id)
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.ui.adapter.social.challenges;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -89,7 +90,7 @@ public class ChallengeTasksRecyclerViewAdapter
|
|||
return addItemSubject.toFlowable(BackpressureStrategy.BUFFER);
|
||||
}
|
||||
|
||||
public int addTaskUnder(Task taskToAdd, Task taskAbove) {
|
||||
public int addTaskUnder(Task taskToAdd, @Nullable Task taskAbove) {
|
||||
int position = U.findIndex(this.getContent(), t -> t.getId().equals(taskAbove.getId()));
|
||||
|
||||
getContent().add(position + 1, taskToAdd);
|
||||
|
|
@ -159,18 +160,18 @@ public class ChallengeTasksRecyclerViewAdapter
|
|||
private PublishSubject<Task> callback;
|
||||
private Task newTask;
|
||||
|
||||
public AddItemViewHolder(View itemView, PublishSubject<Task> callback) {
|
||||
super(itemView, false);
|
||||
AddItemViewHolder(View itemView, PublishSubject<Task> callback) {
|
||||
super(itemView);
|
||||
this.callback = callback;
|
||||
|
||||
addBtn = (Button) itemView.findViewById(R.id.btn_add_task);
|
||||
addBtn = itemView.findViewById(R.id.btn_add_task);
|
||||
addBtn.setClickable(true);
|
||||
addBtn.setOnClickListener(view -> callback.onNext(newTask));
|
||||
setContext(itemView.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindHolder(Task newTask, int position) {
|
||||
public void bindHolder(@NonNull Task newTask, int position) {
|
||||
this.newTask = newTask;
|
||||
addBtn.setText(newTask.getText());
|
||||
}
|
||||
|
|
@ -180,16 +181,16 @@ public class ChallengeTasksRecyclerViewAdapter
|
|||
|
||||
private TextView divider_name;
|
||||
|
||||
public DividerViewHolder(View itemView) {
|
||||
super(itemView, false);
|
||||
DividerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
divider_name = (TextView) itemView.findViewById(R.id.divider_name);
|
||||
divider_name = itemView.findViewById(R.id.divider_name);
|
||||
|
||||
setContext(itemView.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindHolder(Task newTask, int position) {
|
||||
public void bindHolder(@NonNull Task newTask, int position) {
|
||||
divider_name.setText(newTask.getText());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.view.ViewGroup
|
|||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
|
@ -34,7 +35,7 @@ abstract class BaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(var taskTyp
|
|||
this.setHasStableIds(true)
|
||||
this.context = newContext.applicationContext
|
||||
this.filteredContent = ArrayList()
|
||||
injectThis(HabiticaBaseApplication.getComponent())
|
||||
HabiticaBaseApplication.component.notNull { injectThis(it) }
|
||||
|
||||
if (loadFromDatabase()) {
|
||||
this.loadContent(true)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
|
|||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.TutorialRepository
|
||||
import com.habitrpg.android.habitica.events.DisplayTutorialEvent
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
|
|
@ -42,7 +43,9 @@ abstract class BaseFragment : DialogFragment() {
|
|||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
injectFragment(HabiticaBaseApplication.getComponent())
|
||||
HabiticaBaseApplication.component.notNull {
|
||||
injectFragment(it)
|
||||
}
|
||||
this.showsDialog = false
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
|
@ -107,8 +110,10 @@ abstract class BaseFragment : DialogFragment() {
|
|||
}
|
||||
|
||||
super.onDestroyView()
|
||||
val refWatcher = HabiticaApplication.getInstance(context).refWatcher
|
||||
refWatcher.watch(this)
|
||||
context.notNull {
|
||||
val refWatcher = HabiticaBaseApplication.getInstance(it).refWatcher
|
||||
refWatcher?.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
|
|||
|
|
@ -1,190 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.design.widget.CollapsingToolbarLayout;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity;
|
||||
import com.roughike.bottombar.BottomBar;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public abstract class BaseMainFragment extends BaseFragment {
|
||||
|
||||
@Inject
|
||||
public ApiClient apiClient;
|
||||
@Inject
|
||||
protected UserRepository userRepository;
|
||||
@Nullable
|
||||
public MainActivity activity;
|
||||
@Nullable
|
||||
public TabLayout tabLayout;
|
||||
@Nullable
|
||||
private CollapsingToolbarLayout collapsingToolbar;
|
||||
@Nullable
|
||||
protected FrameLayout toolbarAccessoryContainer;
|
||||
@Nullable
|
||||
public BottomBar bottomNavigation;
|
||||
public ViewGroup floatingMenuWrapper;
|
||||
public boolean usesTabLayout;
|
||||
public boolean usesBottomNavigation = false;
|
||||
public String fragmentSidebarIdentifier;
|
||||
@Inject
|
||||
protected SoundManager soundManager;
|
||||
@Nullable
|
||||
protected User user;
|
||||
|
||||
public void setUser(@Nullable User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public void updateUserData(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public void setTabLayout(@Nullable TabLayout tabLayout) {
|
||||
this.tabLayout = tabLayout;
|
||||
}
|
||||
|
||||
public void setBottomNavigation(@Nullable BottomBar bottomNavigation) {
|
||||
this.bottomNavigation = bottomNavigation;
|
||||
}
|
||||
|
||||
public void setFloatingMenuWrapper(ViewGroup view) {
|
||||
this.floatingMenuWrapper = view;
|
||||
}
|
||||
|
||||
public void setActivity(@Nullable MainActivity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewStateRestored(Bundle savedInstanceState) {
|
||||
super.onViewStateRestored(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
if (getActivity().getClass().equals(MainActivity.class)) {
|
||||
this.activity = (MainActivity) getActivity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey("userId")) {
|
||||
String userId = savedInstanceState.getString("userId");
|
||||
if (userId != null && userRepository != null) {
|
||||
getCompositeSubscription().add(userRepository.getUser(userId).subscribe(habitRPGUser -> user = habitRPGUser, RxErrorHandler.handleEmptyError()));
|
||||
}
|
||||
}
|
||||
|
||||
if (bottomNavigation != null) {
|
||||
if (this.usesBottomNavigation) {
|
||||
bottomNavigation.removeOnTabSelectListener();
|
||||
bottomNavigation.removeOnTabReselectListener();
|
||||
bottomNavigation.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
bottomNavigation.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (floatingMenuWrapper != null) {
|
||||
floatingMenuWrapper.removeAllViews();
|
||||
}
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
if (activity != null) {
|
||||
activity.setActiveFragment(this);
|
||||
}
|
||||
|
||||
updateTabLayoutVisibility();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateTabLayoutVisibility() {
|
||||
if (tabLayout != null) {
|
||||
if (this.usesTabLayout) {
|
||||
tabLayout.removeAllTabs();
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
tabLayout.setTabMode(TabLayout.MODE_FIXED);
|
||||
} else {
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (userRepository != null) {
|
||||
userRepository.close();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
if (user != null && user.isValid()) {
|
||||
outState.putString("userId", user.getId());
|
||||
}
|
||||
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
public String customTitle() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void hideToolbar() {
|
||||
if (activity != null) {
|
||||
activity.avatar_with_bars.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void showToolbar() {
|
||||
if (activity != null) {
|
||||
activity.avatar_with_bars.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void disableToolbarScrolling() {
|
||||
if (collapsingToolbar != null) {
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams();
|
||||
params.setScrollFlags(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void enableToolbarScrolling() {
|
||||
if (collapsingToolbar != null) {
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams();
|
||||
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCollapsingToolbar(@Nullable CollapsingToolbarLayout collapsingToolbar) {
|
||||
this.collapsingToolbar = collapsingToolbar;
|
||||
}
|
||||
|
||||
public void setToolbarAccessoryContainer(FrameLayout toolbarAccessoryContainer) {
|
||||
this.toolbarAccessoryContainer = toolbarAccessoryContainer;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.AppBarLayout
|
||||
import android.support.design.widget.CollapsingToolbarLayout
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.roughike.bottombar.BottomBar
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class BaseMainFragment : BaseFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
lateinit var soundManager: SoundManager
|
||||
|
||||
open var activity: MainActivity? = null
|
||||
var tabLayout: TabLayout? = null
|
||||
var collapsingToolbar: CollapsingToolbarLayout? = null
|
||||
var toolbarAccessoryContainer: FrameLayout? = null
|
||||
var bottomNavigation: BottomBar? = null
|
||||
var floatingMenuWrapper: ViewGroup? = null
|
||||
var usesTabLayout: Boolean = false
|
||||
var usesBottomNavigation = false
|
||||
var fragmentSidebarIdentifier: String? = null
|
||||
open var user: User? = null
|
||||
|
||||
open fun updateUserData(user: User?) {
|
||||
this.user = user
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context?) {
|
||||
super.onAttach(context)
|
||||
|
||||
if (getActivity()?.javaClass == MainActivity::class.java) {
|
||||
this.activity = getActivity() as MainActivity?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey("userId")) {
|
||||
val userId = savedInstanceState.getString("userId")
|
||||
if (userId != null) {
|
||||
compositeSubscription.add(userRepository.getUser(userId).subscribe(Consumer { habitRPGUser -> user = habitRPGUser }, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
}
|
||||
|
||||
if (this.usesBottomNavigation) {
|
||||
bottomNavigation?.removeOnTabSelectListener()
|
||||
bottomNavigation?.removeOnTabReselectListener()
|
||||
bottomNavigation?.visibility = View.VISIBLE
|
||||
} else {
|
||||
bottomNavigation?.visibility = View.GONE
|
||||
}
|
||||
|
||||
floatingMenuWrapper?.removeAllViews()
|
||||
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
activity?.setActiveFragment(this)
|
||||
|
||||
updateTabLayoutVisibility()
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun updateTabLayoutVisibility() {
|
||||
if (this.usesTabLayout) {
|
||||
tabLayout?.removeAllTabs()
|
||||
tabLayout?.visibility = View.VISIBLE
|
||||
tabLayout?.tabMode = TabLayout.MODE_FIXED
|
||||
} else {
|
||||
tabLayout?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
userRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
if (user?.isValid == true) {
|
||||
outState.putString("userId", user?.id)
|
||||
}
|
||||
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
open fun customTitle(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
fun hideToolbar() {
|
||||
activity?.avatarWithBars?.visibility = View.GONE
|
||||
}
|
||||
|
||||
fun showToolbar() {
|
||||
activity?.avatarWithBars?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
fun disableToolbarScrolling() {
|
||||
val params = collapsingToolbar?.layoutParams as AppBarLayout.LayoutParams?
|
||||
params?.scrollFlags = 0
|
||||
}
|
||||
|
||||
fun enableToolbarScrolling() {
|
||||
val params = collapsingToolbar?.layoutParams as AppBarLayout.LayoutParams?
|
||||
params?.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
|
||||
}
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ class GemsPurchaseFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
|
|||
this.listener = listener
|
||||
}
|
||||
|
||||
override fun setBillingRequests(billingRequests: BillingRequests) {
|
||||
override fun setBillingRequests(billingRequests: BillingRequests?) {
|
||||
this.billingRequests = billingRequests
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
NavigationDrawerAdapter(0, 0)
|
||||
}
|
||||
subscriptions = CompositeDisposable()
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ class StatsFragment: BaseMainFragment() {
|
|||
|
||||
private fun showBulkAllocateDialog() {
|
||||
context.notNull { context ->
|
||||
val dialog = BulkAllocateStatsDialog(context, HabiticaBaseApplication.getComponent())
|
||||
val dialog = BulkAllocateStatsDialog(context, HabiticaBaseApplication.component)
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ class SubscriptionFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
|
|||
this.listener = listener
|
||||
}
|
||||
|
||||
override fun setBillingRequests(billingRequests: BillingRequests) {
|
||||
override fun setBillingRequests(billingRequests: BillingRequests?) {
|
||||
this.billingRequests = billingRequests
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,13 +141,13 @@ class AvatarCustomizationFragment : BaseMainFragment() {
|
|||
layoutManager.spanCount = spanCount
|
||||
}
|
||||
|
||||
override fun updateUserData(user: User) {
|
||||
override fun updateUserData(user: User?) {
|
||||
super.updateUserData(user)
|
||||
this.adapter.gemBalance = (user.balance * 4).toInt()
|
||||
this.adapter.gemBalance = user?.gemCount ?: 0
|
||||
this.updateActiveCustomization()
|
||||
if (adapter.customizationList.size != 0) {
|
||||
val ownedCustomizations = ArrayList<String>()
|
||||
user.purchased?.customizations?.filter { it.type == this.type }?.mapTo(ownedCustomizations) { it.id }
|
||||
user?.purchased?.customizations?.filter { it.type == this.type }?.mapTo(ownedCustomizations) { it.id }
|
||||
adapter.updateOwnership(ownedCustomizations)
|
||||
} else {
|
||||
this.loadCustomizations()
|
||||
|
|
@ -155,7 +155,7 @@ class AvatarCustomizationFragment : BaseMainFragment() {
|
|||
}
|
||||
|
||||
private fun updateActiveCustomization() {
|
||||
if (this.type == null || this.user == null || this.user!!.preferences == null) {
|
||||
if (this.type == null || user?.preferences == null) {
|
||||
return
|
||||
}
|
||||
val prefs = this.user?.preferences
|
||||
|
|
|
|||
|
|
@ -1,139 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.items;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.events.commands.HatchingCommand;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
public class ItemsFragment extends BaseMainFragment {
|
||||
|
||||
public ViewPager viewPager;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
this.usesTabLayout = true;
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
|
||||
|
||||
viewPager = (ViewPager) v.findViewById(R.id.viewPager);
|
||||
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
setViewPagerAdapter();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
|
||||
ItemRecyclerFragment fragment = new ItemRecyclerFragment();
|
||||
|
||||
switch (position) {
|
||||
case 0: {
|
||||
fragment.setItemType("eggs");
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
fragment.setItemType("hatchingPotions");
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
fragment.setItemType("food");
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
fragment.setItemType("quests");
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
fragment.setItemType("special");
|
||||
}
|
||||
}
|
||||
fragment.setHatching(false);
|
||||
fragment.setFeeding(false);
|
||||
fragment.setItemTypeText(this.getPageTitle(position).toString());
|
||||
fragment.setUser(ItemsFragment.this.user);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
if (activity == null) {
|
||||
return "";
|
||||
}
|
||||
switch (position) {
|
||||
case 0:
|
||||
return activity.getString(R.string.eggs);
|
||||
case 1:
|
||||
return activity.getString(R.string.hatching_potions);
|
||||
case 2:
|
||||
return activity.getString(R.string.food);
|
||||
case 3:
|
||||
return activity.getString(R.string.quests);
|
||||
case 4:
|
||||
return activity.getString(R.string.special);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void showHatchingDialog(HatchingCommand event) {
|
||||
if (event.usingEgg == null || event.usingHatchingPotion == null) {
|
||||
ItemRecyclerFragment fragment = new ItemRecyclerFragment();
|
||||
if (event.usingEgg != null) {
|
||||
fragment.setItemType("hatchingPotions");
|
||||
fragment.setHatchingItem(event.usingEgg);
|
||||
} else {
|
||||
fragment.setItemType("eggs");
|
||||
fragment.setHatchingItem(event.usingHatchingPotion);
|
||||
}
|
||||
fragment.setHatching(true);
|
||||
fragment.setFeeding(false);
|
||||
fragment.show(getFragmentManager(), "hatchingDialog");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String customTitle() {
|
||||
if (!isAdded()) {
|
||||
return "";
|
||||
}
|
||||
return getString(R.string.sidebar_items);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.items
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.events.commands.HatchingCommand
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
|
||||
class ItemsFragment : BaseMainFragment() {
|
||||
|
||||
private val viewPager: ViewPager? by bindView(R.id.viewPager)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = true
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewPager?.currentItem = 0
|
||||
setViewPagerAdapter()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = childFragmentManager
|
||||
|
||||
viewPager?.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
|
||||
val fragment = ItemRecyclerFragment()
|
||||
|
||||
when (position) {
|
||||
0 -> {
|
||||
fragment.itemType = "eggs"
|
||||
}
|
||||
1 -> {
|
||||
fragment.itemType = "hatchingPotions"
|
||||
}
|
||||
2 -> {
|
||||
fragment.itemType = "food"
|
||||
}
|
||||
3 -> {
|
||||
fragment.itemType = "quests"
|
||||
}
|
||||
4 -> {
|
||||
fragment.itemType = "special"
|
||||
}
|
||||
}
|
||||
fragment.isHatching = false
|
||||
fragment.isFeeding = false
|
||||
fragment.itemTypeText = this.getPageTitle(position).toString()
|
||||
fragment.user = this@ItemsFragment.user
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 5
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence {
|
||||
return when (position) {
|
||||
0 -> activity?.getString(R.string.eggs)
|
||||
1 -> activity?.getString(R.string.hatching_potions)
|
||||
2 -> activity?.getString(R.string.food)
|
||||
3 -> activity?.getString(R.string.quests)
|
||||
4 -> activity?.getString(R.string.special)
|
||||
else -> ""
|
||||
} ?: ""
|
||||
}
|
||||
}
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
tabLayout?.tabMode = TabLayout.MODE_SCROLLABLE
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showHatchingDialog(event: HatchingCommand) {
|
||||
if (event.usingEgg == null || event.usingHatchingPotion == null) {
|
||||
val fragment = ItemRecyclerFragment()
|
||||
if (event.usingEgg != null) {
|
||||
fragment.itemType = "hatchingPotions"
|
||||
fragment.hatchingItem = event.usingEgg
|
||||
} else {
|
||||
fragment.itemType = "eggs"
|
||||
fragment.hatchingItem = event.usingHatchingPotion
|
||||
}
|
||||
fragment.isHatching = true
|
||||
fragment.isFeeding = false
|
||||
fragment.show(fragmentManager!!, "hatchingDialog")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun customTitle(): String {
|
||||
return if (!isAdded) {
|
||||
""
|
||||
} else getString(R.string.sidebar_items)
|
||||
}
|
||||
}
|
||||
|
|
@ -87,8 +87,8 @@ class ShopsFragment : BaseMainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout!!.setupWithViewPager(viewPager)
|
||||
if (viewPager != null) {
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ class ShopsFragment : BaseMainFragment() {
|
|||
} else getString(R.string.sidebar_shops)
|
||||
}
|
||||
|
||||
override fun updateUserData(user: User) {
|
||||
override fun updateUserData(user: User?) {
|
||||
super.updateUserData(user)
|
||||
updateCurrencyView()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.stable;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.ui.adapter.inventory.MountDetailRecyclerAdapter;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration;
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class MountDetailRecyclerFragment extends BaseMainFragment {
|
||||
private static final String ANIMAL_TYPE_KEY = "ANIMAL_TYPE_KEY";
|
||||
|
||||
@Inject
|
||||
InventoryRepository inventoryRepository;
|
||||
|
||||
public RecyclerView recyclerView;
|
||||
public MountDetailRecyclerAdapter adapter;
|
||||
public String animalType;
|
||||
public String animalGroup;
|
||||
GridLayoutManager layoutManager = null;
|
||||
|
||||
private View view;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
this.usesTabLayout = false;
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
view = inflater.inflate(R.layout.fragment_recyclerview, container, false);
|
||||
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
|
||||
|
||||
layoutManager = new GridLayoutManager(getActivity(), 2);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.addItemDecoration(new MarginDecoration(getActivity()));
|
||||
|
||||
adapter = (MountDetailRecyclerAdapter) recyclerView.getAdapter();
|
||||
if (adapter == null) {
|
||||
adapter = new MountDetailRecyclerAdapter(null, true);
|
||||
adapter.setItemType(this.animalType);
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
|
||||
this.loadItems();
|
||||
|
||||
getCompositeSubscription().add(adapter.getEquipFlowable()
|
||||
.flatMap(key -> inventoryRepository.equip(user, "mount", key))
|
||||
.subscribe(items -> {}, RxErrorHandler.handleEmptyError()));
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
this.animalType = savedInstanceState.getString(ANIMAL_TYPE_KEY, "");
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
inventoryRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
final View finalView = view;
|
||||
finalView.post(() -> setGridSpanCount(finalView.getWidth()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(ANIMAL_TYPE_KEY, this.animalType);
|
||||
}
|
||||
|
||||
|
||||
private void setGridSpanCount(int width) {
|
||||
int spanCount = 0;
|
||||
if (getContext() != null && getContext().getResources() != null) {
|
||||
float itemWidth;
|
||||
itemWidth = getContext().getResources().getDimension(R.dimen.pet_width);
|
||||
|
||||
spanCount = (int) (width / itemWidth);
|
||||
}
|
||||
if (spanCount == 0) {
|
||||
spanCount = 1;
|
||||
}
|
||||
layoutManager.setSpanCount(spanCount);
|
||||
layoutManager.requestLayout();
|
||||
}
|
||||
|
||||
private void loadItems() {
|
||||
if (animalType != null && animalGroup != null) {
|
||||
inventoryRepository.getMounts(animalType, animalGroup).firstElement().subscribe(adapter::updateData, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String customTitle() {
|
||||
if (!isAdded()) {
|
||||
return "";
|
||||
}
|
||||
return getString(R.string.mounts);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.stable
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.widget.GridLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.ui.adapter.inventory.MountDetailRecyclerAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
class MountDetailRecyclerFragment : BaseMainFragment() {
|
||||
|
||||
@Inject
|
||||
internal lateinit var inventoryRepository: InventoryRepository
|
||||
|
||||
private val recyclerView: RecyclerView by bindView(R.id.recyclerView)
|
||||
var adapter: MountDetailRecyclerAdapter? = null
|
||||
var animalType: String? = null
|
||||
var animalGroup: String? = null
|
||||
internal var layoutManager: GridLayoutManager? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = false
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return inflater.inflate(R.layout.fragment_recyclerview, container, false)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
inventoryRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
layoutManager = GridLayoutManager(activity, 2)
|
||||
recyclerView.layoutManager = layoutManager
|
||||
recyclerView.addItemDecoration(MarginDecoration(activity))
|
||||
|
||||
adapter = recyclerView.adapter as MountDetailRecyclerAdapter?
|
||||
if (adapter == null) {
|
||||
adapter = MountDetailRecyclerAdapter(null, true)
|
||||
adapter?.itemType = this.animalType
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.itemAnimator = SafeDefaultItemAnimator()
|
||||
this.loadItems()
|
||||
|
||||
adapter?.getEquipFlowable()?.flatMap { key -> inventoryRepository.equip(user, "mount", key) }
|
||||
?.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription.add(it) }
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
this.animalType = savedInstanceState.getString(ANIMAL_TYPE_KEY, "")
|
||||
}
|
||||
|
||||
view.post { setGridSpanCount(view.width) }
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString(ANIMAL_TYPE_KEY, this.animalType)
|
||||
}
|
||||
|
||||
|
||||
private fun setGridSpanCount(width: Int) {
|
||||
var spanCount = 0
|
||||
if (context != null && context!!.resources != null) {
|
||||
val itemWidth: Float = context!!.resources.getDimension(R.dimen.pet_width)
|
||||
|
||||
spanCount = (width / itemWidth).toInt()
|
||||
}
|
||||
if (spanCount == 0) {
|
||||
spanCount = 1
|
||||
}
|
||||
layoutManager?.spanCount = spanCount
|
||||
layoutManager?.requestLayout()
|
||||
}
|
||||
|
||||
private fun loadItems() {
|
||||
if (animalType != null && animalGroup != null) {
|
||||
inventoryRepository.getMounts(animalType!!, animalGroup!!).firstElement().subscribe(Consumer { adapter?.updateData(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
override fun customTitle(): String {
|
||||
return if (!isAdded) {
|
||||
""
|
||||
} else getString(R.string.mounts)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val ANIMAL_TYPE_KEY = "ANIMAL_TYPE_KEY"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.stable;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
|
||||
public class StableFragment extends BaseMainFragment {
|
||||
|
||||
public ViewPager viewPager;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
this.usesTabLayout = true;
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
|
||||
|
||||
viewPager = (ViewPager) v.findViewById(R.id.viewPager);
|
||||
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
setViewPagerAdapter();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
|
||||
StableRecyclerFragment fragment = new StableRecyclerFragment();
|
||||
|
||||
switch (position) {
|
||||
case 0: {
|
||||
fragment.setItemType("pets");
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
fragment.setItemType("mounts");
|
||||
break;
|
||||
}
|
||||
}
|
||||
fragment.setUser(StableFragment.this.user);
|
||||
fragment.setItemTypeText(this.getPageTitle(position).toString());
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return activity.getString(R.string.pets);
|
||||
case 1:
|
||||
return activity.getString(R.string.mounts);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String customTitle() {
|
||||
if (!isAdded()) {
|
||||
return "";
|
||||
}
|
||||
return getString(R.string.sidebar_stable);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.stable
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
|
||||
class StableFragment : BaseMainFragment() {
|
||||
|
||||
private val viewPager: ViewPager? by bindView(R.id.viewPager)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = true
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
viewPager?.currentItem = 0
|
||||
|
||||
setViewPagerAdapter()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = childFragmentManager
|
||||
|
||||
viewPager?.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
|
||||
val fragment = StableRecyclerFragment()
|
||||
|
||||
when (position) {
|
||||
0 -> {
|
||||
fragment.itemType = "pets"
|
||||
}
|
||||
1 -> {
|
||||
fragment.itemType = "mounts"
|
||||
}
|
||||
}
|
||||
fragment.user = this@StableFragment.user
|
||||
fragment.itemTypeText = this.getPageTitle(position).toString()
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence {
|
||||
return when (position) {
|
||||
0 -> activity?.getString(R.string.pets)
|
||||
1 -> activity?.getString(R.string.mounts)
|
||||
else -> ""
|
||||
} ?: ""
|
||||
}
|
||||
}
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
|
||||
override fun customTitle(): String {
|
||||
return if (!isAdded) {
|
||||
""
|
||||
} else getString(R.string.sidebar_stable)
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ class APIPreferenceFragment: BasePreferencesFragment() {
|
|||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
|
||||
qrCodeManager = QrCodeManager(userRepository, this.context)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() {
|
|||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() {
|
|||
private fun deleteAccount(password: String) {
|
||||
val dialog = ProgressDialog.show(context, context?.getString(R.string.deleting_account), null, true)
|
||||
userRepository.deleteAccount(password).subscribe({ _ ->
|
||||
HabiticaApplication.logout(context)
|
||||
context.notNull { HabiticaBaseApplication.logout(it) }
|
||||
activity?.finish()
|
||||
}) { throwable ->
|
||||
dialog.dismiss()
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
private var classSelectionPreference: Preference? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val userID = preferenceManager.sharedPreferences.getString(context?.getString(R.string.SP_userID), null)
|
||||
|
|
@ -82,7 +82,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||
when(preference.key) {
|
||||
"logout" -> {
|
||||
HabiticaApplication.logout(context)
|
||||
context.notNull { HabiticaBaseApplication.logout(it) }
|
||||
activity?.finish()
|
||||
}
|
||||
"choose_class" -> {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.O
|
|||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
|
|||
class PushNotificationsPreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
HabiticaBaseApplication.getComponent().inject(this)
|
||||
HabiticaBaseApplication.component?.inject(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ class SkillsFragment : BaseMainFragment() {
|
|||
private var selectedSkill: Skill? = null
|
||||
private var progressDialog: ProgressDialog? = null
|
||||
|
||||
override var user: User? = null
|
||||
set(value) {
|
||||
field = value
|
||||
checkUserLoadSkills()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
adapter = SkillsRecyclerViewAdapter()
|
||||
|
|
@ -81,12 +87,6 @@ class SkillsFragment : BaseMainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUser(user: User?) {
|
||||
super.setUser(user)
|
||||
|
||||
checkUserLoadSkills()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(command: UseSkillCommand) {
|
||||
val skill = command.skill
|
||||
|
|
@ -111,9 +111,9 @@ class SkillsFragment : BaseMainFragment() {
|
|||
adapter?.mana = response.user.stats.mp
|
||||
val activity = activity ?: return
|
||||
if ("special" == usedSkill?.habitClass) {
|
||||
showSnackbar(activity.getFloatingMenuWrapper(), context!!.getString(R.string.used_skill_without_mana, usedSkill.text), HabiticaSnackbar.SnackbarDisplayType.BLUE)
|
||||
showSnackbar(activity.floatingMenuWrapper, context!!.getString(R.string.used_skill_without_mana, usedSkill.text), HabiticaSnackbar.SnackbarDisplayType.BLUE)
|
||||
} else {
|
||||
showSnackbar(activity.getFloatingMenuWrapper(), null,
|
||||
showSnackbar(activity.floatingMenuWrapper, null,
|
||||
context?.getString(R.string.used_skill_without_mana, usedSkill?.text),
|
||||
BitmapDrawable(resources, HabiticaIconsHelper.imageOfMagic()),
|
||||
ContextCompat.getColor(context!!, R.color.blue_10), "-" + usedSkill?.mana,
|
||||
|
|
|
|||
|
|
@ -105,7 +105,9 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
|||
|
||||
chatAdapter = ChatRecyclerViewAdapter(null, true, user, true)
|
||||
chatAdapter.notNull {
|
||||
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer { userId ->
|
||||
context.notNull { FullProfileActivity.open(it, userId) }
|
||||
}, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer{ this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
|
||||
|
|
@ -113,7 +115,6 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
|||
compositeSubscription.add(it.getLikeMessageFlowable().flatMap<ChatMessage> { socialRepository.likeMessage(it) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
|
||||
chatBarView.sendAction = { sendChatMessage(it) }
|
||||
|
||||
recyclerView.adapter = chatAdapter
|
||||
|
|
@ -160,7 +161,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
|||
clipMan.primaryClip = messageText
|
||||
val activity = activity as MainActivity?
|
||||
if (activity != null) {
|
||||
showSnackbar(activity.getFloatingMenuWrapper(), getString(R.string.chat_message_copied), SnackbarDisplayType.NORMAL)
|
||||
showSnackbar(activity.floatingMenuWrapper, getString(R.string.chat_message_copied), SnackbarDisplayType.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +174,9 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
|||
socialRepository.flagMessage(chatMessage)
|
||||
.subscribe(Consumer {
|
||||
val activity = activity as MainActivity?
|
||||
showSnackbar(activity!!.getFloatingMenuWrapper(), "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL)
|
||||
activity?.floatingMenuWrapper.notNull {
|
||||
showSnackbar(it, "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
.setNegativeButton(R.string.action_cancel) { _, _ -> }
|
||||
|
|
@ -199,7 +202,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
|||
clipboard.primaryClip = clip
|
||||
val activity = activity as MainActivity?
|
||||
if (activity != null) {
|
||||
HabiticaSnackbar.showSnackbar(activity.getFloatingMenuWrapper(), getString(R.string.chat_message_copied), HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
HabiticaSnackbar.showSnackbar(activity.floatingMenuWrapper, getString(R.string.chat_message_copied), HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class GroupInformationFragment : BaseFragment() {
|
|||
clipboard.primaryClip = clip
|
||||
val activity = activity as MainActivity?
|
||||
if (activity != null) {
|
||||
HabiticaSnackbar.showSnackbar(activity.getFloatingMenuWrapper(), getString(R.string.id_copied), HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
HabiticaSnackbar.showSnackbar(activity.floatingMenuWrapper, getString(R.string.id_copied), HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,260 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.SocialRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.social.Group;
|
||||
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class GuildFragment extends BaseMainFragment {
|
||||
|
||||
@Inject
|
||||
SocialRepository socialRepository;
|
||||
|
||||
public boolean isMember;
|
||||
public ViewPager viewPager;
|
||||
private Group guild;
|
||||
private GroupInformationFragment guildInformationFragment;
|
||||
private ChatListFragment chatListFragment;
|
||||
private String guildId;
|
||||
|
||||
public void setGuildId(String guildId) {
|
||||
this.guildId = guildId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
this.usesTabLayout = true;
|
||||
hideToolbar();
|
||||
disableToolbarScrolling();
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
|
||||
|
||||
viewPager = (ViewPager) v.findViewById(R.id.viewPager);
|
||||
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
setViewPagerAdapter();
|
||||
|
||||
if (guildId != null && this.socialRepository != null) {
|
||||
getCompositeSubscription().add(socialRepository.getGroup(this.guildId).subscribe(this::setGroup, RxErrorHandler.handleEmptyError()));
|
||||
socialRepository.retrieveGroup(this.guildId).subscribe(group -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
showToolbar();
|
||||
enableToolbarScrolling();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
socialRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
if (this.socialRepository != null && this.guild != null) {
|
||||
socialRepository.retrieveGroup(this.guild.getId()).subscribe(this::setGroup, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
if (this.activity != null && this.guild != null) {
|
||||
if (this.isMember) {
|
||||
if (this.user != null && this.user.getId().equals(this.guild.getLeaderID())) {
|
||||
this.activity.getMenuInflater().inflate(R.menu.guild_admin, menu);
|
||||
} else {
|
||||
this.activity.getMenuInflater().inflate(R.menu.guild_member, menu);
|
||||
}
|
||||
} else {
|
||||
this.activity.getMenuInflater().inflate(R.menu.guild_nonmember, menu);
|
||||
}
|
||||
}
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
switch (id) {
|
||||
case R.id.menu_guild_join:
|
||||
this.socialRepository.joinGroup(this.guild.getId()).subscribe(this::setGroup, RxErrorHandler.handleEmptyError());
|
||||
this.isMember = true;
|
||||
return true;
|
||||
case R.id.menu_guild_leave:
|
||||
this.socialRepository.leaveGroup(this.guild.getId())
|
||||
.subscribe(aVoid -> {
|
||||
if (this.activity != null) {
|
||||
this.activity.supportInvalidateOptionsMenu();
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
this.isMember = false;
|
||||
return true;
|
||||
case R.id.menu_guild_edit:
|
||||
this.displayEditForm();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
|
||||
Fragment fragment;
|
||||
|
||||
switch (position) {
|
||||
case 0: {
|
||||
fragment = guildInformationFragment = GroupInformationFragment.Companion.newInstance(GuildFragment.this.guild, user);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
chatListFragment = new ChatListFragment();
|
||||
chatListFragment.configure(GuildFragment.this.guildId, user, false);
|
||||
fragment = chatListFragment;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fragment = new Fragment();
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getContext().getString(R.string.guild);
|
||||
case 1:
|
||||
return getContext().getString(R.string.chat);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
if (position == 1 && GuildFragment.this.guild != null) {
|
||||
chatListFragment.setNavigatedToFragment(GuildFragment.this.guild.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (position == 1 && GuildFragment.this.guild != null && chatListFragment != null) {
|
||||
chatListFragment.setNavigatedToFragment(GuildFragment.this.guild.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
private void displayEditForm() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("groupID", this.guild.getId());
|
||||
bundle.putString("name", this.guild.getName());
|
||||
bundle.putString("description", this.guild.getDescription());
|
||||
bundle.putString("privacy", this.guild.getPrivacy());
|
||||
bundle.putString("leader", this.guild.getLeaderID());
|
||||
|
||||
Intent intent = new Intent(activity, GroupFormActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
startActivityForResult(intent, GroupFormActivity.GROUP_FORM_ACTIVITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case (GroupFormActivity.GROUP_FORM_ACTIVITY): {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Bundle bundle = data.getExtras();
|
||||
this.socialRepository.updateGroup(this.guild,
|
||||
bundle.getString("name"),
|
||||
bundle.getString("description"),
|
||||
bundle.getString("leader"),
|
||||
bundle.getString("privacy"))
|
||||
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroup(Group group) {
|
||||
if (group != null) {
|
||||
if (this.guildInformationFragment != null) {
|
||||
this.guildInformationFragment.setGroup(group);
|
||||
}
|
||||
|
||||
if (this.chatListFragment != null) {
|
||||
this.chatListFragment.setSeenGroupId(group.getId());
|
||||
}
|
||||
|
||||
this.guild = group;
|
||||
}
|
||||
if (this.activity != null) {
|
||||
this.activity.supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String customTitle() {
|
||||
if (!isAdded()) {
|
||||
return "";
|
||||
}
|
||||
return getString(R.string.guild);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
class GuildFragment : BaseMainFragment() {
|
||||
|
||||
@Inject
|
||||
internal lateinit var socialRepository: SocialRepository
|
||||
|
||||
var isMember: Boolean = false
|
||||
private val viewPager: ViewPager? by bindView(R.id.viewPager)
|
||||
private var guild: Group? = null
|
||||
private var guildInformationFragment: GroupInformationFragment? = null
|
||||
private var chatListFragment: ChatListFragment? = null
|
||||
private var guildId: String? = null
|
||||
|
||||
fun setGuildId(guildId: String) {
|
||||
this.guildId = guildId
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = true
|
||||
hideToolbar()
|
||||
disableToolbarScrolling()
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
showToolbar()
|
||||
enableToolbarScrolling()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
socialRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewPager?.currentItem = 0
|
||||
|
||||
setViewPagerAdapter()
|
||||
|
||||
guildId.notNull { guildId ->
|
||||
compositeSubscription.add(socialRepository.getGroup(guildId).subscribe(Consumer { this.setGroup(it) }, RxErrorHandler.handleEmptyError()))
|
||||
socialRepository.retrieveGroup(guildId).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
socialRepository.getGroup(guildId).subscribe(Consumer<Group> { this.setGroup(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
|
||||
if (this.activity != null && this.guild != null) {
|
||||
if (this.isMember) {
|
||||
if (this.user != null && this.user!!.id == this.guild!!.leaderID) {
|
||||
this.activity!!.menuInflater.inflate(R.menu.guild_admin, menu)
|
||||
} else {
|
||||
this.activity!!.menuInflater.inflate(R.menu.guild_member, menu)
|
||||
}
|
||||
} else {
|
||||
this.activity!!.menuInflater.inflate(R.menu.guild_nonmember, menu)
|
||||
}
|
||||
}
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
val id = item!!.itemId
|
||||
|
||||
when (id) {
|
||||
R.id.menu_guild_join -> {
|
||||
this.socialRepository.joinGroup(this.guild?.id).subscribe(Consumer { this.setGroup(it) }, RxErrorHandler.handleEmptyError())
|
||||
this.isMember = true
|
||||
return true
|
||||
}
|
||||
R.id.menu_guild_leave -> {
|
||||
this.socialRepository.leaveGroup(this.guild?.id)
|
||||
.subscribe(Consumer {
|
||||
this.activity?.supportInvalidateOptionsMenu()
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
this.isMember = false
|
||||
return true
|
||||
}
|
||||
R.id.menu_guild_edit -> {
|
||||
this.displayEditForm()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = childFragmentManager
|
||||
|
||||
viewPager?.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment? {
|
||||
|
||||
val fragment: Fragment?
|
||||
|
||||
when (position) {
|
||||
0 -> {
|
||||
guildInformationFragment = GroupInformationFragment.newInstance(this@GuildFragment.guild, user)
|
||||
fragment = guildInformationFragment
|
||||
}
|
||||
1 -> {
|
||||
chatListFragment = ChatListFragment()
|
||||
chatListFragment!!.configure(this@GuildFragment.guildId!!, user, false)
|
||||
fragment = chatListFragment
|
||||
}
|
||||
else -> fragment = Fragment()
|
||||
}
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
when (position) {
|
||||
0 -> return context!!.getString(R.string.guild)
|
||||
1 -> return context!!.getString(R.string.chat)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
if (position == 1 && this@GuildFragment.guild != null) {
|
||||
chatListFragment!!.setNavigatedToFragment(this@GuildFragment.guild!!.id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
if (position == 1 && this@GuildFragment.guild != null && chatListFragment != null) {
|
||||
chatListFragment!!.setNavigatedToFragment(this@GuildFragment.guild!!.id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
private fun displayEditForm() {
|
||||
val bundle = Bundle()
|
||||
bundle.putString("groupID", this.guild!!.id)
|
||||
bundle.putString("name", this.guild!!.name)
|
||||
bundle.putString("description", this.guild!!.description)
|
||||
bundle.putString("privacy", this.guild!!.privacy)
|
||||
bundle.putString("leader", this.guild!!.leaderID)
|
||||
|
||||
val intent = Intent(activity, GroupFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
startActivityForResult(intent, GroupFormActivity.GROUP_FORM_ACTIVITY)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
GroupFormActivity.GROUP_FORM_ACTIVITY -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val bundle = data!!.extras
|
||||
this.socialRepository.updateGroup(this.guild,
|
||||
bundle!!.getString("name"),
|
||||
bundle.getString("description"),
|
||||
bundle.getString("leader"),
|
||||
bundle.getString("privacy"))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setGroup(group: Group?) {
|
||||
if (group != null) {
|
||||
guildInformationFragment?.setGroup(group)
|
||||
|
||||
this.chatListFragment?.seenGroupId = group.id
|
||||
|
||||
this.guild = group
|
||||
}
|
||||
this.activity?.supportInvalidateOptionsMenu()
|
||||
}
|
||||
|
||||
override fun customTitle(): String {
|
||||
return if (!isAdded) {
|
||||
""
|
||||
} else getString(R.string.guild)
|
||||
}
|
||||
}
|
||||
|
|
@ -107,8 +107,9 @@ class GuildsOverviewFragment : BaseMainFragment(), View.OnClickListener, SwipeRe
|
|||
fragment = publicGuildsFragment
|
||||
} else {
|
||||
val guildIndex = (v.parent as ViewGroup).indexOfChild(v)
|
||||
val guildId = this.guilds?.get(guildIndex)?.id ?: return
|
||||
val guildFragment = GuildFragment()
|
||||
guildFragment.setGuildId(this.guilds?.get(guildIndex)?.id)
|
||||
guildFragment.setGuildId(guildId)
|
||||
guildFragment.isMember = true
|
||||
fragment = guildFragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres
|
|||
recyclerView.adapter = chatAdapter
|
||||
recyclerView.itemAnimator = SafeDefaultItemAnimator()
|
||||
chatAdapter.notNull {
|
||||
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer<String> { FullProfileActivity.open(context, it) }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer<String> {
|
||||
context.notNull { context -> FullProfileActivity.open(context, it) }
|
||||
}, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer<ChatMessage> { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer<ChatMessage> { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer<ChatMessage> { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
|
||||
|
|
@ -140,7 +142,7 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres
|
|||
clipMan.primaryClip = messageText
|
||||
val activity = getActivity() as MainActivity?
|
||||
if (activity != null) {
|
||||
showSnackbar(activity.getFloatingMenuWrapper(), getString(R.string.chat_message_copied), HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
showSnackbar(activity.floatingMenuWrapper, getString(R.string.chat_message_copied), HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +153,9 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres
|
|||
socialRepository.flagMessage(chatMessage)
|
||||
.subscribe(Consumer {
|
||||
val activity = getActivity() as MainActivity?
|
||||
showSnackbar(activity!!.getFloatingMenuWrapper(), "Flagged message by " + chatMessage.user, HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
activity?.floatingMenuWrapper.notNull {
|
||||
showSnackbar(it, "Flagged message by " + chatMessage.user, HabiticaSnackbar.SnackbarDisplayType.NORMAL)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
.setNegativeButton(R.string.action_cancel) { dialog, id -> }
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ class ChallengeDetailDialogHolder private constructor(view: View, private val co
|
|||
}
|
||||
|
||||
private fun openLeaderProfile() {
|
||||
FullProfileActivity.open(context, challenge?.leaderId)
|
||||
FullProfileActivity.open(context, challenge?.leaderId ?: "")
|
||||
}
|
||||
|
||||
private fun openChallengeActivity() {
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.challenges;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository;
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailActivityCommand;
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailDialogCommand;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class ChallengesOverviewFragment extends BaseMainFragment {
|
||||
|
||||
@Inject
|
||||
ChallengeRepository challengeRepository;
|
||||
|
||||
public ViewPager viewPager;
|
||||
public FragmentStatePagerAdapter statePagerAdapter;
|
||||
private ChallengeListFragment userChallengesFragment;
|
||||
private ChallengeListFragment availableChallengesFragment;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
this.usesTabLayout = true;
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
|
||||
|
||||
viewPager = (ViewPager) v.findViewById(R.id.viewPager);
|
||||
|
||||
setViewPagerAdapter();
|
||||
|
||||
userChallengesFragment = new ChallengeListFragment();
|
||||
userChallengesFragment.setUser(this.user);
|
||||
userChallengesFragment.setViewUserChallengesOnly(true);
|
||||
|
||||
availableChallengesFragment = new ChallengeListFragment();
|
||||
availableChallengesFragment.setUser(this.user);
|
||||
availableChallengesFragment.setViewUserChallengesOnly(false);
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
challengeRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
|
||||
|
||||
statePagerAdapter = new FragmentStatePagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
Fragment fragment = new Fragment();
|
||||
|
||||
switch (position) {
|
||||
case 0:
|
||||
return userChallengesFragment;
|
||||
case 1:
|
||||
return availableChallengesFragment;
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getString(R.string.my_challenges);
|
||||
case 1:
|
||||
return getString(R.string.public_challenges);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
viewPager.setAdapter(statePagerAdapter);
|
||||
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(ShowChallengeDetailDialogCommand cmd) {
|
||||
challengeRepository.getChallenge(cmd.challengeId).firstElement().subscribe(challenge -> ChallengeDetailDialogHolder.Companion.showDialog(getActivity(), challengeRepository, challenge,
|
||||
challenge1 -> {
|
||||
// challenge left
|
||||
}), RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(ShowChallengeDetailActivityCommand cmd) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(ChallengeDetailActivity.CHALLENGE_ID, cmd.challengeId);
|
||||
|
||||
Intent intent = new Intent(getActivity(), ChallengeDetailActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String customTitle() {
|
||||
if (!isAdded()) {
|
||||
return "";
|
||||
}
|
||||
return getString(R.string.challenges);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.challenges
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailActivityCommand
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailDialogCommand
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.utils.Action1
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
class ChallengesOverviewFragment : BaseMainFragment() {
|
||||
|
||||
@Inject
|
||||
internal lateinit var challengeRepository: ChallengeRepository
|
||||
|
||||
private val viewPager: ViewPager? by bindView(R.id.viewPager)
|
||||
var statePagerAdapter: FragmentStatePagerAdapter? = null
|
||||
private var userChallengesFragment: ChallengeListFragment? = null
|
||||
private var availableChallengesFragment: ChallengeListFragment? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = true
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
val v = inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setViewPagerAdapter()
|
||||
|
||||
userChallengesFragment = ChallengeListFragment()
|
||||
userChallengesFragment?.user = this.user
|
||||
userChallengesFragment?.setViewUserChallengesOnly(true)
|
||||
|
||||
availableChallengesFragment = ChallengeListFragment()
|
||||
availableChallengesFragment?.user = this.user
|
||||
availableChallengesFragment?.setViewUserChallengesOnly(false)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
challengeRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = childFragmentManager
|
||||
|
||||
statePagerAdapter = object : FragmentStatePagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment? {
|
||||
val fragment = Fragment()
|
||||
|
||||
when (position) {
|
||||
0 -> return userChallengesFragment
|
||||
1 -> return availableChallengesFragment
|
||||
}
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
when (position) {
|
||||
0 -> return getString(R.string.my_challenges)
|
||||
1 -> return getString(R.string.public_challenges)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
viewPager?.adapter = statePagerAdapter
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(cmd: ShowChallengeDetailDialogCommand) {
|
||||
challengeRepository.getChallenge(cmd.challengeId).firstElement().subscribe(Consumer { challenge ->
|
||||
ChallengeDetailDialogHolder.showDialog(activity, challengeRepository, challenge,
|
||||
object: Action1<Challenge> {
|
||||
override fun call(t: Challenge) {
|
||||
|
||||
}
|
||||
})
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(cmd: ShowChallengeDetailActivityCommand) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(ChallengeDetailActivity.CHALLENGE_ID, cmd.challengeId)
|
||||
|
||||
val intent = Intent(activity, ChallengeDetailActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
activity?.startActivity(intent)
|
||||
}
|
||||
|
||||
override fun customTitle(): String {
|
||||
return if (!isAdded) {
|
||||
""
|
||||
} else getString(R.string.challenges)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,362 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.party;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository;
|
||||
import com.habitrpg.android.habitica.data.SocialRepository;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.social.Group;
|
||||
import com.habitrpg.android.habitica.models.social.UserParty;
|
||||
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.PartyInviteActivity;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.ChatListFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.GroupInformationFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
||||
public class PartyFragment extends BaseMainFragment {
|
||||
|
||||
@Inject
|
||||
SocialRepository socialRepository;
|
||||
|
||||
public ViewPager viewPager;
|
||||
@Inject
|
||||
InventoryRepository inventoryRepository;
|
||||
@Nullable
|
||||
private Group group;
|
||||
private PartyMemberListFragment partyMemberListFragment;
|
||||
private ChatListFragment chatListFragment;
|
||||
private FragmentPagerAdapter viewPagerAdapter;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
this.usesTabLayout = true;
|
||||
hideToolbar();
|
||||
disableToolbarScrolling();
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
|
||||
|
||||
viewPager = (ViewPager) v.findViewById(R.id.viewPager);
|
||||
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
// Get the full group data
|
||||
if (userHasParty()) {
|
||||
if (user != null) {
|
||||
getCompositeSubscription().add(socialRepository.getGroup(user.getParty().getId())
|
||||
.firstElement()
|
||||
//delay, so that realm can save party first
|
||||
.delay(500, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(group -> {
|
||||
PartyFragment.this.group = group;
|
||||
updateGroupUI();
|
||||
}, RxErrorHandler.handleEmptyError()));
|
||||
}
|
||||
socialRepository.retrieveGroup("party")
|
||||
.flatMap(group1 -> socialRepository.retrieveGroupMembers(group1.getId(), true))
|
||||
.subscribe(members -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
setViewPagerAdapter();
|
||||
this.setTutorialStepIdentifier("party");
|
||||
this.setTutorialText(getString(R.string.tutorial_party));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
private boolean userHasParty() {
|
||||
return this.user != null && this.user.getParty() != null && this.user.getParty().id != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
showToolbar();
|
||||
enableToolbarScrolling();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
socialRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void updateGroupUI() {
|
||||
if (viewPagerAdapter != null) {
|
||||
viewPagerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
if (tabLayout != null) {
|
||||
if (group == null) {
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
return;
|
||||
} else {
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (partyMemberListFragment != null && group != null) {
|
||||
partyMemberListFragment.setPartyId(group.getId());
|
||||
}
|
||||
|
||||
if (chatListFragment != null && group != null) {
|
||||
chatListFragment.setSeenGroupId(group.getId());
|
||||
}
|
||||
|
||||
if (this.activity != null) {
|
||||
this.activity.supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
if (this.group != null && this.user != null) {
|
||||
if (this.group.getLeaderID().equals(this.user.getId())) {
|
||||
inflater.inflate(R.menu.menu_party_admin, menu);
|
||||
} else {
|
||||
inflater.inflate(R.menu.menu_party, menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
switch (id) {
|
||||
case R.id.menu_invite_item:
|
||||
Intent intent = new Intent(getActivity(), PartyInviteActivity.class);
|
||||
startActivityForResult(intent, PartyInviteActivity.RESULT_SEND_INVITES);
|
||||
return true;
|
||||
case R.id.menu_guild_edit:
|
||||
this.displayEditForm();
|
||||
return true;
|
||||
case R.id.menu_guild_leave:
|
||||
new AlertDialog.Builder(viewPager.getContext())
|
||||
.setTitle(viewPager.getContext().getString(R.string.leave_party))
|
||||
.setMessage(viewPager.getContext().getString(R.string.leave_party_confirmation))
|
||||
.setPositiveButton(viewPager.getContext().getString(R.string.yes), (dialog, which) -> {
|
||||
if (this.group != null){
|
||||
this.socialRepository.leaveGroup(this.group.getId())
|
||||
.subscribe(group -> getActivity().getSupportFragmentManager().beginTransaction().remove(PartyFragment.this).commit(), RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
})
|
||||
.setNegativeButton(viewPager.getContext().getString(R.string.no), (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void displayEditForm() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("groupID", this.group != null ? this.group.getId() : null);
|
||||
bundle.putString("name", this.group.getName());
|
||||
bundle.putString("description", this.group.getDescription());
|
||||
bundle.putString("leader", this.group.getLeaderID());
|
||||
|
||||
Intent intent = new Intent(activity, GroupFormActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
startActivityForResult(intent, GroupFormActivity.GROUP_FORM_ACTIVITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case (GroupFormActivity.GROUP_FORM_ACTIVITY): {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
boolean needsSaving = false;
|
||||
Bundle bundle = data.getExtras();
|
||||
if (this.group == null) {
|
||||
break;
|
||||
}
|
||||
this.socialRepository.updateGroup(this.group, bundle.getString("name"), bundle.getString("description"), bundle.getString("leader"), bundle.getString("privacy"))
|
||||
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (PartyInviteActivity.RESULT_SEND_INVITES): {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Map<String, Object> inviteData = new HashMap<>();
|
||||
inviteData.put("inviter", this.user != null ? this.user.getProfile().getName() : null);
|
||||
if (data.getBooleanExtra(PartyInviteActivity.IS_EMAIL_KEY, false)) {
|
||||
String[] emails = data.getStringArrayExtra(PartyInviteActivity.EMAILS_KEY);
|
||||
List<HashMap<String, String>> invites = new ArrayList<>();
|
||||
for (String email : emails) {
|
||||
HashMap<String, String> invite = new HashMap<>();
|
||||
invite.put("name", "");
|
||||
invite.put("email", email);
|
||||
invites.add(invite);
|
||||
}
|
||||
inviteData.put("emails", invites);
|
||||
} else {
|
||||
String[] userIDs = data.getStringArrayExtra(PartyInviteActivity.USER_IDS_KEY);
|
||||
List<String> invites = new ArrayList<>();
|
||||
Collections.addAll(invites, userIDs);
|
||||
inviteData.put("uuids", invites);
|
||||
}
|
||||
if (this.group != null) {
|
||||
this.socialRepository.inviteToGroup(this.group.getId(), inviteData)
|
||||
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
|
||||
if (this.user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserParty party = this.user.getParty();
|
||||
|
||||
if (party == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
viewPagerAdapter = new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
|
||||
Fragment fragment;
|
||||
|
||||
switch (position) {
|
||||
case 0: {
|
||||
if (user.hasParty()) {
|
||||
PartyDetailFragment detailFragment = new PartyDetailFragment();
|
||||
detailFragment.setPartyId(user.getParty().id);
|
||||
fragment = detailFragment;
|
||||
} else {
|
||||
fragment = GroupInformationFragment.Companion.newInstance(null, user);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
if (chatListFragment == null) {
|
||||
chatListFragment = new ChatListFragment();
|
||||
if (user.hasParty()) {
|
||||
chatListFragment.configure(user.getParty().id, user, false);
|
||||
}
|
||||
}
|
||||
fragment = chatListFragment;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if (partyMemberListFragment == null) {
|
||||
partyMemberListFragment = new PartyMemberListFragment();
|
||||
if (user.hasParty()) {
|
||||
partyMemberListFragment.setPartyId(user.getParty().id);
|
||||
}
|
||||
}
|
||||
fragment = partyMemberListFragment;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fragment = new Fragment();
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (group == null) {
|
||||
return 1;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getContext().getString(R.string.party);
|
||||
case 1:
|
||||
return getContext().getString(R.string.chat);
|
||||
case 2:
|
||||
return getContext().getString(R.string.members);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
this.viewPager.setAdapter(viewPagerAdapter);
|
||||
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
if (position == 1 && group != null) {
|
||||
if (chatListFragment != null) {
|
||||
chatListFragment.setNavigatedToFragment(group.getId());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (position == 1 && group != null) {
|
||||
if (chatListFragment != null) {
|
||||
chatListFragment.setNavigatedToFragment(group.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String customTitle() {
|
||||
if (!isAdded()) {
|
||||
return "";
|
||||
}
|
||||
return getString(R.string.sidebar_party);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.party
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.social.UserParty
|
||||
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.PartyInviteActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.ChatListFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.GroupInformationFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import java.util.HashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
class PartyFragment : BaseMainFragment() {
|
||||
|
||||
@Inject
|
||||
internal lateinit var socialRepository: SocialRepository
|
||||
@Inject
|
||||
internal lateinit var inventoryRepository: InventoryRepository
|
||||
|
||||
private val viewPager: ViewPager? by bindView(R.id.viewpager)
|
||||
private var group: Group? = null
|
||||
private var partyMemberListFragment: PartyMemberListFragment? = null
|
||||
private var chatListFragment: ChatListFragment? = null
|
||||
private var viewPagerAdapter: FragmentPagerAdapter? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = true
|
||||
hideToolbar()
|
||||
disableToolbarScrolling()
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
||||
viewPager?.currentItem = 0
|
||||
|
||||
// Get the full group data
|
||||
if (userHasParty()) {
|
||||
if (user != null) {
|
||||
compositeSubscription.add(socialRepository.getGroup(user?.party?.id)
|
||||
.firstElement()
|
||||
//delay, so that realm can save party first
|
||||
.delay(500, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(Consumer { group ->
|
||||
this@PartyFragment.group = group
|
||||
updateGroupUI()
|
||||
}, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
socialRepository.retrieveGroup("party")
|
||||
.flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) }
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
setViewPagerAdapter()
|
||||
this.tutorialStepIdentifier = "party"
|
||||
this.tutorialText = getString(R.string.tutorial_party)
|
||||
}
|
||||
|
||||
private fun userHasParty(): Boolean {
|
||||
return user?.party?.id != null
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
showToolbar()
|
||||
enableToolbarScrolling()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
socialRepository.close()
|
||||
inventoryRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
private fun updateGroupUI() {
|
||||
if (viewPagerAdapter != null) {
|
||||
viewPagerAdapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
if (tabLayout != null) {
|
||||
if (group == null) {
|
||||
tabLayout?.visibility = View.GONE
|
||||
return
|
||||
} else {
|
||||
tabLayout?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
partyMemberListFragment?.setPartyId(group!!.id)
|
||||
|
||||
chatListFragment?.seenGroupId = group!!.id
|
||||
|
||||
this.activity?.supportInvalidateOptionsMenu()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
|
||||
if (this.group != null && this.user != null) {
|
||||
if (this.group!!.leaderID == this.user!!.id) {
|
||||
inflater!!.inflate(R.menu.menu_party_admin, menu)
|
||||
} else {
|
||||
inflater!!.inflate(R.menu.menu_party, menu)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
val id = item!!.itemId
|
||||
|
||||
when (id) {
|
||||
R.id.menu_invite_item -> {
|
||||
val intent = Intent(activity, PartyInviteActivity::class.java)
|
||||
startActivityForResult(intent, PartyInviteActivity.RESULT_SEND_INVITES)
|
||||
return true
|
||||
}
|
||||
R.id.menu_guild_edit -> {
|
||||
this.displayEditForm()
|
||||
return true
|
||||
}
|
||||
R.id.menu_guild_leave -> {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context?.getString(R.string.leave_party))
|
||||
.setMessage(context?.getString(R.string.leave_party_confirmation))
|
||||
.setPositiveButton(context?.getString(R.string.yes)) { _, _ ->
|
||||
if (this.group != null) {
|
||||
this.socialRepository.leaveGroup(this.group!!.id)
|
||||
.subscribe(Consumer { activity?.supportFragmentManager?.beginTransaction()?.remove(this@PartyFragment)?.commit() }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
.setNegativeButton(context?.getString(R.string.no)) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun displayEditForm() {
|
||||
val bundle = Bundle()
|
||||
bundle.putString("groupID", if (this.group != null) this.group!!.id else null)
|
||||
bundle.putString("name", this.group!!.name)
|
||||
bundle.putString("description", this.group!!.description)
|
||||
bundle.putString("leader", this.group!!.leaderID)
|
||||
|
||||
val intent = Intent(activity, GroupFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
startActivityForResult(intent, GroupFormActivity.GROUP_FORM_ACTIVITY)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
GroupFormActivity.GROUP_FORM_ACTIVITY -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val needsSaving = false
|
||||
val bundle = data!!.extras
|
||||
if (this.group == null) {
|
||||
return
|
||||
}
|
||||
this.socialRepository.updateGroup(this.group, bundle!!.getString("name"), bundle.getString("description"), bundle.getString("leader"), bundle.getString("privacy"))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
PartyInviteActivity.RESULT_SEND_INVITES -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val inviteData = HashMap<String, Any>()
|
||||
inviteData["inviter"] = user?.profile?.name ?: ""
|
||||
if (data!!.getBooleanExtra(PartyInviteActivity.IS_EMAIL_KEY, false)) {
|
||||
val emails = data.getStringArrayExtra(PartyInviteActivity.EMAILS_KEY)
|
||||
val invites = ArrayList<HashMap<String, String>>()
|
||||
for (email in emails) {
|
||||
val invite = HashMap<String, String>()
|
||||
invite["name"] = ""
|
||||
invite["email"] = email
|
||||
invites.add(invite)
|
||||
}
|
||||
inviteData["emails"] = invites
|
||||
} else {
|
||||
val userIDs = data.getStringArrayExtra(PartyInviteActivity.USER_IDS_KEY)
|
||||
val invites = ArrayList<String>()
|
||||
Collections.addAll(invites, *userIDs)
|
||||
inviteData["uuids"] = invites
|
||||
}
|
||||
if (this.group != null) {
|
||||
this.socialRepository.inviteToGroup(this.group!!.id, inviteData)
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setViewPagerAdapter() {
|
||||
val fragmentManager = childFragmentManager
|
||||
if (this.user == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val party = this.user!!.party ?: return
|
||||
|
||||
viewPagerAdapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment? {
|
||||
|
||||
val fragment: Fragment?
|
||||
|
||||
when (position) {
|
||||
0 -> {
|
||||
if (user!!.hasParty()) {
|
||||
val detailFragment = PartyDetailFragment()
|
||||
detailFragment.partyId = user!!.party.id
|
||||
fragment = detailFragment
|
||||
} else {
|
||||
fragment = GroupInformationFragment.newInstance(null, user)
|
||||
}
|
||||
}
|
||||
1 -> {
|
||||
if (chatListFragment == null) {
|
||||
chatListFragment = ChatListFragment()
|
||||
if (user!!.hasParty()) {
|
||||
chatListFragment!!.configure(user!!.party.id, user, false)
|
||||
}
|
||||
}
|
||||
fragment = chatListFragment
|
||||
}
|
||||
2 -> {
|
||||
if (partyMemberListFragment == null) {
|
||||
partyMemberListFragment = PartyMemberListFragment()
|
||||
if (user!!.hasParty()) {
|
||||
partyMemberListFragment!!.setPartyId(user!!.party.id)
|
||||
}
|
||||
}
|
||||
fragment = partyMemberListFragment
|
||||
}
|
||||
else -> fragment = Fragment()
|
||||
}
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return if (group == null) {
|
||||
1
|
||||
} else {
|
||||
3
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
when (position) {
|
||||
0 -> return context!!.getString(R.string.party)
|
||||
1 -> return context!!.getString(R.string.chat)
|
||||
2 -> return context!!.getString(R.string.members)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
this.viewPager?.adapter = viewPagerAdapter
|
||||
|
||||
viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
if (position == 1 && group != null) {
|
||||
chatListFragment?.setNavigatedToFragment(group!!.id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
if (position == 1 && group != null) {
|
||||
chatListFragment?.setNavigatedToFragment(group!!.id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
})
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
|
||||
override fun customTitle(): String {
|
||||
return if (!isAdded) {
|
||||
""
|
||||
} else getString(R.string.sidebar_party)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -48,7 +48,9 @@ class PartyMemberListFragment : BaseFragment() {
|
|||
|
||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||
adapter = PartyMemberRecyclerViewAdapter(null, true)
|
||||
adapter?.getUserClickedEvents()?.subscribe(Consumer { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription.add(it) }
|
||||
context.notNull {
|
||||
adapter?.getUserClickedEvents()?.subscribe(Consumer { userId -> FullProfileActivity.open(it, userId) }, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription.add(it) }
|
||||
}
|
||||
recyclerView?.adapter = adapter
|
||||
recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
|
||||
|
|
@ -59,7 +61,7 @@ class PartyMemberListFragment : BaseFragment() {
|
|||
|
||||
private fun refreshMembers() {
|
||||
setRefreshing(true)
|
||||
socialRepository.retrieveGroupMembers(partyId!!, true).doOnComplete { setRefreshing(false) }.subscribe(Consumer { users -> }, RxErrorHandler.handleEmptyError())
|
||||
socialRepository.retrieveGroupMembers(partyId!!, true).doOnComplete { setRefreshing(false) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun setRefreshing(isRefreshing: Boolean) {
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class TasksFragment : BaseMainFragment() {
|
|||
|
||||
private fun showFilterDialog() {
|
||||
context.notNull {
|
||||
val dialog = TaskFilterDialog(it, HabiticaBaseApplication.getComponent())
|
||||
val dialog = TaskFilterDialog(it, HabiticaBaseApplication.component)
|
||||
if (user != null) {
|
||||
dialog.setTags(user?.tags?.createSnapshot() ?: emptyList())
|
||||
}
|
||||
|
|
@ -378,7 +378,7 @@ class TasksFragment : BaseMainFragment() {
|
|||
override val displayedClassName: String?
|
||||
get() = null
|
||||
|
||||
override fun customTitle(): String? = null
|
||||
override fun customTitle(): String = ""
|
||||
|
||||
override fun addToBackStack(): Boolean = false
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ import java.util.*
|
|||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
object ButterKnife {
|
||||
fun reset(target: Any) {
|
||||
LazyRegistry.reset(target)
|
||||
}
|
||||
}
|
||||
|
||||
fun <V : View> View.bindView(@IdRes id: Int)
|
||||
: ReadOnlyProperty<View, V> = required(id, viewFinder)
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class ShopItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), Vi
|
|||
override fun onClick(view: View) {
|
||||
val item = item
|
||||
if (item != null) {
|
||||
val dialog = PurchaseDialog(context, HabiticaBaseApplication.getComponent(), item)
|
||||
val dialog = PurchaseDialog(context, HabiticaBaseApplication.component, item)
|
||||
dialog.shopIdentifier = shopIdentifier
|
||||
dialog.isPinned = isPinned
|
||||
dialog.show()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import io.reactivex.schedulers.Schedulers
|
|||
import net.pherth.android.emoji_library.EmojiTextView
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
abstract class BaseTaskViewHolder @JvmOverloads constructor(itemView: View, useButterKnife: Boolean = true) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
abstract class BaseTaskViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
|
||||
|
||||
var task: Task? = null
|
||||
|
|
@ -65,7 +65,7 @@ abstract class BaseTaskViewHolder @JvmOverloads constructor(itemView: View, useB
|
|||
|
||||
init {
|
||||
|
||||
itemView.setOnClickListener(this)
|
||||
itemView.setOnClickListener { onClick(it) }
|
||||
itemView.isClickable = true
|
||||
|
||||
//Re enable when we find a way to only react when a link is tapped.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ import org.greenrobot.eventbus.EventBus
|
|||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class PurchaseDialog(context: Context, component: AppComponent, val item: ShopItem) : AlertDialog(context) {
|
||||
class PurchaseDialog(context: Context, component: AppComponent?, val item: ShopItem) : AlertDialog(context) {
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
|
@ -133,7 +133,7 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt
|
|||
}
|
||||
}
|
||||
init {
|
||||
component.inject(this)
|
||||
component?.inject(this)
|
||||
|
||||
setView(customView)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import android.widget.ImageButton
|
|||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.extensions.bindView
|
||||
import com.habitrpg.android.habitica.ui.helpers.NavbarUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
|
||||
class ChatBarView : FrameLayout {
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import io.reactivex.functions.Consumer
|
|||
import kotlinx.android.synthetic.main.dialog_bulk_allocate.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class BulkAllocateStatsDialog(context: Context, component: AppComponent) : AlertDialog(context) {
|
||||
class BulkAllocateStatsDialog(context: Context, component: AppComponent?) : AlertDialog(context) {
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
|
@ -57,7 +57,7 @@ class BulkAllocateStatsDialog(context: Context, component: AppComponent) : Alert
|
|||
}
|
||||
|
||||
init {
|
||||
component.inject(this)
|
||||
component?.inject(this)
|
||||
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val view = inflater.inflate(R.layout.dialog_bulk_allocate, null)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.ui.views.subscriptions
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
|
|
@ -57,19 +58,19 @@ class SubscriptionOptionView(context: Context, attrs: AttributeSet) : FrameLayou
|
|||
subscriptionSelectedView.setBackgroundResource(R.drawable.subscription_selected)
|
||||
subscriptionSelectedFrameView.setBackgroundResource(R.color.brand_300)
|
||||
gemCapTextView.setBackgroundResource(R.drawable.pill_bg_green)
|
||||
gemCapTextView.setTextColor(context.resources.getColor(R.color.white))
|
||||
gemCapTextView.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
gemCapTextView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding)
|
||||
hourGlassTextView.setBackgroundResource(R.drawable.pill_bg_green)
|
||||
hourGlassTextView.setTextColor(context.resources.getColor(R.color.white))
|
||||
hourGlassTextView.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
hourGlassTextView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding)
|
||||
} else {
|
||||
subscriptionSelectedView.setBackgroundResource(R.drawable.subscription_unselected)
|
||||
subscriptionSelectedFrameView.setBackgroundResource(R.color.brand_700)
|
||||
gemCapTextView.setBackgroundResource(R.drawable.pill_bg)
|
||||
gemCapTextView.setTextColor(context.resources.getColor(R.color.text_light))
|
||||
gemCapTextView.setTextColor(ContextCompat.getColor(context, R.color.text_light))
|
||||
gemCapTextView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding)
|
||||
hourGlassTextView.setBackgroundResource(R.drawable.pill_bg)
|
||||
hourGlassTextView.setTextColor(context.resources.getColor(R.color.text_light))
|
||||
hourGlassTextView.setTextColor(ContextCompat.getColor(context, R.color.text_light))
|
||||
hourGlassTextView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import io.reactivex.functions.Consumer
|
|||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class TaskFilterDialog(context: Context, component: AppComponent) : AlertDialog(context), RadioGroup.OnCheckedChangeListener {
|
||||
class TaskFilterDialog(context: Context, component: AppComponent?) : AlertDialog(context), RadioGroup.OnCheckedChangeListener {
|
||||
|
||||
@Inject
|
||||
lateinit var repository: TagRepository
|
||||
|
|
@ -55,7 +55,7 @@ class TaskFilterDialog(context: Context, component: AppComponent) : AlertDialog(
|
|||
private var isEditing: Boolean = false
|
||||
|
||||
init {
|
||||
component.inject(this)
|
||||
component?.inject(this)
|
||||
addIcon = ContextCompat.getDrawable(context, R.drawable.ic_add_purple_300_36dp)
|
||||
|
||||
val inflater = LayoutInflater.from(context)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ 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;
|
||||
|
||||
|
|
@ -42,7 +44,7 @@ public class AvatarStatsWidgetProvider extends BaseWidgetProvider {
|
|||
|
||||
private void setUp() {
|
||||
if (userRepository == null) {
|
||||
HabiticaBaseApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import com.habitrpg.android.habitica.interactors.NotifyUserUseCase;
|
|||
import com.habitrpg.android.habitica.models.responses.TaskScoringResult;
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
||||
|
|
@ -74,7 +76,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
|
|||
|
||||
protected void showToastForTaskDirection(Context context, TaskScoringResult data, String userID) {
|
||||
if (userRepository == null) {
|
||||
HabiticaApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaApplication.Companion.getComponent()).inject(this);
|
||||
}
|
||||
if (data != null) {
|
||||
Pair<SpannableStringBuilder, HabiticaSnackbar.SnackbarDisplayType> pair = NotifyUserUseCase.Companion.getNotificationAndAddStatsToUserAsText(context, data.getExperienceDelta(), data.getHealthDelta(), data.getGoldDelta(), data.getManaDelta());
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ 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 {
|
||||
|
|
@ -22,8 +24,7 @@ public class DailiesWidgetProvider extends TaskListWidgetProvider {
|
|||
|
||||
private void setUp(Context context) {
|
||||
if (apiClient == null) {
|
||||
HabiticaBaseApplication application = HabiticaApplication.getInstance(context);
|
||||
application.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ 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;
|
||||
|
||||
|
|
@ -31,7 +33,7 @@ public class HabitButtonWidgetProvider extends BaseWidgetProvider {
|
|||
|
||||
private void setUp() {
|
||||
if (taskRepository == null) {
|
||||
HabiticaBaseApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ 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;
|
||||
|
|
@ -51,7 +52,7 @@ public class HabitButtonWidgetService extends Service {
|
|||
|
||||
@Override
|
||||
public int onStartCommand(final Intent intent, int flags, int startId) {
|
||||
HabiticaBaseApplication.getComponent().inject(this);
|
||||
Objects.requireNonNull(HabiticaBaseApplication.Companion.getComponent()).inject(this);
|
||||
this.appWidgetManager = AppWidgetManager.getInstance(this);
|
||||
ComponentName thisWidget = new ComponentName(this, HabitButtonWidgetProvider.class);
|
||||
allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue