Continue refactoring

This commit is contained in:
Phillip Thelen 2018-07-10 14:56:24 +02:00
parent a98eeb347d
commit b52b4563e9
26 changed files with 1251 additions and 1420 deletions

View file

@ -58,14 +58,14 @@ interface SocialRepository : BaseRepository {
fun markPrivateMessagesRead(user: User?): Flowable<Void>
fun acceptQuest(user: User, partyId: String): Flowable<Void>
fun rejectQuest(user: User, partyId: String): Flowable<Void>
fun acceptQuest(user: User?, partyId: String): Flowable<Void>
fun rejectQuest(user: User?, partyId: String): Flowable<Void>
fun leaveQuest(partyId: String?): Flowable<Void>
fun leaveQuest(partyId: String): Flowable<Void>
fun cancelQuest(partyId: String?): Flowable<Void>
fun cancelQuest(partyId: String): Flowable<Void>
fun abortQuest(partyId: String?): Flowable<Quest>
fun abortQuest(partyId: String): Flowable<Quest>
fun rejectGroupInvite(groupId: String): Flowable<Void>

View file

@ -3,6 +3,7 @@ package com.habitrpg.android.habitica.data.implementation
import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.local.SocialLocalRepository
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.AchievementResult
import com.habitrpg.android.habitica.models.inventory.Quest
@ -196,34 +197,34 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
override fun getUserGroups(): Flowable<RealmResults<Group>> = localRepository.getUserGroups()
override fun acceptQuest(user: User, partyId: String): Flowable<Void> {
override fun acceptQuest(user: User?, partyId: String): Flowable<Void> {
return apiClient.acceptQuest(partyId)
.doOnNext { localRepository.updateRSVPNeeded(user, false) }
.doOnNext {
user.notNull {
localRepository.updateRSVPNeeded(it, false)
}
}
}
override fun rejectQuest(user: User, partyId: String): Flowable<Void> {
override fun rejectQuest(user: User?, partyId: String): Flowable<Void> {
return apiClient.rejectQuest(partyId)
.doOnNext { localRepository.updateRSVPNeeded(user, false) }
.doOnNext {
user.notNull {
localRepository.updateRSVPNeeded(it, false)
}
}
}
override fun leaveQuest(partyId: String?): Flowable<Void> {
return if (partyId == null) {
Flowable.empty()
} else apiClient.leaveQuest(partyId)
override fun leaveQuest(partyId: String): Flowable<Void> {
return apiClient.leaveQuest(partyId)
}
override fun cancelQuest(partyId: String?): Flowable<Void> {
if (partyId == null) {
return Flowable.empty()
}
override fun cancelQuest(partyId: String): Flowable<Void> {
return apiClient.cancelQuest(partyId)
.doOnNext { localRepository.removeQuest(partyId) }
}
override fun abortQuest(partyId: String?): Flowable<Quest> {
if (partyId == null) {
return Flowable.empty()
}
override fun abortQuest(partyId: String): Flowable<Quest> {
return apiClient.abortQuest(partyId)
.doOnNext { localRepository.removeQuest(partyId) }
}

View file

@ -1,145 +0,0 @@
package com.habitrpg.android.habitica.ui.activities;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.ui.fragments.AboutFragment;
import com.mikepenz.aboutlibraries.Libs;
import com.mikepenz.aboutlibraries.LibsBuilder;
import butterknife.BindView;
public class AboutActivity extends BaseActivity {
@BindView(R.id.pager)
ViewPager pager;
@BindView(R.id.tab_layout)
TabLayout tabLayout;
@Override
protected int getLayoutResId() {
return R.layout.activity_about;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(R.string.about_title);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setHomeButtonEnabled(false);
actionBar.setElevation(0);
}
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), 2);
pager.setAdapter(adapter);
pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
pager.setOffscreenPageLimit(1);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
pager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
tabLayout.setupWithViewPager(pager);
}
@Override
protected void injectActivity(AppComponent component) {
component.inject(this);
}
@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 == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new AboutFragment();
case 1:
return new LibsBuilder()
//Pass the fields of your application to the lib so it can find all external lib information
.withFields(R.string.class.getFields())
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutAppName(getString(R.string.app_name))
.withAboutDescription("<h2>Used Libraries</h2>")
.withAboutIconShown(true)
.withAboutVersionShown(true)
.withAboutVersionShownCode(true)
.withAboutVersionShownName(true)
.supportFragment();
default:
return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return getString(R.string.about_title);
} else if (position == 1) {
return getString(R.string.about_libraries);
}
return getString(R.string.about_versionhistory);
}
@Override
public int getCount() {
return mNumOfTabs;
}
}
}

View file

@ -0,0 +1,121 @@
package com.habitrpg.android.habitica.ui.activities
import android.os.Bundle
import android.support.design.widget.TabLayout
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter
import android.support.v4.view.ViewPager
import android.view.MenuItem
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.ui.fragments.AboutFragment
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder
class AboutActivity : BaseActivity() {
private val pager: ViewPager by bindView(R.id.pager)
private val tabLayout: TabLayout by bindView(R.id.tab_layout)
override fun getLayoutResId(): Int {
return R.layout.activity_about
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val actionBar = supportActionBar
if (actionBar != null) {
actionBar.setTitle(R.string.about_title)
actionBar.setDisplayHomeAsUpEnabled(true)
actionBar.setDisplayShowHomeEnabled(false)
actionBar.setDisplayShowTitleEnabled(true)
actionBar.setDisplayUseLogoEnabled(false)
actionBar.setHomeButtonEnabled(false)
actionBar.elevation = 0f
}
tabLayout.tabGravity = TabLayout.GRAVITY_FILL
val adapter = PagerAdapter(supportFragmentManager, 2)
pager.adapter = adapter
pager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))
pager.offscreenPageLimit = 1
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
pager.currentItem = tab.position
}
override fun onTabUnselected(tab: TabLayout.Tab) {
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
tabLayout.setupWithViewPager(pager)
}
override fun injectActivity(component: AppComponent) {
component.inject(this)
}
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 == android.R.id.home) {
finish()
return true
}
return super.onOptionsItemSelected(item)
}
private inner class PagerAdapter(fm: FragmentManager, internal var mNumOfTabs: Int) : FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment? {
when (position) {
0 ->
return AboutFragment()
1 -> return LibsBuilder()
//Pass the fields of your application to the lib so it can find all external lib information
.withFields(R.string::class.java.fields)
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutAppName(getString(R.string.app_name))
.withAboutDescription("<h2>Used Libraries</h2>")
.withAboutIconShown(true)
.withAboutVersionShown(true)
.withAboutVersionShownCode(true)
.withAboutVersionShownName(true)
.supportFragment()
else -> return null
}
}
override fun getPageTitle(position: Int): CharSequence? {
if (position == 0) {
return getString(R.string.about_title)
} else if (position == 1) {
return getString(R.string.about_libraries)
}
return getString(R.string.about_versionhistory)
}
override fun getCount(): Int {
return mNumOfTabs
}
}
}

View file

@ -1,61 +0,0 @@
package com.habitrpg.android.habitica.ui.activities;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
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.SocialRepository;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAdapter;
import javax.inject.Inject;
import butterknife.BindView;
public class SkillMemberActivity extends BaseActivity {
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
private PartyMemberRecyclerViewAdapter viewAdapter;
@Inject
public SocialRepository socialRepository;
@Inject
public UserRepository userRepository;
@Override
protected int getLayoutResId() {
return R.layout.activity_skill_members;
}
@Override
protected void injectActivity(AppComponent component) {
component.inject(this);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadMemberList();
}
private void loadMemberList() {
recyclerView.setLayoutManager(new LinearLayoutManager(this));
viewAdapter = new PartyMemberRecyclerViewAdapter(null, true, this);
viewAdapter.getUserClickedEvents().subscribe(userId -> {
Intent resultIntent = new Intent();
resultIntent.putExtra("member_id", userId);
setResult(Activity.RESULT_OK, resultIntent);
finish();
}, RxErrorHandler.handleEmptyError());
recyclerView.setAdapter(viewAdapter);
userRepository.getUser()
.firstElement()
.flatMap(user -> socialRepository.getGroupMembers(user.getParty().id).firstElement())
.subscribe(viewAdapter::updateData, RxErrorHandler.handleEmptyError());
}
}

View file

@ -0,0 +1,57 @@
package com.habitrpg.android.habitica.ui.activities
import android.app.Activity
import android.content.Intent
import android.os.Bundle
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.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.functions.Consumer
import javax.inject.Inject
class SkillMemberActivity : BaseActivity() {
private val recyclerView: RecyclerView by bindView(R.id.recyclerView)
private var viewAdapter: PartyMemberRecyclerViewAdapter? = null
@Inject
lateinit var socialRepository: SocialRepository
@Inject
lateinit var userRepository: UserRepository
override fun getLayoutResId(): Int {
return R.layout.activity_skill_members
}
override fun injectActivity(component: AppComponent) {
component.inject(this)
}
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadMemberList()
}
private fun loadMemberList() {
recyclerView.layoutManager = LinearLayoutManager(this)
viewAdapter = PartyMemberRecyclerViewAdapter(null, true)
viewAdapter?.getUserClickedEvents()?.subscribe(Consumer { userId ->
val resultIntent = Intent()
resultIntent.putExtra("member_id", userId)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}, RxErrorHandler.handleEmptyError())
recyclerView.adapter = viewAdapter
userRepository.getUser()
.firstElement()
.flatMap { user -> socialRepository.getGroupMembers(user.party.id).firstElement() }
.subscribe(Consumer { viewAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError())
}
}

View file

@ -62,13 +62,13 @@ public class SkillTasksActivity extends BaseActivity {
SkillTasksRecyclerViewFragment fragment = new SkillTasksRecyclerViewFragment();
switch (position) {
case 0:
fragment.taskType = Task.TYPE_HABIT;
fragment.setTaskType(Task.TYPE_HABIT);
break;
case 1:
fragment.taskType = Task.TYPE_DAILY;
fragment.setTaskType(Task.TYPE_DAILY);
break;
default:
fragment.taskType = Task.TYPE_TODO;
fragment.setTaskType(Task.TYPE_TODO);
}
compositeSubscription.add(fragment.getTaskSelectionEvents().subscribe(task -> taskSelected(task), RxErrorHandler.handleEmptyError()));

View file

@ -23,7 +23,7 @@ import io.reactivex.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, autoUpdate: Boolean, private val context: Context) : RealmRecyclerViewAdapter<Member, PartyMemberRecyclerViewAdapter.MemberViewHolder>(data, autoUpdate) {
class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Member, PartyMemberRecyclerViewAdapter.MemberViewHolder>(data, autoUpdate) {
private val userClickedEvents = PublishSubject.create<String>()
@ -60,9 +60,9 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, auto
AvatarWithBarsViewModel.setHpBarData(hpBar, user.stats)
lvl.text = context.getString(R.string.user_level, user.stats.getLvl())
lvl.text = itemView.context.getString(R.string.user_level, user.stats.getLvl())
classLabel.text = user.stats.getTranslatedClassName(context)
classLabel.text = user.stats.getTranslatedClassName(itemView.context)
val colorResourceID: Int = when (user.stats.habitClass) {
Stats.HEALER -> {
@ -79,7 +79,7 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, auto
}
else -> R.color.task_gray
}
ViewHelper.SetBackgroundTint(classBackground, ContextCompat.getColor(context, colorResourceID))
ViewHelper.SetBackgroundTint(classBackground, ContextCompat.getColor(itemView.context, colorResourceID))
userName.text = user.profile.name
itemView.isClickable = true

View file

@ -1,136 +0,0 @@
package com.habitrpg.android.habitica.ui.fragments;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy;
import com.habitrpg.android.habitica.ui.GemPurchaseOptionsView;
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity;
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
import org.solovyev.android.checkout.ActivityCheckout;
import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Inventory;
import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.Sku;
import javax.inject.Inject;
import butterknife.BindView;
public class GemsPurchaseFragment extends BaseFragment implements GemPurchaseActivity.CheckoutFragment {
@BindView(R.id.gems_4_view)
GemPurchaseOptionsView gems4View;
@BindView(R.id.gems_21_view)
GemPurchaseOptionsView gems21View;
@BindView(R.id.gems_42_view)
GemPurchaseOptionsView gems42View;
@BindView(R.id.gems_84_view)
GemPurchaseOptionsView gems84View;
@BindView(R.id.supportTextView)
TextView supportTextView;
@Inject
CrashlyticsProxy crashlyticsProxy;
private GemPurchaseActivity listener;
private BillingRequests billingRequests;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_gem_purchase, container, false);
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
gems4View.setOnPurchaseClickListener(v -> purchaseGems(PurchaseTypes.Purchase4Gems));
gems21View.setOnPurchaseClickListener(v -> purchaseGems(PurchaseTypes.Purchase21Gems));
gems42View.setOnPurchaseClickListener(v -> purchaseGems(PurchaseTypes.Purchase42Gems));
gems84View.setOnPurchaseClickListener(v -> purchaseGems(PurchaseTypes.Purchase84Gems));
Drawable heartDrawable = new BitmapDrawable(getResources(), HabiticaIconsHelper.imageOfHeartLarge());
supportTextView.setCompoundDrawables(null, heartDrawable, null, null);
gems84View.getSeedsImageButton().setOnClickListener(v -> ((GemPurchaseActivity) this.getActivity()).showSeedsPromo(getString(R.string.seeds_interstitial_gems), "store"));
}
@Override
public void setupCheckout() {
final ActivityCheckout checkout = listener.getActivityCheckout();
if (checkout != null) {
Inventory inventory = checkout.makeInventory();
inventory.load(Inventory.Request.create()
.loadAllPurchases().loadSkus(ProductTypes.IN_APP, PurchaseTypes.allGemTypes),
products -> {
Inventory.Product gems = products.get(ProductTypes.IN_APP);
if (!gems.supported) {
// billing is not supported, user can't purchase anything
return;
}
java.util.List<Sku> skus = gems.getSkus();
for (Sku sku : skus) {
updateButtonLabel(sku.id.code, sku.price);
}
});
}
}
@Override
public void setListener(GemPurchaseActivity listener) {
this.listener = listener;
}
@Override
public void setBillingRequests(BillingRequests billingRequests) {
this.billingRequests = billingRequests;
}
private void updateButtonLabel(String sku, String price) {
GemPurchaseOptionsView matchingView;
if (sku.equals(PurchaseTypes.Purchase4Gems)) {
matchingView = gems4View;
} else if (sku.equals(PurchaseTypes.Purchase21Gems)) {
matchingView = gems21View;
} else if (sku.equals(PurchaseTypes.Purchase42Gems)) {
matchingView = gems42View;
} else if (sku.equals(PurchaseTypes.Purchase84Gems)) {
matchingView = gems84View;
} else {
return;
}
if (matchingView != null) {
matchingView.setPurchaseButtonText(price);
matchingView.setSku(sku);
}
}
public void purchaseGems(String sku) {
if (listener != null) {
final ActivityCheckout checkout = listener.getActivityCheckout();
billingRequests.purchase(ProductTypes.IN_APP, sku, null, checkout.getPurchaseFlow());
}
}
}

View file

@ -0,0 +1,112 @@
package com.habitrpg.android.habitica.ui.fragments
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.extensions.inflate
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.GemPurchaseOptionsView
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import org.solovyev.android.checkout.BillingRequests
import org.solovyev.android.checkout.Inventory
import org.solovyev.android.checkout.ProductTypes
import javax.inject.Inject
class GemsPurchaseFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragment {
private val gems4View: GemPurchaseOptionsView? by bindView(R.id.gems_4_view)
private val gems21View: GemPurchaseOptionsView? by bindView(R.id.gems_21_view)
private val gems42View: GemPurchaseOptionsView? by bindView(R.id.gems_42_view)
private val gems84View: GemPurchaseOptionsView? by bindView(R.id.gems_84_view)
private val supportTextView: TextView? by bindView(R.id.supportTextView)
@Inject
lateinit var crashlyticsProxy: CrashlyticsProxy
private var listener: GemPurchaseActivity? = null
private var billingRequests: BillingRequests? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return container?.inflate(R.layout.fragment_gem_purchase)
}
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
gems4View?.setOnPurchaseClickListener(View.OnClickListener { purchaseGems(PurchaseTypes.Purchase4Gems) })
gems21View?.setOnPurchaseClickListener(View.OnClickListener { purchaseGems(PurchaseTypes.Purchase21Gems) })
gems42View?.setOnPurchaseClickListener(View.OnClickListener { purchaseGems(PurchaseTypes.Purchase42Gems) })
gems84View?.setOnPurchaseClickListener(View.OnClickListener { purchaseGems(PurchaseTypes.Purchase84Gems) })
val heartDrawable = BitmapDrawable(resources, HabiticaIconsHelper.imageOfHeartLarge())
supportTextView?.setCompoundDrawables(null, heartDrawable, null, null)
gems84View?.seedsImageButton?.setOnClickListener { (this.activity as GemPurchaseActivity).showSeedsPromo(getString(R.string.seeds_interstitial_gems), "store") }
}
override fun setupCheckout() {
val checkout = listener?.activityCheckout
if (checkout != null) {
val inventory = checkout.makeInventory()
inventory.load(Inventory.Request.create()
.loadAllPurchases().loadSkus(ProductTypes.IN_APP, PurchaseTypes.allGemTypes)
) { products ->
val gems = products.get(ProductTypes.IN_APP)
if (!gems.supported) {
// billing is not supported, user can't purchase anything
return@load
}
val skus = gems.skus
for (sku in skus) {
updateButtonLabel(sku.id.code, sku.price)
}
}
}
}
override fun setListener(listener: GemPurchaseActivity) {
this.listener = listener
}
override fun setBillingRequests(billingRequests: BillingRequests) {
this.billingRequests = billingRequests
}
private fun updateButtonLabel(sku: String, price: String) {
val matchingView: GemPurchaseOptionsView? = when (sku) {
PurchaseTypes.Purchase4Gems -> gems4View
PurchaseTypes.Purchase21Gems -> gems21View
PurchaseTypes.Purchase42Gems -> gems42View
PurchaseTypes.Purchase84Gems -> gems84View
else -> return
}
if (matchingView != null) {
matchingView.setPurchaseButtonText(price)
matchingView.sku = sku
}
}
fun purchaseGems(sku: String) {
listener?.activityCheckout.notNull {
billingRequests?.purchase(ProductTypes.IN_APP, sku, null, it.purchaseFlow)
}
}
}

View file

@ -1,321 +0,0 @@
package com.habitrpg.android.habitica.ui.fragments;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
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.events.UserSubscribedEvent;
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.user.SubscriptionPlan;
import com.habitrpg.android.habitica.models.user.User;
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy;
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity;
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionDetailsView;
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView;
import org.greenrobot.eventbus.Subscribe;
import org.solovyev.android.checkout.ActivityCheckout;
import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Inventory;
import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.RequestListener;
import org.solovyev.android.checkout.Sku;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.OnClick;
public class SubscriptionFragment extends BaseFragment implements GemPurchaseActivity.CheckoutFragment {
@Inject
CrashlyticsProxy crashlyticsProxy;
@Inject
UserRepository userRepository;
@BindView(R.id.subscribe_listitem1_box)
View subscribeListitem1Box;
@BindView(R.id.subscribe_listitem2_box)
View subscribeListitem2Box;
@BindView(R.id.subscribe_listitem3_box)
View subscribeListitem3Box;
@BindView(R.id.subscribe_listitem4_box)
View subscribeListitem4Box;
@BindView(R.id.subscribe_listitem1_expand)
ImageView subscribeListitem1Button;
@BindView(R.id.subscribe_listitem2_expand)
ImageView subscribeListitem2Button;
@BindView(R.id.subscribe_listitem3_expand)
ImageView subscribeListitem3Button;
@BindView(R.id.subscribe_listitem4_expand)
ImageView subscribeListitem4Button;
@BindView(R.id.subscribe_listitem1_description)
TextView subscribeListItem1Description;
@BindView(R.id.subscribe_listitem2_description)
TextView subscribeListItem2Description;
@BindView(R.id.subscribe_listitem3_description)
TextView subscribeListItem3Description;
@BindView(R.id.subscribe_listitem4_description)
TextView subscribeListItem4Description;
@BindView(R.id.loadingIndicator)
ProgressBar loadingIndicator;
@BindView(R.id.subscriptionOptions)
View subscriptionOptions;
@BindView(R.id.subscription1month)
SubscriptionOptionView subscription1MonthView;
@BindView(R.id.subscription3month)
SubscriptionOptionView subscription3MonthView;
@BindView(R.id.subscription6month)
SubscriptionOptionView subscription6MonthView;
@BindView(R.id.subscription12month)
SubscriptionOptionView subscription12MonthView;
@BindView(R.id.subscribeButton)
Button subscriptionButton;
@BindView(R.id.subscriptionDetails)
SubscriptionDetailsView subscriptionDetailsView;
@BindView(R.id.subscribeBenefitsTitle)
TextView subscribeBenefitsTitle;
@BindView(R.id.supportTextView)
TextView supportTextView;
@Nullable
Sku selectedSubscriptionSku;
List<Sku> skus;
private GemPurchaseActivity listener;
private BillingRequests billingRequests;
private User user;
private boolean hasLoadedSubscriptionOptions;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
fetchUser(null);
return inflater.inflate(R.layout.fragment_subscription, container, false);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Subscribe
public void fetchUser(@Nullable UserSubscribedEvent event) {
userRepository.retrieveUser(false).subscribe(this::setUser, RxErrorHandler.handleEmptyError());
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
subscriptionOptions.setVisibility(View.GONE);
subscriptionDetailsView.setVisibility(View.GONE);
this.subscription1MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription1Month));
this.subscription3MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription3Month));
this.subscription6MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription6Month));
this.subscription12MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription12Month));
this.subscribeListitem1Box.setOnClickListener(view1 -> toggleDescriptionView(this.subscribeListitem1Button, this.subscribeListItem1Description));
this.subscribeListitem2Box.setOnClickListener(view1 -> toggleDescriptionView(this.subscribeListitem2Button, this.subscribeListItem2Description));
this.subscribeListitem3Box.setOnClickListener(view1 -> toggleDescriptionView(this.subscribeListitem3Button, this.subscribeListItem3Description));
this.subscribeListitem4Box.setOnClickListener(view1 -> toggleDescriptionView(this.subscribeListitem4Button, this.subscribeListItem4Description));
Drawable heartDrawable = new BitmapDrawable(getResources(), HabiticaIconsHelper.imageOfHeartLarge());
supportTextView.setCompoundDrawables(null, heartDrawable, null, null);
}
private void toggleDescriptionView(ImageView button, TextView descriptionView) {
if (descriptionView.getVisibility() == View.VISIBLE) {
descriptionView.setVisibility(View.GONE);
button.setImageResource(R.drawable.ic_keyboard_arrow_down_black_24dp);
} else {
descriptionView.setVisibility(View.VISIBLE);
button.setImageResource(R.drawable.ic_keyboard_arrow_up_black_24dp);
}
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Override
public void setupCheckout() {
final ActivityCheckout checkout = listener.getActivityCheckout();
if (checkout != null) {
Inventory inventory = checkout.makeInventory();
inventory.load(Inventory.Request.create()
.loadAllPurchases().loadSkus(ProductTypes.SUBSCRIPTION, PurchaseTypes.allSubscriptionTypes),
products -> {
Inventory.Product subscriptions = products.get(ProductTypes.SUBSCRIPTION);
skus = subscriptions.getSkus();
for (Sku sku : skus) {
updateButtonLabel(sku, sku.price, subscriptions);
}
selectSubscription(PurchaseTypes.Subscription1Month);
hasLoadedSubscriptionOptions = true;
updateSubscriptionInfo();
});
}
}
private void updateButtonLabel(Sku sku, String price, Inventory.Product subscriptions) {
SubscriptionOptionView matchingView = buttonForSku(sku);
if (matchingView != null) {
matchingView.setPriceText(price);
matchingView.setSku(sku.id.code);
matchingView.setIsPurchased(subscriptions.isPurchased(sku));
}
}
private void selectSubscription(String sku) {
for (Sku thisSku : skus) {
if (thisSku.id.code.equals(sku)) {
selectSubscription(thisSku);
return;
}
}
}
private void selectSubscription(Sku sku) {
if (this.selectedSubscriptionSku != null) {
SubscriptionOptionView oldButton = buttonForSku(this.selectedSubscriptionSku);
if (oldButton != null) {
oldButton.setIsPurchased(false);
}
}
this.selectedSubscriptionSku = sku;
SubscriptionOptionView subscriptionOptionButton = buttonForSku(this.selectedSubscriptionSku);
if (subscriptionOptionButton != null) {
subscriptionOptionButton.setIsPurchased(true);
}
if (this.subscriptionButton != null) {
this.subscriptionButton.setEnabled(true);
}
}
@Nullable
private SubscriptionOptionView buttonForSku(Sku sku) {
return buttonForSku(sku.id.code);
}
@Nullable
private SubscriptionOptionView buttonForSku(String sku) {
if (sku.equals(PurchaseTypes.Subscription1Month)) {
return subscription1MonthView;
} else if (sku.equals(PurchaseTypes.Subscription3Month)) {
return subscription3MonthView;
} else if (sku.equals(PurchaseTypes.Subscription6Month)) {
return subscription6MonthView;
} else if (sku.equals(PurchaseTypes.Subscription12Month)) {
return subscription12MonthView;
} else {
return null;
}
}
@Override
public void setListener(GemPurchaseActivity listener) {
this.listener = listener;
}
@Override
public void setBillingRequests(BillingRequests billingRequests) {
this.billingRequests = billingRequests;
}
private void purchaseSubscription() {
if (selectedSubscriptionSku != null) {
billingRequests.isPurchased(ProductTypes.SUBSCRIPTION, this.selectedSubscriptionSku.id.code, new RequestListener<Boolean>() {
@Override
public void onSuccess(@NonNull Boolean aBoolean) {
if (!aBoolean) {
// no current product exist
final ActivityCheckout checkout = listener.getActivityCheckout();
billingRequests.purchase(ProductTypes.SUBSCRIPTION, selectedSubscriptionSku.id.code, null, checkout.getPurchaseFlow());
}
}
@Override
public void onError(int i, @NonNull Exception e) {
crashlyticsProxy.fabricLogE("Purchase", "Error", e);
}
});
}
}
public void setUser(User newUser) {
user = newUser;
this.updateSubscriptionInfo();
}
private void updateSubscriptionInfo() {
if (user != null) {
SubscriptionPlan plan = user.getPurchased().getPlan();
boolean isSubscribed = false;
if (plan != null) {
if (plan.isActive()) {
isSubscribed = true;
}
}
if (this.subscriptionDetailsView == null) {
return;
}
if (isSubscribed) {
this.subscriptionDetailsView.setVisibility(View.VISIBLE);
this.subscriptionDetailsView.setPlan(plan);
this.subscribeBenefitsTitle.setText(R.string.subscribe_prompt_thanks);
this.subscriptionOptions.setVisibility(View.GONE);
} else {
if (!hasLoadedSubscriptionOptions) {
return;
}
this.subscriptionOptions.setVisibility(View.VISIBLE);
this.subscriptionDetailsView.setVisibility(View.GONE);
}
this.loadingIndicator.setVisibility(View.GONE);
}
}
@OnClick(R.id.subscribeButton)
public void subscribeUser() {
purchaseSubscription();
}
}

View file

@ -0,0 +1,261 @@
package com.habitrpg.android.habitica.ui.fragments
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
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.events.UserSubscribedEvent
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.PurchaseTypes
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionDetailsView
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView
import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.fragment_subscription.*
import org.greenrobot.eventbus.Subscribe
import org.solovyev.android.checkout.*
import javax.inject.Inject
class SubscriptionFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragment {
@Inject
lateinit var crashlyticsProxy: CrashlyticsProxy
@Inject
lateinit var userRepository: UserRepository
private val subscribeListitem1Box: View? by bindView(R.id.subscribe_listitem1_box)
private val subscribeListitem2Box: View? by bindView(R.id.subscribe_listitem2_box)
private val subscribeListitem3Box: View? by bindView(R.id.subscribe_listitem3_box)
private val subscribeListitem4Box: View? by bindView(R.id.subscribe_listitem4_box)
private val subscribeListitem1Button: ImageView? by bindView(R.id.subscribe_listitem1_expand)
private val subscribeListitem2Button: ImageView? by bindView(R.id.subscribe_listitem2_expand)
private val subscribeListitem3Button: ImageView? by bindView(R.id.subscribe_listitem3_expand)
private val subscribeListitem4Button: ImageView? by bindView(R.id.subscribe_listitem4_expand)
private val subscribeListItem1Description: TextView? by bindView(R.id.subscribe_listitem1_description)
private val subscribeListItem2Description: TextView? by bindView(R.id.subscribe_listitem2_description)
private val subscribeListItem3Description: TextView? by bindView(R.id.subscribe_listitem3_description)
private val subscribeListItem4Description: TextView? by bindView(R.id.subscribe_listitem4_description)
private val loadingIndicator: ProgressBar? by bindView(R.id.loadingIndicator)
private val subscriptionOptions: View? by bindView(R.id.subscriptionOptions)
private val subscription1MonthView: SubscriptionOptionView? by bindView(R.id.subscription1month)
private val subscription3MonthView: SubscriptionOptionView? by bindView(R.id.subscription3month)
private val subscription6MonthView: SubscriptionOptionView? by bindView(R.id.subscription6month)
private val subscription12MonthView: SubscriptionOptionView? by bindView(R.id.subscription12month)
private val subscriptionButton: Button? by bindView(R.id.subscribeButton)
private val subscriptionDetailsView: SubscriptionDetailsView? by bindView(R.id.subscriptionDetails)
private val subscribeBenefitsTitle: TextView? by bindView(R.id.subscribeBenefitsTitle)
private val supportTextView: TextView? by bindView(R.id.supportTextView)
private var selectedSubscriptionSku: Sku? = null
private var skus: List<Sku> = emptyList()
private var listener: GemPurchaseActivity? = null
private var billingRequests: BillingRequests? = null
private var user: User? = null
private var hasLoadedSubscriptionOptions: Boolean = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
fetchUser(null)
return inflater.inflate(R.layout.fragment_subscription, container, false)
}
@Subscribe
fun fetchUser(event: UserSubscribedEvent?) {
userRepository.retrieveUser(false).subscribe(Consumer { this.setUser(it) }, RxErrorHandler.handleEmptyError())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
subscriptionOptions?.visibility = View.GONE
subscriptionDetailsView?.visibility = View.GONE
this.subscription1MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription1Month) })
this.subscription3MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription3Month) })
this.subscription6MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription6Month) })
this.subscription12MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription12Month) })
this.subscribeListitem1Box?.setOnClickListener { toggleDescriptionView(this.subscribeListitem1Button, this.subscribeListItem1Description) }
this.subscribeListitem2Box?.setOnClickListener { toggleDescriptionView(this.subscribeListitem2Button, this.subscribeListItem2Description) }
this.subscribeListitem3Box?.setOnClickListener { toggleDescriptionView(this.subscribeListitem3Button, this.subscribeListItem3Description) }
this.subscribeListitem4Box?.setOnClickListener { toggleDescriptionView(this.subscribeListitem4Button, this.subscribeListItem4Description) }
val heartDrawable = BitmapDrawable(resources, HabiticaIconsHelper.imageOfHeartLarge())
supportTextView?.setCompoundDrawables(null, heartDrawable, null, null)
subscribeButton.setOnClickListener { subscribeUser() }
}
private fun toggleDescriptionView(button: ImageView?, descriptionView: TextView?) {
if (descriptionView?.visibility == View.VISIBLE) {
descriptionView.visibility = View.GONE
button?.setImageResource(R.drawable.ic_keyboard_arrow_down_black_24dp)
} else {
descriptionView?.visibility = View.VISIBLE
button?.setImageResource(R.drawable.ic_keyboard_arrow_up_black_24dp)
}
}
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
override fun setupCheckout() {
val checkout = listener?.activityCheckout
if (checkout != null) {
val inventory = checkout.makeInventory()
inventory.load(Inventory.Request.create()
.loadAllPurchases().loadSkus(ProductTypes.SUBSCRIPTION, PurchaseTypes.allSubscriptionTypes)
) { products ->
val subscriptions = products.get(ProductTypes.SUBSCRIPTION)
skus = subscriptions.skus
for (sku in skus) {
updateButtonLabel(sku, sku.price, subscriptions)
}
selectSubscription(PurchaseTypes.Subscription1Month)
hasLoadedSubscriptionOptions = true
updateSubscriptionInfo()
}
}
}
private fun updateButtonLabel(sku: Sku, price: String, subscriptions: Inventory.Product) {
val matchingView = buttonForSku(sku)
if (matchingView != null) {
matchingView.setPriceText(price)
matchingView.sku = sku.id.code
matchingView.setIsPurchased(subscriptions.isPurchased(sku))
}
}
private fun selectSubscription(sku: String) {
for (thisSku in skus) {
if (thisSku.id.code == sku) {
selectSubscription(thisSku)
return
}
}
}
private fun selectSubscription(sku: Sku) {
if (this.selectedSubscriptionSku != null) {
val oldButton = buttonForSku(this.selectedSubscriptionSku)
oldButton?.setIsPurchased(false)
}
this.selectedSubscriptionSku = sku
val subscriptionOptionButton = buttonForSku(this.selectedSubscriptionSku)
subscriptionOptionButton?.setIsPurchased(true)
if (this.subscriptionButton != null) {
this.subscriptionButton?.isEnabled = true
}
}
private fun buttonForSku(sku: Sku?): SubscriptionOptionView? {
return buttonForSku(sku?.id?.code)
}
private fun buttonForSku(sku: String?): SubscriptionOptionView? {
return when (sku) {
PurchaseTypes.Subscription1Month -> subscription1MonthView
PurchaseTypes.Subscription3Month -> subscription3MonthView
PurchaseTypes.Subscription6Month -> subscription6MonthView
PurchaseTypes.Subscription12Month -> subscription12MonthView
else -> null
}
}
override fun setListener(listener: GemPurchaseActivity) {
this.listener = listener
}
override fun setBillingRequests(billingRequests: BillingRequests) {
this.billingRequests = billingRequests
}
private fun purchaseSubscription() {
selectedSubscriptionSku?.id?.code.notNull { code ->
billingRequests?.isPurchased(ProductTypes.SUBSCRIPTION, code, object : RequestListener<Boolean> {
override fun onSuccess(aBoolean: Boolean) {
if (!aBoolean) {
// no current product exist
val checkout = listener?.activityCheckout
checkout.notNull {
billingRequests?.purchase(ProductTypes.SUBSCRIPTION, code, null, it.purchaseFlow)
}
}
}
override fun onError(i: Int, e: Exception) {
crashlyticsProxy.fabricLogE("Purchase", "Error", e)
}
})
}
}
fun setUser(newUser: User) {
user = newUser
this.updateSubscriptionInfo()
}
private fun updateSubscriptionInfo() {
if (user != null) {
val plan = user?.purchased?.plan
var isSubscribed = false
if (plan != null) {
if (plan.isActive) {
isSubscribed = true
}
}
if (this.subscriptionDetailsView == null) {
return
}
if (isSubscribed) {
this.subscriptionDetailsView?.visibility = View.VISIBLE
plan.notNull { this.subscriptionDetailsView?.setPlan(it) }
this.subscribeBenefitsTitle?.setText(R.string.subscribe_prompt_thanks)
this.subscriptionOptions?.visibility = View.GONE
} else {
if (!hasLoadedSubscriptionOptions) {
return
}
this.subscriptionOptions?.visibility = View.VISIBLE
this.subscriptionDetailsView?.visibility = View.GONE
}
this.loadingIndicator?.visibility = View.GONE
}
}
fun subscribeUser() {
purchaseSubscription()
}
}

View file

@ -12,7 +12,6 @@ import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.RelativeLayout
import butterknife.OnClick
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.ApiClient

View file

@ -1,76 +0,0 @@
package com.habitrpg.android.habitica.ui.fragments.skills;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import 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.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import io.reactivex.Flowable;
public class SkillTasksRecyclerViewFragment extends BaseFragment {
@Inject
TaskRepository taskRepository;
@Inject
@Named(AppModule.NAMED_USER_ID)
String userId;
@BindView(R.id.recyclerView)
public RecyclerView recyclerView;
public SkillTasksRecyclerViewAdapter adapter;
LinearLayoutManager layoutManager = null;
public String taskType;
private View view;
public SkillTasksRecyclerViewFragment() {
super();
adapter = new SkillTasksRecyclerViewAdapter(null, true);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_recyclerview, container, false);
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
taskRepository.getTasks(taskType, userId).firstElement().subscribe(tasks -> adapter.updateData(tasks), RxErrorHandler.handleEmptyError());
recyclerView.setAdapter(adapter);
layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager == null) {
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
}
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
}
public Flowable<Task> getTaskSelectionEvents() {
return adapter.getTaskSelectionEvents();
}
}

View file

@ -0,0 +1,67 @@
package com.habitrpg.android.habitica.ui.fragments.skills
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import 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.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import javax.inject.Inject
import javax.inject.Named
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.Flowable
import io.reactivex.functions.Consumer
class SkillTasksRecyclerViewFragment : BaseFragment() {
@Inject
lateinit var taskRepository: TaskRepository
@field:[Inject Named(AppModule.NAMED_USER_ID)]
lateinit var userId: String
private val recyclerView: RecyclerView? by bindView(R.id.recyclerView)
var adapter: SkillTasksRecyclerViewAdapter = SkillTasksRecyclerViewAdapter(null, true)
internal var layoutManager: LinearLayoutManager? = null
var taskType: String? = null
val taskSelectionEvents: Flowable<Task>
get() = adapter.getTaskSelectionEvents()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return container?.inflate(R.id.recyclerView)
}
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
taskRepository.getTasks(taskType ?: "", userId).firstElement().subscribe(Consumer { tasks -> adapter.updateData(tasks) }, RxErrorHandler.handleEmptyError())
recyclerView?.adapter = adapter
layoutManager = recyclerView?.layoutManager as LinearLayoutManager?
if (layoutManager == null) {
layoutManager = LinearLayoutManager(context)
recyclerView?.layoutManager = layoutManager
}
recyclerView?.itemAnimator = SafeDefaultItemAnimator()
}
}

View file

@ -1,268 +0,0 @@
package com.habitrpg.android.habitica.ui.fragments.social;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
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.data.UserRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.members.Member;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.modules.AppModule;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.OnClick;
public class QuestDetailFragment extends BaseMainFragment {
@Inject
SocialRepository socialRepository;
@Inject
UserRepository userRepository;
@Inject
InventoryRepository inventoryRepository;
@Inject
@Named(AppModule.NAMED_USER_ID)
String userId;
@BindView(R.id.quest_title_view)
TextView questTitleView;
@BindView(R.id.quest_scroll_image_view)
SimpleDraweeView questScrollImageView;
@BindView(R.id.quest_leader_view)
TextView questLeaderView;
@BindView(R.id.description_view)
TextView questDescriptionView;
@BindView(R.id.quest_participant_list)
LinearLayout questParticipantList;
@BindView(R.id.participants_header)
TextView participantHeader;
@BindView(R.id.participants_header_count)
TextView participantHeaderCount;
@BindView(R.id.quest_participant_response_wrapper)
ViewGroup questParticipantResponseWrapper;
@BindView(R.id.quest_leader_response_wrapper)
ViewGroup questLeaderResponseWrapper;
@BindView(R.id.quest_accept_button)
Button questAcceptButton;
@BindView(R.id.quest_reject_button)
Button questRejectButton;
@BindView(R.id.quest_begin_button)
Button questBeginButton;
@BindView(R.id.quest_cancel_button)
Button questCancelButton;
@BindView(R.id.quest_abort_button)
Button questAbortButton;
public String partyId;
public String questKey;
private Group party;
private Quest quest;
private String begin_quest_message;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_quest_detail, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
getCompositeSubscription().add(socialRepository.getGroup(partyId).subscribe(this::updateParty, RxErrorHandler.handleEmptyError()));
if (questKey != null) {
getCompositeSubscription().add(inventoryRepository.getQuestContent(questKey).subscribe(this::updateQuestContent, RxErrorHandler.handleEmptyError()));
}
}
private void updateParty(Group group) {
if (questTitleView == null || group == null|| group.getQuest() == null) {
return;
}
party = group;
quest = group.getQuest();
setQuestParticipants(group.getQuest().getParticipants());
socialRepository.getMember(quest.getLeader()).firstElement().subscribe(member -> {
if (getContext() != null && questLeaderView != null && member != null) {
questLeaderView.setText(getContext().getString(R.string.quest_leader_header, member.getDisplayName()));
}
}, RxErrorHandler.handleEmptyError());
if (questLeaderResponseWrapper != null) {
if (showParticipatantButtons()) {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.VISIBLE);
} else if (showLeaderButtons()) {
questParticipantResponseWrapper.setVisibility(View.GONE);
questLeaderResponseWrapper.setVisibility(View.VISIBLE);
if (isQuestActive()) {
questBeginButton.setVisibility(View.GONE);
questCancelButton.setVisibility(View.GONE);
questAbortButton.setVisibility(View.VISIBLE);
} else {
questBeginButton.setVisibility(View.VISIBLE);
questCancelButton.setVisibility(View.VISIBLE);
questAbortButton.setVisibility(View.GONE);
}
} else {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.GONE);
}
}
}
private boolean showLeaderButtons() {
return party != null && party.getQuest() != null && userId != null && userId.equals(party.getQuest().getLeader());
}
private boolean showParticipatantButtons() {
if (user == null || user.getParty() == null || user.getParty().getQuest() == null) {
return false;
}
return !isQuestActive() && user.getParty().getQuest().getRSVPNeeded();
}
private boolean isQuestActive() {
return quest != null && quest.getActive();
}
private void updateQuestContent(QuestContent questContent) {
if (questTitleView == null || !questContent.isManaged()) {
return;
}
questTitleView.setText(questContent.getText());
//TODO: FIX
//questDescriptionView.setText(MarkdownParser.parseMarkdown(questContent.getNotes()));
DataBindingUtils.INSTANCE.loadImage(questScrollImageView, "inventory_quest_scroll_"+questContent.getKey());
}
private void setQuestParticipants(List<Member> participants) {
if (questParticipantList == null) {
return;
}
questParticipantList.removeAllViews();
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int participantCount = 0;
for (Member participant : participants) {
if (quest.getActive() && (participant.getParticipatesInQuest() == null || !participant.getParticipatesInQuest())) {
continue;
}
View participantView = inflater.inflate(R.layout.quest_participant, questParticipantList, false);
TextView textView = (TextView) participantView.findViewById(R.id.participant_name);
textView.setText(participant.getDisplayName());
TextView statusTextView = (TextView) participantView.findViewById(R.id.status_view);
if (!quest.getActive()) {
if (participant.getParticipatesInQuest() == null) {
statusTextView.setText(R.string.pending);
statusTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.gray_200));
} else if (participant.getParticipatesInQuest()) {
statusTextView.setText(R.string.accepted);
statusTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.green_100));
} else {
statusTextView.setText(R.string.declined);
statusTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.red_100));
}
} else {
statusTextView.setVisibility(View.GONE);
}
questParticipantList.addView(participantView);
if (quest.getActive() || (participant.getParticipatesInQuest() != null && participant.getParticipatesInQuest())) {
participantCount += 1;
}
}
if (quest.getActive()) {
participantHeader.setText(R.string.participants);
participantHeaderCount.setText(String.valueOf(participantCount));
} else {
participantHeader.setText(R.string.invitations);
participantHeaderCount.setText(participantCount + "/" + quest.getParticipants().size());
begin_quest_message = getString(R.string.quest_begin_message, participantCount, quest.getParticipants().size());
}
}
@Override
public void onDestroyView() {
socialRepository.close();
userRepository.close();
inventoryRepository.close();
super.onDestroyView();
}
@OnClick(R.id.quest_accept_button)
public void onQuestAccept() {
socialRepository.acceptQuest(user, partyId).subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
@OnClick(R.id.quest_reject_button)
public void onQuestReject() {
socialRepository.rejectQuest(user, partyId).subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
@OnClick(R.id.quest_begin_button)
public void onQuestBegin() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(begin_quest_message)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.forceStartQuest(party)
.subscribe(quest -> {}, RxErrorHandler.handleEmptyError()))
.setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show();
}
@OnClick(R.id.quest_cancel_button)
public void onQuestCancel() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_cancel_message)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.cancelQuest(partyId)
.subscribe(aVoid -> getActivity().getFragmentManager().popBackStack(), RxErrorHandler.handleEmptyError())).setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show();
}
@OnClick(R.id.quest_abort_button)
public void onQuestAbort() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_abort_message)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.abortQuest(partyId)
.subscribe(aVoid -> getActivity().getFragmentManager().popBackStack(), RxErrorHandler.handleEmptyError())).setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show();
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
}

View file

@ -0,0 +1,263 @@
package com.habitrpg.android.habitica.ui.fragments.social
import android.app.AlertDialog
import android.content.Context
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
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.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.inventory.Quest
import com.habitrpg.android.habitica.models.inventory.QuestContent
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.helpers.resetViews
import io.reactivex.functions.Consumer
import javax.inject.Inject
import javax.inject.Named
class QuestDetailFragment : BaseMainFragment() {
@Inject
lateinit var socialRepository: SocialRepository
@Inject
lateinit var inventoryRepository: InventoryRepository
@field:[Inject Named(AppModule.NAMED_USER_ID)]
lateinit var userId: String
private val questTitleView: TextView? by bindView(R.id.title_view)
private val questScrollImageView: SimpleDraweeView? by bindView(R.id.quest_scroll_image_view)
private val questLeaderView: TextView? by bindView(R.id.quest_leader_view)
private val questDescriptionView: TextView? by bindView(R.id.description_view)
private val questParticipantList: LinearLayout? by bindView(R.id.quest_participant_list)
private val participantHeader: TextView? by bindView(R.id.participants_header)
private val participantHeaderCount: TextView? by bindView(R.id.participants_header_count)
private val questParticipantResponseWrapper: ViewGroup? by bindView(R.id.quest_participant_response_wrapper)
private val questLeaderResponseWrapper: ViewGroup? by bindView(R.id.quest_leader_response_wrapper)
private val questAcceptButton: Button? by bindView(R.id.quest_accept_button)
private val questRejectButton: Button? by bindView(R.id.quest_reject_button)
private val questBeginButton: Button? by bindView(R.id.quest_begin_button)
private val questCancelButton: Button? by bindView(R.id.quest_cancel_button)
private val questAbortButton: Button? by bindView(R.id.quest_abort_button)
var partyId: String? = null
var questKey: String? = null
private var party: Group? = null
private var quest: Quest? = null
private var beginQuestMessage: String? = null
private val isQuestActive: Boolean
get() = quest?.active == true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_quest_detail, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
resetViews()
questAcceptButton?.setOnClickListener { onQuestAccept() }
questRejectButton?.setOnClickListener { onQuestReject() }
questBeginButton?.setOnClickListener { onQuestBegin() }
questCancelButton?.setOnClickListener { onQuestCancel() }
questAbortButton?.setOnClickListener { onQuestAbort() }
}
override fun onResume() {
super.onResume()
compositeSubscription.add(socialRepository.getGroup(partyId).subscribe(Consumer { this.updateParty(it) }, RxErrorHandler.handleEmptyError()))
if (questKey != null) {
compositeSubscription.add(inventoryRepository.getQuestContent(questKey).subscribe(Consumer { this.updateQuestContent(it) }, RxErrorHandler.handleEmptyError()))
}
}
private fun updateParty(group: Group?) {
if (questTitleView == null || group == null || group.quest == null) {
return
}
party = group
quest = group.quest
setQuestParticipants(group.quest?.participants)
socialRepository.getMember(quest?.leader).firstElement().subscribe(Consumer { member ->
if (context != null && questLeaderView != null && member != null) {
questLeaderView?.text = context?.getString(R.string.quest_leader_header, member.displayName)
}
}, RxErrorHandler.handleEmptyError())
if (questLeaderResponseWrapper != null) {
if (showParticipatantButtons()) {
questLeaderResponseWrapper?.visibility = View.GONE
questParticipantResponseWrapper?.visibility = View.VISIBLE
} else if (showLeaderButtons()) {
questParticipantResponseWrapper?.visibility = View.GONE
questLeaderResponseWrapper?.visibility = View.VISIBLE
if (isQuestActive) {
questBeginButton?.visibility = View.GONE
questCancelButton?.visibility = View.GONE
questAbortButton?.visibility = View.VISIBLE
} else {
questBeginButton?.visibility = View.VISIBLE
questCancelButton?.visibility = View.VISIBLE
questAbortButton?.visibility = View.GONE
}
} else {
questLeaderResponseWrapper?.visibility = View.GONE
questParticipantResponseWrapper?.visibility = View.GONE
}
}
}
private fun showLeaderButtons(): Boolean {
return userId == party?.quest?.leader
}
private fun showParticipatantButtons(): Boolean {
return if (user == null || user?.party == null || user?.party?.quest == null) {
false
} else !isQuestActive && user?.party?.quest?.RSVPNeeded == true
}
private fun updateQuestContent(questContent: QuestContent) {
if (questTitleView == null || !questContent.isManaged) {
return
}
questTitleView?.text = questContent.text
//TODO: FIX
questDescriptionView?.text = MarkdownParser.parseMarkdown(questContent.notes)
DataBindingUtils.loadImage(questScrollImageView, "inventory_quest_scroll_" + questContent.key)
}
private fun setQuestParticipants(participants: List<Member>?) {
if (questParticipantList == null) {
return
}
questParticipantList?.removeAllViews()
val inflater = context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
var participantCount = 0
for (participant in participants ?: emptyList()) {
if (quest?.active == true && (participant.participatesInQuest == null || !participant.participatesInQuest)) {
continue
}
val participantView = inflater.inflate(R.layout.quest_participant, questParticipantList, false)
val textView = participantView.findViewById<View>(R.id.participant_name) as TextView
textView.text = participant.displayName
val statusTextView = participantView.findViewById<View>(R.id.status_view) as TextView
if (quest?.active == false) {
context.notNull {
when {
participant.participatesInQuest == null -> {
statusTextView.setText(R.string.pending)
statusTextView.setTextColor(ContextCompat.getColor(it, R.color.gray_200))
}
participant.participatesInQuest -> {
statusTextView.setText(R.string.accepted)
statusTextView.setTextColor(ContextCompat.getColor(it, R.color.green_100))
}
else -> {
statusTextView.setText(R.string.declined)
statusTextView.setTextColor(ContextCompat.getColor(it, R.color.red_100))
}
}
}
} else {
statusTextView.visibility = View.GONE
}
questParticipantList?.addView(participantView)
if (quest?.active == true || participant.participatesInQuest != null && participant.participatesInQuest) {
participantCount += 1
}
}
if (quest?.active == true) {
participantHeader?.setText(R.string.participants)
participantHeaderCount?.text = participantCount.toString()
} else {
participantHeader?.setText(R.string.invitations)
participantHeaderCount?.text = participantCount.toString() + "/" + quest?.participants?.size
beginQuestMessage = getString(R.string.quest_begin_message, participantCount, quest?.participants?.size)
}
}
override fun onDestroyView() {
socialRepository.close()
userRepository.close()
inventoryRepository.close()
super.onDestroyView()
}
fun onQuestAccept() {
partyId.notNull {
socialRepository.acceptQuest(user, it).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
fun onQuestReject() {
partyId.notNull {
socialRepository.rejectQuest(user, it).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
fun onQuestBegin() {
val builder = AlertDialog.Builder(getActivity())
.setMessage(beginQuestMessage)
.setPositiveButton(R.string.yes) { _, _ ->
party.notNull {
socialRepository.forceStartQuest(it)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
.setNegativeButton(R.string.no) { _, _ -> }
builder.show()
}
fun onQuestCancel() {
val builder = AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_cancel_message)
.setPositiveButton(R.string.yes) { _, _ ->
partyId.notNull {
socialRepository.cancelQuest(it)
.subscribe(Consumer { getActivity()?.fragmentManager?.popBackStack() }, RxErrorHandler.handleEmptyError())
}
}.setNegativeButton(R.string.no) { _, _ -> }
builder.show()
}
fun onQuestAbort() {
val builder = AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_abort_message)
.setPositiveButton(R.string.yes) { _, _ ->
partyId.notNull {
socialRepository.abortQuest(it)
.subscribe(Consumer { getActivity()?.fragmentManager?.popBackStack() }, RxErrorHandler.handleEmptyError())
}
}.setNegativeButton(R.string.no) { _, _ -> }
builder.show()
}
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
}

View file

@ -1,272 +0,0 @@
package com.habitrpg.android.habitica.ui.fragments.social.party;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
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.data.UserRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.models.user.User;
import com.habitrpg.android.habitica.modules.AppModule;
import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment;
import com.habitrpg.android.habitica.ui.fragments.social.QuestDetailFragment;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
import com.habitrpg.android.habitica.ui.views.social.OldQuestProgressView;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.OnClick;
public class PartyDetailFragment extends BaseFragment {
@Inject
SocialRepository socialRepository;
@Inject
UserRepository userRepository;
@Inject
InventoryRepository inventoryRepository;
@Inject
@Named(AppModule.NAMED_USER_ID)
String userId;
@BindView(R.id.refreshLayout)
SwipeRefreshLayout refreshLayout;
@BindView(R.id.party_invitation_wrapper)
ViewGroup partyInvitationWrapper;
@BindView(R.id.title_view)
TextView titleView;
@BindView(R.id.description_view)
TextView descriptionView;
@BindView(R.id.new_quest_button)
Button newQuestButton;
@BindView(R.id.quest_detail_button)
ViewGroup questDetailButton;
@BindView(R.id.quest_scroll_image_view)
SimpleDraweeView questScrollImageView;
@BindView(R.id.quest_title_view)
TextView questTitleView;
@BindView(R.id.quest_participation_view)
TextView questParticipationView;
@BindView(R.id.quest_image_wrapper)
ViewGroup questImageWrapper;
@BindView(R.id.quest_image_view)
SimpleDraweeView questImageView;
@BindView(R.id.quest_participant_response_wrapper)
ViewGroup questParticipantResponseWrapper;
@BindView(R.id.quest_accept_button)
Button questAcceptButton;
@BindView(R.id.quest_reject_button)
Button questRejectButton;
@BindView(R.id.quest_progress_view)
OldQuestProgressView questProgressView;
@BindView(R.id.quest_participant_list)
LinearLayout questParticipantList;
public String partyId;
private Group party;
private Quest quest;
private User user;
@Override
public void injectFragment(@NonNull AppComponent component) {
component.inject(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_party_detail, container, false);
}
@Override
public void onDestroyView() {
socialRepository.close();
userRepository.close();
inventoryRepository.close();
super.onDestroyView();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
refreshLayout.setOnRefreshListener(this::refreshParty);
getCompositeSubscription().add(socialRepository.getGroup(partyId).subscribe(this::updateParty, RxErrorHandler.handleEmptyError()));
getCompositeSubscription().add(userRepository.getUser(userId).subscribe(this::updateUser, RxErrorHandler.handleEmptyError()));
}
private void refreshParty() {
socialRepository.retrieveGroup("party")
.flatMap(group1 -> socialRepository.retrieveGroupMembers(group1.getId(), true))
.subscribe(members -> {}, RxErrorHandler.handleEmptyError(), () -> {
if (refreshLayout != null) {
refreshLayout.setRefreshing(false);
}
});
}
private void updateParty(Group party) {
if (party == null) {
return;
}
this.party = party;
this.quest = party.getQuest();
if (titleView == null) {
return;
}
titleView.setText(party.getName());
//TODO: FIX
//descriptionView.setText(MarkdownParser.parseMarkdown(party.getDescription()));
if (quest != null && !quest.getKey().isEmpty()) {
newQuestButton.setVisibility(View.GONE);
questDetailButton.setVisibility(View.VISIBLE);
questImageWrapper.setVisibility(View.VISIBLE);
Handler mainHandler = new Handler(getContext().getMainLooper());
mainHandler.postDelayed(() -> inventoryRepository.getQuestContent(quest.getKey())
.firstElement()
.subscribe(PartyDetailFragment.this::updateQuestContent, RxErrorHandler.handleEmptyError()), 500);
} else {
newQuestButton.setVisibility(View.VISIBLE);
questDetailButton.setVisibility(View.GONE);
questImageWrapper.setVisibility(View.GONE);
questProgressView.setVisibility(View.GONE);
}
}
private void updateUser(User user) {
if (user == null || user.getParty() == null || user.getParty().getQuest() == null) {
return;
}
this.user = user;
int invitationVisibility = View.GONE;
if (user.getInvitations() != null && user.getInvitations().getParty() != null && user.getInvitations().getParty().getId() != null) {
invitationVisibility = View.VISIBLE;
}
if (partyInvitationWrapper != null) {
partyInvitationWrapper.setVisibility(invitationVisibility);
}
if (questParticipantResponseWrapper != null) {
if (showParticipantButtons()) {
questParticipantResponseWrapper.setVisibility(View.VISIBLE);
} else {
questParticipantResponseWrapper.setVisibility(View.GONE);
}
}
questProgressView.configure(user);
}
private boolean showParticipantButtons() {
return !(user == null || user.getParty() == null || user.getParty().getQuest() == null) && !isQuestActive() && user.getParty().getQuest().getRSVPNeeded();
}
private void updateQuestContent(QuestContent questContent) {
if (questTitleView == null || !questContent.isValid()) {
return;
}
questTitleView.setText(questContent.getText());
DataBindingUtils.INSTANCE.loadImage(questScrollImageView, "inventory_quest_scroll_"+questContent.getKey());
DataBindingUtils.INSTANCE.loadImage(questImageView, "quest_"+questContent.getKey());
if (isQuestActive()) {
questProgressView.setVisibility(View.VISIBLE);
questProgressView.setData(questContent, quest.getProgress());
questParticipationView.setText(getString(R.string.number_participants, quest.getMembers().size()));
} else {
questProgressView.setVisibility(View.GONE);
}
}
private boolean isQuestActive() {
return quest != null && quest.getActive();
}
@OnClick(R.id.new_quest_button)
public void inviteNewQuest() {
ItemRecyclerFragment fragment = new ItemRecyclerFragment();
fragment.setItemType("quests");
fragment.setItemTypeText(getString(R.string.quest));
fragment.show(getFragmentManager(), "questDialog");
}
@OnClick(R.id.leave_button)
public void leaveParty() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.leave_party_confirmation)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.leaveGroup(partyId)
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError())).setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show(); }
@OnClick(R.id.quest_accept_button)
public void onQuestAccept() {
socialRepository.acceptQuest(user, partyId).subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
@OnClick(R.id.quest_reject_button)
public void onQuestReject() {
socialRepository.rejectQuest(user, partyId).subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
@OnClick(R.id.party_invite_accept_button)
public void onPartyInviteAccepted() {
if (user != null) {
socialRepository.joinGroup(user.getInvitations().getParty().getId())
.subscribe(group -> {}, RxErrorHandler.handleEmptyError());
}
}
@OnClick(R.id.party_invite_reject_button)
public void onPartyInviteRejected() {
if (user != null) {
socialRepository.rejectGroupInvite(user.getInvitations().getParty().getId())
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
}
@OnClick(R.id.quest_detail_button)
public void questDetailButtonClicked() {
QuestDetailFragment fragment = new QuestDetailFragment();
fragment.partyId = partyId;
if (party != null && party.getQuest() != null) {
fragment.questKey = party.getQuest().getKey();
}
if (getActivity() != null) {
MainActivity activity = (MainActivity) getActivity();
activity.displayFragment(fragment);
}
}
}

View file

@ -0,0 +1,247 @@
package com.habitrpg.android.habitica.ui.fragments.social.party
import android.app.AlertDialog
import android.os.Bundle
import android.os.Handler
import android.support.v4.widget.SwipeRefreshLayout
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
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.data.UserRepository
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.inventory.Quest
import com.habitrpg.android.habitica.models.inventory.QuestContent
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment
import com.habitrpg.android.habitica.ui.fragments.social.QuestDetailFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.social.OldQuestProgressView
import io.reactivex.functions.Consumer
import javax.inject.Inject
import javax.inject.Named
class PartyDetailFragment : BaseFragment() {
@Inject
lateinit var socialRepository: SocialRepository
@Inject
lateinit var userRepository: UserRepository
@Inject
lateinit var inventoryRepository: InventoryRepository
@field:[Inject Named(AppModule.NAMED_USER_ID)]
lateinit var userId: String
private val refreshLayout: SwipeRefreshLayout? by bindView(R.id.refreshLayout)
private val partyInvitationWrapper: ViewGroup? by bindView(R.id.party_invitation_wrapper)
private val titleView: TextView? by bindView(R.id.title_view)
private val descriptionView: TextView? by bindView(R.id.description_view)
private val newQuestButton: Button? by bindView(R.id.new_quest_button)
private val questDetailButton: ViewGroup? by bindView(R.id.quest_detail_button)
private val questScrollImageView: SimpleDraweeView? by bindView(R.id.quest_scroll_image_view)
private val questTitleView: TextView? by bindView(R.id.quest_title_view)
private val questParticipationView: TextView? by bindView(R.id.quest_participation_view)
private val questImageWrapper: ViewGroup? by bindView(R.id.quest_image_wrapper)
private val questImageView: SimpleDraweeView? by bindView(R.id.quest_image_view)
private val questParticipantResponseWrapper: ViewGroup? by bindView(R.id.quest_participant_response_wrapper)
private val questAcceptButton: Button? by bindView(R.id.quest_accept_button)
private val questRejectButton: Button? by bindView(R.id.quest_reject_button)
private val questProgressView: OldQuestProgressView? by bindView(R.id.quest_progress_view)
private val questParticipantList: LinearLayout? by bindView(R.id.quest_participant_list)
private val leaveButton: Button? by bindView(R.id.leave_button)
var partyId: String? = null
private var party: Group? = null
private var quest: Quest? = null
private var user: User? = null
private val isQuestActive: Boolean
get() = quest?.active == true
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_party_detail, container, false)
}
override fun onDestroyView() {
socialRepository.close()
userRepository.close()
inventoryRepository.close()
super.onDestroyView()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
refreshLayout?.setOnRefreshListener { this.refreshParty() }
compositeSubscription.add(socialRepository.getGroup(partyId).subscribe(Consumer { this.updateParty(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(userRepository.getUser(userId).subscribe(Consumer { this.updateUser(it) }, RxErrorHandler.handleEmptyError()))
questAcceptButton?.setOnClickListener { onQuestAccept() }
questRejectButton?.setOnClickListener { onQuestReject() }
newQuestButton?.setOnClickListener { inviteNewQuest() }
questDetailButton?.setOnClickListener { questDetailButtonClicked() }
leaveButton?.setOnClickListener { leaveParty() }
}
private fun refreshParty() {
socialRepository.retrieveGroup("party")
.flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) }
.doOnComplete { refreshLayout?.isRefreshing = false }
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
private fun updateParty(party: Group?) {
if (party == null) {
return
}
this.party = party
this.quest = party.quest
if (titleView == null) {
return
}
titleView?.text = party.name
descriptionView?.text = MarkdownParser.parseMarkdown(party.description)
if (quest?.key?.isEmpty() == false) {
newQuestButton?.visibility = View.GONE
questDetailButton?.visibility = View.VISIBLE
questImageWrapper?.visibility = View.VISIBLE
val mainHandler = Handler(context?.mainLooper)
mainHandler.postDelayed({
inventoryRepository.getQuestContent(quest?.key)
.firstElement()
.subscribe(Consumer<QuestContent> { this@PartyDetailFragment.updateQuestContent(it) }, RxErrorHandler.handleEmptyError())
}, 500)
} else {
newQuestButton?.visibility = View.VISIBLE
questDetailButton?.visibility = View.GONE
questImageWrapper?.visibility = View.GONE
questProgressView?.visibility = View.GONE
}
}
private fun updateUser(user: User?) {
if (user == null || user.party == null || user.party.quest == null) {
return
}
this.user = user
var invitationVisibility = View.GONE
if (user.invitations != null && user.invitations.party != null && user.invitations.party.id != null) {
invitationVisibility = View.VISIBLE
}
if (partyInvitationWrapper != null) {
partyInvitationWrapper?.visibility = invitationVisibility
}
if (questParticipantResponseWrapper != null) {
if (showParticipantButtons()) {
questParticipantResponseWrapper?.visibility = View.VISIBLE
} else {
questParticipantResponseWrapper?.visibility = View.GONE
}
}
questProgressView?.configure(user)
}
private fun showParticipantButtons(): Boolean {
return !(user == null || user?.party == null || user?.party?.quest == null) && !isQuestActive && user?.party?.quest?.RSVPNeeded == true
}
private fun updateQuestContent(questContent: QuestContent) {
if (questTitleView == null || !questContent.isValid) {
return
}
questTitleView?.text = questContent.text
DataBindingUtils.loadImage(questScrollImageView, "inventory_quest_scroll_" + questContent.key)
DataBindingUtils.loadImage(questImageView, "quest_" + questContent.key)
if (isQuestActive) {
questProgressView?.visibility = View.VISIBLE
questProgressView?.setData(questContent, quest?.progress)
questParticipationView?.text = getString(R.string.number_participants, quest?.members?.size)
} else {
questProgressView?.visibility = View.GONE
}
}
fun inviteNewQuest() {
val fragment = ItemRecyclerFragment()
fragment.itemType = "quests"
fragment.itemTypeText = getString(R.string.quest)
fragment.show(fragmentManager, "questDialog")
}
fun leaveParty() {
val builder = AlertDialog.Builder(activity)
.setMessage(R.string.leave_party_confirmation)
.setPositiveButton(R.string.yes) { _, _ ->
socialRepository.leaveGroup(partyId)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}.setNegativeButton(R.string.no) { _, _ -> }
builder.show()
}
fun onQuestAccept() {
partyId.notNull {
socialRepository.acceptQuest(user, it).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
fun onQuestReject() {
partyId.notNull {
socialRepository.rejectQuest(user, it).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
fun onPartyInviteAccepted() {
user?.invitations?.party?.id.notNull {
socialRepository.joinGroup(it)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
fun onPartyInviteRejected() {
user?.invitations?.party?.id.notNull {
socialRepository.rejectGroupInvite(it)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
fun questDetailButtonClicked() {
val fragment = QuestDetailFragment()
fragment.partyId = partyId
if (party != null && party?.quest != null) {
fragment.questKey = party?.quest?.key
}
if (activity != null) {
val activity = activity as MainActivity?
activity?.displayFragment(fragment)
}
}
}

View file

@ -262,7 +262,7 @@ public class PartyFragment extends BaseMainFragment {
case 0: {
if (user.hasParty()) {
PartyDetailFragment detailFragment = new PartyDetailFragment();
detailFragment.partyId = user.getParty().id;
detailFragment.setPartyId(user.getParty().id);
fragment = detailFragment;
} else {
fragment = GroupInformationFragment.Companion.newInstance(null, user);

View file

@ -1,94 +0,0 @@
package com.habitrpg.android.habitica.ui.fragments.social.party;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import 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.ui.activities.FullProfileActivity;
import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator;
import javax.inject.Inject;
import butterknife.BindView;
/**
* Created by Negue on 15.09.2015.
*/
public class PartyMemberListFragment extends BaseFragment {
@Inject
SocialRepository socialRepository;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.refreshLayout)
SwipeRefreshLayout refreshLayout;
private PartyMemberRecyclerViewAdapter adapter;
private View view;
private String partyId;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
view = inflater.inflate(R.layout.fragment_refresh_recyclerview, container, false);
return view;
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
adapter = new PartyMemberRecyclerViewAdapter(null, true, getContext());
getCompositeSubscription().add(adapter.getUserClickedEvents().subscribe(userId -> FullProfileActivity.open(getContext(), userId), RxErrorHandler.handleEmptyError()));
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
refreshLayout.setOnRefreshListener(this::refreshMembers);
getUsers();
}
private void refreshMembers() {
setRefreshing(true);
socialRepository.retrieveGroupMembers(partyId, true).subscribe(users -> {}, RxErrorHandler.handleEmptyError(), () -> setRefreshing(false));
}
private void setRefreshing(boolean isRefreshing) {
if (refreshLayout != null) {
refreshLayout.setRefreshing(isRefreshing);
}
}
public void setPartyId(String id) {
this.partyId = id;
}
private void getUsers() {
if (partyId == null) {
return;
}
socialRepository.getGroupMembers(partyId).firstElement().subscribe(users -> {
if (adapter != null) {
adapter.updateData(users);
}
}, RxErrorHandler.handleEmptyError());
}
}

View file

@ -0,0 +1,81 @@
package com.habitrpg.android.habitica.ui.fragments.social.party
import android.os.Bundle
import android.support.v4.widget.SwipeRefreshLayout
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import 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.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.ui.activities.FullProfileActivity
import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
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
/**
* Created by Negue on 15.09.2015.
*/
class PartyMemberListFragment : BaseFragment() {
@Inject
lateinit var socialRepository: SocialRepository
private val recyclerView: RecyclerView? by bindView(R.id.recyclerView)
private val refreshLayout: SwipeRefreshLayout? by bindView(R.id.refreshLayout)
private var adapter: PartyMemberRecyclerViewAdapter? = null
private var partyId: String? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return container?.inflate(R.layout.fragment_refresh_recyclerview)
}
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView?.layoutManager = LinearLayoutManager(context)
adapter = PartyMemberRecyclerViewAdapter(null, true)
adapter?.getUserClickedEvents()?.subscribe(Consumer { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription.add(it) }
recyclerView?.adapter = adapter
recyclerView?.itemAnimator = SafeDefaultItemAnimator()
refreshLayout?.setOnRefreshListener { this.refreshMembers() }
getUsers()
}
private fun refreshMembers() {
setRefreshing(true)
socialRepository.retrieveGroupMembers(partyId!!, true).doOnComplete { setRefreshing(false) }.subscribe(Consumer { users -> }, RxErrorHandler.handleEmptyError())
}
private fun setRefreshing(isRefreshing: Boolean) {
refreshLayout?.isRefreshing = isRefreshing
}
fun setPartyId(id: String) {
this.partyId = id
}
private fun getUsers() {
if (partyId == null) {
return
}
socialRepository.getGroupMembers(partyId!!).firstElement().subscribe(Consumer { users ->
adapter?.updateData(users)
}, RxErrorHandler.handleEmptyError())
}
}

View file

@ -12,7 +12,6 @@ import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.LinearLayout
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.commands.ChecklistCheckedCommand
import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand
@ -20,18 +19,13 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
import net.pherth.android.emoji_library.EmojiTextView
import org.greenrobot.eventbus.EventBus
import butterknife.BindView
import butterknife.OnClick
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import net.pherth.android.emoji_library.EmojiTextView
import org.greenrobot.eventbus.EventBus
abstract class ChecklistedViewHolder(itemView: View) : BaseTaskViewHolder(itemView), CompoundButton.OnCheckedChangeListener {
@ -45,6 +39,7 @@ abstract class ChecklistedViewHolder(itemView: View) : BaseTaskViewHolder(itemVi
init {
checklistIndicatorWrapper.isClickable = true
checklistIndicatorWrapper.setOnClickListener { onChecklistIndicatorClicked() }
checkbox.setOnCheckedChangeListener(this)
expandCheckboxTouchArea(checkboxHolder, checkbox)
}
@ -116,7 +111,6 @@ abstract class ChecklistedViewHolder(itemView: View) : BaseTaskViewHolder(itemVi
}
}
@OnClick(R.id.checklistIndicatorWrapper)
fun onChecklistIndicatorClicked() {
expandedChecklistRow = if (this.shouldDisplayExpandedChecklist()) null else adapterPosition
if (this.shouldDisplayExpandedChecklist()) {

View file

@ -5,7 +5,6 @@ import android.widget.Button
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import butterknife.OnClick
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.HabitScoreEvent
import com.habitrpg.android.habitica.ui.helpers.bindView
@ -31,6 +30,11 @@ class HabitViewHolder(itemView: View) : BaseTaskViewHolder(itemView) {
return isVisible
}
init {
btnPlus.setOnClickListener { onPlusButtonClicked() }
btnMinus.setOnClickListener { onMinusButtonClicked() }
}
override fun bindHolder(newTask: Task, position: Int) {
this.task = newTask
if (newTask.up == true) {
@ -82,7 +86,6 @@ class HabitViewHolder(itemView: View) : BaseTaskViewHolder(itemView) {
super.bindHolder(newTask, position)
}
@OnClick(R.id.btnPlus)
fun onPlusButtonClicked() {
val event = HabitScoreEvent()
event.Up = true
@ -90,7 +93,6 @@ class HabitViewHolder(itemView: View) : BaseTaskViewHolder(itemView) {
EventBus.getDefault().post(event)
}
@OnClick(R.id.btnMinus)
fun onMinusButtonClicked() {
val event = HabitScoreEvent()
event.Up = false

View file

@ -4,14 +4,13 @@ import android.support.v4.content.ContextCompat
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import butterknife.OnClick
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.TaskTappedEvent
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.helpers.NumberAbbreviator
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.ItemDetailDialog
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import org.greenrobot.eventbus.EventBus

View file

@ -10,12 +10,11 @@ import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import butterknife.OnClick
import com.habitrpg.android.habitica.BuildConfig
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.user.SubscriptionPlan
import com.habitrpg.android.habitica.ui.helpers.bindView
class SubscriptionDetailsView : LinearLayout {
@ -41,6 +40,8 @@ class SubscriptionDetailsView : LinearLayout {
private fun setupView() {
inflate(R.layout.subscription_details)
visitWebsiteButton.setOnClickListener { openSubscriptionWebsite() }
}
fun setPlan(plan: SubscriptionPlan) {
@ -93,7 +94,6 @@ class SubscriptionDetailsView : LinearLayout {
}
}
@OnClick(R.id.visitWebsiteButton)
fun openSubscriptionWebsite() {
if (plan?.paymentMethod != null) {
val intent: Intent = if (plan?.paymentMethod == "Google") {