diff --git a/Habitica/res/layout/activity_group_form.xml b/Habitica/res/layout/activity_group_form.xml
new file mode 100644
index 000000000..303b7f31f
--- /dev/null
+++ b/Habitica/res/layout/activity_group_form.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/fragment_party_info.xml b/Habitica/res/layout/fragment_group_info.xml
similarity index 72%
rename from Habitica/res/layout/fragment_party_info.xml
rename to Habitica/res/layout/fragment_group_info.xml
index bd6d5b3bd..6f79bd159 100644
--- a/Habitica/res/layout/fragment_party_info.xml
+++ b/Habitica/res/layout/fragment_group_info.xml
@@ -10,7 +10,7 @@
-
+
+ bind:parsemarkdown="@{group.description}" />
+
+
+
+
+
diff --git a/Habitica/res/layout/fragment_guilds_overview.xml b/Habitica/res/layout/fragment_guilds_overview.xml
index 1de15d2b1..afb3384a5 100644
--- a/Habitica/res/layout/fragment_guilds_overview.xml
+++ b/Habitica/res/layout/fragment_guilds_overview.xml
@@ -38,10 +38,13 @@
android:id="@+id/my_guilds_listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:showDividers="middle"
+ android:divider="@android:drawable/divider_horizontal_dark">
diff --git a/Habitica/res/layout/item_public_guild.xml b/Habitica/res/layout/item_public_guild.xml
new file mode 100644
index 000000000..1b88848f3
--- /dev/null
+++ b/Habitica/res/layout/item_public_guild.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/plain_list_item.xml b/Habitica/res/layout/plain_list_item.xml
index 14d9faea0..10a43f54f 100644
--- a/Habitica/res/layout/plain_list_item.xml
+++ b/Habitica/res/layout/plain_list_item.xml
@@ -1,16 +1,6 @@
-
-
-
-
\ No newline at end of file
diff --git a/Habitica/res/menu/chat_message.xml b/Habitica/res/menu/chat_message.xml
index 86b389eaf..d9e167150 100644
--- a/Habitica/res/menu/chat_message.xml
+++ b/Habitica/res/menu/chat_message.xml
@@ -6,24 +6,22 @@
android:id="@+id/menu.chat.copy.as.todo"
android:icon="@drawable/ic_action_launch"
- android:title="Copy as ToDo" />
+ android:title="@string/copy_as_todo" />
+ android:title="@string/send_pm" />
-
+ android:title="@string/flag" />
+ android:title="@string/delete" />
diff --git a/Habitica/res/menu/guild_admin.xml b/Habitica/res/menu/guild_admin.xml
new file mode 100644
index 000000000..0969ef891
--- /dev/null
+++ b/Habitica/res/menu/guild_admin.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/Habitica/res/menu/guild_member.xml b/Habitica/res/menu/guild_member.xml
new file mode 100644
index 000000000..508e51470
--- /dev/null
+++ b/Habitica/res/menu/guild_member.xml
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/Habitica/res/menu/guild_nonmember.xml b/Habitica/res/menu/guild_nonmember.xml
new file mode 100644
index 000000000..e17b8736e
--- /dev/null
+++ b/Habitica/res/menu/guild_nonmember.xml
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 2578ef363..430676c0e 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -215,4 +215,15 @@ To start, which parts of your life do you want to improve?
Want to help us keep Habitica running? You can support the developers by buying gems!\n\nGems allow you to buy fun extras for your account, including: \n\n - Cool costumes for your avatar\n - Awesome backgrounds\n - Fun quests that reward you with pet eggs\n - The ability to change your class before level 100\n\nThank you so much for helping us make Habitica the best it can be. Your support means a lot to us!
My Guilds
Public Guilds
+ Guild
+ Leave
+ Join
+ Leader
+ Gems
+ Copy as ToDo
+ Send PM
+ Flag
+ Delete
+ Name
+ Description
\ No newline at end of file
diff --git a/Habitica/src/com/habitrpg/android/habitica/APIHelper.java b/Habitica/src/com/habitrpg/android/habitica/APIHelper.java
index 957f6a72b..ec0795ff5 100644
--- a/Habitica/src/com/habitrpg/android/habitica/APIHelper.java
+++ b/Habitica/src/com/habitrpg/android/habitica/APIHelper.java
@@ -23,6 +23,7 @@ import com.magicmicky.habitrpgwrapper.lib.api.Server;
import com.magicmicky.habitrpgwrapper.lib.api.TypeAdapter.TagsAdapter;
import com.magicmicky.habitrpgwrapper.lib.models.Customization;
import com.magicmicky.habitrpgwrapper.lib.models.FAQArticle;
+import com.magicmicky.habitrpgwrapper.lib.models.Group;
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest;
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult;
import com.magicmicky.habitrpgwrapper.lib.models.Purchases;
@@ -40,6 +41,7 @@ import com.magicmicky.habitrpgwrapper.lib.utils.ChecklistItemSerializer;
import com.magicmicky.habitrpgwrapper.lib.utils.CustomizationDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.DateDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.FAQArticleListDeserilializer;
+import com.magicmicky.habitrpgwrapper.lib.utils.GroupDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.PurchasedDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.SkillDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.TaskListDeserializer;
@@ -117,6 +119,7 @@ public class APIHelper implements ErrorHandler, Profiler {
.registerTypeAdapter(customizationListType, new CustomizationDeserializer())
.registerTypeAdapter(tutorialStepListType, new TutorialStepListDeserializer())
.registerTypeAdapter(faqArticleListType, new FAQArticleListDeserilializer())
+ .registerTypeAdapter(Group.class, new GroupDeserializer())
.registerTypeAdapter(Date.class, new DateDeserializer())
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.create();
diff --git a/Habitica/src/com/habitrpg/android/habitica/events/DisplayFragmentEvent.java b/Habitica/src/com/habitrpg/android/habitica/events/DisplayFragmentEvent.java
new file mode 100644
index 000000000..bea9802bb
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/events/DisplayFragmentEvent.java
@@ -0,0 +1,8 @@
+package com.habitrpg.android.habitica.events;
+
+import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
+
+public class DisplayFragmentEvent {
+
+ public BaseMainFragment fragment;
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.java b/Habitica/src/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.java
new file mode 100644
index 000000000..d6bd3529f
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.java
@@ -0,0 +1,151 @@
+package com.habitrpg.android.habitica.ui.activities;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.content.ContextCompat;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.PopupWindow;
+
+import com.github.data5tream.emojilib.EmojiEditText;
+import com.github.data5tream.emojilib.EmojiGridView;
+import com.github.data5tream.emojilib.EmojiPopup;
+import com.github.data5tream.emojilib.emoji.Emojicon;
+import com.habitrpg.android.habitica.R;
+
+import butterknife.Bind;
+
+public class GroupFormActivity extends BaseActivity {
+
+ @Bind(R.id.group_name_edittext)
+ EditText groupNameEditText;
+
+ @Bind(R.id.group_description_edittext)
+ EmojiEditText groupDescriptionEditText;
+
+ @Bind(R.id.emoji_toggle_btn)
+ ImageButton emojiButton;
+
+ EmojiPopup popup;
+
+ @Override
+ protected int getLayoutResId() {
+ return R.layout.activity_group_form;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Emoji keyboard stuff
+
+ popup = new EmojiPopup(emojiButton.getRootView(), this, ContextCompat.getColor(this, R.color.brand));
+
+ popup.setSizeForSoftKeyboard();
+ popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
+
+ @Override
+ public void onDismiss() {
+ changeEmojiKeyboardIcon(false);
+ }
+ });
+ popup.setOnSoftKeyboardOpenCloseListener(new EmojiPopup.OnSoftKeyboardOpenCloseListener() {
+
+ @Override
+ public void onKeyboardOpen(int keyBoardHeight) {
+
+ }
+
+ @Override
+ public void onKeyboardClose() {
+ if (popup.isShowing())
+ popup.dismiss();
+ }
+ });
+
+ popup.setOnEmojiconClickedListener(new EmojiGridView.OnEmojiconClickedListener() {
+
+ @Override
+ public void onEmojiconClicked(Emojicon emojicon) {
+ EmojiEditText emojiEditText = null;
+ if (getCurrentFocus() == null || !isEmojiEditText(getCurrentFocus()) || emojicon == null) {
+ return;
+ } else {
+ emojiEditText = (EmojiEditText) getCurrentFocus();
+ }
+ int start = emojiEditText.getSelectionStart();
+ int end = emojiEditText.getSelectionEnd();
+ if (start < 0) {
+ emojiEditText.append(emojicon.getEmoji());
+ } else {
+ emojiEditText.getText().replace(Math.min(start, end),
+ Math.max(start, end), emojicon.getEmoji(), 0,
+ emojicon.getEmoji().length());
+ }
+ }
+ });
+
+ popup.setOnEmojiconBackspaceClickedListener(new EmojiPopup.OnEmojiconBackspaceClickedListener() {
+
+ @Override
+ public void onEmojiconBackspaceClicked(View v) {
+ if (isEmojiEditText(getCurrentFocus())) {
+ KeyEvent event = new KeyEvent(
+ 0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL);
+ getCurrentFocus().dispatchKeyEvent(event);
+ }
+ }
+ });
+
+ emojiButton.setOnClickListener(new emojiClickListener(groupDescriptionEditText));
+ }
+
+ private boolean isEmojiEditText(View view) {
+ return view instanceof EmojiEditText;
+ }
+
+ private void changeEmojiKeyboardIcon(Boolean keyboardOpened) {
+
+ if (keyboardOpened) {
+ emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_keyboard_grey600_24dp));
+ } else {
+ emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_emoticon_grey600_24dp));
+ }
+ }
+
+ private class emojiClickListener implements View.OnClickListener {
+
+ EmojiEditText view;
+
+ public emojiClickListener(EmojiEditText view) {
+ this.view = view;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if(!popup.isShowing()){
+
+ if(popup.isKeyBoardOpen()){
+ popup.showAtBottom();
+ changeEmojiKeyboardIcon(true);
+ }
+
+ else{
+ view.setFocusableInTouchMode(true);
+ view.requestFocus();
+ popup.showAtBottomPending();
+ final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
+ changeEmojiKeyboardIcon(true);
+ }
+ }
+
+ else{
+ popup.dismiss();
+ changeEmojiKeyboardIcon(false);
+ }
+ }
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java
index 89b87cca1..d7ff85f1d 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java
@@ -31,6 +31,7 @@ import com.habitrpg.android.habitica.HabiticaApplication;
import com.habitrpg.android.habitica.HostConfig;
import com.habitrpg.android.habitica.NotificationPublisher;
import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.events.DisplayFragmentEvent;
import com.habitrpg.android.habitica.events.DisplayTutorialEvent;
import com.habitrpg.android.habitica.ui.TutorialView;
import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
@@ -223,7 +224,7 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
if (this.activeFragment != null && fragment.getClass() == this.activeFragment.getClass()) {
return;
}
-
+ this.activeFragment = fragment;
fragment.setArguments(getIntent().getExtras());
fragment.mAPIHelper = mAPIHelper;
fragment.setUser(user);
@@ -492,6 +493,7 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
drawer.getDrawerLayout().closeDrawer(Gravity.RIGHT);
} else {
super.onBackPressed();
+
}
}
@@ -619,6 +621,10 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
this.displayTutorialStep(tutorialEvent.step, tutorialEvent.tutorialText);
}
+ public void onEvent(DisplayFragmentEvent event) {
+ this.displayFragment(event.fragment);
+ }
+
// endregion
@Override
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.java b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.java
new file mode 100644
index 000000000..22438b97d
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.java
@@ -0,0 +1,137 @@
+package com.habitrpg.android.habitica.ui.adapter.social;
+
+import android.content.res.Resources;
+import android.databinding.DataBindingUtil;
+import android.support.v7.widget.RecyclerView;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.habitrpg.android.habitica.APIHelper;
+import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.databinding.ValueBarBinding;
+import com.habitrpg.android.habitica.events.DisplayFragmentEvent;
+import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
+import com.habitrpg.android.habitica.ui.fragments.social.GuildFragment;
+import com.habitrpg.android.habitica.ui.helpers.ViewHelper;
+import com.habitrpg.android.habitica.userpicture.UserPicture;
+import com.magicmicky.habitrpgwrapper.lib.api.ApiService;
+import com.magicmicky.habitrpgwrapper.lib.models.Group;
+import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
+
+import java.util.ArrayList;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.greenrobot.event.EventBus;
+import retrofit.Callback;
+import retrofit.RetrofitError;
+import retrofit.client.Response;
+
+public class PublicGuildsRecyclerViewAdapter extends RecyclerView.Adapter {
+
+ public APIHelper apiHelper;
+ private ArrayList publicGuildList;
+ private ArrayList memberGuildIDs;
+
+ public void setPublicGuildList(ArrayList publicGuildList) {
+ this.publicGuildList = publicGuildList;
+ this.notifyDataSetChanged();
+ }
+
+ public void setMemberGuildIDs(ArrayList memberGuildIDs) {
+ this.memberGuildIDs = memberGuildIDs;
+ }
+
+ @Override
+ public GuildViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.item_public_guild, parent, false);
+
+ return new GuildViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(GuildViewHolder holder, int position) {
+ holder.bind(publicGuildList.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return this.publicGuildList == null ? 0 : this.publicGuildList.size();
+ }
+
+ class GuildViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, Callback {
+
+ @Bind(R.id.nameTextView)
+ TextView nameTextView;
+
+ @Bind(R.id.memberCountTextView)
+ TextView memberCountTextView;
+
+ @Bind(R.id.descriptionTextView)
+ TextView descriptionTextView;
+
+ @Bind(R.id.joinleaveButton)
+ Button joinLeaveButton;
+
+ Group guild;
+ Boolean isMember;
+
+ public GuildViewHolder(View itemView) {
+ super(itemView);
+
+ ButterKnife.bind(this, itemView);
+ itemView.setOnClickListener(this);
+ joinLeaveButton.setOnClickListener(this);
+ }
+
+ public void bind(Group guild) {
+ android.content.Context ctx = itemView.getContext();
+ this.guild = guild;
+ this.nameTextView.setText(guild.name);
+ this.memberCountTextView.setText(String.valueOf(guild.memberCount));
+ this.descriptionTextView.setText(guild.description);
+ if (PublicGuildsRecyclerViewAdapter.this.memberGuildIDs.contains(guild.id)) {
+ this.isMember = true;
+ this.joinLeaveButton.setText(R.string.leave);
+ } else {
+ this.isMember = false;
+ this.joinLeaveButton.setText(R.string.join);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == this.joinLeaveButton) {
+ if (this.isMember) {
+ PublicGuildsRecyclerViewAdapter.this.apiHelper.apiService.leaveGroup(this.guild.id, this);
+ } else {
+ PublicGuildsRecyclerViewAdapter.this.apiHelper.apiService.joinGroup(this.guild.id, this);
+ }
+ } else {
+ GuildFragment guildFragment = new GuildFragment();
+ guildFragment.setGuild(this.guild);
+ guildFragment.isMember = this.isMember;
+ DisplayFragmentEvent event = new DisplayFragmentEvent();
+ event.fragment = guildFragment;
+ EventBus.getDefault().post(event);
+ }
+ }
+
+ @Override
+ public void success(Group group, Response response) {
+ this.bind(guild);
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+
+ }
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInformationFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.java
similarity index 71%
rename from Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInformationFragment.java
rename to Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.java
index 5c6704153..f2ec5c5e4 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInformationFragment.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.java
@@ -1,4 +1,4 @@
-package com.habitrpg.android.habitica.ui.fragments.social.party;
+package com.habitrpg.android.habitica.ui.fragments.social;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
@@ -9,32 +9,31 @@ import android.view.View;
import android.view.ViewGroup;
import com.habitrpg.android.habitica.R;
-import com.habitrpg.android.habitica.databinding.FragmentPartyInfoBinding;
+import com.habitrpg.android.habitica.databinding.FragmentGroupInfoBinding;
import com.magicmicky.habitrpgwrapper.lib.models.Group;
import com.magicmicky.habitrpgwrapper.lib.models.QuestContent;
/**
* Created by Negue on 16.09.2015.
*/
-public class PartyInformationFragment extends Fragment {
+public class GroupInformationFragment extends Fragment {
private View view;
- FragmentPartyInfoBinding viewBinding;
+ FragmentGroupInfoBinding viewBinding;
private Group group;
-
- public static PartyInformationFragment newInstance(Group group) {
+ public static GroupInformationFragment newInstance(Group group) {
Bundle args = new Bundle();
- PartyInformationFragment fragment = new PartyInformationFragment();
+ GroupInformationFragment fragment = new GroupInformationFragment();
fragment.setArguments(args);
fragment.group = group;
return fragment;
}
- public PartyInformationFragment(){
+ public GroupInformationFragment(){
}
@@ -42,7 +41,7 @@ public class PartyInformationFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (view == null)
- view = inflater.inflate(R.layout.fragment_party_info, container, false);
+ view = inflater.inflate(R.layout.fragment_group_info, container, false);
viewBinding = DataBindingUtil.bind(view);
@@ -55,7 +54,7 @@ public class PartyInformationFragment extends Fragment {
public void setGroup(Group group) {
if (viewBinding != null) {
- viewBinding.setParty(group);
+ viewBinding.setGroup(group);
}
}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java
new file mode 100644
index 000000000..f9b7217c2
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java
@@ -0,0 +1,216 @@
+package com.habitrpg.android.habitica.ui.fragments.social;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.habitrpg.android.habitica.ContentCache;
+import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
+import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
+import com.magicmicky.habitrpgwrapper.lib.models.Group;
+import com.magicmicky.habitrpgwrapper.lib.models.UserParty;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import retrofit.Callback;
+import retrofit.RetrofitError;
+import retrofit.client.Response;
+
+public class GuildFragment extends BaseMainFragment implements Callback {
+
+ private Group guild;
+ public boolean isMember;
+
+ public ViewPager viewPager;
+
+ private GroupInformationFragment guildInformationFragment;
+ private ChatListFragment chatListFragment;
+
+ public void setGuild(Group guild) {
+ this.guild = guild;
+ if (this.guildInformationFragment != null) {
+ this.guildInformationFragment.setGroup(guild);
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ this.usesTabLayout = true;
+ super.onCreateView(inflater, container, savedInstanceState);
+ View v = inflater.inflate(R.layout.fragment_party, container, false);
+
+ viewPager = (ViewPager) v.findViewById(R.id.view_pager);
+
+ viewPager.setCurrentItem(0);
+
+ final ContentCache contentCache = new ContentCache(mAPIHelper.apiService);
+
+ // Get the full group data
+ mAPIHelper.apiService.getGroup(this.guild.id, new Callback() {
+ @Override
+ public void success(Group group, Response response) {
+ if (group == null) {
+ tabLayout.removeAllTabs();
+ return;
+ }
+ GuildFragment.this.guild = group;
+
+ if (guildInformationFragment != null) {
+ guildInformationFragment.setGroup(group);
+ }
+
+ if (chatListFragment != null) {
+ chatListFragment.seenGroupId = group.id;
+ }
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+ }
+ });
+
+ setViewPagerAdapter();
+
+ return v;
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (this.isMember) {
+ if (this.user.getId().equals(this.guild.leaderID)) {
+ this.activity.getMenuInflater().inflate(R.menu.guild_admin, menu);
+ } else {
+ this.activity.getMenuInflater().inflate(R.menu.guild_member, menu);
+ }
+ } else {
+ this.activity.getMenuInflater().inflate(R.menu.guild_nonmember, menu);
+ }
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+
+ switch (id) {
+ case R.id.menu_guild_join:
+ this.mAPIHelper.apiService.joinGroup(this.guild.id, this);
+ return true;
+ case R.id.menu_guild_leave:
+ this.mAPIHelper.apiService.leaveGroup(this.guild.id, this);
+ return true;
+ case R.id.menu_guild_edit:
+ this.displayEditForm();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ public void setViewPagerAdapter() {
+ android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
+
+ UserParty party = user.getParty();
+
+ if (party == null) {
+ return;
+ }
+
+ viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
+
+ @Override
+ public Fragment getItem(int position) {
+
+ Fragment fragment;
+
+ switch (position) {
+ case 0: {
+ fragment = guildInformationFragment = GroupInformationFragment.newInstance(GuildFragment.this.guild);
+ break;
+ }
+ case 1: {
+ chatListFragment = new ChatListFragment();
+ chatListFragment.configure(activity, GuildFragment.this.guild.id, mAPIHelper, user, activity, false);
+ fragment = chatListFragment;
+ break;
+ }
+ default:
+ fragment = new Fragment();
+ }
+
+ return fragment;
+ }
+
+ @Override
+ public int getCount() {
+ return 2;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case 0:
+ return activity.getString(R.string.guild);
+ case 1:
+ return activity.getString(R.string.chat);
+ }
+ return "";
+ }
+ });
+
+ viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ if (position == 1 && GuildFragment.this.guild != null) {
+ chatListFragment.setNavigatedToFragment(GuildFragment.this.guild.id);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if (position == 1 && GuildFragment.this.guild != null) {
+ chatListFragment.setNavigatedToFragment(GuildFragment.this.guild.id);
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+
+ }
+ });
+
+ tabLayout.setupWithViewPager(viewPager);
+ }
+
+ @Override
+ public void success(Group group, Response response) {
+ this.guild = group;
+ this.guildInformationFragment.setGroup(group);
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+
+ }
+
+ private void displayEditForm() {
+ Bundle bundle = new Bundle();
+ bundle.putString("groupID",this.guild.id);
+
+ Intent intent = new Intent(activity, TaskFormActivity.class);
+ intent.putExtras(bundle);
+ intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+ startActivity(intent);
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java
index 3b62e9dc4..9bed66faf 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java
@@ -3,8 +3,10 @@ package com.habitrpg.android.habitica.ui.fragments.social;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
@@ -18,28 +20,47 @@ import com.raizlabs.android.dbflow.sql.language.OrderBy;
import com.raizlabs.android.dbflow.sql.language.Select;
import com.raizlabs.android.dbflow.sql.language.Where;
+import org.w3c.dom.Text;
+
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
+import butterknife.OnClick;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
-public class GuildsOverviewFragment extends BaseMainFragment implements Callback> {
+public class GuildsOverviewFragment extends BaseMainFragment implements Callback>, View.OnClickListener {
@Bind(R.id.my_guilds_listview)
LinearLayout guildsListView;
+ @Bind(R.id.publicGuildsButton)
+ Button publicGuildsButton;
+
+
+ private List guilds;
+ private ArrayList guildIDs;
+
+ @Override
+ public void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+ this.fetchGuilds();
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_guilds_overview, container, false);
ButterKnife.bind(this, v);
- this.fetchGuilds();
+ this.publicGuildsButton.setOnClickListener(this);
+ if (this.guilds != null) {
+ this.setGuildsOnListView();
+ }
return v;
}
@@ -56,26 +77,48 @@ public class GuildsOverviewFragment extends BaseMainFragment implements Callback
.from(Group.class)
.where(Condition.column("type").eq("guild"));
- List guilds = select.queryList();
+ this.guilds = select.queryList();
+ this.setGuildsOnListView();
}
- private void setGuildsOnListView(List guilds) {
+ private void setGuildsOnListView() {
+ if (this.guildsListView == null) {
+ return;
+ }
+ this.guildIDs = new ArrayList<>();
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- for (Group guild : guilds) {
- LinearLayout entry = (LinearLayout) inflater.inflate(R.layout.plain_list_item, null);
- TextView textView = (TextView) entry.findViewById(R.id.textView);
- textView.setText(guild.name);
+ for (Group guild : this.guilds) {
+ TextView entry = (TextView) inflater.inflate(R.layout.plain_list_item, null);
+ entry.setText(guild.name);
+ entry.setOnClickListener(this);
this.guildsListView.addView(entry);
+ this.guildIDs.add(guild.id);
}
}
@Override
public void success(ArrayList groups, Response response) {
- this.setGuildsOnListView(groups);
+ this.guilds = groups;
+ this.setGuildsOnListView();
}
@Override
public void failure(RetrofitError error) {
}
+
+ @Override
+ public void onClick(View v) {
+ if (v == this.publicGuildsButton) {
+ PublicGuildsFragment publicGuildsFragment = new PublicGuildsFragment();
+ publicGuildsFragment.memberGuildIDs = this.guildIDs;
+ this.activity.displayFragment(publicGuildsFragment);
+ } else {
+ Integer guildIndex = ((ViewGroup)v.getParent()).indexOfChild(v);
+ GuildFragment guildFragment = new GuildFragment();
+ guildFragment.setGuild(this.guilds.get(guildIndex));
+ guildFragment.isMember = true;
+ this.activity.displayFragment(guildFragment);
+ }
+ }
}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java
new file mode 100644
index 000000000..2686bc68d
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java
@@ -0,0 +1,79 @@
+package com.habitrpg.android.habitica.ui.fragments.social;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAdapter;
+import com.habitrpg.android.habitica.ui.adapter.social.PublicGuildsRecyclerViewAdapter;
+import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
+import com.magicmicky.habitrpgwrapper.lib.models.Group;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import retrofit.Callback;
+import retrofit.RetrofitError;
+import retrofit.client.Response;
+
+public class PublicGuildsFragment extends BaseMainFragment implements Callback> {
+
+ ArrayList memberGuildIDs;
+ ArrayList guilds;
+
+ @Bind(R.id.recyclerView)
+ RecyclerView recyclerView;
+
+ private View view;
+ private PublicGuildsRecyclerViewAdapter viewAdapter;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ if (view == null) {
+ view = inflater.inflate(R.layout.fragment_recyclerview, container, false);
+
+ ButterKnife.bind(this, view);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this.activity));
+ viewAdapter = new PublicGuildsRecyclerViewAdapter();
+ viewAdapter.setMemberGuildIDs(this.memberGuildIDs);
+ viewAdapter.apiHelper = this.mAPIHelper;
+ recyclerView.setAdapter(viewAdapter);
+ if (this.guilds != null) {
+ this.viewAdapter.setPublicGuildList(this.guilds);
+ }
+ }
+ return view;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+ this.fetchGuilds();
+ }
+
+ private void fetchGuilds() {
+ this.mAPIHelper.apiService.listGroups("public", this);
+ }
+
+ @Override
+ public void success(ArrayList groups, Response response) {
+ this.guilds = groups;
+ if (this.viewAdapter!= null) {
+ this.viewAdapter.setPublicGuildList(groups);
+ }
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java
index 7d82d4146..22a0454bb 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java
@@ -14,6 +14,7 @@ import com.habitrpg.android.habitica.ContentCache;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.habitrpg.android.habitica.ui.fragments.social.ChatListFragment;
+import com.habitrpg.android.habitica.ui.fragments.social.GroupInformationFragment;
import com.magicmicky.habitrpgwrapper.lib.models.Group;
import com.magicmicky.habitrpgwrapper.lib.models.QuestContent;
import com.magicmicky.habitrpgwrapper.lib.models.UserParty;
@@ -34,7 +35,7 @@ public class PartyFragment extends BaseMainFragment {
private HashMap fragmentDictionary = new HashMap<>();
private PartyMemberListFragment partyMemberListFragment;
- private PartyInformationFragment partyInformationFragment;
+ private GroupInformationFragment groupInformationFragment;
private ChatListFragment chatListFragment;
@Override
@@ -72,8 +73,8 @@ public class PartyFragment extends BaseMainFragment {
partyMemberListFragment.setMemberList(group.members);
}
- if (partyInformationFragment != null) {
- partyInformationFragment.setGroup(group);
+ if (groupInformationFragment != null) {
+ groupInformationFragment.setGroup(group);
}
if(chatListFragment != null){
@@ -84,8 +85,8 @@ public class PartyFragment extends BaseMainFragment {
contentCache.GetQuestContent(group.quest.key, new ContentCache.QuestContentCallback() {
@Override
public void GotQuest(QuestContent content) {
- if (partyInformationFragment != null) {
- partyInformationFragment.setQuestContent(content);
+ if (groupInformationFragment != null) {
+ groupInformationFragment.setQuestContent(content);
}
}
});
@@ -122,7 +123,7 @@ public class PartyFragment extends BaseMainFragment {
switch (position) {
case 0: {
- fragment = partyInformationFragment = PartyInformationFragment.newInstance(group);
+ fragment = groupInformationFragment = GroupInformationFragment.newInstance(group);
break;
}
case 1: {
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java
index d9b35d284..d36d09a1e 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java
@@ -446,19 +446,21 @@ public class TasksFragment extends BaseMainFragment implements OnCheckedChangeLi
//endregion Events
public void fillTagFilterDrawer(List tagList) {
- filterDrawer.removeAllItems();
- filterDrawer.addItems(
- new SectionDrawerItem().withName("Filter by Tag"),
- new EditTextDrawer()
- );
-
- for (Tag t : tagList) {
- filterDrawer.addItem(new SwitchDrawerItem()
- .withName(t.getName())
- .withTag(t)
- .withChecked(this.tagsHelper.isTagChecked(t.getId()))
- .withOnCheckedChangeListener(this)
+ if (filterDrawer != null) {
+ filterDrawer.removeAllItems();
+ filterDrawer.addItems(
+ new SectionDrawerItem().withName("Filter by Tag"),
+ new EditTextDrawer()
);
+
+ for (Tag t : tagList) {
+ filterDrawer.addItem(new SwitchDrawerItem()
+ .withName(t.getName())
+ .withTag(t)
+ .withChecked(this.tagsHelper.isTagChecked(t.getId()))
+ .withOnCheckedChangeListener(this)
+ );
+ }
}
}
diff --git a/Habitica/src/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java b/Habitica/src/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java
index 58de1ad8e..b4fce3681 100644
--- a/Habitica/src/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java
+++ b/Habitica/src/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java
@@ -117,6 +117,12 @@ public interface ApiService {
@GET("/groups/{gid}/chat")
void listGroupChat(@Path("gid") String groupId, Callback> cb);
+ @GET("/groups/{gid}/join")
+ void joinGroup(@Path("gid") String groupId, Callback cb);
+
+ @GET("/groups/{gid}/leave")
+ void leaveGroup(@Path("gid") String groupId, Callback cb);
+
@POST("/groups/{gid}/chat")
void postGroupChat(@Path("gid") String groupId, @Query("message") String message, Callback cb);
diff --git a/Habitica/src/com/magicmicky/habitrpgwrapper/lib/models/Group.java b/Habitica/src/com/magicmicky/habitrpgwrapper/lib/models/Group.java
index 3a8a35246..f5b0ab183 100644
--- a/Habitica/src/com/magicmicky/habitrpgwrapper/lib/models/Group.java
+++ b/Habitica/src/com/magicmicky/habitrpgwrapper/lib/models/Group.java
@@ -17,9 +17,7 @@ public class Group extends BaseModel {
public String description;
- // TODO Leader
- // GET /groups?type={0} => leader is string
- // GET /groups/{gid} => leader is user-object
+ public String leaderID;
public String name;
diff --git a/Habitica/src/com/magicmicky/habitrpgwrapper/lib/utils/GroupDeserializer.java b/Habitica/src/com/magicmicky/habitrpgwrapper/lib/utils/GroupDeserializer.java
new file mode 100644
index 000000000..802573086
--- /dev/null
+++ b/Habitica/src/com/magicmicky/habitrpgwrapper/lib/utils/GroupDeserializer.java
@@ -0,0 +1,54 @@
+package com.magicmicky.habitrpgwrapper.lib.utils;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.reflect.TypeToken;
+import com.magicmicky.habitrpgwrapper.lib.models.ChatMessage;
+import com.magicmicky.habitrpgwrapper.lib.models.Group;
+import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+public class GroupDeserializer implements JsonDeserializer {
+ @Override
+ public Group deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+ Group group = new Group();
+ JsonObject obj = json.getAsJsonObject();
+ group.id = obj.get("_id").getAsString();
+ group.name = obj.get("name").getAsString();
+ group.description = obj.get("description").getAsString();
+
+ if (obj.has("memberCount")) {
+ group.memberCount = obj.get("memberCount").getAsInt();
+ }
+ if (obj.has("balance")) {
+ group.balance = obj.get("balance").getAsDouble();
+ }
+ if (obj.has("logo")) {
+ group.logo = obj.get("logo").getAsString();
+ }
+ if (obj.has("type")) {
+ group.type = obj.get("type").getAsString();
+ }
+ if (obj.has("chat")) {
+ group.chat = context.deserialize(obj.get("chat"), new TypeToken>() {
+ }.getType());
+ }
+ if (obj.has("members")) {
+ group.members = context.deserialize(obj.get("members"), new TypeToken>(){}.getType());
+ }
+ if (obj.has("leader")) {
+ if (obj.get("leader").isJsonPrimitive()) {
+ group.leaderID = obj.get("leader").getAsString();
+ } else {
+ group.leaderID = obj.get("leader").getAsJsonObject().get("_id").getAsString();
+ }
+ }
+
+ return group;
+ }
+}