improve party view

This commit is contained in:
Phillip Thelen 2017-07-17 16:41:18 +02:00
parent 44d1673f7d
commit cc79b47fb3
19 changed files with 628 additions and 79 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="1916"
android:versionName="1.1.3"
android:versionCode="1917"
android:versionName="1.1.4"
android:screenOrientation="portrait"
android:installLocation="auto" >

View file

@ -17,9 +17,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView.Default"
android:id="@+id/party_invitation_wrapper"
>
android:id="@+id/party_invitation_wrapper">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
@ -119,8 +117,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_keyboard_arrow_right_gray_24dp"
android:visibility="gone"/>
app:srcCompat="@drawable/ic_keyboard_arrow_right_gray_24dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/quest_image_wrapper"

View file

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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">
<LinearLayout
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_border"
android:paddingRight="@dimen/content_border"
android:paddingTop="12dp"
android:paddingBottom="12dp"
>
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/quest_scroll_image_view"
android:layout_width="63dp"
android:layout_height="63dp"
android:scaleType="fitCenter"
android:padding="6dp"
android:background="@color/gray_700"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/quest_title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Headline"
tools:text="Vice, Part 3: Vice Awakens"
android:textStyle="bold"/>
<TextView
android:id="@+id/quest_leader_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Subheader2"
tools:text="Started by Username"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_10_alpha"/>
<LinearLayout
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="12dp"
android:paddingLeft="@dimen/content_border"
android:paddingRight="@dimen/content_border"
android:paddingBottom="12dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/description"
style="@style/Body1"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/description_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Body2"
tools:text="This is the description"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/content_section_spacing"
android:layout_marginBottom="@dimen/header_spacing">
<TextView
android:id="@+id/participants_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Participants"
style="@style/Body1"/>
<TextView
android:id="@+id/participants_header_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Body1"
tools:text="3"
android:textColor="@color/gray_300"
android:layout_marginLeft="6dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/quest_participant_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_10_alpha"/>
<LinearLayout
android:id="@+id/quest_participant_response_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
android:padding="@dimen/content_border">
<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"
android:visibility="gone"
android:padding="@dimen/content_border">
<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" />
<Button
android:id="@+id/quest_abort_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest.abort"
style="@style/HabiticaButton.Red" />
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>

View file

@ -0,0 +1,26 @@
<?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="match_parent"
android:paddingTop="6dp"
android:paddingBottom="6dp">
<ImageView
android:id="@+id/avatar_view"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="fitCenter"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/participant_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"/>
<TextView
android:id="@+id/status_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View file

@ -107,4 +107,7 @@
<dimen name="setup_customization_size">56dp</dimen>
<dimen name="outer_inset">16dp</dimen>
<dimen name="rounded_button_radius">6dp</dimen>
<dimen name="content_border">21dp</dimen>
<dimen name="content_section_spacing">21dp</dimen>
<dimen name="header_spacing">6dp</dimen>
</resources>

View file

@ -615,4 +615,11 @@
<string name="start_day">Start My Day</string>
<string name="leave_party_confirmation">Are you sure you want to leave the Party?</string>
<string name="nextPrizeUnlocksIn" formatted="false">Next Prize in %d Check-ins</string>
<string name="pending">Pending</string>
<string name="accepted">Accepted</string>
<string name="declined">Declined</string>
<string name="participants">Participants</string>
<string name="invitations">Invitations</string>
<string name="quest_leader_header" formatted="false">Started by %s</string>
<string name="quest_abort_message">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>
</resources>

View file

@ -70,6 +70,7 @@ 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.InboxMessageListFragment;
import com.habitrpg.android.habitica.ui.fragments.social.PublicGuildsFragment;
import com.habitrpg.android.habitica.ui.fragments.social.QuestDetailFragment;
import com.habitrpg.android.habitica.ui.fragments.social.TavernDetailFragment;
import com.habitrpg.android.habitica.ui.fragments.social.TavernFragment;
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDetailDialogHolder;
@ -271,4 +272,6 @@ public interface AppComponent {
void inject(TavernDetailFragment tavernDetailFragment);
void inject(PartyDetailFragment partyDetailFragment);
void inject(QuestDetailFragment questDetailFragment);
}

View file

@ -184,7 +184,7 @@ public class SocialRepositoryImpl extends BaseRepositoryImpl<SocialLocalReposito
@Override
public Observable<List<Member>> retrieveGroupMembers(String id, boolean includeAllPublicFields) {
return apiClient.getGroupMembers(id, includeAllPublicFields)
.doOnNext(localRepository::save);
.doOnNext(members -> localRepository.saveGroupMembers(id, members));
}
@Override
@ -232,12 +232,14 @@ public class SocialRepositoryImpl extends BaseRepositoryImpl<SocialLocalReposito
@Override
public Observable<Void> cancelQuest(String partyId) {
return apiClient.cancelQuest(partyId);
return apiClient.cancelQuest(partyId)
.doOnNext(aVoid -> localRepository.removeQuest(partyId));
}
@Override
public Observable<Quest> abortQuest(String partyId) {
return apiClient.abortQuest(partyId);
return apiClient.abortQuest(partyId)
.doOnNext(aVoid -> localRepository.removeQuest(partyId));
}
@Override
@ -247,6 +249,7 @@ public class SocialRepositoryImpl extends BaseRepositoryImpl<SocialLocalReposito
@Override
public Observable<Quest> forceStartQuest(Group party) {
return apiClient.forceStartQuest(party.id, localRepository.getUnmanagedCopy(party));
return apiClient.forceStartQuest(party.id, localRepository.getUnmanagedCopy(party))
.doOnNext(aVoid -> localRepository.setQuestActivity(party, true));
}
}

View file

@ -29,4 +29,10 @@ public interface SocialLocalRepository extends BaseLocalRepository {
void updateRSVPNeeded(User user, boolean newValue);
void likeMessage(ChatMessage chatMessage, String userId, boolean liked);
void saveGroupMembers(String groupId, List<Member> members);
void removeQuest(String partyId);
void setQuestActivity(Group party, boolean active);
}

View file

@ -7,6 +7,9 @@ import com.habitrpg.android.habitica.models.social.ChatMessageLike;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.models.user.User;
import java.util.ArrayList;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
@ -107,6 +110,53 @@ public class RealmSocialLocalRepository extends RealmBaseLocalRepository impleme
});
}
@Override
public void saveGroupMembers(String groupId, List<Member> members) {
realm.executeTransaction(realm1 -> realm.insertOrUpdate(members));
if (groupId != null) {
List<Member> existingMembers = realm.where(Member.class).equalTo("party.id", groupId).findAll();
List<Member> membersToRemove = new ArrayList<>();
for (Member existingMember : existingMembers) {
boolean isStillMember = false;
for (Member newMember : members) {
if (existingMember.getId() != null && existingMember.getId().equals(newMember.getId())) {
isStillMember = true;
break;
}
}
if (!isStillMember) {
membersToRemove.add(existingMember);
}
}
realm.executeTransaction(realm1 -> {
for (Member member : membersToRemove) {
member.deleteFromRealm();
}
});
}
}
@Override
public void removeQuest(String partyId) {
Group party = realm.where(Group.class).equalTo("id", partyId).findFirst();
if (party != null) {
realm.executeTransaction(realm1 -> {
party.quest = null;
});
}
}
@Override
public void setQuestActivity(Group party, boolean active) {
realm.executeTransaction(realm1 -> {
if (party != null && party.quest != null) {
party.quest.active = active;
}
});
}
private Observable<ChatMessage> getMessage(String id) {
return realm.where(ChatMessage.class).equalTo("id", id)
.findAllAsync()

View file

@ -1,5 +1,7 @@
package com.habitrpg.android.habitica.models.inventory;
import com.habitrpg.android.habitica.models.members.Member;
import java.util.HashMap;
import io.realm.RealmList;
@ -18,6 +20,8 @@ public class Quest extends RealmObject {
public RealmList<QuestMember> members;
private QuestProgress progress;
public RealmList<Member> participants;
private Quest(String key, QuestProgress progress) {
this.key = key;
this.progress = progress;

View file

@ -39,6 +39,8 @@ public class Member extends RealmObject implements Avatar {
private String currentMount;
private String currentPet;
private Boolean participatesInQuest;
public Preferences getPreferences() {
return preferences;
}
@ -313,4 +315,19 @@ public class Member extends RealmObject implements Avatar {
public boolean getSleep() {
return getPreferences() != null && getPreferences().getSleep();
}
public Boolean getParticipatesInQuest() {
return participatesInQuest;
}
public void setParticipatesInQuest(Boolean participatesInQuest) {
this.participatesInQuest = participatesInQuest;
}
public String getDisplayName() {
if (profile == null) {
return "";
}
return profile.getName();
}
}

View file

@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.models.social;
import com.google.gson.annotations.SerializedName;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.members.Member;
import com.habitrpg.android.habitica.models.user.User;
import io.realm.RealmList;
@ -44,7 +45,6 @@ public class Group extends RealmObject {
public String leaderMessage;
@Override
public boolean equals(Object o) {
if (this == o) {

View file

@ -38,8 +38,8 @@ import rx.subjects.PublishSubject;
public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter<Item, ItemRecyclerAdapter.ItemViewHolder> {
public Boolean isHatching;
public Boolean isFeeding;
public boolean isHatching;
public boolean isFeeding;
public Item hatchingItem;
public Pet feedingPet;
public ItemRecyclerFragment fragment;
@ -135,7 +135,7 @@ public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter<Item, ItemRecy
}
imageName = "Pet_" + type + "_" + item.getKey();
if (isHatching != null && isHatching) {
if (isHatching) {
disabled = this.isPetOwned();
}
}

View file

@ -54,8 +54,8 @@ public class ItemRecyclerFragment extends BaseFragment {
public ItemRecyclerAdapter adapter;
public String itemType;
public String itemTypeText;
public Boolean isHatching;
public Boolean isFeeding;
public boolean isHatching;
public boolean isFeeding;
public Item hatchingItem;
public Pet feedingPet;
@Nullable
@ -118,14 +118,14 @@ public class ItemRecyclerFragment extends BaseFragment {
this.itemType = savedInstanceState.getString(ITEM_TYPE_KEY, "");
}
if (this.isHatching != null && this.isHatching) {
if (this.isHatching) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
this.titleView.setText(getString(R.string.hatch_with, this.hatchingItem.getText()));
this.titleView.setVisibility(View.VISIBLE);
this.footerView.setText(getString(R.string.hatching_market_info));
this.footerView.setVisibility(View.VISIBLE);
this.openMarketButton.setVisibility(View.VISIBLE);
} else if (this.isFeeding != null && this.isFeeding) {
} else if (this.isFeeding) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
this.titleView.setText(getString(R.string.dialog_feeding, this.feedingPet.getColorText(), this.feedingPet.getAnimalText()));
this.titleView.setVisibility(View.VISIBLE);
@ -160,7 +160,7 @@ public class ItemRecyclerFragment extends BaseFragment {
@Override
public void onResume() {
if (((this.isHatching != null && this.isHatching) || (this.isFeeding != null && this.isFeeding)) && getDialog().getWindow() != null) {
if ((this.isHatching || this.isFeeding) && getDialog().getWindow() != null) {
android.view.WindowManager.LayoutParams params = getDialog().getWindow().getAttributes();
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.verticalMargin = 60;

View file

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

View file

@ -24,7 +24,10 @@ import com.habitrpg.android.habitica.models.inventory.QuestContent;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.models.user.User;
import com.habitrpg.android.habitica.modules.AppModule;
import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment;
import com.habitrpg.android.habitica.ui.fragments.social.QuestDetailFragment;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
import com.habitrpg.android.habitica.ui.views.social.QuestProgressView;
@ -75,16 +78,10 @@ public class PartyDetailFragment extends BaseFragment {
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;
@BindView(R.id.quest_participant_list)
@ -145,7 +142,7 @@ public class PartyDetailFragment extends BaseFragment {
titleView.setText(party.name);
descriptionView.setText(MarkdownParser.parseMarkdown(party.description));
if (quest.key != null) {
if (quest != null && quest.key != null) {
newQuestButton.setVisibility(View.GONE);
questDetailButton.setVisibility(View.VISIBLE);
questImageWrapper.setVisibility(View.VISIBLE);
@ -175,34 +172,17 @@ public class PartyDetailFragment extends BaseFragment {
partyInvitationWrapper.setVisibility(invitationVisibility);
}
if (questLeaderResponseWrapper != null) {
if (questParticipantResponseWrapper != null) {
if (showParticipatantButtons()) {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.VISIBLE);
} else if (showLeaderButtons()) {
if (isQuestActive()) {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.GONE);
} else {
questLeaderResponseWrapper.setVisibility(View.VISIBLE);
questParticipantResponseWrapper.setVisibility(View.GONE);
}
} else {
questLeaderResponseWrapper.setVisibility(View.GONE);
questParticipantResponseWrapper.setVisibility(View.GONE);
}
}
}
private boolean showLeaderButtons() {
return party != null && party.quest != null && user != null && user.getId().equals(party.quest.leader);
}
private boolean showParticipatantButtons() {
if (user == null || user.getParty() == null || user.getParty().getQuest() == null) {
return false;
}
return !isQuestActive() && user.getParty().getQuest().RSVPNeeded;
return !(user == null || user.getParty() == null || user.getParty().getQuest() == null) && !isQuestActive() && user.getParty().getQuest().RSVPNeeded;
}
private void updateQuestContent(QuestContent questContent) {
@ -227,13 +207,19 @@ public class PartyDetailFragment extends BaseFragment {
@OnClick(R.id.new_quest_button)
public void inviteNewQuest() {
ItemRecyclerFragment fragment = new ItemRecyclerFragment();
fragment.itemType = "quests";
fragment.itemTypeText = getString(R.string.quest);
fragment.show(getFragmentManager(), "questDialog");
}
@OnClick(R.id.leave_button)
public void leaveParty() {
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setMessage(R.string.leave_party_confirmation)
.setPositiveButton(R.string.yes, (dialog, which) -> socialRepository.leaveGroup(partyId)
.subscribe(aVoid -> {}, throwable -> {})).setNegativeButton(R.string.no, (dialog, which) -> {});
builder.show(); }
@OnClick(R.id.quest_accept_button)
public void onQuestAccept() {
@ -246,25 +232,6 @@ public class PartyDetailFragment extends BaseFragment {
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) {
@ -280,4 +247,17 @@ public class PartyDetailFragment extends BaseFragment {
.subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError());
}
}
@OnClick(R.id.quest_detail_button)
public void questDetailButtonClicked() {
QuestDetailFragment fragment = new QuestDetailFragment();
fragment.partyId = partyId;
if (party != null && party.quest != null) {
fragment.questKey = party.quest.key;
}
if (getActivity() != null) {
MainActivity activity = (MainActivity) getActivity();
activity.displayFragment(fragment);
}
}
}

View file

@ -10,14 +10,18 @@ import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.members.Member;
import com.habitrpg.android.habitica.models.social.ChatMessage;
import com.habitrpg.android.habitica.models.social.Group;
import com.habitrpg.android.habitica.models.user.User;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import io.realm.Realm;
import io.realm.RealmList;
import io.realm.RealmResults;
public class GroupSerialization implements JsonDeserializer<Group>, JsonSerializer<Group> {
@Override
@ -51,13 +55,6 @@ public class GroupSerialization implements JsonDeserializer<Group>, JsonSerializ
group.chat = context.deserialize(obj.get("chat"), new TypeToken<RealmList<ChatMessage>>() {
}.getType());
}
if (obj.has("members")) {
JsonArray memberList = obj.get("members").getAsJsonArray();
if (memberList.size() > 0 && memberList.get(0).isJsonObject()) {
group.members = context.deserialize(memberList, new TypeToken<List<User>>() {
}.getType());
}
}
if (obj.has("leader")) {
if (obj.get("leader").isJsonPrimitive()) {
group.leaderID = obj.get("leader").getAsString();
@ -74,6 +71,37 @@ public class GroupSerialization implements JsonDeserializer<Group>, JsonSerializ
group.quest = context.deserialize(obj.get("quest"), new TypeToken<Quest>() {
}.getType());
group.quest.id = group.id;
if (obj.getAsJsonObject("quest").has("members")) {
JsonObject members = obj.getAsJsonObject("quest").getAsJsonObject("members");
Realm realm = Realm.getDefaultInstance();
List<Member> dbMembers = realm.copyFromRealm(realm.where(Member.class).equalTo("party.id", group.id).findAll());
realm.close();
for (Member member : dbMembers) {
if (members.has(member.getId())) {
JsonElement value = members.get(member.getId());
if (value.isJsonNull()) {
member.setParticipatesInQuest(null);
} else {
member.setParticipatesInQuest(value.getAsBoolean());
}
} else {
member.setParticipatesInQuest(null);
}
members.remove(member.getId());
}
for (Map.Entry<String, JsonElement> entry : members.entrySet()) {
Member member = new Member();
member.setId(entry.getKey());
if (!entry.getValue().isJsonNull()) {
member.setParticipatesInQuest(entry.getValue().getAsBoolean());
}
dbMembers.add(member);
}
RealmList<Member> newMembers = new RealmList<>();
newMembers.addAll(dbMembers);
group.quest.participants = newMembers;
}
}
return group;

View file

@ -23,11 +23,15 @@ import io.realm.Realm;
public class MemberSerialization implements JsonDeserializer<Member> {
@Override
public Member deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Member member = new Member();
JsonObject obj = json.getAsJsonObject();
String id = obj.get("_id").getAsString();
if (obj.has("_id")) {
member.setId(obj.get("_id").getAsString());
Realm realm = Realm.getDefaultInstance();
Member member = realm.where(Member.class).equalTo("id", id).findFirst();
if (member == null) {
member = new Member();
} else {
member = realm.copyFromRealm(member);
}
if (obj.has("stats")) {
@ -47,7 +51,6 @@ public class MemberSerialization implements JsonDeserializer<Member> {
if (member.getParty() != null && member.getParty().getQuest() != null) {
member.getParty().getQuest().id = member.getId();
if (!obj.get("party").getAsJsonObject().get("quest").getAsJsonObject().has("RSVPNeeded")) {
Realm realm = Realm.getDefaultInstance();
Quest quest = realm.where(Quest.class).equalTo("id", member.getId()).findFirst();
if (quest != null && quest.isValid()) {
member.getParty().getQuest().RSVPNeeded = quest.RSVPNeeded;
@ -81,6 +84,7 @@ public class MemberSerialization implements JsonDeserializer<Member> {
member.setContributor(context.deserialize(obj.get("contributor"), ContributorInfo.class));
}
realm.close();
return member;
}
}