Refactor all views and adapters to kotlin

This commit is contained in:
Phillip Thelen 2018-07-06 16:32:08 +02:00
parent 381b76a33a
commit a98eeb347d
57 changed files with 2366 additions and 2942 deletions

View file

@ -1,72 +0,0 @@
package com.habitrpg.android.habitica.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import butterknife.BindView;
import butterknife.ButterKnife;
public class GemPurchaseOptionsView extends FrameLayout {
@BindView(R.id.seedsImageButton)
public
ImageButton seedsImageButton;
@BindView(R.id.gem_image)
ImageView gemImageView;
@BindView(R.id.gem_amount)
TextView gemAmountTextView;
@BindView(R.id.purchase_button)
Button purchaseButton;
private String sku;
public GemPurchaseOptionsView(Context context, AttributeSet attrs) {
super(context, attrs);
inflate(context, R.layout.purchase_gem_view, this);
ButterKnife.bind(this);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.GemPurchaseOptionsView,
0, 0);
gemAmountTextView.setText(a.getText(R.styleable.GemPurchaseOptionsView_gemAmount));
Drawable iconRes = a.getDrawable(R.styleable.GemPurchaseOptionsView_gemDrawable);
if (iconRes != null) {
gemImageView.setImageDrawable(iconRes);
}
if (a.getBoolean(R.styleable.GemPurchaseOptionsView_showSeedsPromo, false)) {
seedsImageButton.setVisibility(View.VISIBLE);
}
}
public void setOnPurchaseClickListener(Button.OnClickListener listener) {
purchaseButton.setOnClickListener(listener);
}
public void setPurchaseButtonText(String price) {
purchaseButton.setText(price);
}
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
}

View file

@ -0,0 +1,47 @@
package com.habitrpg.android.habitica.ui
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.*
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.ui.helpers.bindView
class GemPurchaseOptionsView(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs) {
val seedsImageButton: ImageButton by bindView(R.id.seedsImageButton)
private val gemImageView: ImageView by bindView(R.id.gem_image)
private val gemAmountTextView: TextView by bindView(R.id.gem_amount)
private val purchaseButton: Button by bindView(R.id.purchase_button)
var sku: String? = null
init {
inflate(R.layout.purchase_gem_view)
val a = context.theme.obtainStyledAttributes(
attrs,
R.styleable.GemPurchaseOptionsView,
0, 0)
gemAmountTextView.text = a.getText(R.styleable.GemPurchaseOptionsView_gemAmount)
val iconRes = a.getDrawable(R.styleable.GemPurchaseOptionsView_gemDrawable)
if (iconRes != null) {
gemImageView.setImageDrawable(iconRes)
}
if (a.getBoolean(R.styleable.GemPurchaseOptionsView_showSeedsPromo, false)) {
seedsImageButton.visibility = View.VISIBLE
}
}
fun setOnPurchaseClickListener(listener: OnClickListener) {
purchaseButton.setOnClickListener(listener)
}
fun setPurchaseButtonText(price: String) {
purchaseButton.text = price
}
}

View file

@ -1,97 +0,0 @@
package com.habitrpg.android.habitica.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.ui.views.Typewriter;
import butterknife.BindView;
import butterknife.ButterKnife;
public class SpeechBubbleView extends FrameLayout implements View.OnClickListener {
@BindView(R.id.name_plate)
TextView namePlate;
@BindView(R.id.textView)
Typewriter textView;
@BindView(R.id.npc_image_view)
ImageView npcImageView;
@BindView(R.id.confirmation_buttons)
ViewGroup confirmationButtons;
@BindView(R.id.continue_indicator)
View continueIndicator;
private ShowNextListener showNextListener;
public SpeechBubbleView(Context context, AttributeSet attrs) {
super(context, attrs);
inflate(context, R.layout.speechbubble, this);
ButterKnife.bind(this);
TypedArray attributes = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.SpeechBubbleView,
0, 0);
namePlate.setText(attributes.getString(R.styleable.SpeechBubbleView_namePlate));
textView.setText(attributes.getString(R.styleable.SpeechBubbleView_text));
Drawable iconRes = attributes.getDrawable(R.styleable.SpeechBubbleView_npcDrawable);
if (iconRes != null) {
npcImageView.setImageDrawable(iconRes);
}
confirmationButtons.setVisibility(View.GONE);
this.setOnClickListener(this);
}
public void setConfirmationButtonVisibility(int visibility) {
confirmationButtons.setVisibility(visibility);
}
public void animateText(String text) {
this.textView.animateText(text);
}
public void setText(String text) {
this.textView.setText(text);
}
public void setHasMoreContent(Boolean hasMoreContent) {
continueIndicator.setVisibility(hasMoreContent ? View.VISIBLE : View.GONE);
}
public void setShowNextListener(ShowNextListener listener) {
showNextListener = listener;
}
@Override
public void onClick(View v) {
if (textView.isAnimating()) {
textView.stopTextAnimation();
} else {
if (showNextListener != null) {
showNextListener.showNextStep();
}
}
}
public interface ShowNextListener {
void showNextStep();
}
}

View file

@ -0,0 +1,80 @@
package com.habitrpg.android.habitica.ui
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.Typewriter
class SpeechBubbleView(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs), View.OnClickListener {
private val namePlate: TextView by bindView(R.id.name_plate)
private val textView: Typewriter by bindView(R.id.textView)
private val npcImageView: ImageView by bindView(R.id.npc_image_view)
private val confirmationButtons: ViewGroup by bindView(R.id.confirmation_buttons)
private val continueIndicator: View by bindView(R.id.continue_indicator)
private var showNextListener: ShowNextListener? = null
init {
inflate(R.layout.speechbubble)
val attributes = context.theme.obtainStyledAttributes(
attrs,
R.styleable.SpeechBubbleView,
0, 0)
namePlate.text = attributes.getString(R.styleable.SpeechBubbleView_namePlate)
textView.text = attributes.getString(R.styleable.SpeechBubbleView_text)
val iconRes = attributes.getDrawable(R.styleable.SpeechBubbleView_npcDrawable)
if (iconRes != null) {
npcImageView.setImageDrawable(iconRes)
}
confirmationButtons.visibility = View.GONE
this.setOnClickListener(this)
}
fun setConfirmationButtonVisibility(visibility: Int) {
confirmationButtons.visibility = visibility
}
fun animateText(text: String) {
this.textView.animateText(text)
}
fun setText(text: String) {
this.textView.text = text
}
fun setHasMoreContent(hasMoreContent: Boolean) {
continueIndicator.visibility = if (hasMoreContent) View.VISIBLE else View.GONE
}
fun setShowNextListener(listener: ShowNextListener) {
showNextListener = listener
}
override fun onClick(v: View) {
if (textView.isAnimating) {
textView.stopTextAnimation()
} else {
if (showNextListener != null) {
showNextListener!!.showNextStep()
}
}
}
interface ShowNextListener {
fun showNextStep()
}
}

View file

@ -1,108 +0,0 @@
package com.habitrpg.android.habitica.ui;
import android.content.Context;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.TutorialStep;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class TutorialView extends FrameLayout {
public TutorialStep step;
@Nullable
public OnTutorialReaction onReaction;
@BindView(R.id.speech_bubble)
SpeechBubbleView speechBubbleView;
@BindView(R.id.background)
RelativeLayout background;
@BindView(R.id.dismissButton)
Button dismissButton;
@BindView(R.id.completeButton)
Button completeButton;
private List<String> tutorialTexts;
private int currentTextIndex;
public TutorialView(Context context, TutorialStep step, @Nullable OnTutorialReaction onReaction) {
super(context);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mInflater.inflate(R.layout.overlay_tutorial, this, true);
ButterKnife.bind(this);
speechBubbleView.setConfirmationButtonVisibility(View.GONE);
speechBubbleView.setShowNextListener(this::displayNextTutorialText);
this.step = step;
this.onReaction = onReaction;
}
public void setTutorialText(String text) {
this.speechBubbleView.animateText(text);
speechBubbleView.setConfirmationButtonVisibility(View.VISIBLE);
}
public void setTutorialTexts(List<String> texts) {
tutorialTexts = texts;
currentTextIndex = -1;
displayNextTutorialText();
}
public void setCanBeDeferred(boolean canBeDeferred) {
dismissButton.setVisibility(canBeDeferred ? View.VISIBLE : View.GONE);
}
private void displayNextTutorialText() {
currentTextIndex++;
if (tutorialTexts != null && currentTextIndex < tutorialTexts.size()) {
speechBubbleView.animateText(tutorialTexts.get(currentTextIndex));
if (isDisplayingLastStep()) {
speechBubbleView.setConfirmationButtonVisibility(View.VISIBLE);
speechBubbleView.setHasMoreContent(false);
} else {
speechBubbleView.setHasMoreContent(true);
}
} else {
if (this.onReaction != null) {
this.onReaction.onTutorialCompleted(this.step);
}
}
}
@OnClick(R.id.completeButton)
public void completeButtonClicked() {
if (this.onReaction != null) {
this.onReaction.onTutorialCompleted(this.step);
}
}
@OnClick(R.id.dismissButton)
public void dismissButtonClicked() {
if (this.onReaction != null) {
this.onReaction.onTutorialDeferred(this.step);
}
}
@OnClick(R.id.background)
public void backgroundClicked() {
speechBubbleView.onClick(speechBubbleView);
}
private boolean isDisplayingLastStep() {
return currentTextIndex == (tutorialTexts.size()-1);
}
public interface OnTutorialReaction {
void onTutorialCompleted(TutorialStep step);
void onTutorialDeferred(TutorialStep step);
}
}

View file

@ -0,0 +1,86 @@
package com.habitrpg.android.habitica.ui
import android.content.Context
import android.view.View
import android.widget.Button
import android.widget.FrameLayout
import android.widget.RelativeLayout
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.TutorialStep
import com.habitrpg.android.habitica.ui.helpers.bindView
class TutorialView(context: Context, var step: TutorialStep, var onReaction: OnTutorialReaction?) : FrameLayout(context) {
private val speechBubbleView: SpeechBubbleView by bindView(R.id.speech_bubble)
private val background: RelativeLayout by bindView(R.id.background)
private val dismissButton: Button by bindView(R.id.dismissButton)
private val completeButton: Button by bindView(R.id.completeButton)
private var tutorialTexts: List<String> = emptyList()
private var currentTextIndex: Int = 0
private val isDisplayingLastStep: Boolean
get() = currentTextIndex == tutorialTexts.size - 1
init {
inflate(R.layout.overlay_tutorial)
speechBubbleView.setConfirmationButtonVisibility(View.GONE)
speechBubbleView.setShowNextListener(object : SpeechBubbleView.ShowNextListener {
override fun showNextStep() {
displayNextTutorialText()
}
})
completeButton.setOnClickListener { completeButtonClicked() }
dismissButton.setOnClickListener { dismissButtonClicked() }
background.setOnClickListener { backgroundClicked() }
}
fun setTutorialText(text: String) {
this.speechBubbleView.animateText(text)
speechBubbleView.setConfirmationButtonVisibility(View.VISIBLE)
}
fun setTutorialTexts(texts: List<String>) {
tutorialTexts = texts
currentTextIndex = -1
displayNextTutorialText()
}
fun setCanBeDeferred(canBeDeferred: Boolean) {
dismissButton.visibility = if (canBeDeferred) View.VISIBLE else View.GONE
}
private fun displayNextTutorialText() {
currentTextIndex++
if (currentTextIndex < tutorialTexts.size) {
speechBubbleView.animateText(tutorialTexts[currentTextIndex])
if (isDisplayingLastStep) {
speechBubbleView.setConfirmationButtonVisibility(View.VISIBLE)
speechBubbleView.setHasMoreContent(false)
} else {
speechBubbleView.setHasMoreContent(true)
}
} else {
this.onReaction?.onTutorialCompleted(this.step)
}
}
fun completeButtonClicked() {
this.onReaction?.onTutorialCompleted(this.step)
}
fun dismissButtonClicked() {
this.onReaction?.onTutorialDeferred(this.step)
}
fun backgroundClicked() {
speechBubbleView.onClick(speechBubbleView)
}
interface OnTutorialReaction {
fun onTutorialCompleted(step: TutorialStep)
fun onTutorialDeferred(step: TutorialStep)
}
}

View file

@ -458,7 +458,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
});
displayDeathDialogIfNeeded();
YesterdailyDialog.showDialogIfNeeded(this, user.getId(), userRepository, taskRepository);
YesterdailyDialog.Companion.showDialogIfNeeded(this, user.getId(), userRepository, taskRepository);
displayNewInboxMessagesBadge();
}
@ -833,7 +833,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
TutorialView view = new TutorialView(this, step, this);
this.activeTutorialView = view;
view.setTutorialText(text);
view.onReaction = this;
view.setOnReaction(this);
view.setCanBeDeferred(canBeDeferred);
this.overlayLayout.addView(view);
@ -848,7 +848,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
TutorialView view = new TutorialView(this, step, this);
this.activeTutorialView = view;
view.setTutorialTexts(texts);
view.onReaction = this;
view.setOnReaction(this);
view.setCanBeDeferred(canBeDeferred);
this.overlayLayout.addView(view);

View file

@ -1,116 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.FAQArticle;
import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.fragments.faq.FAQDetailFragment;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.subjects.PublishSubject;
public class FAQOverviewRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_JUSTIN = 0;
private static final int VIEW_TYPE_FAQ = 1;
public MainActivity activity;
private List<FAQArticle> articles;
private PublishSubject<Void> resetWalkthroughEvents = PublishSubject.create();
public void setArticles(List<FAQArticle> articles) {
this.articles = articles;
this.notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_JUSTIN) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.button_list_item, parent, false);
return new ResetWalkthroughViewHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.plain_list_item, parent, false);
return new FAQArticleViewHolder(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == VIEW_TYPE_FAQ) {
((FAQArticleViewHolder) holder).bind(this.articles.get(position-1));
}
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return VIEW_TYPE_JUSTIN;
} else {
return VIEW_TYPE_FAQ;
}
}
@Override
public int getItemCount() {
return this.articles == null ? 1 : this.articles.size()+1;
}
public Flowable<Void> getResetWalkthroughEvents() {
return resetWalkthroughEvents.toFlowable(BackpressureStrategy.DROP);
}
class FAQArticleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@BindView(R.id.textView)
TextView textView;
FAQArticle article;
Context context;
FAQArticleViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
textView.setOnClickListener(this);
context = itemView.getContext();
}
public void bind(FAQArticle article) {
this.article = article;
this.textView.setText(this.article.getQuestion());
}
@Override
public void onClick(View v) {
FAQDetailFragment fragment = new FAQDetailFragment();
fragment.setArticle(this.article);
activity.displayFragment(fragment);
}
}
private class ResetWalkthroughViewHolder extends RecyclerView.ViewHolder {
ResetWalkthroughViewHolder(View itemView) {
super(itemView);
Button button = (Button)itemView;
button.setText(itemView.getContext().getString(R.string.reset_walkthrough));
button.setOnClickListener(v -> resetWalkthroughEvents.onNext(null));
}
}
}

View file

@ -0,0 +1,102 @@
package com.habitrpg.android.habitica.ui.adapter
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.FAQArticle
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.fragments.faq.FAQDetailFragment
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.subjects.PublishSubject
class FAQOverviewRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var activity: MainActivity? = null
private var articles: List<FAQArticle> = emptyList()
private val resetWalkthroughEvents = PublishSubject.create<String>()
fun setArticles(articles: List<FAQArticle>) {
this.articles = articles
this.notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == VIEW_TYPE_JUSTIN) {
val view = LayoutInflater.from(parent.context).inflate(R.layout.button_list_item, parent, false)
ResetWalkthroughViewHolder(view)
} else {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.plain_list_item, parent, false)
FAQArticleViewHolder(view)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (getItemViewType(position) == VIEW_TYPE_FAQ) {
(holder as FAQArticleViewHolder).bind(articles[position - 1])
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) {
VIEW_TYPE_JUSTIN
} else {
VIEW_TYPE_FAQ
}
}
override fun getItemCount(): Int {
return this.articles.size + 1
}
fun getResetWalkthroughEvents(): Flowable<String> {
return resetWalkthroughEvents.toFlowable(BackpressureStrategy.DROP)
}
internal inner class FAQArticleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val textView: TextView by bindView(itemView, R.id.textView)
private var article: FAQArticle? = null
init {
textView.setOnClickListener(this)
}
fun bind(article: FAQArticle) {
this.article = article
this.textView.text = this.article?.question
}
override fun onClick(v: View) {
val fragment = FAQDetailFragment()
article.notNull {
fragment.setArticle(it)
}
activity?.displayFragment(fragment)
}
}
private inner class ResetWalkthroughViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
val button = itemView as Button
button.text = itemView.getContext().getString(R.string.reset_walkthrough)
button.setOnClickListener { resetWalkthroughEvents.onNext("") }
}
}
companion object {
private const val VIEW_TYPE_JUSTIN = 0
private const val VIEW_TYPE_FAQ = 1
}
}

View file

@ -1,103 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.tasks.Task;
import java.util.UUID;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.subjects.PublishSubject;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
public class SkillTasksRecyclerViewAdapter extends RealmRecyclerViewAdapter<Task, SkillTasksRecyclerViewAdapter.ViewHolder> {
private PublishSubject<Task> taskSelectionEvents = PublishSubject.create();
public SkillTasksRecyclerViewAdapter(@Nullable OrderedRealmCollection<Task> data, boolean autoUpdate) {
super(data, autoUpdate);
}
@Override
public long getItemId(int position) {
if (getData() != null) {
Task task = getData().get(position);
if (task.getId() != null && task.getId().length() == 36) {
return UUID.fromString(task.getId()).getMostSignificantBits();
}
}
return UUID.randomUUID().getMostSignificantBits();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.skill_task_item_card, parent, false);
return new SkillTasksRecyclerViewAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (getData() != null) {
holder.bindHolder(getData().get(position));
}
}
public Flowable<Task> getTaskSelectionEvents() {
return taskSelectionEvents.toFlowable(BackpressureStrategy.DROP);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public Task task;
protected android.content.res.Resources resources;
@BindView(R.id.titleTextView)
TextView titleTextView;
@BindView(R.id.notesTextView)
TextView notesTextView;
@BindView(R.id.rightBorderView)
View rightBorderView;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setClickable(true);
ButterKnife.bind(this, itemView);
resources = itemView.getResources();
}
void bindHolder(Task task) {
this.task = task;
titleTextView.setText(task.getText());
if (task.getNotes() == null || task.getNotes().length() == 0) {
notesTextView.setVisibility(View.GONE);
} else {
notesTextView.setVisibility(View.VISIBLE);
notesTextView.setText(task.getNotes());
}
rightBorderView.setBackgroundResource(task.getLightTaskColor());
}
@Override
public void onClick(View v) {
if (v.equals(itemView)) {
taskSelectionEvents.onNext(task);
}
}
}
}

View file

@ -0,0 +1,83 @@
package com.habitrpg.android.habitica.ui.adapter
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import java.util.*
class SkillTasksRecyclerViewAdapter(data: OrderedRealmCollection<Task>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Task, SkillTasksRecyclerViewAdapter.TaskViewHolder>(data, autoUpdate) {
private val taskSelectionEvents = PublishSubject.create<Task>()
override fun getItemId(position: Int): Long {
if (data != null) {
val task = data!![position]
if (task.id != null && task.id!!.length == 36) {
return UUID.fromString(task.id).mostSignificantBits
}
}
return UUID.randomUUID().mostSignificantBits
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.skill_task_item_card, parent, false)
return TaskViewHolder(view)
}
override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
data.notNull {
holder.bindHolder(it[position])
}
}
fun getTaskSelectionEvents(): Flowable<Task> {
return taskSelectionEvents.toFlowable(BackpressureStrategy.DROP)
}
inner class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var task: Task? = null
private val titleTextView: TextView by bindView(R.id.titleTextView)
private val notesTextView: TextView by bindView(R.id.notesTextView)
private val rightBorderView: View by bindView(R.id.rightBorderView)
init {
itemView.setOnClickListener(this)
itemView.isClickable = true
}
internal fun bindHolder(task: Task) {
this.task = task
titleTextView.text = task.text
if (task.notes?.isEmpty() == true) {
notesTextView.visibility = View.GONE
} else {
notesTextView.visibility = View.VISIBLE
notesTextView.text = task.notes
}
rightBorderView.setBackgroundResource(task.lightTaskColor)
}
override fun onClick(v: View) {
if (v == itemView) {
task.notNull {
taskSelectionEvents.onNext(it)
}
}
}
}
}

View file

@ -1,130 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.commands.UseSkillCommand;
import com.habitrpg.android.habitica.models.Skill;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class SkillsRecyclerViewAdapter extends RecyclerView.Adapter<SkillsRecyclerViewAdapter.SkillViewHolder> {
public Double mana;
private List<Skill> skillList;
public void setSkillList(List<Skill> skillList) {
this.skillList = skillList;
this.notifyDataSetChanged();
}
public void setMana(Double mana) {
this.mana = mana;
this.notifyDataSetChanged();
}
@Override
public SkillViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.skill_list_item, parent, false);
return new SkillViewHolder(view);
}
@Override
public void onBindViewHolder(SkillViewHolder holder, int position) {
holder.bind(skillList.get(position));
}
@Override
public int getItemCount() {
return skillList == null ? 0 : skillList.size();
}
class SkillViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final Drawable magicDrawable;
@BindView(R.id.skill_image)
SimpleDraweeView skillImageView;
@BindView(R.id.skill_text)
TextView skillNameTextView;
@BindView(R.id.skill_notes)
TextView skillNotesTextView;
@BindView(R.id.price_button)
Button priceButton;
Skill skill;
Context context;
public SkillViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
context = itemView.getContext();
priceButton.setOnClickListener(this);
magicDrawable = new BitmapDrawable(context.getResources(), HabiticaIconsHelper.imageOfMagic());
}
public void bind(Skill skill) {
this.skill = skill;
skillNameTextView.setText(skill.text);
skillNotesTextView.setText(skill.notes);
if ("special".equals(skill.habitClass)) {
priceButton.setText(R.string.skill_transformation_use);
priceButton.setCompoundDrawables(null, null, null, null);
} else {
priceButton.setText(skill.mana + "");
priceButton.setCompoundDrawablesWithIntrinsicBounds(magicDrawable, null, null, null);
}
DataBindingUtils.INSTANCE.loadImage(skillImageView, "shop_" + skill.key);
if (skill.mana > mana) {
priceButton.setEnabled(false);
priceButton.setBackgroundResource(R.color.task_gray);
skillNameTextView.setTextColor(ContextCompat.getColor(context, R.color.task_gray));
skillNotesTextView.setTextColor(ContextCompat.getColor(context, R.color.task_gray));
} else {
skillNameTextView.setTextColor(ContextCompat.getColor(context, android.R.color.black));
skillNotesTextView.setTextColor(ContextCompat.getColor(context, android.R.color.black));
priceButton.setEnabled(true);
}
}
@Override
public void onClick(View v) {
UseSkillCommand event = new UseSkillCommand();
event.skill = this.skill;
EventBus.getDefault().post(event);
}
}
}

View file

@ -0,0 +1,101 @@
package com.habitrpg.android.habitica.ui.adapter
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.commands.UseSkillCommand
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.Skill
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import org.greenrobot.eventbus.EventBus
class SkillsRecyclerViewAdapter : RecyclerView.Adapter<SkillsRecyclerViewAdapter.SkillViewHolder>() {
var mana: Double = 0.toDouble()
set(value) {
field = value
notifyDataSetChanged()
}
private var skillList: List<Skill> = emptyList()
fun setSkillList(skillList: List<Skill>) {
this.skillList = skillList
this.notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SkillViewHolder {
return SkillViewHolder(parent.inflate(R.layout.skill_list_item))
}
override fun onBindViewHolder(holder: SkillViewHolder, position: Int) {
holder.bind(skillList[position])
}
override fun getItemCount(): Int {
return skillList.size
}
inner class SkillViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val magicDrawable: Drawable
private val skillImageView: SimpleDraweeView by bindView(R.id.skill_image)
private val skillNameTextView: TextView by bindView(R.id.skill_text)
private val skillNotesTextView: TextView by bindView(R.id.skill_image)
private val priceButton: Button by bindView(itemView, R.id.price_button)
var skill: Skill? = null
var context: Context = itemView.context
init {
priceButton.setOnClickListener(this)
magicDrawable = BitmapDrawable(context.resources, HabiticaIconsHelper.imageOfMagic())
}
fun bind(skill: Skill) {
this.skill = skill
skillNameTextView.text = skill.text
skillNotesTextView.text = skill.notes
if ("special" == skill.habitClass) {
priceButton.setText(R.string.skill_transformation_use)
priceButton.setCompoundDrawables(null, null, null, null)
} else {
priceButton.text = skill.mana.toString()
priceButton.setCompoundDrawablesWithIntrinsicBounds(magicDrawable, null, null, null)
}
DataBindingUtils.loadImage(skillImageView, "shop_" + skill.key)
if (skill.mana > mana) {
priceButton.isEnabled = false
priceButton.setBackgroundResource(R.color.task_gray)
skillNameTextView.setTextColor(ContextCompat.getColor(context, R.color.task_gray))
skillNotesTextView.setTextColor(ContextCompat.getColor(context, R.color.task_gray))
} else {
skillNameTextView.setTextColor(ContextCompat.getColor(context, android.R.color.black))
skillNotesTextView.setTextColor(ContextCompat.getColor(context, android.R.color.black))
priceButton.isEnabled = true
}
}
override fun onClick(v: View) {
val event = UseSkillCommand()
event.skill = this.skill
EventBus.getDefault().post(event)
}
}
}

View file

@ -1,223 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.inventory;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.OpenMysteryItemEvent;
import com.habitrpg.android.habitica.events.commands.FeedCommand;
import com.habitrpg.android.habitica.events.commands.HatchingCommand;
import com.habitrpg.android.habitica.models.inventory.Egg;
import com.habitrpg.android.habitica.models.inventory.Food;
import com.habitrpg.android.habitica.models.inventory.HatchingPotion;
import com.habitrpg.android.habitica.models.inventory.Item;
import com.habitrpg.android.habitica.models.inventory.Pet;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.inventory.SpecialItem;
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu;
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem;
import org.greenrobot.eventbus.EventBus;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.subjects.PublishSubject;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
import io.realm.RealmResults;
public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter<Item, ItemRecyclerAdapter.ItemViewHolder> {
public boolean isHatching;
public boolean isFeeding;
public Item hatchingItem;
public Pet feedingPet;
public ItemRecyclerFragment fragment;
private RealmResults<Pet> ownedPets;
public Context context;
private PublishSubject<Item> sellItemEvents = PublishSubject.create();
private PublishSubject<QuestContent> questInvitationEvents = PublishSubject.create();
public ItemRecyclerAdapter(@Nullable OrderedRealmCollection<Item> data, boolean autoUpdate) {
super(data, autoUpdate);
}
public Flowable<Item> getSellItemEvents() {
return sellItemEvents.toFlowable(BackpressureStrategy.DROP);
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_item, parent, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
if (getData() != null) {
holder.bind(getData().get(position));
}
}
public void setOwnedPets(RealmResults<Pet> pets) {
ownedPets = pets;
}
public Flowable<QuestContent> getQuestInvitationEvents() {
return questInvitationEvents.toFlowable(BackpressureStrategy.DROP);
}
class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
Item item;
@BindView(R.id.titleTextView)
TextView titleTextView;
@BindView(R.id.ownedTextView)
TextView ownedTextView;
@BindView(R.id.imageView)
SimpleDraweeView imageView;
Resources resources;
ItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
resources = itemView.getResources();
itemView.setOnClickListener(this);
}
Boolean isPetOwned() {
String petKey;
if (item instanceof Egg) {
petKey = item.getKey() + "-" + hatchingItem.getKey();
} else {
petKey = hatchingItem.getKey() + "-" + item.getKey();
}
return ownedPets != null && ownedPets.where().equalTo("key", petKey).count() > 0;
}
public void bind(Item item) {
this.item = item;
titleTextView.setText(item.getText());
ownedTextView.setText(String.valueOf(item.getOwned()));
boolean disabled = false;
String imageName;
if (item instanceof QuestContent) {
imageName = "inventory_quest_scroll_" + item.getKey();
} else if (item instanceof SpecialItem) {
imageName = item.getKey();
} else {
String type = "";
if (item instanceof Egg) {
type = "Egg";
} else if (item instanceof Food) {
type = "Food";
} else if (item instanceof HatchingPotion) {
type = "HatchingPotion";
}
imageName = "Pet_" + type + "_" + item.getKey();
if (isHatching) {
disabled = this.isPetOwned();
}
}
DataBindingUtils.INSTANCE.loadImage(imageView, imageName != null ? imageName : "head_0");
float alpha = 1.0f;
if (disabled) {
alpha = 0.3f;
}
imageView.setAlpha(alpha);
titleTextView.setAlpha(alpha);
ownedTextView.setAlpha(alpha);
}
@Override
public void onClick(View v) {
if (!isHatching && !isFeeding) {
BottomSheetMenu menu = new BottomSheetMenu(context);
if (!(item instanceof QuestContent) && !(item instanceof SpecialItem)) {
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.sell, item.getValue()), true));
}
if (item instanceof Egg) {
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.hatch_with_potion)));
} else if (item instanceof HatchingPotion) {
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.hatch_egg)));
} else if (item instanceof QuestContent) {
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.invite_party)));
} else if (item instanceof SpecialItem) {
SpecialItem specialItem = (SpecialItem) item;
if (specialItem.isMysteryItem && specialItem.getOwned() > 0) {
menu.addMenuItem(new BottomSheetMenuItem(context.getString(R.string.open)));
}
}
menu.setSelectionRunnable(index -> {
if (!((item instanceof QuestContent) || (item instanceof SpecialItem)) && index == 0) {
sellItemEvents.onNext(item);
return;
}
if (item instanceof Egg) {
HatchingCommand event = new HatchingCommand();
event.usingEgg = (Egg) item;
EventBus.getDefault().post(event);
} else if (item instanceof Food) {
FeedCommand event = new FeedCommand();
event.usingFood = (Food) item;
EventBus.getDefault().post(event);
} else if (item instanceof HatchingPotion) {
HatchingCommand event = new HatchingCommand();
event.usingHatchingPotion = (HatchingPotion) item;
EventBus.getDefault().post(event);
} else if (item instanceof QuestContent) {
questInvitationEvents.onNext((QuestContent) item);
} else if (item instanceof SpecialItem) {
EventBus.getDefault().post(new OpenMysteryItemEvent());
}
});
menu.show();
} else if (isHatching) {
if (this.isPetOwned()) {
return;
}
if (item instanceof Egg) {
HatchingCommand event = new HatchingCommand();
event.usingEgg = (Egg) item;
event.usingHatchingPotion = (HatchingPotion) hatchingItem;
EventBus.getDefault().post(event);
} else if (item instanceof HatchingPotion) {
HatchingCommand event = new HatchingCommand();
event.usingHatchingPotion = (HatchingPotion) item;
event.usingEgg = (Egg) hatchingItem;
EventBus.getDefault().post(event);
}
fragment.dismiss();
} else if (isFeeding) {
FeedCommand event = new FeedCommand();
event.usingPet = feedingPet;
event.usingFood = (Food) item;
EventBus.getDefault().post(event);
fragment.dismiss();
}
}
}
}

View file

@ -0,0 +1,194 @@
package com.habitrpg.android.habitica.ui.adapter.inventory
import android.content.Context
import android.content.res.Resources
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.OpenMysteryItemEvent
import com.habitrpg.android.habitica.events.commands.FeedCommand
import com.habitrpg.android.habitica.events.commands.HatchingCommand
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.inventory.*
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import io.realm.RealmResults
import org.greenrobot.eventbus.EventBus
class ItemRecyclerAdapter(data: OrderedRealmCollection<Item>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Item, ItemRecyclerAdapter.ItemViewHolder>(data, autoUpdate) {
var isHatching: Boolean = false
var isFeeding: Boolean = false
var hatchingItem: Item? = null
var feedingPet: Pet? = null
var fragment: ItemRecyclerFragment? = null
private var ownedPets: RealmResults<Pet>? = null
var context: Context? = null
private val sellItemEvents = PublishSubject.create<Item>()
private val questInvitationEvents = PublishSubject.create<QuestContent>()
fun getSellItemFlowable(): Flowable<Item> {
return sellItemEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getQuestInvitationFlowable(): Flowable<QuestContent> {
return questInvitationEvents.toFlowable(BackpressureStrategy.DROP)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
return ItemViewHolder(parent.inflate(R.layout.item_item))
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
data.notNull { holder.bind(it[position]) }
}
fun setOwnedPets(pets: RealmResults<Pet>) {
ownedPets = pets
}
inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var item: Item? = null
private val titleTextView: TextView by bindView(R.id.titleTextView)
private val ownedTextView: TextView by bindView(R.id.ownedTextView)
private val imageView: SimpleDraweeView by bindView(R.id.imageView)
var resources: Resources = itemView.resources
private val isPetOwned: Boolean?
get() {
val petKey: String = if (item is Egg) {
item?.key + "-" + hatchingItem?.key
} else {
hatchingItem?.key + "-" + item?.key
}
return ownedPets != null && ownedPets?.where()?.equalTo("key", petKey)?.count() ?: 0 > 0
}
init {
itemView.setOnClickListener(this)
}
fun bind(item: Item) {
this.item = item
titleTextView.text = item.text
ownedTextView.text = item.owned.toString()
var disabled = false
val imageName: String?
if (item is QuestContent) {
imageName = "inventory_quest_scroll_" + item.getKey()
} else if (item is SpecialItem) {
imageName = item.getKey()
} else {
val type = when (item) {
is Egg -> "Egg"
is Food -> "Food"
is HatchingPotion -> "HatchingPotion"
else -> ""
}
imageName = "Pet_" + type + "_" + item.key
if (isHatching) {
disabled = this.isPetOwned!!
}
}
DataBindingUtils.loadImage(imageView, imageName ?: "head_0")
var alpha = 1.0f
if (disabled) {
alpha = 0.3f
}
imageView.alpha = alpha
titleTextView.alpha = alpha
ownedTextView.alpha = alpha
}
override fun onClick(v: View) {
if (!isHatching && !isFeeding) {
val menu = BottomSheetMenu(context)
if (item !is QuestContent && item !is SpecialItem) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.sell, item?.value), true))
}
if (item is Egg) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.hatch_with_potion)))
} else if (item is HatchingPotion) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.hatch_egg)))
} else if (item is QuestContent) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.invite_party)))
} else if (item is SpecialItem) {
val specialItem = item as SpecialItem
if (specialItem.isMysteryItem && specialItem.owned > 0) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.open)))
}
}
menu.setSelectionRunnable { index ->
item.notNull { selectedItem ->
if (!(selectedItem is QuestContent || selectedItem is SpecialItem) && index == 0) {
sellItemEvents.onNext(selectedItem)
return@notNull
}
when (selectedItem) {
is Egg -> {
val event = HatchingCommand()
event.usingEgg = selectedItem
EventBus.getDefault().post(event)
}
is Food -> {
val event = FeedCommand()
event.usingFood = selectedItem
EventBus.getDefault().post(event)
}
is HatchingPotion -> {
val event = HatchingCommand()
event.usingHatchingPotion = selectedItem
EventBus.getDefault().post(event)
}
is QuestContent -> questInvitationEvents.onNext(selectedItem)
is SpecialItem -> EventBus.getDefault().post(OpenMysteryItemEvent())
}
}
}
menu.show()
} else if (isHatching) {
if (this.isPetOwned == true) {
return
}
if (item is Egg) {
val event = HatchingCommand()
event.usingEgg = item as Egg
event.usingHatchingPotion = hatchingItem as HatchingPotion?
EventBus.getDefault().post(event)
} else if (item is HatchingPotion) {
val event = HatchingCommand()
event.usingHatchingPotion = item as HatchingPotion
event.usingEgg = hatchingItem as Egg?
EventBus.getDefault().post(event)
}
fragment?.dismiss()
} else if (isFeeding) {
val event = FeedCommand()
event.usingPet = feedingPet
event.usingFood = item as Food
EventBus.getDefault().post(event)
fragment?.dismiss()
}
}
}
}

View file

@ -1,110 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.inventory;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.inventory.Mount;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu;
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.subjects.PublishSubject;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
public class MountDetailRecyclerAdapter extends RealmRecyclerViewAdapter<Mount, MountDetailRecyclerAdapter.MountViewHolder> {
public String itemType;
public Context context;
private PublishSubject<String> equipEvents = PublishSubject.create();
public MountDetailRecyclerAdapter(@Nullable OrderedRealmCollection<Mount> data, boolean autoUpdate) {
super(data, autoUpdate);
}
public Flowable<String> getEquipEvents() {
return equipEvents.toFlowable(BackpressureStrategy.DROP);
}
@Override
public MountViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.animal_overview_item, parent, false);
return new MountViewHolder(view);
}
@Override
public void onBindViewHolder(MountViewHolder holder, int position) {
if (getData() != null) {
holder.bind(this.getData().get(position));
}
}
class MountViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
Mount animal;
@BindView(R.id.card_view)
CardView cardView;
@BindView(R.id.imageView)
SimpleDraweeView imageView;
@BindView(R.id.titleTextView)
TextView titleView;
@BindView(R.id.ownedTextView)
TextView ownedTextView;
Resources resources;
MountViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
resources = itemView.getResources();
itemView.setOnClickListener(this);
}
public void bind(Mount item) {
animal = item;
titleView.setText(item.getColorText());
ownedTextView.setVisibility(View.GONE);
this.imageView.setAlpha(1.0f);
if (this.animal.getOwned()) {
DataBindingUtils.INSTANCE.loadImage(this.imageView, "Mount_Icon_" + itemType + "-" + item.getColor());
} else {
DataBindingUtils.INSTANCE.loadImage(this.imageView, "PixelPaw");
this.imageView.setAlpha(0.3f);
}
}
@Override
public void onClick(View v) {
if (!this.animal.getOwned()) {
return;
}
BottomSheetMenu menu = new BottomSheetMenu(context);
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.use_animal)));
menu.setSelectionRunnable(index -> equipEvents.onNext(animal.getKey()));
menu.show();
}
}
}

View file

@ -0,0 +1,81 @@
package com.habitrpg.android.habitica.ui.adapter.inventory
import android.content.Context
import android.content.res.Resources
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.inventory.Mount
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
class MountDetailRecyclerAdapter(data: OrderedRealmCollection<Mount>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Mount, MountDetailRecyclerAdapter.MountViewHolder>(data, autoUpdate) {
var itemType: String? = null
private val equipEvents = PublishSubject.create<String>()
fun getEquipFlowable(): Flowable<String> {
return equipEvents.toFlowable(BackpressureStrategy.DROP)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MountViewHolder {
return MountViewHolder(parent.inflate(R.layout.animal_overview_item))
}
override fun onBindViewHolder(holder: MountViewHolder, position: Int) {
data.notNull { holder.bind(it[position]) }
}
inner class MountViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var animal: Mount? = null
private val imageView: SimpleDraweeView by bindView(R.id.imageView)
private val titleView: TextView by bindView(R.id.titleTextView)
private val ownedTextView: TextView by bindView(R.id.ownedTextView)
var resources: Resources = itemView.resources
init {
itemView.setOnClickListener(this)
}
fun bind(item: Mount) {
animal = item
titleView.text = item.colorText
ownedTextView.visibility = View.GONE
this.imageView.alpha = 1.0f
if (this.animal?.owned == true) {
DataBindingUtils.loadImage(this.imageView, "Mount_Icon_" + itemType + "-" + item.color)
} else {
DataBindingUtils.loadImage(this.imageView, "PixelPaw")
this.imageView.alpha = 0.3f
}
}
override fun onClick(v: View) {
if (this.animal?.owned == false) {
return
}
val menu = BottomSheetMenu(itemView.context)
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.use_animal)))
menu.setSelectionRunnable {
animal.notNull { equipEvents.onNext(it.key) }
}
menu.show()
}
}
}

View file

@ -1,154 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.inventory;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.commands.FeedCommand;
import com.habitrpg.android.habitica.models.inventory.Mount;
import com.habitrpg.android.habitica.models.inventory.Pet;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu;
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem;
import org.greenrobot.eventbus.EventBus;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.subjects.PublishSubject;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
import io.realm.RealmResults;
public class PetDetailRecyclerAdapter extends RealmRecyclerViewAdapter<Pet, PetDetailRecyclerAdapter.PetViewHolder> {
public String itemType;
public Context context;
private RealmResults<Mount> ownedMounts;
private PublishSubject<String> equipEvents = PublishSubject.create();
public PetDetailRecyclerAdapter(@Nullable OrderedRealmCollection<Pet> data, boolean autoUpdate) {
super(data, autoUpdate);
}
public Flowable<String> getEquipEvents() {
return equipEvents.toFlowable(BackpressureStrategy.DROP);
}
@Override
public PetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.pet_detail_item, parent, false);
return new PetViewHolder(view);
}
@Override
public void onBindViewHolder(PetViewHolder holder, int position) {
if (getData() != null) {
holder.bind(this.getData().get(position));
}
}
public void setOwnedMounts(RealmResults<Mount> ownedMounts) {
this.ownedMounts = ownedMounts;
notifyDataSetChanged();
}
class PetViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
Pet animal;
@BindView(R.id.card_view)
CardView cardView;
@BindView(R.id.imageView)
SimpleDraweeView imageView;
@BindView(R.id.titleTextView)
TextView titleView;
@BindView(R.id.trainedProgressBar)
ProgressBar trainedProgressbar;
Resources resources;
public PetViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
resources = itemView.getResources();
itemView.setOnClickListener(this);
}
public void bind(Pet item) {
this.animal = item;
this.titleView.setText(item.getColorText());
this.trainedProgressbar.setVisibility(animal.getAnimalGroup().equals("specialPets") ? View.GONE : View.VISIBLE);
this.imageView.setAlpha(1.0f);
if (this.animal.getTrained() > 0) {
if (this.isMountOwned()) {
this.trainedProgressbar.setVisibility(View.GONE);
} else {
this.trainedProgressbar.setProgress(this.animal.getTrained());
}
DataBindingUtils.INSTANCE.loadImage(this.imageView, "Pet-" + itemType + "-" + item.getColor());
} else {
this.trainedProgressbar.setVisibility(View.GONE);
if (this.animal.getTrained() == 0) {
DataBindingUtils.INSTANCE.loadImage(this.imageView, "PixelPaw");
} else {
DataBindingUtils.INSTANCE.loadImage(this.imageView, "Pet-" + itemType + "-" + item.getColor());
}
this.imageView.setAlpha(0.3f);
}
}
@Override
public void onClick(View v) {
if (!this.isOwned()) {
return;
}
BottomSheetMenu menu = new BottomSheetMenu(context);
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.use_animal)));
if (!animal.getAnimalGroup().equals("specialPets") && !this.isMountOwned()) {
menu.addMenuItem(new BottomSheetMenuItem(resources.getString(R.string.feed)));
}
menu.setSelectionRunnable(index -> {
if (index == 0) {
equipEvents.onNext(animal.getKey());
} else if (index == 1) {
FeedCommand event = new FeedCommand();
event.usingPet = animal;
EventBus.getDefault().post(event);
}
});
menu.show();
}
private boolean isOwned() {
return this.animal.getTrained() > 0;
}
public boolean isMountOwned() {
for (Mount ownedMount : ownedMounts) {
if (ownedMount.getKey().equals(animal.getKey())) {
return true;
}
}
return false;
}
}
}

View file

@ -0,0 +1,124 @@
package com.habitrpg.android.habitica.ui.adapter.inventory
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.commands.FeedCommand
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.inventory.Mount
import com.habitrpg.android.habitica.models.inventory.Pet
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import io.realm.RealmResults
import org.greenrobot.eventbus.EventBus
class PetDetailRecyclerAdapter(data: OrderedRealmCollection<Pet>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Pet, PetDetailRecyclerAdapter.PetViewHolder>(data, autoUpdate) {
var itemType: String? = null
var context: Context? = null
private var ownedMounts: RealmResults<Mount>? = null
private val equipEvents = PublishSubject.create<String>()
fun getEquipFlowable(): Flowable<String> {
return equipEvents.toFlowable(BackpressureStrategy.DROP)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PetViewHolder {
return PetViewHolder(parent.inflate(R.layout.pet_detail_item))
}
override fun onBindViewHolder(holder: PetViewHolder, position: Int) {
data.notNull {
holder.bind(it[position])
}
}
fun setOwnedMounts(ownedMounts: RealmResults<Mount>) {
this.ownedMounts = ownedMounts
notifyDataSetChanged()
}
inner class PetViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var animal: Pet? = null
private val imageView: SimpleDraweeView by bindView(R.id.imageView)
private val titleView: TextView by bindView(R.id.titleTextView)
private val trainedProgressbar: ProgressBar by bindView(R.id.trainedProgressBar)
private val isOwned: Boolean
get() = this.animal?.trained ?: 0 > 0
private val isMountOwned: Boolean
get() {
for (ownedMount in ownedMounts ?: emptyList<Mount>()) {
if (ownedMount.key == animal?.key) {
return true
}
}
return false
}
init {
itemView.setOnClickListener(this)
}
fun bind(item: Pet) {
this.animal = item
this.titleView.text = item.colorText
this.trainedProgressbar.visibility = if (animal?.animalGroup == "specialPets") View.GONE else View.VISIBLE
this.imageView.alpha = 1.0f
if (this.animal?.trained ?: 0 > 0) {
if (this.isMountOwned) {
this.trainedProgressbar.visibility = View.GONE
} else {
this.trainedProgressbar.progress = animal?.trained ?: 0
}
DataBindingUtils.loadImage(this.imageView, "Pet-" + itemType + "-" + item.color)
} else {
this.trainedProgressbar.visibility = View.GONE
if (this.animal?.trained == 0) {
DataBindingUtils.loadImage(this.imageView, "PixelPaw")
} else {
DataBindingUtils.loadImage(this.imageView, "Pet-" + itemType + "-" + item.color)
}
this.imageView.alpha = 0.3f
}
}
override fun onClick(v: View) {
if (!this.isOwned) {
return
}
val menu = BottomSheetMenu(context)
menu.addMenuItem(BottomSheetMenuItem(itemView.resources.getString(R.string.use_animal)))
if (animal?.animalGroup != "specialPets" && !this.isMountOwned) {
menu.addMenuItem(BottomSheetMenuItem(itemView.resources.getString(R.string.feed)))
}
menu.setSelectionRunnable { index ->
if (index == 0) {
animal.notNull {
equipEvents.onNext(it.key)
}
} else if (index == 1) {
val event = FeedCommand()
event.usingPet = animal
EventBus.getDefault().post(event)
}
}
menu.show()
}
}
}

View file

@ -1,184 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.setup;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.commands.EquipCommand;
import com.habitrpg.android.habitica.events.commands.UpdateUserCommand;
import com.habitrpg.android.habitica.models.SetupCustomization;
import com.habitrpg.android.habitica.models.user.Preferences;
import com.habitrpg.android.habitica.models.user.User;
import org.greenrobot.eventbus.EventBus;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
public class CustomizationSetupAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public String userSize;
public User user;
private List<SetupCustomization> customizationList;
public void setCustomizationList(List<SetupCustomization> newCustomizationList) {
this.customizationList = newCustomizationList;
this.notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int viewID = R.layout.setup_customization_item;
View view = LayoutInflater.from(parent.getContext())
.inflate(viewID, parent, false);
return new CustomizationViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((CustomizationViewHolder) holder).bind(customizationList.get(position));
}
@Override
public int getItemCount() {
return customizationList == null ? 0 : customizationList.size();
}
private boolean isCustomizationActive(SetupCustomization customization) {
if (this.user == null) {
return false;
}
Preferences prefs = this.user.getPreferences();
switch (customization.getCategory()) {
case "body": {
switch (customization.getSubcategory()) {
case "size":
return customization.getKey().equals(prefs.getSize());
case "shirt":
return customization.getKey().equals(prefs.getShirt());
}
}
case "skin":
return customization.getKey().equals(prefs.getSkin());
case "background":
return customization.getKey().equals(prefs.getBackground());
case "hair":
switch (customization.getSubcategory()) {
case "bangs":
return Integer.parseInt(customization.getKey()) == prefs.getHair().getBangs();
case "base":
return Integer.parseInt(customization.getKey()) == prefs.getHair().getBase();
case "color":
return customization.getKey().equals(prefs.getHair().getColor());
case "flower":
return Integer.parseInt(customization.getKey()) == prefs.getHair().getFlower();
case "beard":
return Integer.parseInt(customization.getKey()) == prefs.getHair().getBeard();
case "mustache":
return Integer.parseInt(customization.getKey()) == prefs.getHair().getMustache();
}
case "extras": {
switch (customization.getSubcategory()) {
case "glasses":
return customization.getKey().equals(this.user.getItems().getGear().getEquipped().getEyeWear()) || ("eyewear_base_0".equals(this.user.getItems().getGear().getEquipped().getEyeWear()) && customization.getKey().length() == 0);
case "flower":
return Integer.parseInt(customization.getKey()) == prefs.getHair().getFlower();
case "wheelchair":
return ("chair_"+ customization.getKey()).equals(prefs.getChair()) || customization.getKey().equals(prefs.getChair()) || (customization.getKey().equals("none") && prefs.getChair() == null);
}
}
}
return false;
}
class CustomizationViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@BindView(R.id.imageView)
ImageView imageView;
@BindView(R.id.textView)
TextView textView;
SetupCustomization customization;
Context context;
CustomizationViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
context = itemView.getContext();
}
public void bind(SetupCustomization customization) {
this.customization = customization;
if (customization.getDrawableId() != null) {
imageView.setImageResource(customization.getDrawableId());
} else if (customization.getColorId() != null) {
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.setup_customization_circle);
if (drawable != null) {
drawable.setColorFilter(ContextCompat.getColor(context, customization.getColorId()), PorterDuff.Mode.MULTIPLY);
}
imageView.setImageDrawable(drawable);
} else {
imageView.setImageDrawable(null);
}
textView.setText(customization.getText());
if (!"0".equals(customization.getKey()) && "flower".equals(customization.getSubcategory())) {
if (isCustomizationActive(customization)) {
imageView.setBackgroundResource(R.drawable.setup_customization_flower_bg_selected);
} else {
imageView.setBackgroundResource(R.drawable.setup_customization_flower_bg);
}
} else {
if (isCustomizationActive(customization)) {
imageView.setBackgroundResource(R.drawable.setup_customization_bg_selected);
textView.setTextColor(ContextCompat.getColor(context, R.color.white));
} else {
imageView.setBackgroundResource(R.drawable.setup_customization_bg);
textView.setTextColor(ContextCompat.getColor(context, R.color.white_50_alpha));
}
}
}
@Override
public void onClick(View v) {
if (customization.getPath().equals("glasses")) {
EquipCommand command = new EquipCommand();
if (customization.getKey().length() == 0) {
command.key = user.getItems().getGear().getEquipped().getEyeWear();
} else {
command.key = customization.getKey();
}
command.type = "equipped";
EventBus.getDefault().post(command);
} else {
UpdateUserCommand command = new UpdateUserCommand();
Map<String, Object> updateData = new HashMap<>();
String updatePath = "preferences." + customization.getPath();
updateData.put(updatePath, customization.getKey());
command.updateData = updateData;
EventBus.getDefault().post(command);
}
}
}
}

View file

@ -0,0 +1,147 @@
package com.habitrpg.android.habitica.ui.adapter.setup
import android.content.Context
import android.graphics.PorterDuff
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.commands.EquipCommand
import com.habitrpg.android.habitica.events.commands.UpdateUserCommand
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.SetupCustomization
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.helpers.bindView
import org.greenrobot.eventbus.EventBus
import java.util.*
class CustomizationSetupAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var userSize: String? = null
var user: User? = null
private var customizationList: List<SetupCustomization> = emptyList()
fun setCustomizationList(newCustomizationList: List<SetupCustomization>) {
this.customizationList = newCustomizationList
this.notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return CustomizationViewHolder(parent.inflate(R.layout.setup_customization_item))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as CustomizationViewHolder).bind(customizationList[position])
}
override fun getItemCount(): Int {
return customizationList.size
}
private fun isCustomizationActive(customization: SetupCustomization): Boolean {
val prefs = this.user?.preferences ?: return false
when (customization.category) {
"body" -> {
when (customization.subcategory) {
"size" -> return customization.key == prefs.size
"shirt" -> return customization.key == prefs.shirt
}
}
"skin" -> return customization.key == prefs.skin
"background" -> return customization.key == prefs.background
"hair" -> {
when (customization.subcategory) {
"bangs" -> return Integer.parseInt(customization.key) == prefs.hair?.bangs
"base" -> return Integer.parseInt(customization.key) == prefs.hair?.base
"color" -> return customization.key == prefs.hair?.color
"flower" -> return Integer.parseInt(customization.key) == prefs.hair?.flower
"beard" -> return Integer.parseInt(customization.key) == prefs.hair?.beard
"mustache" -> return Integer.parseInt(customization.key) == prefs.hair?.mustache
}
}
"extras" -> {
when (customization.subcategory) {
"glasses" -> return customization.key == this.user?.items?.gear?.equipped?.eyeWear || "eyewear_base_0" == this.user?.items?.gear?.equipped?.eyeWear && customization.key.isEmpty()
"flower" -> return Integer.parseInt(customization.key) == prefs.hair?.flower
"wheelchair" -> return "chair_" + customization.key == prefs.chair || customization.key == prefs.chair || customization.key == "none" && prefs.chair == null
}
}
}
return false
}
internal inner class CustomizationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val imageView: ImageView by bindView(R.id.imageView)
private val textView: TextView by bindView(R.id.textView)
var customization: SetupCustomization? = null
var context: Context
init {
itemView.setOnClickListener(this)
context = itemView.context
}
fun bind(customization: SetupCustomization) {
this.customization = customization
when {
customization.drawableId != null -> imageView.setImageResource(customization.drawableId ?: 0)
customization.colorId != null -> {
val drawable = ContextCompat.getDrawable(context, R.drawable.setup_customization_circle)
drawable?.setColorFilter(ContextCompat.getColor(context, customization.colorId ?: 0), PorterDuff.Mode.MULTIPLY)
imageView.setImageDrawable(drawable)
}
else -> imageView.setImageDrawable(null)
}
textView.text = customization.text
if ("0" != customization.key && "flower" == customization.subcategory) {
if (isCustomizationActive(customization)) {
imageView.setBackgroundResource(R.drawable.setup_customization_flower_bg_selected)
} else {
imageView.setBackgroundResource(R.drawable.setup_customization_flower_bg)
}
} else {
if (isCustomizationActive(customization)) {
imageView.setBackgroundResource(R.drawable.setup_customization_bg_selected)
textView.setTextColor(ContextCompat.getColor(context, R.color.white))
} else {
imageView.setBackgroundResource(R.drawable.setup_customization_bg)
textView.setTextColor(ContextCompat.getColor(context, R.color.white_50_alpha))
}
}
}
override fun onClick(v: View) {
customization.notNull { selectedCustomization ->
if (selectedCustomization.path == "glasses") {
val command = EquipCommand()
if (selectedCustomization.key.isEmpty()) {
command.key = user?.items?.gear?.equipped?.eyeWear
} else {
command.key = selectedCustomization.key
}
command.type = "equipped"
EventBus.getDefault().post(command)
} else {
val command = UpdateUserCommand()
val updateData = HashMap<String, Any>()
val updatePath = "preferences." + selectedCustomization.path
updateData[updatePath] = selectedCustomization.key
command.updateData = updateData
EventBus.getDefault().post(command)
}
}
}
}
}

View file

@ -1,104 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.setup;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class TaskSetupAdapter extends RecyclerView.Adapter<TaskSetupAdapter.TaskViewHolder> {
public List<Boolean> checkedList;
private String[][] taskList;
public void setTaskList(String[][] taskList) {
this.taskList = taskList;
this.checkedList = new ArrayList<>();
for (String[] ignored : this.taskList) {
this.checkedList.add(false);
}
}
@Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.task_setup_item, parent, false);
return new TaskViewHolder(view);
}
@Override
public void onBindViewHolder(TaskViewHolder holder, int position) {
holder.bind(this.taskList[position], this.checkedList.get(position));
}
@Override
public int getItemCount() {
return this.taskList == null ? 0 : this.taskList.length;
}
class TaskViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final Drawable icon;
@BindView(R.id.textView)
TextView textView;
String[] taskGroup;
Boolean isChecked;
Context context;
TaskViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
context = itemView.getContext();
itemView.setOnClickListener(this);
icon = VectorDrawableCompat.create(context.getResources(), R.drawable.ic_check_white_18dp, null);
if (icon != null) {
icon.setColorFilter(ContextCompat.getColor(context, R.color.brand_100), PorterDuff.Mode.MULTIPLY);
}
}
public void bind(String[] taskGroup, Boolean isChecked) {
this.taskGroup = taskGroup;
this.isChecked = isChecked;
this.textView.setText(this.taskGroup[0]);
if (this.isChecked) {
this.textView.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
textView.getBackground().setColorFilter(ContextCompat.getColor(context, R.color.white), PorterDuff.Mode.MULTIPLY);
textView.setTextColor(ContextCompat.getColor(context, R.color.brand_100));
} else {
this.textView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
textView.getBackground().setColorFilter(ContextCompat.getColor(context, R.color.brand_100), PorterDuff.Mode.MULTIPLY);
textView.setTextColor(ContextCompat.getColor(context, R.color.white));
}
}
@Override
public void onClick(View v) {
int position = this.getAdapterPosition();
checkedList.set(position, !checkedList.get(position));
notifyItemChanged(position);
}
}
}

View file

@ -0,0 +1,85 @@
package com.habitrpg.android.habitica.ui.adapter.setup
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.support.graphics.drawable.VectorDrawableCompat
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.ui.helpers.bindView
import java.util.*
class TaskSetupAdapter : RecyclerView.Adapter<TaskSetupAdapter.TaskViewHolder>() {
var checkedList: MutableList<Boolean> = mutableListOf()
private var taskList: Array<Array<String>> = emptyArray()
fun setTaskList(taskList: Array<Array<String>>) {
this.taskList = taskList
this.checkedList = ArrayList()
for (ignored in this.taskList) {
this.checkedList.add(false)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder {
return TaskViewHolder(parent.inflate(R.layout.task_setup_item))
}
override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
holder.bind(this.taskList[position], this.checkedList[position])
}
override fun getItemCount(): Int {
return this.taskList.size
}
inner class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val icon: Drawable?
private val textView: TextView by bindView(R.id.textView)
private var taskGroup: Array<String>? = null
private var isChecked: Boolean? = null
var context: Context = itemView.context
init {
itemView.setOnClickListener(this)
icon = VectorDrawableCompat.create(context.resources, R.drawable.ic_check_white_18dp, null)
icon?.setColorFilter(ContextCompat.getColor(context, R.color.brand_100), PorterDuff.Mode.MULTIPLY)
}
fun bind(taskGroup: Array<String>, isChecked: Boolean?) {
this.taskGroup = taskGroup
this.isChecked = isChecked
taskGroup.notNull {
textView.text = it[0]
}
if (this.isChecked == true) {
this.textView.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null)
textView.background.setColorFilter(ContextCompat.getColor(context, R.color.white), PorterDuff.Mode.MULTIPLY)
textView.setTextColor(ContextCompat.getColor(context, R.color.brand_100))
} else {
this.textView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
textView.background.setColorFilter(ContextCompat.getColor(context, R.color.brand_100), PorterDuff.Mode.MULTIPLY)
textView.setTextColor(ContextCompat.getColor(context, R.color.white))
}
}
override fun onClick(v: View) {
val position = this.adapterPosition
checkedList[position] = !checkedList[position]
notifyItemChanged(position)
}
}
}

View file

@ -1,152 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.imagepipeline.image.ImageInfo;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.Achievement;
import com.habitrpg.android.habitica.ui.AvatarView;
import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class AchievementAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public String itemType;
public MainActivity activity;
private List<Object> itemList;
public void setItemList(List<Object> itemList) {
this.itemList = itemList;
this.notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.profile_achievement_category, parent, false);
return new SectionViewHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.profile_achievement_item, parent, false);
return new AchievementViewHolder(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Object obj = this.itemList.get(position);
if (obj.getClass().equals(String.class)) {
((SectionViewHolder) holder).bind((String) obj);
} else {
((AchievementViewHolder) holder).bind((Achievement) itemList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if (this.itemList.get(position).getClass().equals(String.class)) {
return 0;
} else {
return 1;
}
}
@Override
public int getItemCount() {
return itemList == null ? 0 : itemList.size();
}
static class AchievementViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
Achievement achievement;
@BindView(R.id.achievement_drawee)
SimpleDraweeView draweeView;
@BindView(R.id.achievement_text)
TextView titleView;
@BindView(R.id.achievement_count_label)
TextView countText;
@BindView(R.id.achievement_item_layout)
LinearLayout item_layout;
Context context;
AchievementViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
item_layout = (LinearLayout) itemView;
context = itemView.getContext();
item_layout.setClickable(true);
item_layout.setOnClickListener(this);
}
public void bind(Achievement item) {
String iconUrl = AvatarView.IMAGE_URI_ROOT + (!item.earned ? "achievement-unearned" : item.icon) + "2x.png";
draweeView.setController(Fresco.newDraweeControllerBuilder()
.setUri(iconUrl)
.setControllerListener(new BaseControllerListener<ImageInfo>() {
@Override
public void onFailure(String id, Throwable throwable) {
}
})
.build());
this.achievement = item;
titleView.setText(item.title);
if (item.optionalCount == null) {
countText.setVisibility(View.GONE);
} else {
countText.setVisibility(View.VISIBLE);
countText.setText(item.optionalCount.toString());
}
}
@Override
public void onClick(View view) {
AlertDialog.Builder b = new AlertDialog.Builder(context);
View customView = LayoutInflater.from(context)
.inflate(R.layout.dialog_achievement_details, null);
ImageView achievementImage = (ImageView) customView.findViewById(R.id.achievement_image);
achievementImage.setImageDrawable(draweeView.getDrawable());
TextView titleView = (TextView) customView.findViewById(R.id.achievement_title);
titleView.setText(achievement.title);
TextView textView = (TextView) customView.findViewById(R.id.achievement_text);
textView.setText(achievement.text);
b.setView(customView);
b.setPositiveButton(R.string.profile_achievement_ok, (dialogInterface, i) -> {
});
b.show();
}
}
}

View file

@ -0,0 +1,116 @@
package com.habitrpg.android.habitica.ui.adapter.social
import android.support.v7.app.AlertDialog
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.Achievement
import com.habitrpg.android.habitica.ui.AvatarView
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder
class AchievementAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var itemType: String? = null
var activity: MainActivity? = null
private var itemList: List<Any> = emptyList()
fun setItemList(itemList: List<Any>) {
this.itemList = itemList
this.notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == 0) {
SectionViewHolder(parent.inflate(R.layout.profile_achievement_category))
} else {
AchievementViewHolder(parent.inflate(R.layout.profile_achievement_item))
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val obj = this.itemList[position]
if (obj.javaClass == String::class.java) {
(holder as SectionViewHolder).bind(obj as String)
} else {
(holder as AchievementViewHolder).bind(itemList[position] as Achievement)
}
}
override fun getItemViewType(position: Int): Int {
return if (this.itemList[position].javaClass == String::class.java) {
0
} else {
1
}
}
override fun getItemCount(): Int {
return itemList.size
}
internal class AchievementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private var achievement: Achievement? = null
private val draweeView: SimpleDraweeView by bindView(R.id.achievement_drawee)
private val titleView: TextView by bindView(R.id.achievement_text)
private val countText: TextView by bindView(R.id.achievement_count_label)
init {
itemView.isClickable = true
itemView.setOnClickListener(this)
}
fun bind(item: Achievement) {
val iconUrl = AvatarView.IMAGE_URI_ROOT + (if (!item.earned) "achievement-unearned" else item.icon) + "2x.png"
draweeView.controller = Fresco.newDraweeControllerBuilder()
.setUri(iconUrl)
.setControllerListener(object : BaseControllerListener<ImageInfo>() {
override fun onFailure(id: String?, throwable: Throwable?) {}
})
.build()
this.achievement = item
titleView.text = item.title
if (item.optionalCount == null) {
countText.visibility = View.GONE
} else {
countText.visibility = View.VISIBLE
countText.text = item.optionalCount.toString()
}
}
override fun onClick(view: View) {
val context = itemView.context
val b = AlertDialog.Builder(context)
val customView = LayoutInflater.from(context)
.inflate(R.layout.dialog_achievement_details, null)
val achievementImage = customView.findViewById<View>(R.id.achievement_image) as ImageView
achievementImage.setImageDrawable(draweeView.drawable)
val titleView = customView.findViewById<View>(R.id.achievement_title) as TextView
titleView.text = achievement?.title
val textView = customView.findViewById<View>(R.id.achievement_text) as TextView
textView.text = achievement?.text
b.setView(customView)
b.setPositiveButton(R.string.profile_achievement_ok) { _, _ -> }
b.show()
}
}
}

View file

@ -1,182 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailActivityCommand;
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailDialogCommand;
import com.habitrpg.android.habitica.models.social.Challenge;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeFilterOptions;
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
import net.pherth.android.emoji_library.EmojiParser;
import net.pherth.android.emoji_library.EmojiTextView;
import org.greenrobot.eventbus.EventBus;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.realm.OrderedRealmCollection;
import io.realm.RealmQuery;
import io.realm.RealmRecyclerViewAdapter;
public class ChallengesListViewAdapter extends RealmRecyclerViewAdapter<Challenge, ChallengesListViewAdapter.ChallengeViewHolder> {
private boolean viewUserChallengesOnly;
private OrderedRealmCollection<Challenge> unfilteredData;
private final String userId;
public ChallengesListViewAdapter(@Nullable OrderedRealmCollection<Challenge> data, boolean autoUpdate, boolean viewUserChallengesOnly, String userId) {
super(data, autoUpdate);
this.viewUserChallengesOnly = viewUserChallengesOnly;
this.userId = userId;
}
@Override
public ChallengeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.challenge_item, parent, false);
return new ChallengeViewHolder(view, viewUserChallengesOnly);
}
@Override
public void onBindViewHolder(ChallengeViewHolder holder, int position) {
if (getData() != null) {
holder.bind(getData().get(position));
}
}
public void updateUnfilteredData(@Nullable OrderedRealmCollection<Challenge> data) {
super.updateData(data);
unfilteredData = data;
}
public void filter(ChallengeFilterOptions filterOptions) {
if (unfilteredData == null) {
return;
}
RealmQuery<Challenge> query = unfilteredData.where();
if (filterOptions.showByGroups != null && filterOptions.showByGroups.size() > 0) {
String[] groupIds = new String[filterOptions.showByGroups.size()];
int index = 0;
for (Group group : filterOptions.showByGroups) {
groupIds[index] = group.getId();
index += 1;
}
query = query.in("groupId", groupIds);
}
if (filterOptions.showOwned != filterOptions.notOwned) {
if (filterOptions.showOwned) {
query = query.equalTo("leaderId", userId);
} else {
query = query.notEqualTo("leaderId", userId);
}
}
this.updateData(query.findAll());
}
public static class ChallengeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final Context context;
@BindView(R.id.challenge_name)
EmojiTextView challengeName;
@BindView(R.id.challenge_group_name)
TextView challengeDescription;
@BindView(R.id.leaderParticipantLayout)
LinearLayout leaderParticipantLayout;
@BindView(R.id.leaderName)
TextView leaderName;
@BindView(R.id.participantCount)
TextView participantCount;
@BindView(R.id.officialHabiticaChallengeLayout)
LinearLayout officialChallengeLayout;
@BindView(R.id.challenge_is_participating)
View challengeParticipatingTextView;
@Nullable
@BindView(R.id.memberCountTextView)
TextView memberCountTextView;
@BindView(R.id.arrowImage)
LinearLayout arrowImage;
@BindView(R.id.gemPrizeTextView)
TextView gemPrizeTextView;
@BindView(R.id.gem_icon)
ImageView gemIconView;
private Challenge challenge;
private boolean viewUserChallengesOnly;
ChallengeViewHolder(View itemView, boolean viewUserChallengesOnly) {
super(itemView);
this.viewUserChallengesOnly = viewUserChallengesOnly;
ButterKnife.bind(this, itemView);
context = itemView.getContext();
itemView.setOnClickListener(this);
gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem());
if (!viewUserChallengesOnly) {
challengeName.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.brand_200));
}
}
public void bind(Challenge challenge) {
this.challenge = challenge;
challengeName.setText(EmojiParser.parseEmojis(challenge.name.trim()));
challengeDescription.setText(challenge.groupName);
officialChallengeLayout.setVisibility(challenge.official ? View.VISIBLE : View.GONE);
if (viewUserChallengesOnly) {
leaderParticipantLayout.setVisibility(View.GONE);
challengeParticipatingTextView.setVisibility(View.GONE);
arrowImage.setVisibility(View.VISIBLE);
} else {
challengeParticipatingTextView.setVisibility(challenge.isParticipating ? View.VISIBLE : View.GONE);
leaderName.setText(context.getString(R.string.byLeader, challenge.leaderName));
participantCount.setText(String.valueOf(challenge.memberCount));
leaderParticipantLayout.setVisibility(View.VISIBLE);
arrowImage.setVisibility(View.GONE);
}
gemPrizeTextView.setText(String.valueOf(challenge.prize));
}
@Override
public void onClick(View view) {
if (challenge != null && challenge.isManaged() && challenge.isManaged()) {
if (viewUserChallengesOnly) {
EventBus.getDefault().post(new ShowChallengeDetailActivityCommand(challenge.id));
} else {
EventBus.getDefault().post(new ShowChallengeDetailDialogCommand(challenge.id));
}
}
}
}
}

View file

@ -0,0 +1,133 @@
package com.habitrpg.android.habitica.ui.adapter.social
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailActivityCommand
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailDialogCommand
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.social.Challenge
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeFilterOptions
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import net.pherth.android.emoji_library.EmojiParser
import net.pherth.android.emoji_library.EmojiTextView
import org.greenrobot.eventbus.EventBus
class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUpdate: Boolean, private val viewUserChallengesOnly: Boolean, private val userId: String) : RealmRecyclerViewAdapter<Challenge, ChallengesListViewAdapter.ChallengeViewHolder>(data, autoUpdate) {
private var unfilteredData: OrderedRealmCollection<Challenge>? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChallengeViewHolder {
return ChallengeViewHolder(parent.inflate(R.layout.challenge_item), viewUserChallengesOnly)
}
override fun onBindViewHolder(holder: ChallengeViewHolder, position: Int) {
data.notNull {
holder.bind(it[position])
}
}
fun updateUnfilteredData(data: OrderedRealmCollection<Challenge>?) {
super.updateData(data)
unfilteredData = data
}
fun filter(filterOptions: ChallengeFilterOptions) {
if (unfilteredData == null) {
return
}
var query = unfilteredData?.where()
if (filterOptions.showByGroups != null && filterOptions.showByGroups.size > 0) {
val groupIds = arrayOfNulls<String>(filterOptions.showByGroups.size)
var index = 0
for (group in filterOptions.showByGroups) {
groupIds[index] = group.id
index += 1
}
query = query?.`in`("groupId", groupIds)
}
if (filterOptions.showOwned != filterOptions.notOwned) {
query = if (filterOptions.showOwned) {
query?.equalTo("leaderId", userId)
} else {
query?.notEqualTo("leaderId", userId)
}
}
query.notNull {
this.updateData(it.findAll())
}
}
class ChallengeViewHolder internal constructor(itemView: View, private val viewUserChallengesOnly: Boolean) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val challengeName: EmojiTextView by bindView(R.id.challenge_name)
private val challengeDescription: TextView by bindView(R.id.challenge_group_name)
private val leaderParticipantLayout: LinearLayout by bindView(R.id.leaderParticipantLayout)
private val leaderName: TextView by bindView(R.id.leaderName)
private val participantCount: TextView by bindView(R.id.participantCount)
private val officialChallengeLayout: LinearLayout by bindView(R.id.officialHabiticaChallengeLayout)
private val challengeParticipatingTextView: View by bindView(R.id.challenge_is_participating)
private val memberCountTextView: TextView by bindView(R.id.memberCountTextView)
private val arrowImage: LinearLayout by bindView(R.id.arrowImage)
private val gemPrizeTextView: TextView by bindView(R.id.gemPrizeTextView)
private val gemIconView: ImageView by bindView(R.id.gem_icon)
private var challenge: Challenge? = null
init {
itemView.setOnClickListener(this)
gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem())
if (!viewUserChallengesOnly) {
challengeName.setTextColor(ContextCompat.getColor(itemView.context, R.color.brand_200))
}
}
fun bind(challenge: Challenge) {
this.challenge = challenge
challengeName.text = EmojiParser.parseEmojis(challenge.name.trim { it <= ' ' })
challengeDescription.text = challenge.groupName
officialChallengeLayout.visibility = if (challenge.official) View.VISIBLE else View.GONE
if (viewUserChallengesOnly) {
leaderParticipantLayout.visibility = View.GONE
challengeParticipatingTextView.visibility = View.GONE
arrowImage.visibility = View.VISIBLE
} else {
challengeParticipatingTextView.visibility = if (challenge.isParticipating) View.VISIBLE else View.GONE
leaderName.text = itemView.context.getString(R.string.byLeader, challenge.leaderName)
participantCount.text = challenge.memberCount.toString()
leaderParticipantLayout.visibility = View.VISIBLE
arrowImage.visibility = View.GONE
}
gemPrizeTextView.text = challenge.prize.toString()
}
override fun onClick(view: View) {
if (challenge != null && challenge!!.isManaged && challenge!!.isManaged) {
if (viewUserChallengesOnly) {
EventBus.getDefault().post(ShowChallengeDetailActivityCommand(challenge!!.id))
} else {
EventBus.getDefault().post(ShowChallengeDetailDialogCommand(challenge!!.id))
}
}
}
}
}

View file

@ -1,316 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.social.ChatMessage;
import com.habitrpg.android.habitica.models.user.User;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
import net.pherth.android.emoji_library.EmojiTextView;
import java.lang.reflect.Field;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
public class ChatRecyclerViewAdapter extends RealmRecyclerViewAdapter<ChatMessage, ChatRecyclerViewAdapter.ChatRecyclerViewHolder> {
private User user;
private boolean isTavern;
private String uuid;
private User sendingUser;
private PublishSubject<ChatMessage> likeMessageEvents = PublishSubject.create();
private PublishSubject<String> userLabelClickEvents = PublishSubject.create();
private PublishSubject<String> privateMessageClickEvents = PublishSubject.create();
private PublishSubject<ChatMessage> deleteMessageEvents = PublishSubject.create();
private PublishSubject<ChatMessage> flatMessageEvents = PublishSubject.create();
private PublishSubject<ChatMessage> copyMessageAsTodoEvents = PublishSubject.create();
private PublishSubject<ChatMessage> copyMessageEvents = PublishSubject.create();
public ChatRecyclerViewAdapter(@Nullable OrderedRealmCollection<ChatMessage> data, boolean autoUpdate, User user, boolean isTavern) {
super(data, autoUpdate);
this.user = user;
this.isTavern = isTavern;
if (user != null) this.uuid = user.getId();
}
public void setSendingUser(@Nullable User user) {
this.sendingUser = user;
}
@Override
public ChatRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tavern_chat_item, parent, false);
return new ChatRecyclerViewHolder(view, uuid, isTavern);
}
@Override
public void onBindViewHolder(ChatRecyclerViewHolder holder, int position) {
if (getData() != null) {
holder.bind(getData().get(position));
}
}
public Flowable<ChatMessage> getLikeMessageEvents() {
return likeMessageEvents.toFlowable(BackpressureStrategy.DROP);
}
public Flowable<String> getUserLabelClickEvents() {
return userLabelClickEvents.toFlowable(BackpressureStrategy.DROP);
}
public Flowable<String> getPrivateMessageClickEvents() {
return privateMessageClickEvents.toFlowable(BackpressureStrategy.DROP);
}
public Flowable<ChatMessage> getDeleteMessageEvents() {
return deleteMessageEvents.toFlowable(BackpressureStrategy.DROP);
}
public Flowable<ChatMessage> getFlagMessageEvents() {
return flatMessageEvents.toFlowable(BackpressureStrategy.DROP);
}
public Flowable<ChatMessage> getCopyMessageAsTodoEvents() {
return copyMessageAsTodoEvents.toFlowable(BackpressureStrategy.DROP);
}
public Flowable<ChatMessage> getCopyMessageEvents() {
return copyMessageEvents.toFlowable(BackpressureStrategy.DROP);
}
class ChatRecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, PopupMenu.OnMenuItemClickListener {
@BindView(R.id.btn_options)
ImageView btnOptions;
@BindView(R.id.user_background_layout)
LinearLayout userBackground;
@BindView(R.id.user_label)
TextView userLabel;
@BindView(R.id.message_text)
EmojiTextView messageText;
@BindView(R.id.ago_label)
TextView agoLabel;
@BindView(R.id.like_background_layout)
LinearLayout likeBackground;
@BindView(R.id.tvLikes)
TextView tvLikes;
Context context;
Resources res;
private String userId;
private boolean isTavern;
private ChatMessage chatMessage;
ChatRecyclerViewHolder(View itemView, String currentUserId, boolean isTavern) {
super(itemView);
this.userId = currentUserId;
this.isTavern = isTavern;
ButterKnife.bind(this, itemView);
context = itemView.getContext();
res = context.getResources();
if (btnOptions != null) {
btnOptions.setOnClickListener(this);
}
}
public void bind(final ChatMessage msg) {
chatMessage = msg;
setLikeProperties();
if (userBackground != null) {
if (msg.getSent() != null && msg.getSent().equals("true") && sendingUser != null) {
DataBindingUtils.INSTANCE.setRoundedBackgroundInt(userBackground, sendingUser.getContributorColor());
} else {
DataBindingUtils.INSTANCE.setRoundedBackgroundInt(userBackground, msg.getContributorColor());
}
}
if (userLabel != null) {
if (msg.getSent() != null && msg.getSent().equals("true")) {
userLabel.setText(sendingUser.getProfile().getName());
} else {
if (msg.getUser() != null && msg.getUser().length() > 0) {
userLabel.setText(msg.getUser());
} else {
userLabel.setText(R.string.system);
}
}
userLabel.setClickable(true);
userLabel.setOnClickListener(view -> userLabelClickEvents.onNext(msg.getUuid()));
}
DataBindingUtils.INSTANCE.setForegroundTintColor(userLabel, msg.getContributorForegroundColor());
if (messageText != null) {
messageText.setText(chatMessage.getParsedText());
if (msg.getParsedText() == null) {
messageText.setText(chatMessage.getText());
Maybe.just(chatMessage.getText())
.map(MarkdownParser.INSTANCE::parseMarkdown)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(parsedText -> {
chatMessage.setParsedText(parsedText);
messageText.setText(chatMessage.getParsedText());
}, Throwable::printStackTrace);
}
this.messageText.setMovementMethod(LinkMovementMethod.getInstance());
}
if (agoLabel != null) {
agoLabel.setText(msg.getAgoString(res));
}
}
private void setLikeProperties() {
likeBackground.setVisibility(isTavern ? View.VISIBLE : View.INVISIBLE);
tvLikes.setText("+" + chatMessage.getLikeCount());
int backgroundColorRes;
int foregroundColorRes;
if (chatMessage.getLikeCount() != 0) {
if (chatMessage.userLikesMessage(userId)) {
backgroundColorRes = R.color.tavern_userliked_background;
foregroundColorRes = R.color.tavern_userliked_foreground;
} else {
backgroundColorRes = R.color.tavern_somelikes_background;
foregroundColorRes = R.color.tavern_somelikes_foreground;
}
} else {
backgroundColorRes = R.color.tavern_nolikes_background;
foregroundColorRes = R.color.tavern_nolikes_foreground;
}
DataBindingUtils.INSTANCE.setRoundedBackground(likeBackground, ContextCompat.getColor(context, backgroundColorRes));
tvLikes.setTextColor(ContextCompat.getColor(context, foregroundColorRes));
}
@Override
public void onClick(View v) {
if (chatMessage != null) {
if (btnOptions == v) {
PopupMenu popupMenu = new PopupMenu(context, v);
//set my own listener giving the View that activates the event onClick (i.e. YOUR ImageView)
popupMenu.setOnMenuItemClickListener(this);
//inflate your PopUpMenu
popupMenu.getMenuInflater().inflate(R.menu.chat_message, popupMenu.getMenu());
// Force icons to show
Object menuHelper = null;
Class[] argTypes;
try {
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popupMenu);
argTypes = new Class[]{boolean.class};
menuHelper.getClass().getDeclaredMethod("setForceShowIcon", argTypes).invoke(menuHelper, true);
} catch (Exception ignored) {
}
popupMenu.getMenu().findItem(R.id.menu_chat_delete).setVisible(shouldShowDelete(chatMessage));
popupMenu.getMenu().findItem(R.id.menu_chat_flag).setVisible(!chatMessage.getUuid().equals("system"));
popupMenu.getMenu().findItem(R.id.menu_chat_copy_as_todo).setVisible(false);
popupMenu.getMenu().findItem(R.id.menu_chat_send_pm).setVisible(false);
popupMenu.show();
// Try to force some horizontal offset
try {
Field fListPopup = menuHelper.getClass().getDeclaredField("mPopup");
fListPopup.setAccessible(true);
Object listPopup = fListPopup.get(menuHelper);
argTypes = new Class[]{int.class};
Class listPopupClass = listPopup.getClass();
// Get the width of the popup window
int width = (Integer) listPopupClass.getDeclaredMethod("getWidth").invoke(listPopup);
// Invoke setHorizontalOffset() with the negative width to move left by that distance
listPopupClass.getDeclaredMethod("setHorizontalOffset", argTypes).invoke(listPopup, -width);
// Invoke show() to update the window's position
listPopupClass.getDeclaredMethod("show").invoke(listPopup);
} catch (Exception ignored) {
}
}
}
}
private boolean shouldShowDelete(ChatMessage chatMsg) {
return !chatMsg.isSystemMessage() && (chatMsg.getUuid().equals(userId) || user.getContributor() != null && user.getContributor().getAdmin());
}
@OnClick(R.id.tvLikes)
public void toggleLike() {
likeMessageEvents.onNext(chatMessage);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_chat_delete: {
deleteMessageEvents.onNext(chatMessage);
break;
}
case R.id.menu_chat_flag: {
flatMessageEvents.onNext(chatMessage);
break;
}
case R.id.menu_chat_copy_as_todo: {
copyMessageAsTodoEvents.onNext(chatMessage);
break;
}
case R.id.menu_chat_send_pm: {
privateMessageClickEvents.onNext(chatMessage.getUuid());
break;
}
case R.id.menu_chat_copy: {
copyMessageEvents.onNext(chatMessage);
break;
}
}
return false;
}
}
}

View file

@ -0,0 +1,263 @@
package com.habitrpg.android.habitica.ui.adapter.social
import android.content.Context
import android.content.res.Resources
import android.support.v4.content.ContextCompat
import android.support.v7.widget.PopupMenu
import android.support.v7.widget.RecyclerView
import android.text.method.LinkMovementMethod
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.social.ChatMessage
import com.habitrpg.android.habitica.models.user.User
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 io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import net.pherth.android.emoji_library.EmojiTextView
class ChatRecyclerViewAdapter(data: OrderedRealmCollection<ChatMessage>?, autoUpdate: Boolean, private val user: User?, private val isTavern: Boolean) : RealmRecyclerViewAdapter<ChatMessage, ChatRecyclerViewAdapter.ChatRecyclerViewHolder>(data, autoUpdate) {
private var uuid: String = ""
private var sendingUser: User? = null
private val likeMessageEvents = PublishSubject.create<ChatMessage>()
private val userLabelClickEvents = PublishSubject.create<String>()
private val privateMessageClickEvents = PublishSubject.create<String>()
private val deleteMessageEvents = PublishSubject.create<ChatMessage>()
private val flagMessageEvents = PublishSubject.create<ChatMessage>()
private val copyMessageAsTodoEvents = PublishSubject.create<ChatMessage>()
private val copyMessageEvents = PublishSubject.create<ChatMessage>()
init {
if (user != null) this.uuid = user.id
}
fun setSendingUser(user: User?) {
this.sendingUser = user
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatRecyclerViewHolder {
return ChatRecyclerViewHolder(parent.inflate(R.layout.tavern_chat_item), uuid, isTavern)
}
override fun onBindViewHolder(holder: ChatRecyclerViewHolder, position: Int) {
data.notNull { holder.bind(it[position]) }
}
fun getLikeMessageFlowable(): Flowable<ChatMessage> {
return likeMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getUserLabelClickFlowable(): Flowable<String> {
return userLabelClickEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getPrivateMessageClickFlowable(): Flowable<String> {
return privateMessageClickEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getFlagMessageClickFlowable(): Flowable<ChatMessage> {
return flagMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getDeleteMessageFlowable(): Flowable<ChatMessage> {
return deleteMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getCopyMessageAsTodoFlowable(): Flowable<ChatMessage> {
return copyMessageAsTodoEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getCopyMessageFlowable(): Flowable<ChatMessage> {
return copyMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
inner class ChatRecyclerViewHolder(itemView: View, private val userId: String, private val isTavern: Boolean) : RecyclerView.ViewHolder(itemView), View.OnClickListener, PopupMenu.OnMenuItemClickListener {
private val btnOptions: ImageView by bindView(R.id.btn_options)
private val userBackground: LinearLayout by bindView(R.id.user_background_layout)
private val userLabel: TextView by bindView(R.id.user_label)
private val messageText: EmojiTextView by bindView(R.id.message_text)
private val agoLabel: TextView by bindView(R.id.ago_label)
private val likeBackground: LinearLayout by bindView(R.id.like_background_layout)
private val tvLikes: TextView by bindView(R.id.tvLikes)
val context: Context = itemView.context
val res: Resources = itemView.resources
private var chatMessage: ChatMessage? = null
init {
btnOptions.setOnClickListener(this)
tvLikes.setOnClickListener { toggleLike() }
}
fun bind(msg: ChatMessage) {
chatMessage = msg
setLikeProperties()
if (msg.sent != null && msg.sent == "true" && sendingUser != null) {
DataBindingUtils.setRoundedBackgroundInt(userBackground, sendingUser!!.contributorColor)
} else {
DataBindingUtils.setRoundedBackgroundInt(userBackground, msg.contributorColor)
}
if (msg.sent != null && msg.sent == "true") {
userLabel.text = sendingUser?.profile?.name
} else {
if (msg.user != null && msg.user?.isNotEmpty() == true) {
userLabel.text = msg.user
} else {
userLabel.setText(R.string.system)
}
}
userLabel.isClickable = true
userLabel.setOnClickListener { view -> userLabelClickEvents.onNext(msg.uuid ?: "") }
DataBindingUtils.setForegroundTintColor(userLabel, msg.contributorForegroundColor)
messageText.text = chatMessage?.parsedText
if (msg.parsedText == null) {
messageText.text = chatMessage?.text
Maybe.just(chatMessage?.text ?: "")
.map { MarkdownParser.parseMarkdown(it) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ parsedText ->
chatMessage?.parsedText = parsedText
messageText.text = chatMessage?.parsedText
}, { it.printStackTrace() })
}
this.messageText.movementMethod = LinkMovementMethod.getInstance()
agoLabel.text = msg.getAgoString(res)
}
private fun setLikeProperties() {
likeBackground.visibility = if (isTavern) View.VISIBLE else View.INVISIBLE
tvLikes.text = "+" + chatMessage?.likeCount
val backgroundColorRes: Int
val foregroundColorRes: Int
if (chatMessage?.likeCount != 0) {
if (chatMessage?.userLikesMessage(userId) == true) {
backgroundColorRes = R.color.tavern_userliked_background
foregroundColorRes = R.color.tavern_userliked_foreground
} else {
backgroundColorRes = R.color.tavern_somelikes_background
foregroundColorRes = R.color.tavern_somelikes_foreground
}
} else {
backgroundColorRes = R.color.tavern_nolikes_background
foregroundColorRes = R.color.tavern_nolikes_foreground
}
DataBindingUtils.setRoundedBackground(likeBackground, ContextCompat.getColor(context, backgroundColorRes))
tvLikes.setTextColor(ContextCompat.getColor(context, foregroundColorRes))
}
override fun onClick(v: View) {
if (chatMessage != null) {
if (btnOptions === v) {
val popupMenu = PopupMenu(context, v)
//set my own listener giving the View that activates the event onClick (i.e. YOUR ImageView)
popupMenu.setOnMenuItemClickListener(this)
//inflate your PopUpMenu
popupMenu.menuInflater.inflate(R.menu.chat_message, popupMenu.menu)
// Force icons to show
var menuHelper: Any? = null
var argTypes: Array<Class<*>>
try {
val fMenuHelper = PopupMenu::class.java.getDeclaredField("mPopup")
fMenuHelper.isAccessible = true
menuHelper = fMenuHelper.get(popupMenu)
argTypes = arrayOf(Boolean::class.java)
menuHelper?.javaClass?.getDeclaredMethod("setForceShowIcon", *argTypes)?.invoke(menuHelper, true)
} catch (ignored: Exception) {
}
popupMenu.menu.findItem(R.id.menu_chat_delete).isVisible = shouldShowDelete(chatMessage)
popupMenu.menu.findItem(R.id.menu_chat_flag).isVisible = chatMessage?.uuid != "system"
popupMenu.menu.findItem(R.id.menu_chat_copy_as_todo).isVisible = false
popupMenu.menu.findItem(R.id.menu_chat_send_pm).isVisible = false
popupMenu.show()
// Try to force some horizontal offset
try {
val fListPopup = menuHelper?.javaClass?.getDeclaredField("mPopup")
fListPopup?.isAccessible = true
val listPopup = fListPopup?.get(menuHelper)
argTypes = arrayOf(Int::class.java)
val listPopupClass = listPopup?.javaClass
// Get the width of the popup window
val width = listPopupClass?.getDeclaredMethod("getWidth")?.invoke(listPopup) as Int?
// Invoke setHorizontalOffset() with the negative width to move left by that distance
listPopupClass?.getDeclaredMethod("setHorizontalOffset", *argTypes)?.invoke(listPopup, -(width ?: 0))
// Invoke show() to update the window's position
listPopupClass?.getDeclaredMethod("show")?.invoke(listPopup)
} catch (ignored: Exception) {
}
}
}
}
private fun shouldShowDelete(chatMsg: ChatMessage?): Boolean {
return chatMsg?.isSystemMessage != true && (chatMsg?.uuid == userId || user?.contributor != null && user.contributor.admin)
}
fun toggleLike() {
chatMessage.notNull { likeMessageEvents.onNext(it) }
}
override fun onMenuItemClick(item: MenuItem): Boolean {
chatMessage.notNull {
when (item.itemId) {
R.id.menu_chat_delete -> {
deleteMessageEvents.onNext(it)
}
R.id.menu_chat_flag -> {
flagMessageEvents.onNext(it)
}
R.id.menu_chat_copy_as_todo -> {
copyMessageAsTodoEvents.onNext(it)
}
R.id.menu_chat_send_pm -> {
privateMessageClickEvents.onNext(it.uuid ?: "")
}
R.id.menu_chat_copy -> {
copyMessageEvents.onNext(it)
}
}
}
return false
}
}
}

View file

@ -1,138 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.members.Member;
import com.habitrpg.android.habitica.models.members.MemberPreferences;
import com.habitrpg.android.habitica.models.user.Stats;
import com.habitrpg.android.habitica.ui.AvatarView;
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
import com.habitrpg.android.habitica.ui.helpers.ViewHelper;
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
import com.habitrpg.android.habitica.ui.views.ValueBar;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.subjects.PublishSubject;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
public class PartyMemberRecyclerViewAdapter extends RealmRecyclerViewAdapter<Member, PartyMemberRecyclerViewAdapter.MemberViewHolder> {
private Context context;
private PublishSubject<String> userClickedEvents = PublishSubject.create();
public PartyMemberRecyclerViewAdapter(@Nullable OrderedRealmCollection<Member> data, boolean autoUpdate, Context context) {
super(data, autoUpdate);
this.context = context;
}
@Override
public MemberViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.party_member, parent, false);
return new MemberViewHolder(view);
}
@Override
public void onBindViewHolder(MemberViewHolder holder, int position) {
if (getData() != null) {
holder.bind(getData().get(position));
}
}
public Flowable<String> getUserClickedEvents() {
return userClickedEvents.toFlowable(BackpressureStrategy.DROP);
}
class MemberViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.avatarView)
AvatarView avatarView;
@BindView(R.id.username)
TextView userName;
@BindView(R.id.user_lvl)
TextView lvl;
@BindView(R.id.class_label)
TextView classLabel;
@BindView(R.id.class_background_layout)
View classBackground;
@BindView(R.id.hpBar)
ValueBar hpBar;
Resources resources;
MemberViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
hpBar.setLightBackground(true);
hpBar.setIcon(HabiticaIconsHelper.imageOfHeartLightBg());
resources = itemView.getResources();
}
public void bind(Member user) {
avatarView.setAvatar(user);
AvatarWithBarsViewModel.Companion.setHpBarData(hpBar, user.getStats());
lvl.setText(context.getString(R.string.user_level, user.getStats().getLvl()));
classLabel.setText(user.getStats().getTranslatedClassName(context));
MemberPreferences preferences = user.getPreferences();
int colorResourceID;
switch (user.getStats().habitClass) {
case Stats.HEALER: {
colorResourceID = R.color.class_healer;
break;
}
case Stats.WARRIOR: {
colorResourceID = R.color.class_warrior;
break;
}
case Stats.ROGUE: {
colorResourceID = R.color.class_rogue;
break;
}
case Stats.MAGE: {
colorResourceID = R.color.class_wizard;
break;
}
default:
colorResourceID = R.color.task_gray;
}
ViewHelper.SetBackgroundTint(classBackground, ContextCompat.getColor(context, colorResourceID));
userName.setText(user.getProfile().getName());
if (itemView != null) {
itemView.setClickable(true);
itemView.setOnClickListener(view -> userClickedEvents.onNext(user.getId()));
}
}
}
}

View file

@ -0,0 +1,89 @@
package com.habitrpg.android.habitica.ui.adapter.social
import android.content.Context
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.ui.AvatarView
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel
import com.habitrpg.android.habitica.ui.helpers.ViewHelper
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.ValueBar
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
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) {
private val userClickedEvents = PublishSubject.create<String>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MemberViewHolder {
return MemberViewHolder(parent.inflate(R.layout.party_member))
}
override fun onBindViewHolder(holder: MemberViewHolder, position: Int) {
data.notNull {
holder.bind(it[position])
}
}
fun getUserClickedEvents(): Flowable<String> {
return userClickedEvents.toFlowable(BackpressureStrategy.DROP)
}
inner class MemberViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val avatarView: AvatarView by bindView(R.id.avatarView)
private val userName: TextView by bindView(R.id.username)
private val lvl: TextView by bindView(R.id.user_lvl)
private val classLabel: TextView by bindView(R.id.class_label)
private val classBackground: View by bindView(R.id.class_background_layout)
private val hpBar: ValueBar by bindView(R.id.hpBar)
init {
hpBar.setLightBackground(true)
hpBar.setIcon(HabiticaIconsHelper.imageOfHeartLightBg())
}
fun bind(user: Member) {
avatarView.setAvatar(user)
AvatarWithBarsViewModel.setHpBarData(hpBar, user.stats)
lvl.text = context.getString(R.string.user_level, user.stats.getLvl())
classLabel.text = user.stats.getTranslatedClassName(context)
val colorResourceID: Int = when (user.stats.habitClass) {
Stats.HEALER -> {
R.color.class_healer
}
Stats.WARRIOR -> {
R.color.class_warrior
}
Stats.ROGUE -> {
R.color.class_rogue
}
Stats.MAGE -> {
R.color.class_wizard
}
else -> R.color.task_gray
}
ViewHelper.SetBackgroundTint(classBackground, ContextCompat.getColor(context, colorResourceID))
userName.text = user.profile.name
itemView.isClickable = true
itemView.setOnClickListener { userClickedEvents.onNext(user.id) }
}
}
}

View file

@ -1,151 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.events.DisplayFragmentEvent;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.ui.fragments.social.GuildFragment;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.realm.Case;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
public class PublicGuildsRecyclerViewAdapter extends RealmRecyclerViewAdapter<Group, PublicGuildsRecyclerViewAdapter.GuildViewHolder> implements Filterable {
public ApiClient apiClient;
private List<String> memberGuildIDs;
public PublicGuildsRecyclerViewAdapter(@Nullable OrderedRealmCollection<Group> data, boolean autoUpdate) {
super(data, autoUpdate);
}
public void setMemberGuildIDs(List<String> memberGuildIDs) {
this.memberGuildIDs = memberGuildIDs;
}
@Override
public GuildViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_public_guild, parent, false);
GuildViewHolder guildViewHolder = new GuildViewHolder(view);
guildViewHolder.itemView.setOnClickListener(v -> {
Group guild = (Group) v.getTag();
GuildFragment guildFragment = new GuildFragment();
guildFragment.setGuildId(guild.getId());
guildFragment.isMember = isInGroup(guild);
DisplayFragmentEvent event = new DisplayFragmentEvent();
event.fragment = guildFragment;
EventBus.getDefault().post(event);
});
guildViewHolder.joinLeaveButton.setOnClickListener(v -> {
Group guild = (Group) v.getTag();
boolean isMember = this.memberGuildIDs != null && this.memberGuildIDs.contains(guild.getId());
if (isMember) {
PublicGuildsRecyclerViewAdapter.this.apiClient.leaveGroup(guild.getId())
.subscribe(aVoid -> {
memberGuildIDs.remove(guild.getId());
if (getData() != null) {
int indexOfGroup = getData().indexOf(guild);
notifyItemChanged(indexOfGroup);
}
}, RxErrorHandler.handleEmptyError());
} else {
PublicGuildsRecyclerViewAdapter.this.apiClient.joinGroup(guild.getId())
.subscribe(group -> {
memberGuildIDs.add(group.getId());
if (getData() != null) {
int indexOfGroup = getData().indexOf(group);
notifyItemChanged(indexOfGroup);
}
}, RxErrorHandler.handleEmptyError());
}
});
return guildViewHolder;
}
@Override
public void onBindViewHolder(GuildViewHolder holder, int position) {
if (getData() != null && holder != null) {
Group guild = getData().get(position);
boolean isInGroup = isInGroup(guild);
holder.bind(guild, isInGroup);
holder.itemView.setTag(guild);
holder.joinLeaveButton.setTag(guild);
}
}
private boolean isInGroup(Group guild) {
return this.memberGuildIDs != null && this.memberGuildIDs.contains(guild.getId());
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
results.values = constraint;
return new FilterResults();
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (getData() != null && constraint.length() > 0) {
updateData(getData().where()
.contains("name", String.valueOf(constraint), Case.INSENSITIVE)
.findAll());
}
}
};
}
static class GuildViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.nameTextView)
TextView nameTextView;
@BindView(R.id.memberCountTextView)
TextView memberCountTextView;
@BindView(R.id.descriptionTextView)
TextView descriptionTextView;
@BindView(R.id.joinleaveButton)
Button joinLeaveButton;
GuildViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(Group guild, boolean isInGroup) {
this.nameTextView.setText(guild.getName());
this.memberCountTextView.setText(String.valueOf(guild.getMemberCount()));
this.descriptionTextView.setText(guild.getDescription());
if (isInGroup) {
this.joinLeaveButton.setText(R.string.leave);
} else {
this.joinLeaveButton.setText(R.string.join);
}
}
}
}

View file

@ -0,0 +1,125 @@
package com.habitrpg.android.habitica.ui.adapter.social
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Filter
import android.widget.Filterable
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.events.DisplayFragmentEvent
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.models.social.Group
import com.habitrpg.android.habitica.ui.fragments.social.GuildFragment
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.functions.Consumer
import io.realm.Case
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import org.greenrobot.eventbus.EventBus
class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection<Group>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Group, PublicGuildsRecyclerViewAdapter.GuildViewHolder>(data, autoUpdate), Filterable {
var apiClient: ApiClient? = null
private var memberGuildIDs: MutableList<String> = mutableListOf()
fun setMemberGuildIDs(memberGuildIDs: MutableList<String>) {
this.memberGuildIDs = memberGuildIDs
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GuildViewHolder {
val guildViewHolder = GuildViewHolder(parent.inflate(R.layout.item_public_guild))
guildViewHolder.itemView.setOnClickListener { v ->
val guild = v.tag as Group
val guildFragment = GuildFragment()
guildFragment.setGuildId(guild.id)
guildFragment.isMember = isInGroup(guild)
val event = DisplayFragmentEvent()
event.fragment = guildFragment
EventBus.getDefault().post(event)
}
guildViewHolder.joinLeaveButton.setOnClickListener { v ->
val guild = v.tag as Group
val isMember = this.memberGuildIDs.contains(guild.id)
if (isMember) {
this@PublicGuildsRecyclerViewAdapter.apiClient!!.leaveGroup(guild.id)
.subscribe(Consumer {
memberGuildIDs.remove(guild.id)
if (data != null) {
val indexOfGroup = data!!.indexOf(guild)
notifyItemChanged(indexOfGroup)
}
}, RxErrorHandler.handleEmptyError())
} else {
this@PublicGuildsRecyclerViewAdapter.apiClient!!.joinGroup(guild.id)
.subscribe(Consumer { group ->
memberGuildIDs.add(group.id)
if (data != null) {
val indexOfGroup = data!!.indexOf(group)
notifyItemChanged(indexOfGroup)
}
}, RxErrorHandler.handleEmptyError())
}
}
return guildViewHolder
}
override fun onBindViewHolder(holder: GuildViewHolder, position: Int) {
data.notNull {
val guild = it[position]
val isInGroup = isInGroup(guild)
holder.bind(guild, isInGroup)
holder.itemView.tag = guild
holder.joinLeaveButton.tag = guild
}
}
private fun isInGroup(guild: Group): Boolean {
return this.memberGuildIDs.contains(guild.id)
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence): Filter.FilterResults {
val results = Filter.FilterResults()
results.values = constraint
return Filter.FilterResults()
}
override fun publishResults(constraint: CharSequence, results: Filter.FilterResults) {
data.notNull {
if (constraint.isNotEmpty()) {
updateData(it.where()
.contains("name", constraint.toString(), Case.INSENSITIVE)
.findAll())
}
}
}
}
}
class GuildViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val nameTextView: TextView by bindView(R.id.nameTextView)
private val memberCountTextView: TextView by bindView(R.id.memberCountTextView)
private val descriptionTextView: TextView by bindView(R.id.descriptionTextView)
internal val joinLeaveButton: Button by bindView(R.id.joinleaveButton)
fun bind(guild: Group, isInGroup: Boolean) {
this.nameTextView.text = guild.name
this.memberCountTextView.text = guild.memberCount.toString()
this.descriptionTextView.text = guild.description
if (isInGroup) {
this.joinLeaveButton.setText(R.string.leave)
} else {
this.joinLeaveButton.setText(R.string.join)
}
}
}
}

View file

@ -1,100 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social.challenges;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import com.github.underscore.U;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.social.Group;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ChallengesFilterRecyclerViewAdapter extends RecyclerView.Adapter<ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder> {
private List<Group> entries;
private List<ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder> holderList;
public ChallengesFilterRecyclerViewAdapter(Collection<Group> entries) {
this.entries = new ArrayList<>(entries);
this.holderList = new ArrayList<>();
}
@Override
public ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.dialog_challenge_filter_group_item, parent, false);
ChallengeViewHolder challengeViewHolder = new ChallengeViewHolder(view);
holderList.add(challengeViewHolder);
return challengeViewHolder;
}
@Override
public void onBindViewHolder(ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder holder, int position) {
holder.bind(entries.get(position));
}
@Override
public int getItemCount() {
return entries.size();
}
public void deSelectAll(){
for (ChallengeViewHolder h : holderList) {
h.checkbox.setChecked(false);
}
}
public void selectAll(){
for (ChallengeViewHolder h : holderList) {
h.checkbox.setChecked(true);
}
}
public void selectAll(List<Group> groupsToCheck){
for (ChallengeViewHolder h : holderList) {
h.checkbox.setChecked(U.find(groupsToCheck, g -> h.group.getId().equals(g.getId())).isPresent());
}
}
public List<Group> getCheckedEntries(){
ArrayList<Group> result = new ArrayList<>();
for (ChallengeViewHolder h : holderList) {
if(h.checkbox.isChecked()){
result.add(h.group);
}
}
return result;
}
public static class ChallengeViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.challenge_filter_group_checkbox)
CheckBox checkbox;
public Group group;
public ChallengeViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(Group group) {
this.group = group;
checkbox.setText(group.getName());
}
}
}

View file

@ -0,0 +1,86 @@
package com.habitrpg.android.habitica.ui.adapter.social.challenges
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import com.github.underscore.U
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.helpers.bindView
import java.util.*
class ChallengesFilterRecyclerViewAdapter(entries: Collection<Group>) : RecyclerView.Adapter<ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder>() {
private val entries: List<Group>
private val holderList: MutableList<ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder>
val checkedEntries: List<Group>
get() {
val result = ArrayList<Group>()
for (h in holderList) {
if (h.checkbox.isChecked) {
h.group.notNull {
result.add(it)
}
}
}
return result
}
init {
this.entries = ArrayList(entries)
this.holderList = ArrayList()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.dialog_challenge_filter_group_item, parent, false)
val challengeViewHolder = ChallengeViewHolder(view)
holderList.add(challengeViewHolder)
return challengeViewHolder
}
override fun onBindViewHolder(holder: ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder, position: Int) {
holder.bind(entries[position])
}
override fun getItemCount(): Int {
return entries.size
}
fun deSelectAll() {
for (h in holderList) {
h.checkbox.isChecked = false
}
}
fun selectAll() {
for (h in holderList) {
h.checkbox.isChecked = true
}
}
fun selectAll(groupsToCheck: List<Group>) {
for (h in holderList) {
h.checkbox.isChecked = U.find(groupsToCheck) { g -> h.group?.id == g.id }.isPresent
}
}
class ChallengeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal val checkbox: CheckBox by bindView(itemView, R.id.challenge_filter_group_checkbox)
var group: Group? = null
fun bind(group: Group) {
this.group = group
checkbox.text = group.name
}
}
}

View file

@ -1,144 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.tasks;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.tasks.ChecklistItem;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperAdapter;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperViewHolder;
import net.pherth.android.emoji_library.EmojiEditText;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.ItemViewHolder>
implements ItemTouchHelperAdapter {
private final List<ChecklistItem> items = new ArrayList<>();
public CheckListAdapter() {
}
public void setItems(List<ChecklistItem> items) {
this.items.addAll(items);
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.checklist_item, parent, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
holder.textWatcher.id = null;
holder.checkListTextView.setText(items.get(position).getText());
holder.textWatcher.id = items.get(position).getId();
}
public void addItem(ChecklistItem item) {
items.add(item);
notifyItemInserted(items.size() - 1);
}
public List<ChecklistItem> getCheckListItems() {
return items;
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public void onItemDismiss(int position) {
if (position >= 0 && position < items.size()) {
items.remove(position);
notifyItemRemoved(position);
}
}
@Override
public void onItemMove(int fromPosition, int toPosition) {
ChecklistItem item = items.get(fromPosition);
items.remove(fromPosition);
items.add(toPosition, item);
notifyItemMoved(fromPosition, toPosition);
}
class ItemViewHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder, Button.OnClickListener {
ChecklistTextWatcher textWatcher;
@BindView(R.id.item_edittext)
EmojiEditText checkListTextView;
@BindView(R.id.delete_item_button)
Button deleteButton;
ItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
deleteButton.setOnClickListener(this);
textWatcher = new ChecklistTextWatcher();
checkListTextView.addTextChangedListener(textWatcher);
}
@Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
@Override
public void onClick(View v) {
if (v == deleteButton) {
CheckListAdapter.this.onItemDismiss(getAdapterPosition());
}
}
private class ChecklistTextWatcher implements TextWatcher {
public String id;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (id == null) {
return;
}
for (ChecklistItem item : items) {
if (id.equals(item.getId())) {
item.setText(checkListTextView.getText().toString());
break;
}
}
}
}
}
}

View file

@ -0,0 +1,114 @@
package com.habitrpg.android.habitica.ui.adapter.tasks
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperAdapter
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperViewHolder
import com.habitrpg.android.habitica.ui.helpers.bindView
import net.pherth.android.emoji_library.EmojiEditText
import java.util.*
class CheckListAdapter : RecyclerView.Adapter<CheckListAdapter.ItemViewHolder>(), ItemTouchHelperAdapter {
private val items = ArrayList<ChecklistItem>()
val checkListItems: List<ChecklistItem>
get() = items
fun setItems(items: List<ChecklistItem>) {
this.items.addAll(items)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.checklist_item, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.textWatcher.id = null
holder.checkListTextView.setText(items[position].text)
holder.textWatcher.id = items[position].id
}
fun addItem(item: ChecklistItem) {
items.add(item)
notifyItemInserted(items.size - 1)
}
override fun getItemCount(): Int {
return items.size
}
override fun onItemDismiss(position: Int) {
if (position >= 0 && position < items.size) {
items.removeAt(position)
notifyItemRemoved(position)
}
}
override fun onItemMove(fromPosition: Int, toPosition: Int) {
val item = items[fromPosition]
items.removeAt(fromPosition)
items.add(toPosition, item)
notifyItemMoved(fromPosition, toPosition)
}
inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), ItemTouchHelperViewHolder, View.OnClickListener {
internal val textWatcher: ChecklistTextWatcher = ChecklistTextWatcher()
internal val checkListTextView: EmojiEditText by bindView(itemView, R.id.item_edittext)
private val deleteButton: Button by bindView(itemView, R.id.delete_item_button)
init {
deleteButton.setOnClickListener(this)
checkListTextView.addTextChangedListener(textWatcher)
}
override fun onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY)
}
override fun onItemClear() {
itemView.setBackgroundColor(0)
}
override fun onClick(v: View) {
if (v === deleteButton) {
this@CheckListAdapter.onItemDismiss(adapterPosition)
}
}
internal inner class ChecklistTextWatcher : TextWatcher {
var id: String? = null
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
if (id == null) {
return
}
for (item in items) {
if (id == item.id) {
item.text = checkListTextView.text.toString()
break
}
}
}
}
}
}

View file

@ -1,142 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.tasks;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.helpers.RemindersManager;
import com.habitrpg.android.habitica.models.tasks.RemindersItem;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperAdapter;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperViewHolder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by keithholliday on 5/31/16.
*/
public class RemindersAdapter extends RecyclerView.Adapter<RemindersAdapter.ItemViewHolder>
implements ItemTouchHelperAdapter, RemindersManager.ReminderTimeSelectedCallback {
private final List<RemindersItem> reminders = new ArrayList<>();
private final String taskType;
private RemindersManager remindersManager;
public RemindersAdapter(String taskType) {
this.remindersManager = new RemindersManager(taskType);
this.taskType = taskType;
}
public void setReminders(List<RemindersItem> reminders) {
this.reminders.addAll(reminders);
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.reminder_item, parent, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
Date time = reminders.get(position).getTime();
holder.reminderItemTextView.setText(remindersManager.reminderTimeToString(time));
holder.hour = time.getHours();
holder.minute = time.getMinutes();
}
public void addItem(RemindersItem item) {
reminders.add(item);
notifyItemInserted(reminders.size() - 1);
}
public List<RemindersItem> getRemindersItems() {
return reminders;
}
@Override
public int getItemCount() {
return reminders.size();
}
@Override
public void onItemDismiss(int position) {
if (position >= 0 && position < reminders.size()) {
reminders.remove(position);
notifyItemRemoved(position);
}
}
@Override
public void onItemMove(int fromPosition, int toPosition) {
Collections.swap(reminders, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onReminderTimeSelected(@Nullable RemindersItem remindersItem) {
if (remindersItem == null) {
return;
}
for (int pos = 0; pos < reminders.size(); pos++) {
if (remindersItem.getId().equals(reminders.get(pos).getId())) {
reminders.set(pos, remindersItem);
notifyItemChanged(pos);
break;
}
}
}
class ItemViewHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder, Button.OnClickListener {
@BindView(R.id.item_edittext)
EditText reminderItemTextView;
@BindView(R.id.delete_item_button)
Button deleteButton;
int hour, minute;
ItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
deleteButton.setOnClickListener(this);
reminderItemTextView.setOnClickListener(v -> {
RemindersItem reminder = reminders.get(getAdapterPosition());
remindersManager.createReminderTimeDialog(RemindersAdapter.this, taskType, v.getContext(), reminder);
});
}
@Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
@Override
public void onClick(View v) {
if (v == deleteButton) {
RemindersAdapter.this.onItemDismiss(getAdapterPosition());
}
}
}
}

View file

@ -0,0 +1,112 @@
package com.habitrpg.android.habitica.ui.adapter.tasks
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.helpers.RemindersManager
import com.habitrpg.android.habitica.models.tasks.RemindersItem
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperAdapter
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperViewHolder
import com.habitrpg.android.habitica.ui.helpers.bindView
import java.util.*
/**
* Created by keithholliday on 5/31/16.
*/
class RemindersAdapter(private val taskType: String) : RecyclerView.Adapter<RemindersAdapter.ItemViewHolder>(), ItemTouchHelperAdapter, RemindersManager.ReminderTimeSelectedCallback {
private val reminders = ArrayList<RemindersItem>()
private val remindersManager: RemindersManager = RemindersManager(taskType)
val remindersItems: List<RemindersItem>
get() = reminders
fun setReminders(reminders: List<RemindersItem>) {
this.reminders.addAll(reminders)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.reminder_item, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val time = reminders[position].time
holder.reminderItemTextView.setText(remindersManager.reminderTimeToString(time))
holder.hour = time.hours
holder.minute = time.minutes
}
fun addItem(item: RemindersItem) {
reminders.add(item)
notifyItemInserted(reminders.size - 1)
}
override fun getItemCount(): Int {
return reminders.size
}
override fun onItemDismiss(position: Int) {
if (position >= 0 && position < reminders.size) {
reminders.removeAt(position)
notifyItemRemoved(position)
}
}
override fun onItemMove(fromPosition: Int, toPosition: Int) {
Collections.swap(reminders, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
}
override fun onReminderTimeSelected(remindersItem: RemindersItem?) {
if (remindersItem == null) {
return
}
for (pos in reminders.indices) {
if (remindersItem.id == reminders[pos].id) {
reminders[pos] = remindersItem
notifyItemChanged(pos)
break
}
}
}
inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), ItemTouchHelperViewHolder, View.OnClickListener {
internal val reminderItemTextView: EditText by bindView(itemView, R.id.item_edittext)
private val deleteButton: Button by bindView(itemView, R.id.delete_item_button)
var hour: Int = 0
var minute: Int = 0
init {
deleteButton.setOnClickListener(this)
reminderItemTextView.setOnClickListener { v ->
val reminder = reminders[adapterPosition]
remindersManager.createReminderTimeDialog(this@RemindersAdapter, taskType, v.context, reminder)
}
}
override fun onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY)
}
override fun onItemClear() {
itemView.setBackgroundColor(0)
}
override fun onClick(v: View) {
if (v === deleteButton) {
this@RemindersAdapter.onItemDismiss(adapterPosition)
}
}
}
}

View file

@ -73,7 +73,7 @@ public class GemsPurchaseFragment extends BaseFragment implements GemPurchaseAct
Drawable heartDrawable = new BitmapDrawable(getResources(), HabiticaIconsHelper.imageOfHeartLarge());
supportTextView.setCompoundDrawables(null, heartDrawable, null, null);
gems84View.seedsImageButton.setOnClickListener(v -> ((GemPurchaseActivity) this.getActivity()).showSeedsPromo(getString(R.string.seeds_interstitial_gems), "store"));
gems84View.getSeedsImageButton().setOnClickListener(v -> ((GemPurchaseActivity) this.getActivity()).showSeedsPromo(getString(R.string.seeds_interstitial_gems), "store"));
}
@Override

View file

@ -40,7 +40,7 @@ class FAQOverviewFragment : BaseMainFragment() {
resetViews()
adapter = FAQOverviewRecyclerAdapter()
adapter?.resetWalkthroughEvents?.subscribe(Consumer { this.userRepository.resetTutorial(user) }, RxErrorHandler.handleEmptyError())
adapter?.getResetWalkthroughEvents()?.subscribe(Consumer { this.userRepository.resetTutorial(user) }, RxErrorHandler.handleEmptyError())
adapter?.activity = activity
recyclerView?.layoutManager = LinearLayoutManager(activity)
recyclerView?.addItemDecoration(DividerItemDecoration(getActivity()!!, DividerItemDecoration.VERTICAL))

View file

@ -99,11 +99,11 @@ class ItemRecyclerFragment : BaseFragment() {
recyclerView?.adapter = adapter
adapter?.notNull {
compositeSubscription.add(it.sellItemEvents
compositeSubscription.add(it.getSellItemFlowable()
.flatMap { item -> inventoryRepository.sellItem(user, item) }
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.questInvitationEvents
compositeSubscription.add(it.getQuestInvitationFlowable()
.flatMap { quest -> inventoryRepository.inviteToQuest(quest) }
.subscribe(Consumer { EventBus.getDefault().post(OpenMenuItemCommand(NavigationDrawerFragment.SIDEBAR_PARTY)) }, RxErrorHandler.handleEmptyError()))
}

View file

@ -48,13 +48,12 @@ public class MountDetailRecyclerFragment extends BaseMainFragment {
adapter = (MountDetailRecyclerAdapter) recyclerView.getAdapter();
if (adapter == null) {
adapter = new MountDetailRecyclerAdapter(null, true);
adapter.context = this.getActivity();
adapter.itemType = this.animalType;
adapter.setItemType(this.animalType);
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
this.loadItems();
getCompositeSubscription().add(adapter.getEquipEvents()
getCompositeSubscription().add(adapter.getEquipFlowable()
.flatMap(key -> inventoryRepository.equip(user, "mount", key))
.subscribe(items -> {}, RxErrorHandler.handleEmptyError()));
}

View file

@ -67,7 +67,7 @@ class PetDetailRecyclerFragment : BaseMainFragment() {
recyclerView.itemAnimator = SafeDefaultItemAnimator()
this.loadItems()
compositeSubscription.add(adapter.equipEvents
compositeSubscription.add(adapter.getEquipFlowable()
.flatMap<Items> { key -> inventoryRepository.equip(user, "pet", key) }
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))

View file

@ -86,7 +86,7 @@ class StableRecyclerFragment : BaseFragment() {
}
adapter = recyclerView?.adapter as StableRecyclerAdapter
adapter = recyclerView?.adapter as StableRecyclerAdapter?
if (adapter == null) {
adapter = StableRecyclerAdapter()
adapter?.activity = this.activity as MainActivity?

View file

@ -118,7 +118,7 @@ class AvatarSetupFragment : BaseFragment() {
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (isVisibleToUser && context != null) {
speechBubbleView?.animateText(context?.getString(R.string.avatar_setup_description))
speechBubbleView?.animateText(context?.getString(R.string.avatar_setup_description) ?: "")
}
}

View file

@ -61,7 +61,7 @@ class TaskSetupFragment : BaseFragment() {
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (isVisibleToUser && context != null) {
speechBubbleView?.animateText(context?.getString(R.string.task_setup_description))
speechBubbleView?.animateText(context?.getString(R.string.task_setup_description) ?: "")
}
}

View file

@ -34,7 +34,7 @@ class WelcomeFragment : BaseFragment() {
resetViews()
speechBubbleView?.animateText(context?.getString(R.string.welcome_text))
speechBubbleView?.animateText(context?.getString(R.string.welcome_text) ?: "")
heartIconView?.setImageBitmap(HabiticaIconsHelper.imageOfHeartLightBg())
expIconView?.setImageBitmap(HabiticaIconsHelper.imageOfExperience())

View file

@ -72,7 +72,7 @@ class SkillsFragment : BaseMainFragment() {
return
}
adapter?.mana = this.user?.stats?.getMp()
adapter?.mana = this.user?.stats?.getMp() ?: 0.toDouble()
user?.let {
Observable.concat(userRepository.getSkills(it).firstElement().toObservable().flatMap { Observable.fromIterable(it) }, userRepository.getSpecialItems(it).firstElement().toObservable().flatMap { Observable.fromIterable(it) })
@ -108,7 +108,7 @@ class SkillsFragment : BaseMainFragment() {
private fun displaySkillResult(usedSkill: Skill?, response: SkillResponse) {
removeProgressDialog()
adapter?.setMana(response.user.stats.mp)
adapter?.mana = response.user.stats.mp
val activity = activity ?: return
if ("special" == usedSkill?.habitClass) {
showSnackbar(activity.getFloatingMenuWrapper(), context!!.getString(R.string.used_skill_without_mana, usedSkill.text), HabiticaSnackbar.SnackbarDisplayType.BLUE)

View file

@ -105,12 +105,12 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
chatAdapter = ChatRecyclerViewAdapter(null, true, user, true)
chatAdapter.notNull {
compositeSubscription.add(it.userLabelClickEvents.subscribe(Consumer { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.deleteMessageEvents.subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.flagMessageEvents.subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.copyMessageAsTodoEvents.subscribe(Consumer{ this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.copyMessageEvents.subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.likeMessageEvents.flatMap<ChatMessage> { socialRepository.likeMessage(it) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer{ this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageFlowable().subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getLikeMessageFlowable().flatMap<ChatMessage> { socialRepository.likeMessage(it) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}

View file

@ -61,11 +61,11 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres
recyclerView.adapter = chatAdapter
recyclerView.itemAnimator = SafeDefaultItemAnimator()
chatAdapter.notNull {
compositeSubscription.add(it.userLabelClickEvents.subscribe(Consumer<String> { FullProfileActivity.open(context, it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.deleteMessageEvents.subscribe(Consumer<ChatMessage> { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.flagMessageEvents.subscribe(Consumer<ChatMessage> { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.copyMessageAsTodoEvents.subscribe(Consumer<ChatMessage> { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.copyMessageEvents.subscribe(Consumer<ChatMessage> { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer<String> { FullProfileActivity.open(context, it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer<ChatMessage> { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer<ChatMessage> { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer<ChatMessage> { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageFlowable().subscribe(Consumer<ChatMessage> { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
}

View file

@ -48,7 +48,7 @@ class PublicGuildsFragment : BaseMainFragment(), SearchView.OnQueryTextListener
recyclerView?.layoutManager = LinearLayoutManager(this.activity)
recyclerView?.addItemDecoration(DividerItemDecoration(getActivity()!!, DividerItemDecoration.VERTICAL))
viewAdapter.setMemberGuildIDs(this.memberGuildIDs)
viewAdapter.setMemberGuildIDs(this.memberGuildIDs?.toMutableList() ?: mutableListOf<String>())
viewAdapter.apiClient = this.apiClient
viewAdapter = PublicGuildsRecyclerViewAdapter(null, true)
recyclerView?.adapter = viewAdapter

View file

@ -53,11 +53,10 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
}
private fun fillChallengeGroups() {
this.groupRecyclerView?.layoutManager = LinearLayoutManager(context)
adapter = ChallengesFilterRecyclerViewAdapter(getGroups(challengesViewed))
if (currentFilter != null && currentFilter?.showByGroups != null) {
adapter?.selectAll(currentFilter?.showByGroups)
adapter?.selectAll(currentFilter?.showByGroups ?: emptyList())
}
this.groupRecyclerView?.adapter = adapter

View file

@ -8,7 +8,6 @@ import android.support.v7.widget.LinearLayoutManager
import android.view.*
import android.widget.RelativeLayout
import android.widget.TextView
import butterknife.ButterKnife
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.ChallengeRepository
@ -153,7 +152,7 @@ class ChallengeListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshLi
private fun changeFilter(challengeFilterOptions: ChallengeFilterOptions) {
filterOptions = challengeFilterOptions
challengeAdapter?.filter(filterOptions)
challengeAdapter?.filter(challengeFilterOptions)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {

View file

@ -1,176 +0,0 @@
package com.habitrpg.android.habitica.ui.views.yesterdailies;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.data.TaskRepository;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.tasks.ChecklistItem;
import com.habitrpg.android.habitica.models.tasks.Task;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import butterknife.BindColor;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
public class YesterdailyDialog extends AlertDialog {
static boolean isDisplaying = false;
private final List<Task> tasks;
private final TaskRepository taskRepository;
private UserRepository userRepository;
@BindView(R.id.yesterdailies_list)
LinearLayout yesterdailiesList;
@BindColor(R.color.task_gray)
int taskGray;
private YesterdailyDialog(@NonNull Context context, UserRepository userRepository, TaskRepository taskRepository, List<Task> tasks) {
super(context);
this.userRepository = userRepository;
this.taskRepository = taskRepository;
this.tasks = tasks;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.dialog_yesterdaily, null);
ButterKnife.bind(this, view);
this.setView(view);
this.setButton(AlertDialog.BUTTON_POSITIVE,
context.getString(R.string.start_day),
(dialog, which) -> {});
this.setOnDismissListener(dialog -> runCron());
createTaskViews(inflater);
}
private void runCron() {
List<Task> completedTasks = new ArrayList<>();
for (Task task : tasks) {
if (task.getCompleted()) {
completedTasks.add(task);
}
}
userRepository.runCron(completedTasks);
isDisplaying = false;
}
private void createTaskViews(LayoutInflater inflater) {
for (Task task : tasks) {
View taskView = createNewTaskView(inflater);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
taskView.setClipToOutline(true);
}
configureTaskView(taskView, task);
View taskContainer = taskView.findViewById(R.id.taskHolder);
taskContainer.setOnClickListener(v -> {
task.setCompleted(!task.getCompleted());
configureTaskView(taskView, task);
});
if (task.getChecklist().size() > 0) {
View checklistDivider = taskView.findViewById(R.id.checklistDivider);
checklistDivider.setVisibility(View.VISIBLE);
ViewGroup checklistContainer = taskView.findViewById(R.id.checklistView);
for (ChecklistItem item : task.getChecklist()) {
View checklistView = inflater.inflate(R.layout.checklist_item_row, yesterdailiesList, false);
configureChecklistView(checklistView, item);
checklistView.setOnClickListener(v -> {
item.setCompleted(!item.getCompleted());
taskRepository.scoreChecklistItem(task.getId(), item.getId()).subscribe(task1 -> {}, RxErrorHandler.handleEmptyError());
configureChecklistView(checklistView, item);
});
checklistContainer.addView(checklistView);
}
}
CheckBox checkBox = (CheckBox) taskView.findViewById(R.id.checkBox);
checkBox.setEnabled(false);
checkBox.setClickable(false);
yesterdailiesList.addView(taskView);
}
}
private void configureChecklistView(View checklistView, ChecklistItem item) {
CheckBox checkbox = (CheckBox) checklistView.findViewById(R.id.checkBox);
checkbox.setChecked(item.getCompleted());
View checkboxHolder = checklistView.findViewById(R.id.checkBoxHolder);
checkboxHolder.setBackgroundResource(R.color.gray_700);
TextView textView = (TextView) checklistView.findViewById(R.id.checkedTextView);
textView.setText(item.getText());
}
private void configureTaskView(View taskView, Task task) {
boolean completed = !task.isDisplayedActive();
CheckBox checkbox = (CheckBox) taskView.findViewById(R.id.checkBox);
View checkboxHolder = taskView.findViewById(R.id.checkBoxHolder);
checkbox.setChecked(completed);
if (completed) {
checkboxHolder.setBackgroundColor(this.taskGray);
} else {
checkboxHolder.setBackgroundResource(task.getLightTaskColor());
}
TextView textView = (TextView) taskView.findViewById(R.id.text_view);
textView.setText(task.getText());
}
private View createNewTaskView(LayoutInflater inflater) {
return inflater.inflate(R.layout.dialog_yesterdaily_task, yesterdailiesList, false);
}
public static void showDialogIfNeeded(Activity activity, String userId, UserRepository userRepository, TaskRepository taskRepository) {
if (userRepository != null && userId != null) {
Observable.just("")
.delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.filter(aVoid -> !userRepository.isClosed())
.flatMapMaybe(aVoid -> userRepository.getUser(userId).firstElement())
.filter(user -> user != null && user != null && user.getNeedsCron())
.flatMapMaybe(user -> {
final Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
return taskRepository.updateDailiesIsDue(cal.getTime()).firstElement();
})
.flatMapMaybe(user -> taskRepository.getTasks(Task.TYPE_DAILY, userId).firstElement())
.map(tasks -> tasks.where().equalTo("isDue", true).equalTo("completed", false).equalTo("yesterDaily", true).findAll())
.flatMapMaybe( tasks -> taskRepository.getTaskCopies(tasks).firstElement())
.retry(1)
.subscribe(tasks -> {
if (isDisplaying) {
return;
}
if (tasks.size() > 0) {
showDialog(activity, userRepository, taskRepository, tasks);
} else {
userRepository.runCron();
}
}, RxErrorHandler.handleEmptyError());
}
}
private static void showDialog(Activity activity, UserRepository userRepository, TaskRepository taskRepository, List<Task> tasks) {
YesterdailyDialog dialog = new YesterdailyDialog(activity, userRepository, taskRepository, tasks);
if (!activity.isFinishing()) {
dialog.show();
isDisplaying = true;
}
}
}

View file

@ -0,0 +1,161 @@
package com.habitrpg.android.habitica.ui.views.yesterdailies
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.LinearLayout
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.helpers.bindColor
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import java.util.*
import java.util.concurrent.TimeUnit
class YesterdailyDialog private constructor(context: Context, private val userRepository: UserRepository, private val taskRepository: TaskRepository, private val tasks: List<Task>) : AlertDialog(context) {
private val yesterdailiesList: LinearLayout by bindView(R.id.yesterdailies_list)
private val taskGray: Int by bindColor(context, R.color.task_gray)
init {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = inflater.inflate(R.layout.dialog_yesterdaily, null)
this.setView(view)
this.setButton(AlertDialog.BUTTON_POSITIVE,
context.getString(R.string.start_day)
) { _, _ -> }
this.setOnDismissListener { runCron() }
createTaskViews(inflater)
}
private fun runCron() {
val completedTasks = ArrayList<Task>()
for (task in tasks) {
if (task.completed) {
completedTasks.add(task)
}
}
userRepository.runCron(completedTasks)
isDisplaying = false
}
private fun createTaskViews(inflater: LayoutInflater) {
for (task in tasks) {
val taskView = createNewTaskView(inflater)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
taskView.clipToOutline = true
}
configureTaskView(taskView, task)
val taskContainer = taskView.findViewById<View>(R.id.taskHolder)
taskContainer.setOnClickListener {
task.completed = !task.completed
configureTaskView(taskView, task)
}
if (task.checklist?.size ?: 0 > 0) {
val checklistDivider = taskView.findViewById<View>(R.id.checklistDivider)
checklistDivider.visibility = View.VISIBLE
val checklistContainer = taskView.findViewById<ViewGroup>(R.id.checklistView)
for (item in task.checklist ?: emptyList<ChecklistItem>()) {
val checklistView = inflater.inflate(R.layout.checklist_item_row, yesterdailiesList, false)
configureChecklistView(checklistView, item)
checklistView.setOnClickListener {
item.completed = !item.completed
taskRepository.scoreChecklistItem(task.id ?: "", item.id).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
configureChecklistView(checklistView, item)
}
checklistContainer.addView(checklistView)
}
}
val checkBox = taskView.findViewById<View>(R.id.checkBox) as CheckBox
checkBox.isEnabled = false
checkBox.isClickable = false
yesterdailiesList.addView(taskView)
}
}
private fun configureChecklistView(checklistView: View, item: ChecklistItem) {
val checkbox = checklistView.findViewById<View>(R.id.checkBox) as CheckBox
checkbox.isChecked = item.completed
val checkboxHolder = checklistView.findViewById<View>(R.id.checkBoxHolder)
checkboxHolder.setBackgroundResource(R.color.gray_700)
val textView = checklistView.findViewById<View>(R.id.checkedTextView) as TextView
textView.text = item.text
}
private fun configureTaskView(taskView: View, task: Task) {
val completed = !task.isDisplayedActive
val checkbox = taskView.findViewById<View>(R.id.checkBox) as CheckBox
val checkboxHolder = taskView.findViewById<View>(R.id.checkBoxHolder)
checkbox.isChecked = completed
if (completed) {
checkboxHolder.setBackgroundColor(this.taskGray)
} else {
checkboxHolder.setBackgroundResource(task.lightTaskColor)
}
val textView = taskView.findViewById<View>(R.id.text_view) as TextView
textView.text = task.text
}
private fun createNewTaskView(inflater: LayoutInflater): View {
return inflater.inflate(R.layout.dialog_yesterdaily_task, yesterdailiesList, false)
}
companion object {
internal var isDisplaying = false
fun showDialogIfNeeded(activity: Activity, userId: String?, userRepository: UserRepository?, taskRepository: TaskRepository) {
if (userRepository != null && userId != null) {
Observable.just("")
.delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.filter { !userRepository.isClosed }
.flatMapMaybe { userRepository.getUser(userId).firstElement() }
.filter { user -> user.needsCron }
.flatMapMaybe {
val cal = Calendar.getInstance()
cal.add(Calendar.DATE, -1)
taskRepository.updateDailiesIsDue(cal.time).firstElement()
}
.flatMapMaybe { taskRepository.getTasks(Task.TYPE_DAILY, userId).firstElement() }
.map { tasks -> tasks.where().equalTo("isDue", true).equalTo("completed", false).equalTo("yesterDaily", true).findAll() }
.flatMapMaybe<List<Task>> { tasks -> taskRepository.getTaskCopies(tasks).firstElement() }
.retry(1)
.subscribe(Consumer { tasks ->
if (isDisplaying) {
return@Consumer
}
if (tasks.isNotEmpty()) {
showDialog(activity, userRepository, taskRepository, tasks)
} else {
userRepository.runCron()
}
}, RxErrorHandler.handleEmptyError())
}
}
private fun showDialog(activity: Activity, userRepository: UserRepository, taskRepository: TaskRepository, tasks: List<Task>) {
val dialog = YesterdailyDialog(activity, userRepository, taskRepository, tasks)
if (!activity.isFinishing) {
dialog.show()
isDisplaying = true
}
}
}
}

View file

@ -69,23 +69,23 @@ public class YesterdailyDialogTests extends BaseTestCase {
@Test
public void showsDialogIfNeededAndTasks() throws Exception {
when(mockTasks.size()).thenReturn(1);
YesterdailyDialog.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
YesterdailyDialog.Companion.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
verifyNew(YesterdailyDialog.class).withArguments(any(Context.class), any(UserRepository.class), any(List.class));
}
@Test
public void doesntShowDialogIfAlreadyShown() throws Exception {
when(mockTasks.size()).thenReturn(1);
YesterdailyDialog.isDisplaying = true;
YesterdailyDialog.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
YesterdailyDialog.Companion.setIsDisplaying(true);
YesterdailyDialog.Companion.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
verifyNew(YesterdailyDialog.class, times(0)).withArguments(any(Context.class), any(UserRepository.class), any(List.class));
}
@Test
public void doesntShowDialogIfNoTasks() throws Exception {
when(mockTasks.size()).thenReturn(0);
YesterdailyDialog.isDisplaying = true;
YesterdailyDialog.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
YesterdailyDialog.Companion.setIsDisplaying(true);
YesterdailyDialog.Companion.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
verifyNew(YesterdailyDialog.class, times(0)).withArguments(any(Context.class), any(UserRepository.class), any(List.class));
}
@ -93,8 +93,8 @@ public class YesterdailyDialogTests extends BaseTestCase {
public void doesntShowDialogIfNotNeeded() throws Exception {
testUser.setNeedsCron(false);
when(mockTasks.size()).thenReturn(1);
YesterdailyDialog.isDisplaying = true;
YesterdailyDialog.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
YesterdailyDialog.Companion.setIsDisplaying(true);
YesterdailyDialog.Companion.showDialogIfNeeded(mockContext, "", mockUserRepository, mockTaskRepository);
verifyNew(YesterdailyDialog.class, times(0)).withArguments(any(Context.class), any(UserRepository.class), any(List.class));
}