Redo party view

This commit is contained in:
Phillip Thelen 2017-05-23 17:40:13 +02:00
parent 0431e64c19
commit 52f421d71b
44 changed files with 903 additions and 419 deletions

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/gray_700" />
<corners android:radius="@dimen/rounded_button_radius"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/good_100" />
<corners android:radius="@dimen/rounded_button_radius"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/worse_100" />
<corners android:radius="@dimen/rounded_button_radius"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/neutral_100" />
<corners android:radius="@dimen/rounded_button_radius"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="1dip" />
<solid android:color="@color/gray_500" />
</shape>

View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"

View file

@ -348,34 +348,6 @@
android:divider="?android:listDivider"
android:showDividers="middle"
style="@style/CardContent"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
style="?android:buttonBarStyle"
android:visibility="@{group.quest.active? View.VISIBLE : View.GONE}"
android:layout_gravity="right">
<Button
android:id="@+id/btnQuestAbort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/quest.abort"
android:textColor="@color/btn_danger"
style="?android:buttonBarButtonStyle"
android:visibility="@{(group.quest != null &amp;&amp; user.getId().equals(group.quest.leader))? View.VISIBLE : View.GONE}" />
<Button
android:id="@+id/btnQuestLeave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/quest.leave"
android:textColor="@color/btn_warning"
style="?android:buttonBarButtonStyle"
android:visibility="@{(!user.getId().equals(group.quest.leader) &amp;&amp; group.quest.members.containsKey(user.getId()))? View.VISIBLE : View.GONE}" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View file

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="?attr/actionBarSize">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default"
android:id="@+id/party_invitation_wrapper"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/CardContent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/invited_to_party" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="right">
<Button
android:id="@+id/party_invite_accept_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/quest.accept"
android:textColor="@color/btn_success"
style="?android:buttonBarButtonStyle" />
<Button
android:id="@+id/party_invite_reject_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/quest.reject"
android:textColor="@color/btn_danger"
style="?android:buttonBarButtonStyle" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<TextView
android:id="@+id/title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Title1"
tools:text="Awesome Party"
android:gravity="center"
android:layout_margin="@dimen/spacing_large" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/white"
android:showDividers="beginning|end|middle"
android:divider="@drawable/vertical_divider">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/SegmentView">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/quest"
style="@style/SegmentTitle"/>
<Button
android:id="@+id/new_quest_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/start_quest"
style="@style/HabiticaButton.Gray"/>
<LinearLayout
android:id="@+id/quest_detail_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/layout_rounded_bg_gray_700"
android:padding="@dimen/spacing_medium"
android:gravity="center_vertical"
android:layout_marginBottom="@dimen/spacing_medium">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/quest_scroll_image_view"
android:layout_width="@dimen/gear_image_size"
android:layout_height="@dimen/gear_image_size" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="@dimen/spacing_medium">
<TextView
android:id="@+id/quest_title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="The Wail of the Whale"
/>
<TextView
android:id="@+id/quest_participation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="3 Participants"
android:textColor="@color/gray_300"/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_keyboard_arrow_right_gray_24dp"
android:visibility="gone"/>
</LinearLayout>
<LinearLayout
android:id="@+id/quest_image_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/layout_rounded_bg_gray_700"
android:padding="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_medium">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/quest_image_view"
android:layout_width="match_parent"
android:layout_height="@dimen/quest_image_height"
android:scaleType="fitCenter"/>
</LinearLayout>
<com.habitrpg.android.habitica.ui.views.social.QuestProgressView
android:id="@+id/quest_progress_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/quest_participant_response_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/quest_accept_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest.accept"
style="@style/HabiticaButton.Green"
android:layout_marginRight="16dp" />
<Button
android:id="@+id/quest_reject_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest.reject"
style="@style/HabiticaButton.Red"/>
</LinearLayout>
<LinearLayout
android:id="@+id/quest_leader_response_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/quest_begin_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest.begin"
style="@style/HabiticaButton.Yellow"
android:layout_marginRight="16dp" />
<Button
android:id="@+id/quest_cancel_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest.cancel"
style="@style/HabiticaButton.Red" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/SegmentView">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/party_description"
style="@style/SegmentTitle"/>
<TextView
android:id="@+id/description_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="This is our super awesome party!"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/leave_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_large"
style="@style/HabiticaButton.Red"
android:text="@string/leave_party"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.v4.widget.SwipeRefreshLayout>

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="item to collect" />
<TextView
android:id="@+id/count"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="100 / 100" />
</LinearLayout>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/icon_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/name_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
tools:text="item to collect"
android:layout_marginBottom="@dimen/spacing_small"/>
<com.habitrpg.android.habitica.ui.views.ValueBar
android:id="@+id/value_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:lightBackground="true"
app:barForegroundColor="@color/good_100"/>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/boss_name_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Quest Boss"
android:textStyle="bold"
android:layout_marginBottom="@dimen/spacing_small"/>
<com.habitrpg.android.habitica.ui.views.ValueBar
android:id="@+id/boss_health_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:barForegroundColor="@color/worse_100"
app:lightBackground="true" />
<LinearLayout
android:id="@+id/collection_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>

View file

@ -49,6 +49,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/read_community_guidelines"
style="@style/Caption3" />
style="@style/Caption3"
android:textColor="@color/brand_300" />
</LinearLayout>
</merge>

View file

@ -15,7 +15,8 @@
android:layout_alignTop="@+id/bar_full"
android:layout_alignBottom="@id/bar_full"
android:scaleType="center"
android:contentDescription="Bar Icon" />
android:contentDescription="Bar Icon"
android:visibility="gone"/>
<LinearLayout
android:id="@id/bar_full"
android:layout_toRightOf="@id/ic_header"

View file

@ -39,6 +39,17 @@
<color name="best_50">#46A7D9</color>
<color name="best_10">#2995cd</color>
<color name="gray_10">#34313a</color>
<color name="gray_50">#4e4a57</color>
<color name="gray_100">#686274</color>
<color name="gray_200">#878190</color>
<color name="gray_300">#a5a1ac</color>
<color name="gray_400">#c3c0c7</color>
<color name="gray_500">#e1e0e3</color>
<color name="gray_600">#edecee</color>
<color name="gray_700">#f9f9f9</color>
<color name="completed">#D9D9D9</color>
<color name="completed_btn">#989898</color>
@ -63,14 +74,14 @@
<color name="textColorSecondaryLight">#727272</color>
<!-- Cards -->
<color name="stroke">#dddddd</color>
<color name="stroke">@color/gray_500</color>
<color name="text_light">#66000000</color>
<color name="card_text">#ff8d8d8d</color>
<color name="card_title_text">#ff707070</color>
<color name="card_light_text">#ffb5b5b5</color>
<color name="card_grid_text">#ff707070</color>
<color name="card_separator">#ffe5e5e5</color>
<color name="card_border">#ffdedede</color>
<color name="card_text">@color/gray_200</color>
<color name="card_title_text">@color/gray_100</color>
<color name="card_light_text">@color/gray_300</color>
<color name="card_grid_text">@color/gray_100</color>
<color name="card_separator">@color/gray_600</color>
<color name="card_border">@color/gray_500</color>
<!-- dialog -->
<color name="primary_text_light">#000000</color>
@ -79,17 +90,15 @@
<!-- clock styled weekdays -->
<color name="days_gray">#ffb5b5b5</color>
<color name="days_black">#FF000000</color>
<color name="holo_blue_light">#ff33b5e5</color>
<color name="btn_separator">#aaa</color>
<color name="new_task_bar_color">#555555</color>
<color name="white">#ffffff</color>
<color name="btn_separator">@color/gray_300</color>
<color name="white">#ffffff </color>
<color name="checkbox_tint_color">#ffd8dcdd</color>
<color name="checkbox_tint_color">@color/gray_500</color>
<color name="cell_separator">#c3c2c6</color>
<color name="checklist_separator">#ededed</color>
<color name="task_gray">#b7b7b7</color>
<color name="cell_separator">@color/gray_400</color>
<color name="checklist_separator">@color/gray_600</color>
<color name="task_gray">@color/gray_400</color>
<color name="checkbox_fill">#50ffffff</color>
<color name="checkbox_checked_fill">#c8ffffff</color>
<color name="checkbox_checklist_fill">#23000000</color>

View file

@ -38,7 +38,7 @@
<dimen name="btn_height_reward">50dp</dimen>
<dimen name="quest_image_width">128dp</dimen>
<dimen name="quest_image_height">128dp</dimen>
<dimen name="quest_image_height">200dp</dimen>
<!-- Widget -->
<dimen name="widget_bar_horizontal_margin">20dp</dimen>
@ -105,4 +105,6 @@
<dimen name="login_intro_button_size">126dp</dimen>
<dimen name="diamond_button_height">40dp</dimen>
<dimen name="setup_customization_size">56dp</dimen>
<dimen name="outer_inset">16dp</dimen>
<dimen name="rounded_button_radius">6dp</dimen>
</resources>

View file

@ -604,4 +604,10 @@
<string name="ownership">Ownership</string>
<string name="inn">Inn</string>
<string name="system">System</string>
<string name="start_quest">Start a new Quest</string>
<string name="leave_party">Leave Party</string>
<string name="party_description">Party Description</string>
<string name="abort_confirmation">Are you sure you want to abort this mission? It will abort it for everyone in your party and all progress will be lost. The quest scroll will be returned to the quest owner.</string>
<string name="leave_quest_confirmation">Are you sure you want to leave the active quest? All your quest progress will be lost.</string>
<string name="number_participants">%1$d Participants</string>
</resources>

View file

@ -357,4 +357,39 @@
<item name="colorControlNormal">@color/black_20_alpha</item>
<item name="android:drawablePadding">@dimen/spacing_large</item>
</style>
<style name="SegmentView">
<item name="android:layout_margin">@dimen/spacing_large</item>
<item name="android:orientation">vertical</item>
</style>
<style name="HabiticaButton" parent="@style/Widget.AppCompat.Button.Borderless">
<item name="android:textAllCaps">false</item>
<item name="android:minHeight">0dp</item>
<item name="android:paddingTop">12dp</item>
<item name="android:paddingBottom">12dp</item>
<item name="android:shadowColor">@color/transparent</item>
<item name="android:textColor">@color/white</item>
</style>
<style name="HabiticaButton.Gray" parent="HabiticaButton">
<item name="android:background">@drawable/layout_rounded_bg_gray_700</item>
<item name="android:textColor">@color/brand_400</item>
</style>
<style name="HabiticaButton.Red" parent="HabiticaButton">
<item name="android:background">@drawable/layout_rounded_bg_red</item>
</style>
<style name="SegmentTitle" parent="Headline">
<item name="android:layout_marginBottom">@dimen/spacing_medium</item>
</style>
<style name="HabiticaButton.Green" parent="HabiticaButton">
<item name="android:background">@drawable/layout_rounded_bg_green</item>
</style>
<style name="HabiticaButton.Yellow" parent="HabiticaButton">
<item name="android:background">@drawable/layout_rounded_bg_yellow</item>
</style>
</resources>

View file

@ -76,6 +76,7 @@ import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDet
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeListFragment;
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment;
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengesOverviewFragment;
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyDetailFragment;
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyFragment;
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyInviteFragment;
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyMemberListFragment;
@ -268,4 +269,6 @@ public interface AppComponent {
void inject(ChallengeDetailDialogHolder challengeDetailDialogHolder);
void inject(TavernDetailFragment tavernDetailFragment);
void inject(PartyDetailFragment partyDetailFragment);
}

View file

@ -1,5 +1,6 @@
package com.habitrpg.android.habitica.data;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.responses.PostChatMessageResult;
import com.habitrpg.android.habitica.models.social.Challenge;
import com.habitrpg.android.habitica.models.social.ChatMessage;
@ -57,4 +58,17 @@ public interface SocialRepository extends BaseRepository {
Observable<Void> markPrivateMessagesRead(User user);
Observable<RealmResults<Group>> getUserGroups();
Observable<Void> acceptQuest(User user, String partyId);
Observable<Void> rejectQuest(User user, String partyId);
Observable<Void> leaveQuest(String partyId);
Observable<Void> cancelQuest(String partyId);
Observable<Quest> abortQuest(String partyId);
Observable<Void> rejectGroupInvite(String groupId);
Observable<Quest> forceStartQuest(Group party);
}

View file

@ -4,6 +4,7 @@ import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.data.SocialRepository;
import com.habitrpg.android.habitica.data.local.SocialLocalRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.responses.PostChatMessageResult;
import com.habitrpg.android.habitica.models.social.Challenge;
import com.habitrpg.android.habitica.models.social.ChatMessage;
@ -195,4 +196,41 @@ public class SocialRepositoryImpl extends BaseRepositoryImpl<SocialLocalReposito
public Observable<RealmResults<Group>> getUserGroups() {
return localRepository.getUserGroups();
}
@Override
public Observable<Void> acceptQuest(User user, String partyId) {
return apiClient.acceptQuest(partyId)
.doOnNext(aVoid -> localRepository.updateRSVPNeeded(user, false));
}
@Override
public Observable<Void> rejectQuest(User user, String partyId) {
return apiClient.rejectQuest(partyId)
.doOnNext(aVoid -> localRepository.updateRSVPNeeded(user, false));
}
@Override
public Observable<Void> leaveQuest(String partyId) {
return apiClient.leaveQuest(partyId);
}
@Override
public Observable<Void> cancelQuest(String partyId) {
return apiClient.cancelQuest(partyId);
}
@Override
public Observable<Quest> abortQuest(String partyId) {
return apiClient.abortQuest(partyId);
}
@Override
public Observable<Void> rejectGroupInvite(String groupId) {
return apiClient.rejectQuest(groupId);
}
@Override
public Observable<Quest> forceStartQuest(Group party) {
return apiClient.forceStartQuest(party.id, party);
}
}

View file

@ -24,4 +24,6 @@ public interface SocialLocalRepository extends BaseLocalRepository {
void deleteMessage(String id);
Observable<RealmResults<User>> getGroupMembers(String partyId);
void updateRSVPNeeded(User user, boolean newValue);
}

View file

@ -81,6 +81,13 @@ public class RealmSocialLocalRepository extends RealmBaseLocalRepository impleme
.filter(RealmResults::isLoaded);
}
@Override
public void updateRSVPNeeded(User user, boolean newValue) {
if (user != null && user.getParty() != null && user.getParty().getQuest() != null) {
realm.executeTransaction(realm1 -> user.getParty().getQuest().RSVPNeeded = newValue);
}
}
private Observable<ChatMessage> getMessage(String id) {
return realm.where(ChatMessage.class).equalTo("id", id)
.findAllAsync()

View file

@ -17,7 +17,7 @@ public class RealmTagLocalRepository extends RealmBaseLocalRepository implements
@Override
public Observable<RealmResults<Tag>> getTags(String userId) {
return realm.where(Tag.class).equalTo("user.id", userId).findAll().asObservable();
return realm.where(Tag.class).equalTo("userId", userId).findAll().asObservable();
}
@Override

View file

@ -2,19 +2,20 @@ package com.habitrpg.android.habitica.models.inventory;
import java.util.HashMap;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.Ignore;
import io.realm.annotations.PrimaryKey;
public class Quest extends RealmObject {
@PrimaryKey
public String id;
public String key;
public boolean active;
public String leader;
public boolean RSVPNeeded;
@Ignore
public HashMap<String, Boolean> members;
public RealmList<QuestMember> members;
private QuestProgress progress;
private Quest(String key, QuestProgress progress) {

View file

@ -0,0 +1,12 @@
package com.habitrpg.android.habitica.models.inventory;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class QuestMember extends RealmObject {
@PrimaryKey
public String key;
public Boolean isParticipating;
}

View file

@ -8,6 +8,7 @@ import io.realm.annotations.PrimaryKey;
public class UserParty extends RealmObject {
@PrimaryKey
private String userId;
@SerializedName("_id")
public String id; //id
private Quest quest;
@ -57,4 +58,12 @@ public class UserParty extends RealmObject {
public void setQuest(Quest quest) {
this.quest = quest;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}

View file

@ -15,7 +15,17 @@ public class Flags extends RealmObject {
User user;
RealmList<TutorialStep> tutorial;
private boolean showTour, dropsEnabled, itemsEnabled, newStuff, classSelected, rebirthEnabled, welcomed, armoireEnabled, armoireOpened, armoireEmpty;
private boolean showTour;
private boolean dropsEnabled;
private boolean itemsEnabled;
private boolean newStuff;
private boolean classSelected;
private boolean rebirthEnabled;
private boolean welcomed;
private boolean armoireEnabled;
private boolean armoireOpened;
private boolean armoireEmpty;
private boolean communityGuidelinesAccepted;
public List<TutorialStep> getTutorial() {
return tutorial;
@ -112,4 +122,12 @@ public class Flags extends RealmObject {
public void setUserId(String userId) {
this.userId = userId;
}
public boolean isCommunityGuidelinesAccepted() {
return communityGuidelinesAccepted;
}
public void setCommunityGuidelinesAccepted(boolean communityGuidelinesAccepted) {
this.communityGuidelinesAccepted = communityGuidelinesAccepted;
}
}

View file

@ -158,6 +158,9 @@ public class User extends RealmObject {
public void setParty(UserParty party) {
this.party = party;
if (party != null && id != null && !party.isManaged()) {
party.setUserId(id);
}
}
public Items getItems() {
@ -451,4 +454,8 @@ public class User extends RealmObject {
public void setChallenges(RealmList<Challenge> challenges) {
this.challenges = challenges;
}
public boolean hasParty() {
return party != null && party.id != null && party.id.length() > 0;
}
}

View file

@ -73,22 +73,6 @@ public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter<Item, ItemRecy
}
}
public void openedMysteryItem(int numberLeft) {
// TODO: Fix this
/*int itemPos = 0;
for (Object obj : itemList) {
if (obj.getClass().equals(SpecialItem.class)) {
SpecialItem item = (SpecialItem) obj;
if (item.isMysteryItem) {
item.setOwned(numberLeft);
break;
}
}
itemPos++;
}
notifyItemChanged(itemPos);*/
}
public void setOwnedPets(RealmResults<Pet> pets) {
ownedPets = pets;
}

View file

@ -1,85 +0,0 @@
package com.habitrpg.android.habitica.ui.adapter.social;
import android.net.Uri;
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.QuestCollect;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.inventory.QuestProgress;
import com.habitrpg.android.habitica.models.inventory.QuestProgressCollect;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
public class QuestCollectRecyclerViewAdapter extends RecyclerView.Adapter<QuestCollectRecyclerViewAdapter.QuestCollectViewHolder> {
private QuestProgress progress;
private QuestContent quest;
public void setQuestProgress(QuestProgress progress) {
this.progress = progress;
this.notifyDataSetChanged();
}
public void setQuestContent(QuestContent quest) {
this.quest = quest;
this.notifyDataSetChanged();
}
@Override
public QuestCollectViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_quest_collect, parent, false);
return new QuestCollectViewHolder(view);
}
@Override
public void onBindViewHolder(QuestCollectViewHolder holder, int position) {
holder.bind(progress.collect.get(position));
}
@Override
public int getItemCount() {
return progress != null && progress.collect != null ? progress.collect.size() : 0;
}
class QuestCollectViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.image)
SimpleDraweeView image;
@BindView(R.id.name)
TextView name;
@BindView(R.id.count)
TextView count;
View view;
public QuestCollectViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
this.view = itemView;
}
public void bind(QuestProgressCollect collectProgress) {
image.setImageURI(Uri.parse("https://habitica-assets.s3.amazonaws.com/mobileApp/images/" + "quest_" + quest.getKey() + "_" + collectProgress.key + ".png"));
if (quest != null) {
QuestCollect collect = quest.getCollectWithKey(collectProgress.key);
if (collect != null) {
name.setText(collect.text);
count.setText(collectProgress.count + " / " + collect.count);
}
}
}
}
}

View file

@ -209,13 +209,4 @@ public class ItemRecyclerFragment extends BaseFragment {
command.identifier = MainDrawerBuilder.SIDEBAR_SHOPS;
EventBus.getDefault().post(command);
}
@Subscribe
public void openedMysteryItem(OpenedMysteryItemEvent event) {
this.adapter.openedMysteryItem(event.numberLeft);
inventoryRepository.getEquipment(event.mysteryItem.getKey()).subscribe(itemData -> {
MainActivity activity = (MainActivity) getActivity();
showSnackbar(activity, activity.floatingMenuWrapper, getString(R.string.notification_mystery_item, itemData.getText()), UiUtils.SnackbarDisplayType.NORMAL);
});
}
}

View file

@ -32,6 +32,8 @@ import java.util.Map;
import javax.inject.Inject;
import rx.Subscription;
public class PreferencesFragment extends BasePreferencesFragment implements
SharedPreferences.OnSharedPreferenceChangeListener {
@ -48,6 +50,7 @@ public class PreferencesFragment extends BasePreferencesFragment implements
private User user;
@Inject
PushNotificationManager pushNotificationManager;
private Subscription subscription;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -58,13 +61,14 @@ public class PreferencesFragment extends BasePreferencesFragment implements
String userID = getPreferenceManager().getSharedPreferences().getString(context.getString(R.string.SP_userID), null);
if (userID != null) {
userRepository.getUser(userID).subscribe(PreferencesFragment.this::setUser, RxErrorHandler.handleEmptyError());
subscription = userRepository.getUser(userID).subscribe(PreferencesFragment.this::setUser, RxErrorHandler.handleEmptyError());
}
}
@Override
public void onDestroy() {
userRepository.close();
subscription.unsubscribe();
super.onDestroy();
}
@ -209,9 +213,7 @@ public class PreferencesFragment extends BasePreferencesFragment implements
case "audioTheme": {
String newAudioTheme = sharedPreferences.getString(key, "off");
userRepository.updateUser(user, "preferences.sound", newAudioTheme)
.subscribe(habitRPGUser -> {
}, throwable -> {
});
.subscribe(habitRPGUser -> {}, throwable -> {});
Preferences preferences = user.getPreferences();
preferences.setSound(newAudioTheme);
@ -223,9 +225,7 @@ public class PreferencesFragment extends BasePreferencesFragment implements
}
case "dailyDueDefaultView":
userRepository.updateUser(user, "preferences.dailyDueDefaultView", sharedPreferences.getBoolean(key, false))
.subscribe(habitRPGUser -> {
}, throwable -> {
});
.subscribe(habitRPGUser -> {}, throwable -> {});
break;
}
}

View file

@ -3,6 +3,8 @@ package com.habitrpg.android.habitica.ui.fragments.social;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
@ -16,6 +18,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
@ -61,6 +64,8 @@ public class ChatListFragment extends BaseFragment implements SwipeRefreshLayout
EditText chatEditText;
@BindView(R.id.send_button)
ImageButton sendButton;
@BindView(R.id.community_guidelines_view)
TextView communityGuidelinesView;
LinearLayoutManager layoutManager;
private String groupId;
private User user;
@ -101,8 +106,9 @@ public class ChatListFragment extends BaseFragment implements SwipeRefreshLayout
}
if (view == null)
if (view == null) {
view = inflater.inflate(R.layout.fragment_chat, container, false);
}
return view;
}
@ -142,6 +148,18 @@ public class ChatListFragment extends BaseFragment implements SwipeRefreshLayout
recyclerView.setAdapter(chatAdapter);
socialRepository.getGroupChat(groupId).first().subscribe(this::setChatMessages, throwable -> {});
if (user != null && user.getFlags() != null && user.getFlags().isCommunityGuidelinesAccepted()) {
communityGuidelinesView.setVisibility(View.GONE);
} else {
communityGuidelinesView.setOnClickListener(v -> {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://habitica.com/static/community-guidelines"));
getContext().startActivity(i);
userRepository.updateUser(user, "flags.communityGuidelinesAccepted", true).subscribe(user1 -> {}, RxErrorHandler.handleEmptyError());
});
}
onRefresh();
}

View file

@ -1,14 +1,11 @@
package com.habitrpg.android.habitica.ui.fragments.social;
import android.app.AlertDialog;
import android.content.Context;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -21,11 +18,9 @@ import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.databinding.FragmentGroupInfoBinding;
import com.habitrpg.android.habitica.helpers.QrCodeManager;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.models.user.User;
import com.habitrpg.android.habitica.ui.adapter.social.QuestCollectRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.views.ValueBar;
@ -33,7 +28,6 @@ import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class GroupInformationFragment extends BaseFragment {
@ -45,12 +39,6 @@ public class GroupInformationFragment extends BaseFragment {
@Inject
UserRepository userRepository;
@BindView(R.id.questMemberView)
LinearLayout questMemberView;
@BindView(R.id.collectionStats)
RecyclerView collectionStats;
@BindView(R.id.qrLayout)
@Nullable
LinearLayout qrLayout;
@ -68,8 +56,6 @@ public class GroupInformationFragment extends BaseFragment {
private ValueBar bossHpBar;
private ValueBar bossRageBar;
private QuestCollectRecyclerViewAdapter questCollectViewAdapter;
public GroupInformationFragment() {
}
@ -90,7 +76,6 @@ public class GroupInformationFragment extends BaseFragment {
if (view == null) {
view = inflater.inflate(R.layout.fragment_group_info, container, false);
}
questCollectViewAdapter = new QuestCollectRecyclerViewAdapter();
viewBinding = DataBindingUtil.bind(view);
viewBinding.setHideParticipantCard(false);
@ -105,8 +90,6 @@ public class GroupInformationFragment extends BaseFragment {
unbinder = ButterKnife.bind(this, view);
collectionStats.setLayoutManager(new LinearLayoutManager(getContext()));
collectionStats.setAdapter(questCollectViewAdapter);
bossHpBar = (ValueBar) view.findViewById(R.id.bossHpBar);
bossRageBar = (ValueBar) view.findViewById(R.id.bossRageBar);
@ -147,10 +130,6 @@ public class GroupInformationFragment extends BaseFragment {
viewBinding.setGroup(group);
}
if (questMemberView != null) {
updateQuestMember(group);
}
this.group = group;
if (isAdded()) {
@ -175,12 +154,6 @@ public class GroupInformationFragment extends BaseFragment {
if (group == null || quest == null) {
return;
}
if (questCollectViewAdapter != null) {
questCollectViewAdapter.setQuestContent(quest);
if (group.quest.getProgress() != null) {
questCollectViewAdapter.setQuestProgress(group.quest.getProgress());
}
}
boolean showHpBar = (quest.boss != null && quest.boss.hp > 0);
bossHpBar.setVisibility(showHpBar ? View.VISIBLE : View.GONE);
@ -197,181 +170,4 @@ public class GroupInformationFragment extends BaseFragment {
viewBinding.setHideParticipantCard(true);
}
}
private void updateQuestMember(Group group) {
questMemberView.removeAllViewsInLayout();
if (group.quest == null || group.quest.key == null) return;
Context context = getContext();
if (context == null && group.quest.members != null) {
viewBinding.setHideParticipantCard(true);
return;
}
if (group.quest.members == null || group.members == null) {
viewBinding.setHideParticipantCard(true);
return;
}
viewBinding.setHideParticipantCard(false);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (User member : group.members) {
final LinearLayout itemView = (LinearLayout) layoutInflater.inflate(R.layout.party_member_quest, questMemberView, false);
TextView questResponse = (TextView) itemView.findViewById(R.id.rsvpneeded);
TextView userName = (TextView) itemView.findViewById(R.id.username);
userName.setText(member.getProfile().getName());
if (!group.quest.members.containsKey(member.getId()))
continue;
Boolean questresponse = group.quest.members.get(member.getId());
if (group.quest.active) {
questResponse.setText("");
} else if (questresponse == null) {
questResponse.setText(R.string.quest_pending);
} else if (questresponse) {
questResponse.setText(R.string.quest_accepted);
questResponse.setTextColor(ContextCompat.getColor(context, R.color.good_10));
} else {
questResponse.setText(R.string.quest_rejected);
questResponse.setTextColor(ContextCompat.getColor(context, R.color.worse_10));
}
questMemberView.post(() -> {
if (questMemberView != null) {
questMemberView.addView(itemView);
}
});
}
}
@OnClick(R.id.btnQuestAccept)
public void onQuestAccept() {
if (group != null) {
apiClient.acceptQuest(group.id)
.subscribe(aVoid -> {
if (user != null) {
user.getParty().getQuest().RSVPNeeded = false;
group.quest.members.put(user.getId(), true);
}
setGroup(group);
viewBinding.setUser(user);
}, throwable -> {
});
}
}
@OnClick(R.id.btnQuestReject)
public void onQuestReject() {
if (group != null) {
apiClient.rejectQuest(group.id)
.subscribe(aVoid -> {
if (user != null) {
user.getParty().getQuest().RSVPNeeded = false;
group.quest.members.put(user.getId(), false);
}
setGroup(group);
viewBinding.setUser(user);
}, throwable -> {
});
}
}
@OnClick(R.id.btnQuestLeave)
public void onQuestLeave() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage("Are you sure you want to leave the active quest? All your quest progress will be lost.")
.setPositiveButton("Yes", (dialog, which) -> {
if (group != null) {
apiClient.leaveQuest(group.id)
.subscribe(aVoid -> {
if (user != null) {
group.quest.members.remove(user.getId());
}
setGroup(group);
}, throwable -> {
});
}
}).setNegativeButton("No", (dialog, which) -> {
});
builder.show();
}
@OnClick(R.id.btnQuestBegin)
public void onQuestBegin() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_begin_message)
.setPositiveButton(R.string.yes, (dialog, which) -> {
if (group != null) {
apiClient.forceStartQuest(group.id, group)
.subscribe(quest -> {
group.quest = quest;
setGroup(group);
}, throwable -> {
});
}
}).setNegativeButton(R.string.no, (dialog, which) -> {
});
builder.show();
}
@OnClick(R.id.btnQuestCancel)
public void onQuestCancel() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_cancel_message)
.setPositiveButton(R.string.yes, (dialog, which) -> {
if (group != null) {
apiClient.cancelQuest(group.id)
.subscribe(aVoid -> {
setGroup(group);
setQuestContent(null);
}, throwable -> {
});
}
}).setNegativeButton(R.string.no, (dialog, which) -> {
});
builder.show();
}
@OnClick(R.id.btnQuestAbort)
public void onQuestAbort() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage("Are you sure you want to abort this mission? It will abort it for everyone in your party and all progress will be lost. The quest scroll will be returned to the quest owner.")
.setPositiveButton("Yes", (dialog, which) -> {
if (group != null) {
apiClient.abortQuest(group.id)
.subscribe(quest -> {
group.quest = quest;
setGroup(group);
setQuestContent(null);
}, throwable -> {
});
}
}).setNegativeButton("No", (dialog, which) -> {
});
builder.show();
}
@OnClick(R.id.btnPartyInviteAccept)
public void onPartyInviteAccepted() {
if (user != null) {
apiClient.joinGroup(user.getInvitations().getParty().getId())
.subscribe(group -> {
setGroup(group);
viewBinding.setInvitation(null);
}, throwable -> {
});
}
}
@OnClick(R.id.btnPartyInviteReject)
public void onPartyInviteRejected() {
if (user != null) {
apiClient.rejectGroupInvite(user.getInvitations().getParty().getId())
.subscribe(aVoid -> viewBinding.setInvitation(null), RxErrorHandler.handleEmptyError());
}
}
}

View file

@ -0,0 +1,255 @@
package com.habitrpg.android.habitica.ui.fragments.social.party;
import android.app.AlertDialog;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.data.InventoryRepository;
import com.habitrpg.android.habitica.data.SocialRepository;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.models.user.User;
import com.habitrpg.android.habitica.modules.AppModule;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.views.social.QuestProgressView;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.OnClick;
public class PartyDetailFragment extends BaseFragment {
@Inject
SocialRepository socialRepository;
@Inject
UserRepository userRepository;
@Inject
InventoryRepository inventoryRepository;
@Inject
@Named(AppModule.NAMED_USER_ID)
String userId;
@BindView(R.id.refresh_layout)
SwipeRefreshLayout refreshLayout;
@BindView(R.id.party_invitation_wrapper)
ViewGroup partyInvitationWrapper;
@BindView(R.id.title_view)
TextView titleView;
@BindView(R.id.description_view)
TextView descriptionView;
@BindView(R.id.new_quest_button)
Button newQuestButton;
@BindView(R.id.quest_detail_button)
ViewGroup questDetailButton;
@BindView(R.id.quest_scroll_image_view)
SimpleDraweeView questScrollImageView;
@BindView(R.id.quest_title_view)
TextView questTitleView;
@BindView(R.id.quest_participation_view)
TextView questParticipationView;
@BindView(R.id.quest_image_wrapper)
ViewGroup questImageWrapper;
@BindView(R.id.quest_image_view)
SimpleDraweeView questImageView;
@BindView(R.id.quest_participant_response_wrapper)
ViewGroup questParticipantResponseWrapper;
@BindView(R.id.quest_leader_response_wrapper)
ViewGroup questLeaderResponseWrapper;
@BindView(R.id.quest_accept_button)
Button questAcceptButton;
@BindView(R.id.quest_reject_button)
Button questRejectButton;
@BindView(R.id.quest_begin_button)
Button questBeginButton;
@BindView(R.id.quest_cancel_button)
Button questCancelButton;
@BindView(R.id.quest_progress_view)
QuestProgressView questProgressView;
public String partyId;
private Group party;
private Quest quest;
private User user;
@Override
public void injectFragment(AppComponent component) {
component.inject(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_party_detail, container, false);
}
@Override
public void onDestroyView() {
socialRepository.close();
userRepository.close();
inventoryRepository.close();
super.onDestroyView();
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
refreshLayout.setOnRefreshListener(this::refreshParty);
compositeSubscription.add(socialRepository.getGroup(partyId).subscribe(this::updateParty, RxErrorHandler.handleEmptyError()));
compositeSubscription.add(userRepository.getUser(userId).subscribe(this::updateUser, RxErrorHandler.handleEmptyError()));
}
private void refreshParty() {
socialRepository.retrieveGroup("party")
.flatMap(group1 -> socialRepository.retrieveGroupMembers(group1.id, true))
.subscribe(members -> refreshLayout.setRefreshing(false), throwable -> refreshLayout.setRefreshing(false));
}
private void updateParty(Group party) {
this.party = party;
this.quest = party.quest;
if (titleView == null) {
return;
}
if (party.quest != null && user != null && user.getId().equals(party.quest.leader)) {
questLeaderResponseWrapper.setVisibility(View.VISIBLE);
questParticipantResponseWrapper.setVisibility(View.GONE);
}
titleView.setText(party.name);
descriptionView.setText(party.description);
if (quest.key != null) {
newQuestButton.setVisibility(View.GONE);
questDetailButton.setVisibility(View.VISIBLE);
questImageWrapper.setVisibility(View.VISIBLE);
getActivity().runOnUiThread(() -> inventoryRepository.getQuestContent(quest.getKey())
.first()
.subscribe(this::updateQuestContent, RxErrorHandler.handleEmptyError()));
} else {
newQuestButton.setVisibility(View.VISIBLE);
questDetailButton.setVisibility(View.GONE);
questImageWrapper.setVisibility(View.GONE);
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.GONE);
questProgressView.setVisibility(View.GONE);
}
}
private void updateUser(User user) {
if (user == null || user.getParty() == null || user.getParty().getQuest() == null) {
return;
}
this.user = user;
if (user.getInvitations() != null && user.getInvitations().getParty() != null && user.getInvitations().getParty().getId() != null) {
partyInvitationWrapper.setVisibility(View.VISIBLE);
} else {
partyInvitationWrapper.setVisibility(View.GONE);
}
if (isQuestActive() || !user.getParty().getQuest().RSVPNeeded) {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.GONE);
} else {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.VISIBLE);
}
}
private void updateQuestContent(QuestContent questContent) {
questTitleView.setText(questContent.getText());
DataBindingUtils.loadImage(questScrollImageView, "inventory_quest_scroll_"+questContent.getKey());
DataBindingUtils.loadImage(questImageView, "quest_"+questContent.getKey());
if (isQuestActive()) {
questProgressView.setVisibility(View.VISIBLE);
questProgressView.setData(questContent, quest.getProgress());
questParticipationView.setText(getString(R.string.number_participants, quest.members.size()));
} else {
questProgressView.setVisibility(View.GONE);
}
}
private boolean isQuestActive() {
return quest != null && quest.active;
}
@OnClick(R.id.new_quest_button)
public void inviteNewQuest() {
}
@OnClick(R.id.leave_button)
public void leaveParty() {
}
@OnClick(R.id.quest_accept_button)
public void onQuestAccept() {
socialRepository.acceptQuest(user, partyId).subscribe(aVoid -> {}, throwable -> {});
}
@OnClick(R.id.quest_reject_button)
public void onQuestReject() {
socialRepository.rejectQuest(user, partyId).subscribe(aVoid -> {}, throwable -> {});
}
@OnClick(R.id.quest_begin_button)
public void onQuestBegin() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_begin_message)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.forceStartQuest(party)
.subscribe(quest -> {}, throwable -> {}))
.setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show();
}
@OnClick(R.id.quest_cancel_button)
public void onQuestCancel() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_cancel_message)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.cancelQuest(partyId)
.subscribe(aVoid -> {}, throwable -> {})).setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show();
}
@OnClick(R.id.party_invite_accept_button)
public void onPartyInviteAccepted() {
if (user != null) {
socialRepository.joinGroup(user.getInvitations().getParty().getId())
.subscribe(group -> {}, throwable -> {});
}
}
@OnClick(R.id.party_invite_reject_button)
public void onPartyInviteRejected() {
if (user != null) {
socialRepository.rejectGroupInvite(user.getInvitations().getParty().getId())
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
}
}

View file

@ -48,7 +48,6 @@ public class PartyFragment extends BaseMainFragment {
@Nullable
private Group group;
private PartyMemberListFragment partyMemberListFragment;
private GroupInformationFragment groupInformationFragment;
private ChatListFragment chatListFragment;
private FragmentPagerAdapter viewPagerAdapter;
@ -126,10 +125,6 @@ public class PartyFragment extends BaseMainFragment {
partyMemberListFragment.setPartyId(group.id);
}
if (groupInformationFragment != null) {
groupInformationFragment.setGroup(group);
}
if (chatListFragment != null && group != null) {
chatListFragment.seenGroupId = group.id;
}
@ -137,14 +132,6 @@ public class PartyFragment extends BaseMainFragment {
if (this.activity != null) {
this.activity.supportInvalidateOptionsMenu();
}
if (group != null && group.quest != null && group.quest.key != null && !group.quest.key.isEmpty()) {
inventoryRepository.getQuestContent(group.quest.key).first().subscribe(content -> {
if (groupInformationFragment != null) {
groupInformationFragment.setQuestContent(content);
}
}, RxErrorHandler.handleEmptyError());
}
}
@Override
@ -231,10 +218,7 @@ public class PartyFragment extends BaseMainFragment {
}
if (needsSaving) {
this.socialRepository.updateGroup(this.group, bundle.getString("name"), bundle.getString("description"), bundle.getString("leader"), bundle.getString("privacy"))
.subscribe(aVoid -> {
}, throwable -> {
});
this.groupInformationFragment.setGroup(group);
.subscribe(aVoid -> {}, throwable -> {});
}
}
break;
@ -291,7 +275,13 @@ public class PartyFragment extends BaseMainFragment {
switch (position) {
case 0: {
fragment = groupInformationFragment = GroupInformationFragment.newInstance(group, user);
if (user.hasParty()) {
PartyDetailFragment detailFragment = new PartyDetailFragment();
detailFragment.partyId = user.getParty().id;
fragment = detailFragment;
} else {
fragment = GroupInformationFragment.newInstance(null, user);
}
break;
}
case 1: {

View file

@ -126,6 +126,9 @@ public class TasksFragment extends BaseMainFragment {
@Override
public void onDestroy() {
tagRepository.close();
if (bottomNavigation != null) {
bottomNavigation.removeOnTabSelectListener();
}
super.onDestroy();
}

View file

@ -14,6 +14,7 @@ import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

View file

@ -54,6 +54,7 @@ public class ValueBar extends FrameLayout {
Drawable iconRes = attributes.getDrawable(R.styleable.ValueBar_barIconDrawable);
if (iconRes != null) {
iconView.setImageDrawable(iconRes);
iconView.setVisibility(View.VISIBLE);
}
descriptionTextView.setText(attributes.getString(R.styleable.ValueBar_description));
@ -71,7 +72,7 @@ public class ValueBar extends FrameLayout {
public void setLightBackground(boolean lightBackground) {
int textColor;
if (lightBackground) {
textColor = ContextCompat.getColor(getContext(), R.color.md_black_1000);
textColor = ContextCompat.getColor(getContext(), R.color.gray_10);
barBackground.setBackgroundResource(R.drawable.layout_rounded_bg_light_gray);
} else {
textColor = ContextCompat.getColor(getContext(), R.color.brand_500);

View file

@ -0,0 +1,85 @@
package com.habitrpg.android.habitica.ui.views.social;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.models.inventory.QuestCollect;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.inventory.QuestProgress;
import com.habitrpg.android.habitica.models.inventory.QuestProgressCollect;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.views.ValueBar;
import butterknife.BindView;
import butterknife.ButterKnife;
public class QuestProgressView extends LinearLayout {
@BindView(R.id.boss_name_view)
TextView bossNameView;
@BindView(R.id.boss_health_view)
ValueBar bossHealthView;
@BindView(R.id.collection_container)
ViewGroup collectionContainer;
public QuestProgressView(@NonNull Context context) {
super(context);
setupView(context);
}
public QuestProgressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setupView(context);
}
private void setupView(Context context) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.quest_progress, this);
ButterKnife.bind(this, this);
}
public void setData(QuestContent quest, QuestProgress progress) {
collectionContainer.removeAllViews();
if (quest.boss != null) {
bossNameView.setText(quest.boss.name);
if (progress != null) {
bossHealthView.set(progress.hp, quest.boss.hp);
}
bossNameView.setVisibility(View.VISIBLE);
bossHealthView.setVisibility(View.VISIBLE);
} else {
bossNameView.setVisibility(View.GONE);
bossHealthView.setVisibility(View.GONE);
if (progress != null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
for (QuestProgressCollect collect : progress.collect) {
QuestCollect contentCollect = quest.getCollectWithKey(collect.key);
if (contentCollect == null) {
continue;
}
View view = inflater.inflate(R.layout.quest_collect, collectionContainer, false);
SimpleDraweeView iconView = (SimpleDraweeView) view.findViewById(R.id.icon_view);
TextView nameView = (TextView) view.findViewById(R.id.name_view);
ValueBar valueView = (ValueBar) view.findViewById(R.id.value_view);
DataBindingUtils.loadImage(iconView, "quest_" + quest.getKey() + "_" + collect.key);
nameView.setText(contentCollect.text);
valueView.set(collect.count, contentCollect.count);
collectionContainer.addView(view);
}
}
}
}
}

View file

@ -73,6 +73,7 @@ public class GroupSerialization implements JsonDeserializer<Group>, JsonSerializ
if (obj.has("quest")) {
group.quest = context.deserialize(obj.get("quest"), new TypeToken<Quest>() {
}.getType());
group.quest.id = group.id;
}
return group;

View file

@ -6,6 +6,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.inventory.QuestMember;
import com.habitrpg.android.habitica.models.inventory.QuestProgress;
import com.habitrpg.android.habitica.models.inventory.QuestProgressCollect;
@ -59,6 +60,22 @@ public class QuestDeserializer implements JsonDeserializer<Quest> {
progress.collect.add(collect);
}
}
quest.setProgress(progress);
}
if (obj.has("members")) {
RealmList<QuestMember> members = new RealmList<>();
for (Map.Entry<String, JsonElement> entry : obj.get("members").getAsJsonObject().entrySet()) {
QuestMember member = new QuestMember();
member.key = entry.getKey();
if (entry.getValue().isJsonNull()) {
member.isParticipating = null;
} else {
member.isParticipating = entry.getValue().getAsBoolean();
}
members.add(member);
}
quest.members = members;
}
return quest;
}

View file

@ -37,6 +37,9 @@ public class QuestListDeserializer implements JsonDeserializer<List<QuestContent
item.setPrevious(parsedItem.getPrevious());
item.setCanBuy(parsedItem.isCanBuy());
item.setBoss(parsedItem.getBoss());
if (item.getBoss() != null) {
item.getBoss().key = item.getKey();
}
item.setCategory(parsedItem.getCategory());
item.setCollect(parsedItem.getCollect());
item.setLvl(parsedItem.getLvl());

View file

@ -7,6 +7,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import com.habitrpg.android.habitica.models.Tag;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.invitations.Invitations;
import com.habitrpg.android.habitica.models.social.Challenge;
import com.habitrpg.android.habitica.models.social.UserParty;
@ -25,6 +26,7 @@ import com.habitrpg.android.habitica.models.user.User;
import java.lang.reflect.Type;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmList;
public class UserDeserializer implements JsonDeserializer<User> {
@ -53,6 +55,16 @@ public class UserDeserializer implements JsonDeserializer<User> {
}
if (obj.has("party")) {
user.setParty(context.deserialize(obj.get("party"), UserParty.class));
if (user.getParty() != null && user.getParty().getQuest() != null) {
user.getParty().getQuest().id = user.getId();
if (!obj.get("party").getAsJsonObject().get("quest").getAsJsonObject().has("RSVPNeeded")) {
Realm realm = Realm.getDefaultInstance();
Quest quest = realm.where(Quest.class).equalTo("id", user.getId()).findFirst();
if (quest != null && quest.isValid()) {
user.getParty().getQuest().RSVPNeeded = quest.RSVPNeeded;
}
}
}
}
if (obj.has("items")) {
user.setItems(context.deserialize(obj.get("items"), Items.class));