Merge pull request #1 from HabitRPG/develop

Update from original repo
This commit is contained in:
Jack Billings 2016-07-29 09:08:35 -04:00 committed by GitHub
commit 81ded07730
38 changed files with 1150 additions and 183 deletions

View file

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.habitrpg.android.habitica"
android:versionCode="104"
android:versionName="0.0.32"
android:versionCode="106"
android:versionName="0.0.33"
android:screenOrientation="portrait"
android:installLocation="auto" >

View file

@ -154,6 +154,7 @@ android {
}
dexOptions{
javaMaxHeapSize "4g"
preDexLibraries = false
}

View file

@ -1,24 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</DatePicker>
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</DatePicker>
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</TimePicker>
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</TimePicker>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Confirm"
android:id="@+id/customDialogConfirmButton"
/>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/confirm"
android:id="@+id/customDialogConfirmButton"
/>
</LinearLayout>
</ScrollView>

View file

@ -9,7 +9,9 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="bottom"
android:textAppearance="?android:attr/textAppearanceMedium"/>
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginLeft="@dimen/section_leftright_padding"
android:layout_marginRight="@dimen/section_leftright_padding"/>
<Button
android:layout_width="wrap_content"

View file

@ -4,7 +4,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical">
android:orientation="vertical"
android:foreground="?selectableItemBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -4,7 +4,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="horizontal">
android:orientation="horizontal"
android:foreground="?selectableItemBackground">
<LinearLayout
android:layout_width="80dp"
android:layout_height="match_parent"

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/RowWrapper"
android:clickable="true"
android:background="@android:color/white">
<ImageView
android:id="@+id/imageView"
android:layout_width="@dimen/gear_image_size"
android:layout_height="@dimen/gear_image_size"
android:scaleType="fitEnd"
android:layout_marginRight="@dimen/row_padding"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/titleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Title"
style="@style/RowTitle" />
<TextView
android:id="@+id/descriptionView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Description"
android:maxLines="5"
style="@style/RowText" />
</LinearLayout>
<Button
android:id="@+id/buyButton"
android:layout_width="60dp"
android:layout_height="45dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:textColor="@color/white"
android:layout_gravity="center_vertical"
android:textSize="15sp"
android:drawableLeft="@drawable/ic_header_gold"
android:drawableStart="@drawable/ic_header_gold"
android:background="@drawable/rounded_purple_square"
android:paddingLeft="6dp"
android:paddingStart="6dp" />
</LinearLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/section_leftright_padding">
<ImageView
android:id="@+id/imageView"
android:layout_width="@dimen/shop_width"
android:layout_height="@dimen/shop_height"
android:linksClickable="true"
android:autoLink="web" />
<TextView
android:id="@+id/descriptionView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/section_leftright_padding"
android:layout_marginStart="@dimen/section_leftright_padding"/>
</LinearLayout>

View file

@ -4,7 +4,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/white">
android:background="@color/white"
android:foreground="?selectableItemBackground">
<LinearLayout
android:id="@+id/card_view"
android:layout_width="match_parent"

View file

@ -3,6 +3,7 @@
<string name="sidebar.tasks">任務</string>
<string name="sidebar.skills">技能</string>
<string name="sidebar.section.social">社交</string>
<string name="sidebar.inbox">收信匣</string>
<string name="sidebar.tavern">酒館</string>
<string name="sidebar.party">隊伍</string>
<string name="sidebar.purchaseGems">購買寶石</string>

View file

@ -70,6 +70,7 @@
<string name="positive_habit_form">正面的(+)</string>
<string name="negative_habit_form">負面的(-)</string>
<string name="checklist">檢核表</string>
<string name="reminders">提醒</string>
<string name="actions">動作</string>
<string name="attributes">屬性</string>
<string name="physical">物理的</string>
@ -93,6 +94,7 @@
<string name="faint_subtitle">別失望!</string>
<string name="faint_penalty_body">你降了一級,丟失了所有的金幣和一件裝備。不過繼續努力,你還可以把他們都拿回來的!加油!你做的很棒!</string>
<string name="faint_header">你沒有生命值了!</string>
<string name="faint_button">補全生命值 &amp; 请重試</string>
<string name="filter">過濾器</string>
<string name="profile_image">頭像</string>
<string name="mana_price_button" formatted="false">%d MP</string>
@ -303,6 +305,7 @@
<string name="dialog_go_back">返回</string>
<string name="opt_out_confirmation">你確定要退出嗎?</string>
<string name="change_class">更換你的職業</string>
<string name="change_class_description">變更職業並重新分配屬性點這會花費3寶石。你可以在網頁版上分配屬性點。</string>
<string name="enable_class">開啟職業系統</string>
<string name="changing_class_progress">更換職業</string>
<string name="by_email">通過電子郵件</string>
@ -319,4 +322,5 @@
<string name="share_levelup" formatted="false">我在Habitica中通過改善我現實生活中的習慣到達了%s級</string>
<string name="share_hatched" formatted="false">我剛剛在Habitica中通完成我現實生活中的任務孵化了一隻寵物%1$s %2$s</string>
<string name="share_raised" formatted="false">我剛剛在Habitica中通完成我現實生活中的任務得到了一匹坐騎%1$s %2$s</string>
<string name="change_class_confirmation">你確定要變更職業嗎這會花費3寶石。</string>
</resources>

View file

@ -70,4 +70,6 @@
<dimen name="bottom_menu_padding">18dp</dimen>
<dimen name="pet_image_width">81dp</dimen>
<dimen name="pet_image_height">99dp</dimen>
<dimen name="shop_width">162dp</dimen>
<dimen name="shop_height">138dp</dimen>
</resources>

View file

@ -16,4 +16,5 @@
<string name="sidebar.news">News</string>
<string name="sidebar.settings">Settings</string>
<string name="sidebar.about">About</string>
<string name="sidebar_shops">Shops</string>
</resources>

View file

@ -347,4 +347,9 @@ To start, which parts of your life do you want to improve?</string>
<string name="open_in_store">Open in play store</string>
<string name="change_class_confirmation">Are you sure you want to change your class? This will cost 3 gems.</string>
<string name="leaderMessage" formatted="false">Message from %1$s</string>
<string name="confirm">Confirm</string>
<string name="market">Market</string>
<string name="timeTravelers">Time Travelers</string>
<string name="seasonalShop">Seasonal Shop</string>
<string name="empty_inbox">You don\'t have any Inbox messages. You can send a user a new message from their public chat messages!</string>
</resources>

View file

@ -25,6 +25,8 @@ import com.habitrpg.android.habitica.ui.fragments.inventory.equipment.EquipmentD
import com.habitrpg.android.habitica.ui.fragments.inventory.equipment.EquipmentOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemsFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.shops.ShopFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.shops.ShopsFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.stable.MountDetailRecyclerFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.stable.PetDetailRecyclerFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.stable.StableFragment;
@ -150,4 +152,8 @@ public interface AppComponent {
void inject(InboxFragment inboxFragment);
void inject(InboxMessageListFragment inboxMessageListFragment);
void inject(ShopsFragment shopsFragment);
void inject(ShopFragment shopFragment);
}

View file

@ -0,0 +1,9 @@
package com.habitrpg.android.habitica.events.commands;
import com.magicmicky.habitrpgwrapper.lib.models.ShopItem;
public class BuyGemItemCommand {
public String shopIdentifier;
public ShopItem item;
}

View file

@ -0,0 +1,121 @@
package com.habitrpg.android.habitica.ui;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ItemDetailDialog extends AlertDialog {
private final ImageView itemImageView;
private final TextView contentTextView;
private final TextView priceTextView;
private final ImageView currencyImageView;
public ItemDetailDialog(@NonNull Context context) {
super(context);
// External ContentView
LinearLayout contentViewLayout = new LinearLayout(context);
contentViewLayout.setOrientation(LinearLayout.VERTICAL);
// Gear Image
itemImageView = new ImageView(context);
LinearLayout.LayoutParams gearImageLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
gearImageLayoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
gearImageLayoutParams.setMargins(0, 0, 0, 20);
itemImageView.setMinimumWidth(200);
itemImageView.setMinimumHeight(200);
itemImageView.setLayoutParams(gearImageLayoutParams);
itemImageView.setVisibility(View.GONE);
// Gear Description
contentTextView = new TextView(context, null);
contentTextView.setPadding(16, 0, 16, 0);
contentTextView.setVisibility(View.GONE);
// GoldPrice View
LinearLayout goldPriceLayout = new LinearLayout(context);
goldPriceLayout.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams goldPriceLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
goldPriceLayoutParams.setMargins(0, 0, 0, 16);
goldPriceLayoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
goldPriceLayout.setOrientation(LinearLayout.HORIZONTAL);
goldPriceLayout.setLayoutParams(goldPriceLayoutParams);
goldPriceLayout.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
// Price View
priceTextView = new TextView(context);
priceTextView.setPadding(10, 0, 0, 0);
currencyImageView = new ImageView(context);
currencyImageView.setMinimumHeight(50);
currencyImageView.setMinimumWidth(50);
currencyImageView.setPadding(0, 0, 5, 0);
goldPriceLayout.addView(currencyImageView);
goldPriceLayout.addView(priceTextView);
contentViewLayout.setGravity(Gravity.CENTER_VERTICAL);
contentViewLayout.addView(itemImageView);
contentViewLayout.addView(goldPriceLayout);
contentViewLayout.addView(contentTextView);
setView(contentViewLayout);
this.setButton(AlertDialog.BUTTON_NEGATIVE, context.getText(R.string.reward_dialog_dismiss), (clickedDialog, which) -> {
clickedDialog.dismiss();
});
}
public void setDescription(String description) {
contentTextView.setText(description);
contentTextView.setVisibility(View.VISIBLE);
}
public void setCurrency(String currency) {
switch (currency) {
case "gold":
currencyImageView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_header_gold));
break;
case "gems":
currencyImageView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_header_gem));
break;
}
}
public void setValue(Double value) {
priceTextView.setText(value.toString());
}
public void setValue(Integer value) {
priceTextView.setText(value.toString());
}
public void setImage(String imageName) {
itemImageView.setVisibility(View.VISIBLE);
DataBindingUtils.loadImage(itemImageView, imageName);
}
public void setBuyListener(OnClickListener listener) {
this.setButton(BUTTON_POSITIVE, getContext().getText(R.string.reward_dialog_buy), listener);
}
}

View file

@ -21,6 +21,7 @@ import com.habitrpg.android.habitica.events.SelectClassEvent;
import com.habitrpg.android.habitica.events.ShareEvent;
import com.habitrpg.android.habitica.events.TaskRemovedEvent;
import com.habitrpg.android.habitica.events.ToggledInnStateEvent;
import com.habitrpg.android.habitica.events.commands.BuyGemItemCommand;
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand;
import com.habitrpg.android.habitica.events.commands.DeleteTaskCommand;
import com.habitrpg.android.habitica.events.commands.EquipCommand;
@ -42,6 +43,7 @@ import com.habitrpg.android.habitica.ui.menu.MainDrawerBuilder;
import com.habitrpg.android.habitica.userpicture.BitmapUtils;
import com.magicmicky.habitrpgwrapper.lib.api.MaintenanceApiService;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.Shop;
import com.magicmicky.habitrpgwrapper.lib.models.Stats;
import com.magicmicky.habitrpgwrapper.lib.models.SuppressedModals;
import com.magicmicky.habitrpgwrapper.lib.models.Tag;
@ -65,11 +67,9 @@ import com.mikepenz.materialdrawer.AccountHeader;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.holder.BadgeStyle;
import com.mikepenz.materialdrawer.holder.StringHolder;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
import com.mikepenz.materialdrawer.model.utils.BadgeDrawableBuilder;
import com.raizlabs.android.dbflow.runtime.TransactionManager;
import com.raizlabs.android.dbflow.runtime.transaction.BaseTransaction;
import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener;
@ -138,6 +138,7 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import butterknife.BindView;
import rx.Observable;
import rx.functions.Action1;
import static com.habitrpg.android.habitica.ui.helpers.UiUtils.SnackbarDisplayType;
@ -474,7 +475,7 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
.withBadgeStyle(badgeStyle);
}
this.drawer.updateItemAtPosition(newInboxItem, MainDrawerBuilder.SIDEBAR_INBOX + 2);
this.drawer.updateItemAtPosition(newInboxItem, this.drawer.getPosition(MainDrawerBuilder.SIDEBAR_INBOX));
}
@ -865,6 +866,27 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
drawer.setSelection(event.identifier);
}
@Subscribe
public void onEvent(final BuyGemItemCommand event) {
Observable<Void> observable;
if (event.shopIdentifier.equals(Shop.TIME_TRAVELERS_SHOP)) {
if (event.item.purchaseType.equals("gear")) {
observable = apiHelper.apiService.purchaseMysterySet(event.item.categoryIdentifier);
} else {
observable = apiHelper.apiService.purchaseHourglassItem(event.item.purchaseType, event.item.key);
}
} else {
observable = apiHelper.apiService.purchaseItem(event.item.purchaseType, event.item.key);
}
observable
.compose(apiHelper.configureApiCallObserver())
.subscribe(buyResponse -> {
apiHelper.retrieveUser(false)
.compose(apiHelper.configureApiCallObserver())
.subscribe(new HabitRPGUserCallback(this), throwable -> {});
}, throwable -> {});
}
@Subscribe
public void onEvent(final BuyRewardCommand event) {
final String rewardKey = event.Reward.getId();

View file

@ -489,13 +489,15 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem
@OnClick(R.id.add_reminder_button)
public void addReminder() {
RemindersItem item = remindersManager.createReminderFromDateString(newRemindersEditText.getText().toString());
if (item == null) {
return;
if (newRemindersEditText.getText().length() > 0) {
RemindersItem item = remindersManager.createReminderFromDateString(newRemindersEditText.getText().toString());
if (item == null) {
return;
}
item.setType(taskType);
remindersAdapter.addItem(item);
newRemindersEditText.setText("");
}
item.setType(taskType);
remindersAdapter.addItem(item);
newRemindersEditText.setText("");
}
@OnClick(R.id.new_reminder_edittext)

View file

@ -0,0 +1,189 @@
package com.habitrpg.android.habitica.ui.adapter.inventory;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.commands.BuyGemItemCommand;
import com.habitrpg.android.habitica.ui.ItemDetailDialog;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder;
import com.magicmicky.habitrpgwrapper.lib.models.Shop;
import com.magicmicky.habitrpgwrapper.lib.models.ShopCategory;
import com.magicmicky.habitrpgwrapper.lib.models.ShopItem;
import org.greenrobot.eventbus.EventBus;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ShopRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> items;
private String shopIdentifier;
public void setShop(Shop shop) {
shopIdentifier = shop.identifier;
items = new ArrayList<>();
items.add(shop);
for (ShopCategory category : shop.categories) {
if (category.items != null && category.items.size() > 0) {
items.add(category);
for (ShopItem item : category.items) {
item.categoryIdentifier = category.getIdentifier();
items.add(item);
}
}
}
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.shop_header, parent, false);
return new ShopHeaderViewHolder(view);
} else if (viewType == 1) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.customization_section_header, parent, false);
return new SectionViewHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_shopitem, parent, false);
ItemViewHolder viewHolder = new ItemViewHolder(view);
viewHolder.shopIdentifier = shopIdentifier;
return viewHolder;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Object obj = this.items.get(position);
if (obj.getClass().equals(Shop.class)) {
ShopHeaderViewHolder viewHolder = (ShopHeaderViewHolder) holder;
Shop shop = (Shop)obj;
DataBindingUtils.loadImage(viewHolder.imageView, shop.imageName);
viewHolder.descriptionView.setText(Html.fromHtml(shop.getNotes()));
} else if (obj.getClass().equals(ShopCategory.class)) {
((SectionViewHolder) holder).bind(((ShopCategory) obj).getText());
} else {
((ItemViewHolder) holder).bind((ShopItem) items.get(position));
}
}
@Override
public int getItemViewType(int position) {
if (this.items.get(position).getClass().equals(Shop.class)) {
return 0;
} else if (this.items.get(position).getClass().equals(ShopCategory.class)) {
return 1;
} else {
return 2;
}
}
@Override
public int getItemCount() {
return items != null ? items.size() : 0;
}
static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@BindView(R.id.imageView)
ImageView imageView;
@BindView(R.id.titleView)
TextView titleView;
@BindView(R.id.descriptionView)
TextView descriptionView;
@BindView(R.id.buyButton)
Button buyButton;
String shopIdentifier;
ShopItem item;
Context context;
public ItemViewHolder(View itemView) {
super(itemView);
context = itemView.getContext();
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
itemView.setClickable(true);
buyButton.setOnClickListener(view -> this.buyItem());
}
private void buyItem() {
BuyGemItemCommand command = new BuyGemItemCommand();
command.shopIdentifier = shopIdentifier;
command.item = item;
EventBus.getDefault().post(command);
}
public void bind(ShopItem item) {
this.item = item;
titleView.setText(item.getText());
descriptionView.setText(item.getNotes());
DataBindingUtils.loadImage(this.imageView, item.getImageName());
buyButton.setText(item.getValue().toString());
switch (item.getCurrency()) {
case "gold":
buyButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_header_gold, 0, 0, 0);
break;
case "gems":
buyButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_header_gem, 0, 0, 0);
break;
default:
buyButton.setVisibility(View.GONE);
}
}
@Override
public void onClick(View view) {
ItemDetailDialog dialog = new ItemDetailDialog(context);
dialog.setTitle(item.getText());
dialog.setDescription(item.getNotes());
dialog.setImage(item.getImageName());
dialog.setCurrency(item.getCurrency());
dialog.setValue(item.getValue());
dialog.setBuyListener((clickedDialog, which) -> this.buyItem());
dialog.show();
}
}
public static class ShopHeaderViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.imageView)
public ImageView imageView;
@BindView(R.id.descriptionView)
public TextView descriptionView;
public ShopHeaderViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
}

View file

@ -5,6 +5,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.fragments.inventory.stable.MountDetailRecyclerFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.stable.PetDetailRecyclerFragment;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder;
import com.magicmicky.habitrpgwrapper.lib.models.inventory.Animal;
import android.content.Context;
@ -138,31 +139,4 @@ public class StableRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.Vie
}
}
}
class SectionViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.label)
TextView label;
@BindView(R.id.purchaseSetButton)
Button purchaseSetButton;
Context context;
public SectionViewHolder(View itemView) {
super(itemView);
context = itemView.getContext();
ButterKnife.bind(this, itemView);
this.purchaseSetButton.setVisibility(View.GONE);
}
public void bind(String title) {
try {
Integer stringID = context.getResources().getIdentifier("section" + title, "string", context.getPackageName());
this.label.setText(context.getString(stringID));
} catch (Exception e) {
this.label.setText(title);
}
}
}
}

View file

@ -6,12 +6,14 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.DailyViewHolder;
import android.content.Context;
import android.view.ViewGroup;
public class DailiesRecyclerViewHolder extends BaseTasksRecyclerViewAdapter<DailyViewHolder> {
public class DailiesRecyclerViewHolder extends SortableTasksRecyclerViewAdapter<DailyViewHolder> {
public int dailyResetOffset;
public DailiesRecyclerViewHolder(String taskType, TagsHelper tagsHelper, int layoutResource, Context newContext, String userID, int dailyResetOffset) {
super(taskType, tagsHelper, layoutResource, newContext, userID);
public DailiesRecyclerViewHolder(String taskType, TagsHelper tagsHelper, int layoutResource,
Context newContext, String userID, int dailyResetOffset,
SortTasksCallback sortTasksCallback) {
super(taskType, tagsHelper, layoutResource, newContext, userID, sortTasksCallback);
this.dailyResetOffset = dailyResetOffset;
}

View file

@ -6,9 +6,11 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.HabitViewHolder;
import android.content.Context;
import android.view.ViewGroup;
public class HabitsRecyclerViewAdapter extends BaseTasksRecyclerViewAdapter<HabitViewHolder> {
public HabitsRecyclerViewAdapter(String taskType, TagsHelper tagsHelper, int layoutResource, Context newContext, String userID) {
super(taskType, tagsHelper, layoutResource, newContext, userID);
public class HabitsRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter<HabitViewHolder> {
public HabitsRecyclerViewAdapter(String taskType, TagsHelper tagsHelper, int layoutResource, Context newContext, String userID, SortTasksCallback sortCallback) {
super(taskType, tagsHelper, layoutResource, newContext, userID, sortCallback);
}
@Override

View file

@ -0,0 +1,48 @@
package com.habitrpg.android.habitica.ui.adapter.tasks;
import android.content.Context;
import com.habitrpg.android.habitica.helpers.TagsHelper;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperAdapter;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperDropCallback;
import com.habitrpg.android.habitica.ui.viewHolders.tasks.BaseTaskViewHolder;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
import java.util.Collections;
/**
* Created by ell on 7/21/16.
*/
public abstract class SortableTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder>
extends BaseTasksRecyclerViewAdapter<VH> implements ItemTouchHelperAdapter, ItemTouchHelperDropCallback {
public interface SortTasksCallback {
void onMove(Task task, int from, int to);
}
private SortTasksCallback sortCallback;
public SortableTasksRecyclerViewAdapter(String taskType, TagsHelper tagsHelper, int layoutResource,
Context newContext, String userID, SortTasksCallback sortCallback) {
super(taskType, tagsHelper, layoutResource, newContext, userID);
this.sortCallback = sortCallback;
}
@Override
public void onItemMove(int fromPosition, int toPosition) {
Collections.swap(filteredContent, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onItemDismiss(int position) {
//NO OP
}
@Override
public void onDrop(int from, int to) {
if (this.sortCallback != null && from != to){
this.sortCallback.onMove(filteredContent.get(to), from, to);
}
}
}

View file

@ -6,10 +6,11 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder;
import android.content.Context;
import android.view.ViewGroup;
public class TodosRecyclerViewAdapter extends BaseTasksRecyclerViewAdapter<TodoViewHolder> {
public class TodosRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter<TodoViewHolder> {
public TodosRecyclerViewAdapter(String taskType, TagsHelper tagsHelper, int layoutResource, Context newContext, String userID) {
super(taskType, tagsHelper, layoutResource, newContext, userID);
public TodosRecyclerViewAdapter(String taskType, TagsHelper tagsHelper, int layoutResource,
Context newContext, String userID, SortTasksCallback sortCallback) {
super(taskType, tagsHelper, layoutResource, newContext, userID, sortCallback);
}
@Override

View file

@ -0,0 +1,125 @@
package com.habitrpg.android.habitica.ui.fragments.inventory.shops;
import com.habitrpg.android.habitica.APIHelper;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter;
import com.habitrpg.android.habitica.ui.adapter.inventory.StableRecyclerAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration;
import com.habitrpg.android.habitica.ui.helpers.RecyclerViewEmptySupport;
import com.habitrpg.android.habitica.ui.menu.DividerItemDecoration;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.Shop;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ShopFragment extends BaseFragment {
private static final String SHOP_IDENTIFIER_KEY = "SHOP_IDENTIFIER_KEY";
@BindView(R.id.recyclerView)
public RecyclerViewEmptySupport recyclerView;
@BindView(R.id.empty_view)
public TextView emptyView;
private View view;
public ShopRecyclerAdapter adapter;
public String shopIdentifier;
public HabitRPGUser user;
public Shop shop;
@Inject
APIHelper apiHeliper;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
boolean setupViews = false;
if (view == null) {
view = inflater.inflate(R.layout.fragment_recyclerview, container, false);
setupViews = true;
}
unbinder = ButterKnife.bind(this, view);
if (setupViews) {
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
}
adapter = (ShopRecyclerAdapter) recyclerView.getAdapter();
if (adapter == null) {
adapter = new ShopRecyclerAdapter();
recyclerView.setAdapter(adapter);
}
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager == null) {
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
}
if (savedInstanceState != null) {
this.shopIdentifier = savedInstanceState.getString(SHOP_IDENTIFIER_KEY, "");
}
if (shop == null) {
loadShopInventory();
} else {
adapter.setShop(shop);
}
return view;
}
private void loadShopInventory() {
String shopUrl = "";
switch (this.shopIdentifier) {
case Shop.MARKET:
shopUrl = "market";
break;
case Shop.QUEST_SHOP:
shopUrl = "quests";
break;
case Shop.TIME_TRAVELERS_SHOP:
shopUrl = "time-travelers";
break;
case Shop.SEASONAL_SHOP:
shopUrl = "seasonal";
break;
}
this.apiHeliper.apiService.fetchShopInventory(shopUrl)
.compose(this.apiHeliper.configureApiCallObserver())
.subscribe(shop -> {
this.shop = shop;
this.adapter.setShop(shop);
}, throwable -> {});
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(SHOP_IDENTIFIER_KEY, this.shopIdentifier);
}
}

View file

@ -0,0 +1,99 @@
package com.habitrpg.android.habitica.ui.fragments.inventory.shops;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.magicmicky.habitrpgwrapper.lib.models.Shop;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ShopsFragment extends BaseMainFragment {
public ViewPager viewPager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
this.usesTabLayout = true;
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
viewPager = (ViewPager) v.findViewById(R.id.view_pager);
viewPager.setCurrentItem(0);
setViewPagerAdapter();
return v;
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
public void setViewPagerAdapter() {
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
@Override
public Fragment getItem(int position) {
ShopFragment fragment = new ShopFragment();
switch (position) {
case 0: {
fragment.shopIdentifier = Shop.MARKET;
break;
}
case 1: {
fragment.shopIdentifier = Shop.QUEST_SHOP;
break;
}
//case 2: {
// fragment.shopIdentifier = Shop.TIME_TRAVELERS_SHOP;
// break;
//}
case 2: {
fragment.shopIdentifier = Shop.SEASONAL_SHOP;
break;
}
}
fragment.user = ShopsFragment.this.user;
return fragment;
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return activity.getString(R.string.market);
case 1:
return activity.getString(R.string.quests);
//case 2:
// return activity.getString(R.string.timeTravelers);
case 2:
return activity.getString(R.string.seasonalShop);
}
return "";
}
});
if (tabLayout != null && viewPager != null) {
tabLayout.setupWithViewPager(viewPager);
}
}
}

View file

@ -83,24 +83,28 @@ public class InboxFragment extends BaseMainFragment
roomsAdded = new ArrayList<>();
for (Object o : this.messages.entrySet()) {
Map.Entry pair = (Map.Entry) o;
if (this.messages.size() > 0) {
for (Object o : this.messages.entrySet()) {
Map.Entry pair = (Map.Entry) o;
ChatMessage message = (ChatMessage) pair.getValue();
if (roomsAdded.contains(message.uuid)) {
TextView entry = (TextView) this.inboxMessagesListView.findViewWithTag(message.uuid);
entry.setText(message.user);
} else {
roomsAdded.add(message.uuid);
ChatMessage message = (ChatMessage) pair.getValue();
if (roomsAdded.contains(message.uuid)) {
TextView entry = (TextView) this.inboxMessagesListView.findViewWithTag(message.uuid);
entry.setText(message.user);
} else {
roomsAdded.add(message.uuid);
TextView entry = (TextView) inflater.inflate(R.layout.plain_list_item, this.inboxMessagesListView, false);
entry.setText(message.user);
entry.setTag(message.uuid);
entry.setOnClickListener(this);
this.inboxMessagesListView.addView(entry);
TextView entry = (TextView) inflater.inflate(R.layout.plain_list_item, this.inboxMessagesListView, false);
entry.setText(message.user);
entry.setTag(message.uuid);
entry.setOnClickListener(this);
this.inboxMessagesListView.addView(entry);
}
}
} else {
TextView tv = new TextView(getContext());
tv.setText(R.string.empty_inbox);
}
}
@Override

View file

@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.ui.fragments.tasks;
import com.habitrpg.android.habitica.APIHelper;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand;
import com.habitrpg.android.habitica.helpers.TagsHelper;
@ -9,22 +10,32 @@ import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapt
import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder;
import com.habitrpg.android.habitica.ui.adapter.tasks.HabitsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperAdapter;
import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperDropCallback;
import com.habitrpg.android.habitica.ui.menu.DividerItemDecoration;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
import org.greenrobot.eventbus.EventBus;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
@ -49,12 +60,16 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
private String classType;
private HabitRPGUser user;
private View view;
private SortableTasksRecyclerViewAdapter.SortTasksCallback sortCallback;
private ItemTouchHelper.Callback mItemTouchCallback;
public static TaskRecyclerViewFragment newInstance(HabitRPGUser user, String classType) {
public static TaskRecyclerViewFragment newInstance(HabitRPGUser user, String classType,
SortableTasksRecyclerViewAdapter.SortTasksCallback sortCallback) {
TaskRecyclerViewFragment fragment = new TaskRecyclerViewFragment();
fragment.setRetainInstance(true);
fragment.user = user;
fragment.classType = classType;
fragment.sortCallback = sortCallback;
return fragment;
}
@ -65,7 +80,8 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
switch (this.classType) {
case Task.TYPE_HABIT:
layoutOfType = R.layout.habit_item_card;
this.recyclerAdapter = new HabitsRecyclerViewAdapter(Task.TYPE_HABIT, tagsHelper, layoutOfType, getContext(), userID);
this.recyclerAdapter = new HabitsRecyclerViewAdapter(Task.TYPE_HABIT, tagsHelper, layoutOfType, getContext(), userID, sortCallback);
allowReordering();
break;
case Task.TYPE_DAILY:
layoutOfType = R.layout.daily_item_card;
@ -73,11 +89,13 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
if (user != null) {
dailyResetOffset = user.getPreferences().getDayStart();
}
this.recyclerAdapter = new DailiesRecyclerViewHolder(Task.TYPE_DAILY, tagsHelper, layoutOfType, getContext(), userID, dailyResetOffset);
this.recyclerAdapter = new DailiesRecyclerViewHolder(Task.TYPE_DAILY, tagsHelper, layoutOfType, getContext(), userID, dailyResetOffset, sortCallback);
allowReordering();
break;
case Task.TYPE_TODO:
layoutOfType = R.layout.todo_item_card;
this.recyclerAdapter = new TodosRecyclerViewAdapter(Task.TYPE_TODO, tagsHelper, layoutOfType, getContext(), userID);
this.recyclerAdapter = new TodosRecyclerViewAdapter(Task.TYPE_TODO, tagsHelper, layoutOfType, getContext(), userID, sortCallback);
allowReordering();
return;
case Task.TYPE_REWARD:
layoutOfType = R.layout.reward_item_card;
@ -87,8 +105,51 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
}
}
private void allowReordering(){
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mItemTouchCallback = new ItemTouchHelper.Callback() {
private Integer mFromPosition = null;
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (viewHolder != null){
viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
}
}
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (mFromPosition == null) mFromPosition = viewHolder.getAdapterPosition();
((ItemTouchHelperAdapter)recyclerAdapter).onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {}
//defines the enabled move directions in each state (idle, swiping, dragging).
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG,
ItemTouchHelper.DOWN | ItemTouchHelper.UP);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setBackgroundColor(Color.WHITE);
if (mFromPosition != null){
((ItemTouchHelperDropCallback)recyclerAdapter).onDrop(mFromPosition, viewHolder.getAdapterPosition());
}
}
};
if (view == null) {
view = inflater.inflate(R.layout.fragment_recyclerview, container, false);

View file

@ -23,6 +23,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder;
import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.habitrpg.android.habitica.ui.helpers.Debounce;
import com.habitrpg.android.habitica.ui.helpers.UiUtils;
@ -47,6 +48,7 @@ import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -66,6 +68,9 @@ import java.util.Map;
import javax.inject.Inject;
import rx.Observer;
import rx.functions.Action1;
public class TasksFragment extends BaseMainFragment implements OnCheckedChangeListener {
private static final int TASK_CREATED_RESULT = 1;
@ -200,20 +205,29 @@ public class TasksFragment extends BaseMainFragment implements OnCheckedChangeLi
@Override
public Fragment getItem(int position) {
TaskRecyclerViewFragment fragment;
BaseTasksRecyclerViewAdapter adapter;
SortableTasksRecyclerViewAdapter.SortTasksCallback sortCallback =
(task, from, to) -> {
if (apiHelper != null){
apiHelper.apiService.postTaskNewPosition(task.getId(), String.valueOf(to))
.compose(apiHelper.configureApiCallObserver())
.subscribe(aVoid -> {
new HabitRPGUserCallback(activity);
});
}
};
switch (position) {
case 0:
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_HABIT);
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_HABIT, sortCallback);
break;
case 1:
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_DAILY);
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_DAILY, sortCallback);
break;
case 3:
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_REWARD);
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_REWARD, null);
break;
default:
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_TODO);
fragment = TaskRecyclerViewFragment.newInstance(user, Task.TYPE_TODO, sortCallback);
}
ViewFragmentsDictionary.put(position, fragment);

View file

@ -0,0 +1,8 @@
package com.habitrpg.android.habitica.ui.helpers;
/**
* Created by ell on 3/30/16.
*/
public interface ItemTouchHelperDropCallback {
void onDrop(int from, int to);
}

View file

@ -11,6 +11,7 @@ import com.habitrpg.android.habitica.ui.fragments.faq.FAQOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.customization.AvatarOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.equipment.EquipmentOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemsFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.shops.ShopsFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.stable.StableFragment;
import com.habitrpg.android.habitica.ui.fragments.skills.SkillsFragment;
import com.habitrpg.android.habitica.ui.fragments.social.GuildsOverviewFragment;
@ -37,15 +38,16 @@ public class MainDrawerBuilder {
public static final int SIDEBAR_TAVERN = 3;
public static final int SIDEBAR_PARTY = 4;
public static final int SIDEBAR_GUILDS = 5;
public static final int SIDEBAR_AVATAR = 6;
public static final int SIDEBAR_EQUIPMENT = 7;
public static final int SIDEBAR_ITEMS = 8;
public static final int SIDEBAR_STABLE = 9;
public static final int SIDEBAR_PURCHASE = 10;
public static final int SIDEBAR_NEWS = 11;
public static final int SIDEBAR_SETTINGS = 12;
public static final int SIDEBAR_HELP = 13;
public static final int SIDEBAR_ABOUT = 14;
public static final int SIDEBAR_SHOPS = 6;
public static final int SIDEBAR_AVATAR = 7;
public static final int SIDEBAR_EQUIPMENT = 8;
public static final int SIDEBAR_ITEMS = 9;
public static final int SIDEBAR_STABLE = 10;
public static final int SIDEBAR_PURCHASE = 11;
public static final int SIDEBAR_NEWS = 12;
public static final int SIDEBAR_SETTINGS = 13;
public static final int SIDEBAR_HELP = 14;
public static final int SIDEBAR_ABOUT = 15;
public static AccountHeaderBuilder CreateDefaultAccountHeader(final Activity activity) {
return new AccountHeaderBuilder()
@ -80,6 +82,7 @@ public class MainDrawerBuilder {
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_guilds)).withIdentifier(SIDEBAR_GUILDS),
new SectionIconDrawerItem().withName(activity.getString(R.string.sidebar_section_inventory).toUpperCase()),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_shops)).withIdentifier(SIDEBAR_SHOPS),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_avatar)).withIdentifier(SIDEBAR_AVATAR),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_equipment)).withIdentifier(SIDEBAR_EQUIPMENT),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_items)).withIdentifier(SIDEBAR_ITEMS),
@ -124,6 +127,10 @@ public class MainDrawerBuilder {
fragment = new TavernFragment();
break;
}
case SIDEBAR_SHOPS: {
fragment = new ShopsFragment();
break;
}
case SIDEBAR_AVATAR: {
fragment = new AvatarOverviewFragment();
break;

View file

@ -0,0 +1,39 @@
package com.habitrpg.android.habitica.ui.viewHolders;
import com.habitrpg.android.habitica.R;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
public class SectionViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.label)
TextView label;
@BindView(R.id.purchaseSetButton)
Button purchaseSetButton;
Context context;
public SectionViewHolder(View itemView) {
super(itemView);
context = itemView.getContext();
ButterKnife.bind(this, itemView);
this.purchaseSetButton.setVisibility(View.GONE);
}
public void bind(String title) {
try {
Integer stringID = context.getResources().getIdentifier("section" + title, "string", context.getPackageName());
this.label.setText(context.getString(stringID));
} catch (Exception e) {
this.label.setText(title);
}
}
}

View file

@ -3,6 +3,7 @@ package com.habitrpg.android.habitica.ui.viewHolders.tasks;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.TaskTappedEvent;
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand;
import com.habitrpg.android.habitica.ui.ItemDetailDialog;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
@ -71,8 +72,15 @@ public class RewardViewHolder extends BaseTaskViewHolder {
@Override
public void onClick(View v) {
if (task.specialTag != null && task.specialTag.equals("item")) {
LinearLayout contentViewForDialog = createContentViewForGearDialog();
AlertDialog dialog = createGearDialog(contentViewForDialog);
ItemDetailDialog dialog = new ItemDetailDialog(context);
dialog.setTitle(task.getText());
dialog.setDescription(task.getNotes());
dialog.setImage("shop_" + this.task.getId());
dialog.setCurrency("gold");
dialog.setValue(task.getValue());
dialog.setBuyListener((clickedDialog, which) -> {
this.buyReward();
});
dialog.show();
} else {
TaskTappedEvent event = new TaskTappedEvent();
@ -82,83 +90,5 @@ public class RewardViewHolder extends BaseTaskViewHolder {
}
}
private AlertDialog createGearDialog(LinearLayout contentViewForDialog) {
return new AlertDialog.Builder(context)
.setPositiveButton(R.string.reward_dialog_buy, (dialog, which) -> {
this.buyReward();
})
.setTitle(this.task.getText())
.setView(contentViewForDialog)
.setNegativeButton(R.string.reward_dialog_dismiss, (dialog, which) -> {
dialog.dismiss();
}).create();
}
@NonNull
private LinearLayout createContentViewForGearDialog() {
String price = this.priceFormat.format(this.task.value);
String content = this.task.getNotes();
// External ContentView
LinearLayout contentViewLayout = new LinearLayout(context);
contentViewLayout.setOrientation(LinearLayout.VERTICAL);
// Gear Image
ImageView gearImageView = new ImageView(context);
LinearLayout.LayoutParams gearImageLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
gearImageLayoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
gearImageLayoutParams.setMargins(0, 0, 0, 20);
gearImageView.setMinimumWidth(200);
gearImageView.setMinimumHeight(200);
gearImageView.setLayoutParams(gearImageLayoutParams);
DataBindingUtils.loadImage(gearImageView, "shop_" + this.task.getId());
// Gear Description
TextView contentTextView = new TextView(context, null);
if (!content.isEmpty()) {
contentTextView.setText(content);
}
// GoldPrice View
LinearLayout goldPriceLayout = new LinearLayout(context);
goldPriceLayout.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams goldPriceLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
goldPriceLayoutParams.setMargins(0, 0, 0, 16);
goldPriceLayoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
goldPriceLayout.setOrientation(LinearLayout.HORIZONTAL);
goldPriceLayout.setLayoutParams(goldPriceLayoutParams);
goldPriceLayout.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
// Price View
TextView priceTextView = new TextView(context);
priceTextView.setText(price);
priceTextView.setPadding(10, 0, 0, 0);
ImageView gold = new ImageView(context);
gold.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_header_gold));
gold.setMinimumHeight(50);
gold.setMinimumWidth(50);
gold.setPadding(0, 0, 5, 0);
goldPriceLayout.addView(gold);
goldPriceLayout.addView(priceTextView);
if (gearImageView.getDrawable() != null) {
contentViewLayout.addView(gearImageView);
}
contentViewLayout.setGravity(Gravity.CENTER_VERTICAL);
contentViewLayout.addView(goldPriceLayout);
if (!content.isEmpty()) {
contentViewLayout.addView(contentTextView);
}
return contentViewLayout;
}
}

View file

@ -9,6 +9,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.PostChatMessageResult;
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest;
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult;
import com.magicmicky.habitrpgwrapper.lib.models.Quest;
import com.magicmicky.habitrpgwrapper.lib.models.Shop;
import com.magicmicky.habitrpgwrapper.lib.models.Status;
import com.magicmicky.habitrpgwrapper.lib.models.Tag;
import com.magicmicky.habitrpgwrapper.lib.models.TaskDirectionData;
@ -65,6 +66,15 @@ public interface ApiService {
@POST("user/buy/{key}")
Observable<BuyResponse> buyItem(@Path("key") String itemKey);
@POST("user/purchase/{type}/{key}")
Observable<Void> purchaseItem(@Path("type") String type, @Path("key") String itemKey);
@POST("user/purchase-hourglass/{type}/{key}")
Observable<Void> purchaseHourglassItem(@Path("type") String type, @Path("key") String itemKey);
@POST("user/buy-mystery-set/{key}")
Observable<Void> purchaseMysterySet(@Path("key") String itemKey);
@POST("user/sell/{type}/{key}")
Observable<HabitRPGUser> sellItem(@Path("type") String itemType, @Path("key") String itemKey);
@ -87,6 +97,9 @@ public interface ApiService {
@POST("tasks/{id}/score/{direction}")
Observable<TaskDirectionData> postTaskDirection(@Path("id") String id, @Path("direction") String direction);
@POST("tasks/{id}/move/to/{position}")
Observable<Void> postTaskNewPosition(@Path("id") String id, @Path("position") String position);
@POST("tasks/{taskId}/checklist/{itemId}/score")
Observable<Task> scoreChecklistItem(@Path("taskId") String taskId, @Path("itemId") String itemId);
@ -220,6 +233,9 @@ public interface ApiService {
@POST("members/send-private-message")
Observable<PostChatMessageResult> postPrivateMessage(@Body HashMap<String, String> messageDetails);
@GET("shops/{identifier}")
Observable<Shop> fetchShopInventory(@Path("identifier") String identifier);
//DEBUG: These calls only work on a local development server
@POST("debug/add-ten-gems")

View file

@ -0,0 +1,57 @@
package com.magicmicky.habitrpgwrapper.lib.models;
import java.util.List;
public class Shop {
public static final String MARKET = "market";
public static final String QUEST_SHOP = "questShop";
public static final String TIME_TRAVELERS_SHOP = "timeTravelersShop";
public static final String SEASONAL_SHOP = "seasonalShop";
public String identifier;
public String text;
public String notes;
public String imageName;
public List<ShopCategory> categories;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public String getImageName() {
return imageName;
}
public void setImageName(String imageName) {
this.imageName = imageName;
}
public List<ShopCategory> getCategories() {
return categories;
}
public void setCategories(List<ShopCategory> categories) {
this.categories = categories;
}
}

View file

@ -0,0 +1,53 @@
package com.magicmicky.habitrpgwrapper.lib.models;
import java.util.List;
public class ShopCategory {
public String identifier;
public String text;
public String notes;
public Boolean purchaseAll;
public List<ShopItem> items;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public Boolean getPurchaseAll() {
return purchaseAll;
}
public void setPurchaseAll(Boolean purchaseAll) {
this.purchaseAll = purchaseAll;
}
public List<ShopItem> getItems() {
return items;
}
public void setItems(List<ShopItem> items) {
this.items = items;
}
}

View file

@ -0,0 +1,84 @@
package com.magicmicky.habitrpgwrapper.lib.models;
import com.google.gson.annotations.SerializedName;
public class ShopItem {
public String key;
public String text;
public String notes;
@SerializedName("class") public String imageName;
public Integer value;
public Boolean locked;
public String currency;
public String purchaseType;
public String categoryIdentifier;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public String getImageName() {
if (imageName != null) {
return imageName;
} else {
return "shop_"+key;
}
}
public void setImageName(String imageName) {
this.imageName = imageName;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public Boolean getLocked() {
return locked;
}
public void setLocked(Boolean locked) {
this.locked = locked;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public String getPurchaseType() {
return purchaseType;
}
public void setPurchaseType(String purchaseType) {
this.purchaseType = purchaseType;
}
}