load / list challenges of user

This commit is contained in:
Negue 2016-11-25 15:03:47 +01:00
parent bdf31cfac9
commit 7958a08efc
17 changed files with 540 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_view"
style="@style/CardView.Default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
<LinearLayout
style="@style/CardContent.Compact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/challenge_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:weightSum="1.0">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5">
<TextView
android:id="@+id/leader_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:ellipsize="middle"
android:lines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="right">
<ImageView android:src="@drawable/ic_people_black_24dp"
android:layout_width="20dp"
android:layout_height="20dp" />
<TextView
android:id="@+id/memberCountTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:lines="1"
android:text="0"
android:layout_gravity="center"
android:paddingLeft="5dp"
android:paddingStart="5dp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="end"
android:weightSum="1.0">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="end"
android:id="@+id/gem_prize_layout">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_header_gem" />
<TextView
android:id="@+id/gemPrizeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:lines="1"
android:text="0"
android:layout_gravity="center"
android:paddingLeft="5dp"
android:paddingStart="5dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View file

@ -0,0 +1,16 @@
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/challenges.refresh.layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="@+id/challenges.list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:divider="@null"
android:scrollbars="vertical" />
</android.support.v4.widget.SwipeRefreshLayout>

View file

@ -436,4 +436,5 @@ To start, which parts of your life do you want to improve?</string>
<string name="AudioTheme_title">Audio Theme</string>
<string name="AudioTheme_summary">Change Habitica\'s Audio Theme</string>
<string name="by">by</string>
</resources>

View file

@ -7,5 +7,5 @@ public class HabitDatabase {
public static final String NAME = "Habitica";
public static final int VERSION = 29;
public static final int VERSION = 30;
}

View file

@ -43,6 +43,8 @@ import com.habitrpg.android.habitica.ui.fragments.setup.IntroFragment;
import com.habitrpg.android.habitica.ui.fragments.setup.TaskSetupFragment;
import com.habitrpg.android.habitica.ui.fragments.skills.SkillTasksRecyclerViewFragment;
import com.habitrpg.android.habitica.ui.fragments.skills.SkillsFragment;
import com.habitrpg.android.habitica.ui.fragments.social.ChallengeListFragment;
import com.habitrpg.android.habitica.ui.fragments.social.ChallengesOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.social.ChatListFragment;
import com.habitrpg.android.habitica.ui.fragments.social.GroupInformationFragment;
import com.habitrpg.android.habitica.ui.fragments.social.GuildFragment;
@ -184,4 +186,8 @@ public interface AppComponent {
void inject(AvatarStatsWidgetProvider avatarStatsWidgetProvider);
void inject(SoundManager soundManager);
void inject(ChallengesOverviewFragment challengesOverviewFragment);
void inject(ChallengeListFragment challengeListFragment);
}

View file

@ -0,0 +1,96 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.magicmicky.habitrpgwrapper.lib.models.Challenge;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import static com.raizlabs.android.dbflow.config.FlowManager.getContext;
public class ChallengesListViewAdapter extends RecyclerView.Adapter<ChallengesListViewAdapter.ChallengeViewHolder> {
private List<Challenge> challenges = new ArrayList<>();
public void setChallenges(List<Challenge> challenges) {
this.challenges = challenges;
this.notifyDataSetChanged();
}
@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);
}
@Override
public void onBindViewHolder(ChallengeViewHolder holder, int position) {
holder.bind(challenges.get(position));
}
@Override
public int getItemCount() {
return challenges.size();
}
public class ChallengeViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.challenge_name)
TextView challengeName;
@BindView(R.id.leader_label)
TextView leaderName;
@BindView(R.id.memberCountTextView)
TextView memberCountTextView;
@BindView(R.id.gem_prize_layout)
LinearLayout gem_prize_layout;
@BindView(R.id.gemPrizeTextView)
TextView gemPrizeTextView;
public ChallengeViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(Challenge challenge) {
challengeName.setText(challenge.name);
leaderName.setText(getContext().getString(R.string.by) + " " + getLeaderName(challenge.leader));
memberCountTextView.setText(challenge.memberCount + "");
if (challenge.prize == 0) {
gem_prize_layout.setVisibility(View.GONE);
} else {
gem_prize_layout.setVisibility(View.VISIBLE);
gemPrizeTextView.setText(challenge.prize + "");
}
}
private String getLeaderName(HabitRPGUser user) {
try {
return user.getProfile().getName();
} catch (Exception e) {
return "";
}
}
}
}

View file

@ -0,0 +1,122 @@
package com.habitrpg.android.habitica.ui.fragments.social;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.ui.adapter.social.ChallengesListViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.magicmicky.habitrpgwrapper.lib.models.Challenge;
import java.util.HashSet;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ChallengeListFragment extends BaseMainFragment implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener {
@BindView(R.id.challenges_refresh_layout)
SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.challenges_list)
RecyclerView recyclerView;
private ChallengesListViewAdapter challengeAdapter;
private boolean viewUserChallengesOnly;
@Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
challengeAdapter = new ChallengesListViewAdapter();
}
public void setViewUserChallengesOnly(boolean only) {
this.viewUserChallengesOnly = only;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_challengeslist, container, false);
unbinder = ButterKnife.bind(this, v);
swipeRefreshLayout.setOnRefreshListener(this);
recyclerView.setLayoutManager(new LinearLayoutManager(this.activity));
this.onRefresh();
return v;
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(true);
fetchChallenges();
}
private void fetchChallenges() {
if (this.apiHelper != null && this.apiHelper.apiService != null) {
apiHelper.apiService.getUserChallenges().
compose(apiHelper.configureApiCallObserver())
.subscribe(s -> {
if (viewUserChallengesOnly) {
List<Challenge> userChallenges = this.user.getChallengeList();
HashSet<String> userChallengesHash = new HashSet<String>();
for (Challenge userChallenge : userChallenges) {
userChallengesHash.add(userChallenge.id);
}
userChallenges.clear();
for (Challenge challenge : s) {
if (userChallengesHash.contains(challenge.id)) {
challenge.user_id = this.user.getId();
userChallenges.add(challenge);
}
challenge.async().save();
}
challengeAdapter.setChallenges(userChallenges);
} else {
challengeAdapter.setChallenges(s);
for (Challenge challenge : s) {
challenge.async().save();
}
}
recyclerView.setAdapter(challengeAdapter);
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(false);
}
}, throwable -> {
});
}
}
@Override
public void onClick(View v) {
}
}

View file

@ -0,0 +1,87 @@
package com.habitrpg.android.habitica.ui.fragments.social;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
public class ChallengesOverviewFragment 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(1);
setViewPagerAdapter();
challengeListFragment = new ChallengeListFragment();
challengeListFragment.setUser(this.user);
challengeListFragment.setViewUserChallengesOnly(true);
return v;
}
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
private ChallengeListFragment challengeListFragment;
public void setViewPagerAdapter() {
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
@Override
public Fragment getItem(int position) {
Fragment fragment = new Fragment();
switch (position) {
case 0:
return challengeListFragment;
case 1:
return fragment;
}
return fragment;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "My Challenges";
case 1:
return "Public";
}
return "";
}
});
if (tabLayout != null && viewPager != null) {
tabLayout.setupWithViewPager(viewPager);
}
}
}

View file

@ -15,6 +15,7 @@ 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.ChallengesOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.social.GuildsOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.social.InboxFragment;
import com.habitrpg.android.habitica.ui.fragments.social.TavernFragment;
@ -41,16 +42,17 @@ 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_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 final int SIDEBAR_CHALLENGES = 6;
public static final int SIDEBAR_SHOPS = 7;
public static final int SIDEBAR_AVATAR = 8;
public static final int SIDEBAR_EQUIPMENT = 9;
public static final int SIDEBAR_ITEMS = 10;
public static final int SIDEBAR_STABLE = 11;
public static final int SIDEBAR_PURCHASE = 12;
public static final int SIDEBAR_NEWS = 13;
public static final int SIDEBAR_SETTINGS = 14;
public static final int SIDEBAR_HELP = 15;
public static final int SIDEBAR_ABOUT = 16;
public static AccountHeaderBuilder CreateDefaultAccountHeader(final Activity activity) {
return new AccountHeaderBuilder()
@ -83,6 +85,7 @@ public class MainDrawerBuilder {
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_tavern)).withIdentifier(SIDEBAR_TAVERN),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_party)).withIdentifier(SIDEBAR_PARTY),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_guilds)).withIdentifier(SIDEBAR_GUILDS),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_challenges)).withIdentifier(SIDEBAR_CHALLENGES),
new SectionIconDrawerItem().withName(activity.getString(R.string.sidebar_section_inventory).toUpperCase()),
new PrimaryDrawerItem().withName(activity.getString(R.string.sidebar_shops)).withIdentifier(SIDEBAR_SHOPS),
@ -130,6 +133,10 @@ public class MainDrawerBuilder {
fragment = new TavernFragment();
break;
}
case SIDEBAR_CHALLENGES: {
fragment = new ChallengesOverviewFragment();
break;
}
case SIDEBAR_SHOPS: {
fragment = new ShopsFragment();
break;

View file

@ -23,7 +23,9 @@ import com.magicmicky.habitrpgwrapper.lib.models.responses.UnlockResponse;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.ItemData;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.TaskList;
import com.magicmicky.habitrpgwrapper.lib.models.Challenge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -257,6 +259,9 @@ public interface ApiService {
@DELETE("user/push-devices/{regId}")
Observable<Void> deletePushDevice(@Path("regId") String regId);
@GET("challenges/user")
Observable<ArrayList<Challenge>> getUserChallenges();
//DEBUG: These calls only work on a local development server
@POST("debug/add-ten-gems")

View file

@ -0,0 +1,45 @@
package com.magicmicky.habitrpgwrapper.lib.models;
import com.habitrpg.android.habitica.HabitDatabase;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.NotNull;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import java.util.HashMap;
@Table(databaseName = HabitDatabase.NAME)
public class Challenge extends BaseModel {
@NotNull
@PrimaryKey
@Column
public String id;
@Column
public String name;
@Column
public String shortName;
@Column
public String description;
public HabitRPGUser leader;
public Group group;
public int prize;
@Column
public boolean official;
public HashMap<String, String[]> tasksOrder;
@Column
public int memberCount;
@Column
public String user_id;
}

View file

@ -31,6 +31,8 @@ public class HabitRPGUser extends BaseModel {
List<Task> todos;
List<Task> rewards;
List<Task> habits;
List<Challenge> challengeList;
List<Tag> tags;
@Column
@PrimaryKey
@ -106,6 +108,24 @@ public class HabitRPGUser extends BaseModel {
private TasksOrder tasksOrder;
private List<String> challenges;
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "challengeList")
public List<Challenge> getChallengeList() {
if (challengeList == null) {
challengeList = new Select()
.from(Challenge.class)
.where(Condition.column("user_id").eq(this.id))
.queryList();
}
return challengeList;
}
public void setChallengeList(List<Challenge> challenges) {
this.challengeList = challenges;
}
public Preferences getPreferences() {
return preferences;
}
@ -307,6 +327,15 @@ public class HabitRPGUser extends BaseModel {
this.pushDevices = pushDevices;
}
public List<String> getChallenges() {
return challenges;
}
public void setChallenges(List<String> challenges) {
this.challenges = challenges;
}
@Override
public void save() {
// We need to set the user_id to all other objects
@ -345,6 +374,18 @@ public class HabitRPGUser extends BaseModel {
}
}
List<Challenge> challenges = new ArrayList<>();
for (String s : getChallenges()) {
Challenge challenge = new Challenge();
challenge.id = s;
challenge.user_id = id;
challenges.add(challenge);
}
setChallengeList(challenges);
super.save();
}