diff --git a/Habitica/res/layout-w320dp/party_member.xml b/Habitica/res/layout-w320dp/party_member.xml index 465a060b6..eb19cc8cc 100644 --- a/Habitica/res/layout-w320dp/party_member.xml +++ b/Habitica/res/layout-w320dp/party_member.xml @@ -70,10 +70,24 @@ + + diff --git a/Habitica/res/layout/fragment_group_info.xml b/Habitica/res/layout/fragment_group_info.xml index d925b6b36..f6727eb7f 100644 --- a/Habitica/res/layout/fragment_group_info.xml +++ b/Habitica/res/layout/fragment_group_info.xml @@ -173,40 +173,27 @@ android:layout_height="wrap_content" style="@style/CardContent" android:divider="?android:listDivider" + android:dividerPadding="@dimen/spacing_medium" android:showDividers="middle" android:orientation="vertical"> + + - - - - - - - - + android:padding="@dimen/spacing_medium"/> + android:orientation="horizontal" + android:padding="@dimen/spacing_medium"> + + \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt index 38ea7966b..ccde0977b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt @@ -115,8 +115,8 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap return Flowable.empty() } return apiClient.leaveGroup(id) + .doOnNext { _ -> localRepository.updateMembership(userID, id, false) } .flatMapMaybe { localRepository.getGroup(id).firstElement() } - .doOnNext { _ -> localRepository.executeTransaction { localRepository.updateMembership(userID, id, false) } } } override fun joinGroup(id: String?): Flowable { @@ -150,7 +150,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap val memberships = groups.map { GroupMembership(userID, it.id) } - localRepository.save(memberships) + localRepository.saveGroupMemberships(userID, memberships) } localRepository.save(groups) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt index 71352aa53..200915a85 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt @@ -44,4 +44,5 @@ interface SocialLocalRepository : BaseLocalRepository { fun getInboxMessages(userId: String, replyToUserID: String?): Flowable> fun getInboxOverviewList(userId: String): Flowable> + fun saveGroupMemberships(userID: String?, memberships: List) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt index a92e9f7a2..dd9c96474 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt @@ -45,6 +45,23 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm) } } + override fun saveGroupMemberships(userID: String?, memberships: List) { + realm.executeTransaction { realm.insertOrUpdate(memberships) } + if (userID != null) { + val existingMemberships = realm.where(GroupMembership::class.java).equalTo("userID", userID).findAll() + val membersToRemove = ArrayList() + for (existingMembership in existingMemberships) { + val isStillMember = memberships.any { existingMembership.combinedID == it.combinedID } + if (!isStillMember) { + membersToRemove.add(existingMembership) + } + } + realm.executeTransaction { + membersToRemove.forEach { it.deleteFromRealm() } + } + } + } + override fun getPublicGuilds(): Flowable> = realm.where(Group::class.java) .equalTo("type", "guild") .equalTo("privacy", "public") diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt index 3bedf55ae..c40af66dc 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt @@ -18,6 +18,8 @@ open class Group : RealmObject() { var description: String? = null + var summary: String? = null + var leaderID: String? = null var leaderName: String? = null @@ -44,13 +46,8 @@ open class Group : RealmObject() { if (this === other) { return true } - if (other == null || javaClass != other.javaClass) { - return false - } - - val group = other as Group - - return id == group.id + val group = other as? Group + return id == group?.id } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt index 5cc6148ce..e11fa4562 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt @@ -69,8 +69,7 @@ open class Task : RealmObject, Parcelable { var isDue: Boolean? = null - var nextDue: Date? = null - var yesterDaily: Boolean? = null + var nextDue: RealmList? = null //Needed for offline creating/updating var isSaving: Boolean = false @@ -171,14 +170,15 @@ open class Task : RealmObject, Parcelable { today.add(Calendar.DAY_OF_MONTH, -1) } - if (nextDue != null && !isDisplayedActive) { + val nextDate = nextDue?.firstOrNull() + if (nextDate != null && !isDisplayedActive) { val nextDueCalendar = GregorianCalendar() - nextDueCalendar.time = nextDue + nextDueCalendar.time = nextDate newTime.set(nextDueCalendar.get(Calendar.YEAR), nextDueCalendar.get(Calendar.MONTH), nextDueCalendar.get(Calendar.DAY_OF_MONTH)) return newTime.time } - return newTime.time + return if (isDisplayedActive) newTime.time else null } fun parseMarkdown() { @@ -198,7 +198,7 @@ open class Task : RealmObject, Parcelable { fun markdownText(callback: (CharSequence) -> Unit): CharSequence { if (this.parsedText != null) { - return this.parsedText as CharSequence + return this.parsedText ?: "" } MarkdownParser.parseMarkdownAsync(this.text, Consumer { parsedText -> diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/VerifyUsernameActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/VerifyUsernameActivity.kt index b7a81f8b3..6096ef7aa 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/VerifyUsernameActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/VerifyUsernameActivity.kt @@ -146,4 +146,8 @@ class VerifyUsernameActivity: BaseActivity() { finish() } } + + override fun onBackPressed() { + moveTaskToBack(true) + } } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt index d2f9220b4..282ff3ecf 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt @@ -31,7 +31,12 @@ import io.realm.OrderedRealmCollection import io.realm.RealmRecyclerViewAdapter import net.pherth.android.emoji_library.EmojiTextView -class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean, internal var user: User?, private val isTavern: Boolean, private val releasedUsernames: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) { +class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean, user: User?, private val isTavern: Boolean, private val releasedUsernames: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) { + internal var user = user + set(value) { + field = value + uuid = user?.id ?: "" + } private var uuid: String = "" private var expandedMessageId: String? = null diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt index a9d1b3943..2486d547f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt @@ -1,7 +1,5 @@ package com.habitrpg.android.habitica.ui.adapter.social -import androidx.core.content.ContextCompat -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.view.ViewGroup import android.widget.ImageView @@ -13,7 +11,6 @@ import com.habitrpg.android.habitica.models.members.Member import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.ui.AvatarView import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel -import com.habitrpg.android.habitica.ui.helpers.ViewHelper import com.habitrpg.android.habitica.ui.helpers.bindView import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.ValueBar @@ -26,6 +23,8 @@ import io.realm.RealmRecyclerViewAdapter class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) { + var leaderID: String? = null + private val userClickedEvents = PublishSubject.create() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MemberViewHolder { @@ -49,11 +48,18 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection?, auto private val sublineTextView: TextView by bindView(R.id.subline_textview) private val buffIconView: ImageView by bindView(R.id.buff_icon_view) private val classIconView: ImageView by bindView(R.id.class_icon_view) - private val hpBar: ValueBar by bindView(R.id.hpBar) + private val hpBar: ValueBar by bindView(R.id.hp_bar) + private val expBar: ValueBar by bindView(R.id.exp_bar) + private val mpBar: ValueBar by bindView(R.id.mp_bar) + private val leaderTextView: TextView by bindView(R.id.leader_textview) init { hpBar.setLightBackground(true) hpBar.setIcon(HabiticaIconsHelper.imageOfHeartLightBg()) + expBar.setLightBackground(true) + expBar.setIcon(HabiticaIconsHelper.imageOfExperience()) + mpBar.setLightBackground(true) + mpBar.setIcon(HabiticaIconsHelper.imageOfMagic()) buffIconView.setImageBitmap(HabiticaIconsHelper.imageOfBuffIcon()) } @@ -61,7 +67,11 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection?, auto fun bind(user: Member) { avatarView.setAvatar(user) - user.stats.notNull { AvatarWithBarsViewModel.setHpBarData(hpBar, it) } + user.stats.notNull { + AvatarWithBarsViewModel.setHpBarData(hpBar, it) + expBar.set(it.exp ?: 0.0, it.toNextLevel?.toDouble() ?: 0.0) + mpBar.set(it.mp ?: 0.0, it.maxMP?.toDouble() ?: 0.0) + } displayNameTextView.username = user.profile?.name displayNameTextView.tier = user.contributor?.level ?: 0 @@ -98,6 +108,8 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection?, auto itemView.isClickable = true itemView.setOnClickListener { userClickedEvents.onNext(user.id ?: "") } + + leaderTextView.visibility = if (user.id == leaderID) View.VISIBLE else View.GONE } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.kt index ea502a30c..276473104 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PublicGuildsRecyclerViewAdapter.kt @@ -115,7 +115,7 @@ class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection?, auto fun bind(guild: Group, isInGroup: Boolean) { this.nameTextView.text = guild.name this.memberCountTextView.text = guild.memberCount.toString() - this.descriptionTextView.text = MarkdownParser.parseMarkdown(guild.description) + this.descriptionTextView.text = MarkdownParser.parseMarkdown(guild.summary) if (isInGroup) { this.joinLeaveButton.setText(R.string.leave) } else { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatFragment.kt index ab67d8d30..7039862b7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatFragment.kt @@ -92,8 +92,6 @@ class ChatFragment constructor(private val viewModel: PartyViewModel) : BaseFrag compositeSubscription.add(viewModel.getChatMessages().firstElement().subscribe(Consumer> { this.setChatMessages(it) }, RxErrorHandler.handleEmptyError())) - - viewModel.getUserData().observe(viewLifecycleOwner, Observer { chatAdapter?.user = it if (it?.flags?.isCommunityGuidelinesAccepted == true) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt index b58c68c8f..34444df0d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt @@ -9,6 +9,7 @@ import android.graphics.Shader import android.graphics.drawable.BitmapDrawable import android.net.Uri import android.os.Bundle +import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -119,6 +120,9 @@ class GroupInformationFragment : BaseFragment() { }, RxErrorHandler.handleEmptyError()) } } + + groupDescriptionView.movementMethod = LinkMovementMethod.getInstance() + groupSummaryView.movementMethod = LinkMovementMethod.getInstance() } private fun refresh() { @@ -170,12 +174,9 @@ class GroupInformationFragment : BaseFragment() { groupDescriptionWrapper.visibility = groupItemVisibility groupDescriptionView.text = MarkdownParser.parseMarkdown(group?.description) - leadernameWrapper.visibility = if (group?.leaderName != null) View.VISIBLE else View.GONE - leadernameTextView.text = group?.leaderName - leaderMessageWrapper.visibility = if (group?.leaderMessage != null) View.VISIBLE else View.GONE - leaderMessageTextView.text = group?.leaderMessage - leadernameWrapper.visibility = if (group?.balance != null && group.balance > 0) View.VISIBLE else View.GONE - leadernameTextView.text = (group?.balance ?: 0 * 4.0).toString() + groupSummaryView.text = MarkdownParser.parseMarkdown(group?.summary) + gemCountWrapper.visibility = if (group?.balance != null && group.balance > 0) View.VISIBLE else View.GONE + gemCountTextView.text = (group?.balance ?: 0 * 4.0).toInt().toString() } companion object { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.kt index 4d4524d92..5d7dd33f6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.kt @@ -76,10 +76,10 @@ class GuildsOverviewFragment : BaseMainFragment(), View.OnClickListener, android } private fun fetchGuilds() { - this.socialRepository.retrieveGroups("guilds") + compositeSubscription.add(this.socialRepository.retrieveGroups("guilds") .subscribe(Consumer { swipeRefreshLayout?.isRefreshing = false - }, RxErrorHandler.handleEmptyError()) + }, RxErrorHandler.handleEmptyError())) } private fun setGuilds(guilds: RealmResults) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.kt index 261f22ceb..108023e5a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.kt @@ -49,9 +49,9 @@ class PublicGuildsFragment : BaseMainFragment(), SearchView.OnQueryTextListener recyclerView?.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this.activity) recyclerView?.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(getActivity()!!, androidx.recyclerview.widget.DividerItemDecoration.VERTICAL)) + viewAdapter = PublicGuildsRecyclerViewAdapter(null, true) viewAdapter.setMemberGuildIDs(this.memberGuildIDs?.toMutableList() ?: mutableListOf()) viewAdapter.apiClient = this.apiClient - viewAdapter = PublicGuildsRecyclerViewAdapter(null, true) recyclerView?.adapter = viewAdapter recyclerView?.itemAnimator = SafeDefaultItemAnimator() this.fetchGuilds() @@ -63,12 +63,12 @@ class PublicGuildsFragment : BaseMainFragment(), SearchView.OnQueryTextListener } private fun fetchGuilds() { - this.socialRepository.getPublicGuilds() + compositeSubscription.add(this.socialRepository.getPublicGuilds() .firstElement() .subscribe(Consumer { groups -> this@PublicGuildsFragment.viewAdapter.updateData(groups) - }, RxErrorHandler.handleEmptyError()) - this.socialRepository.retrieveGroups("publicGuilds").subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) + }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(this.socialRepository.retrieveGroups("publicGuilds").subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt index db5d8620f..81928b973 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt @@ -175,9 +175,9 @@ class PartyDetailFragment constructor(private val viewModel: PartyViewModel) : B } if (viewModel.isQuestActive) { questProgressView?.visibility = View.VISIBLE - questProgressView?.setData(questContent, viewModel.getQuestData().value?.progress) + questProgressView?.setData(questContent, viewModel.getGroupData().value?.quest?.progress) - questParticipationView?.text = getString(R.string.number_participants, viewModel.getQuestData().value?.members?.size) + questParticipationView?.text = getString(R.string.number_participants, viewModel.getGroupData().value?.quest?.members?.size) } else { questProgressView?.visibility = View.GONE } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt index 939d6c4ed..7441644b4 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt @@ -219,7 +219,7 @@ class PartyFragment : BaseMainFragment() { } 2 -> { if (partyMemberListFragment == null) { - partyMemberListFragment = PartyMemberListFragment() + partyMemberListFragment = PartyMemberListFragment(viewModel) if (user?.hasParty() == true) { partyMemberListFragment?.setPartyId(user?.party?.id ?: "") } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.kt index 1d1400c15..bfb481522 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.kt @@ -1,5 +1,6 @@ package com.habitrpg.android.habitica.ui.fragments.social.party +import android.annotation.SuppressLint import android.os.Bundle import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.recyclerview.widget.LinearLayoutManager @@ -7,6 +8,7 @@ import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.lifecycle.Observer import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.SocialRepository @@ -18,13 +20,15 @@ import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAd import com.habitrpg.android.habitica.ui.fragments.BaseFragment import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator import com.habitrpg.android.habitica.ui.helpers.bindView +import com.habitrpg.android.habitica.ui.viewmodels.PartyViewModel import io.reactivex.functions.Consumer import javax.inject.Inject /** * Created by Negue on 15.09.2015. */ -class PartyMemberListFragment : BaseFragment() { +@SuppressLint("ValidFragment") +class PartyMemberListFragment constructor(private val viewModel: PartyViewModel) : BaseFragment() { @Inject lateinit var socialRepository: SocialRepository @@ -59,9 +63,18 @@ class PartyMemberListFragment : BaseFragment() { getUsers() } + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + viewModel.getGroupData().observe(viewLifecycleOwner, Observer { + adapter?.leaderID = it?.leaderID + adapter?.notifyDataSetChanged() + }) + } + private fun refreshMembers() { setRefreshing(true) - socialRepository.retrieveGroupMembers(partyId ?: "", true).doOnComplete { setRefreshing(false) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) + compositeSubscription.add(socialRepository.retrieveGroupMembers(partyId ?: "", true).doOnComplete { setRefreshing(false) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) } private fun setRefreshing(isRefreshing: Boolean) { @@ -76,8 +89,8 @@ class PartyMemberListFragment : BaseFragment() { if (partyId == null) { return } - socialRepository.getGroupMembers(partyId ?: "").firstElement().subscribe(Consumer { users -> + compositeSubscription.add(socialRepository.getGroupMembers(partyId ?: "").firstElement().subscribe(Consumer { users -> adapter?.updateData(users) - }, RxErrorHandler.handleEmptyError()) + }, RxErrorHandler.handleEmptyError())) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt index 43c8c9ef4..2d57e39cf 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt @@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.data.TaskRepository import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand +import com.habitrpg.android.habitica.extensions.notNull import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.TaskFilterHelper import com.habitrpg.android.habitica.models.tasks.Task @@ -88,12 +89,13 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, andr recyclerAdapter?.errorButtonEvents?.subscribe(Consumer { taskRepository.syncErroredTasks().subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) - }, RxErrorHandler.handleEmptyError()) + }, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription.add(it) } if (this.classType != null) { - taskRepository.getTasks(this.classType ?: "", userID).firstElement().subscribe(Consumer { this.recyclerAdapter?.updateUnfilteredData(it) + compositeSubscription.add(taskRepository.getTasks(this.classType ?: "", userID).firstElement().subscribe(Consumer { + this.recyclerAdapter?.updateUnfilteredData(it) this.recyclerAdapter?.filter() - }, RxErrorHandler.handleEmptyError()) + }, RxErrorHandler.handleEmptyError())) } } @@ -157,11 +159,11 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, andr val movingTaskID = movingTaskID if (fromPosition != null && movingTaskID != null) { recyclerAdapter?.ignoreUpdates = true - taskRepository.updateTaskPosition(classType ?: "", movingTaskID, viewHolder.adapterPosition) + compositeSubscription.add(taskRepository.updateTaskPosition(classType ?: "", movingTaskID, viewHolder.adapterPosition) .delay(1, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(Consumer { recyclerAdapter?.ignoreUpdates = false - recyclerAdapter?.notifyDataSetChanged()}, RxErrorHandler.handleEmptyError()) + recyclerAdapter?.notifyDataSetChanged()}, RxErrorHandler.handleEmptyError())) } this.fromPosition = null this.movingTaskID = null @@ -260,10 +262,10 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, andr override fun onRefresh() { refreshLayout.isRefreshing = true - userRepository.retrieveUser(true, true) + compositeSubscription.add(userRepository.retrieveUser(true, true) .doOnTerminate { refreshLayout?.isRefreshing = false - }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) + }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) } fun setActiveFilter(activeFilter: String) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt index e93c77755..3a384c9e9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt @@ -27,7 +27,6 @@ object MarkdownParser { private val processor = AndDown() private val regex = Pattern.compile("(?!\\b)@[\\w-]+") - private val colorSpan = ForegroundColorSpan(Color.parseColor("#6133b4")) /** * Parses formatted markdown and returns it as styled CharSequence @@ -48,6 +47,7 @@ object MarkdownParser { val matcher = regex.matcher(output) while (matcher.find()) { + val colorSpan = ForegroundColorSpan(Color.parseColor("#6133b4")) output.setSpan(colorSpan, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/PartyViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/PartyViewModel.kt index 3d1c09b69..fd361b3a1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/PartyViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/PartyViewModel.kt @@ -12,10 +12,8 @@ import kotlinx.android.synthetic.main.fragment_chat.* class PartyViewModel: GroupViewModel() { - private val quest = Transformations.map(getGroupData()) { it?.quest } - internal val isQuestActive: Boolean - get() = quest.value?.active == true + get() = getGroupData().value?.quest?.active == true init { groupViewType = GroupViewType.PARTY @@ -37,8 +35,6 @@ class PartyViewModel: GroupViewModel() { } } - fun getQuestData(): LiveData = quest - fun showParticipantButtons(): Boolean { val user = getUserData().value return !(user?.party == null || user.party?.quest == null) && !isQuestActive && user.party?.quest?.RSVPNeeded == true diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/DateDeserializer.java b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/DateDeserializer.java index 19d08b257..fb3a96218 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/DateDeserializer.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/DateDeserializer.java @@ -19,12 +19,16 @@ public class DateDeserializer implements JsonDeserializer, JsonSerializer< private final DateFormat dateFormat; private final DateFormat alternativeFormat; + private final DateFormat nextDueFormat; public DateDeserializer() { dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); alternativeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); alternativeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + nextDueFormat = new SimpleDateFormat("E MMM dd yyyy HH:mm:ss zzzz", Locale.US); + nextDueFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } @Override @@ -45,14 +49,18 @@ public class DateDeserializer implements JsonDeserializer, JsonSerializer< return alternativeFormat.parse(jsonElement.getAsString()); } catch (ParseException e1) { try { - Long timestamp = jsonElement.getAsLong(); - if (timestamp > 0) { - return new Date(timestamp); - } else { + return nextDueFormat.parse(jsonElement.getAsString()); + } catch (ParseException e2) { + try { + Long timestamp = jsonElement.getAsLong(); + if (timestamp > 0) { + return new Date(timestamp); + } else { + return null; + } + } catch (NumberFormatException e3) { return null; } - } catch (NumberFormatException e2) { - return null; } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt index d77917223..d980b861f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt @@ -29,6 +29,9 @@ class GroupSerialization : JsonDeserializer, JsonSerializer { if (obj.has("description") && !obj.get("description").isJsonNull) { group.description = obj.get("description").asString } + if (obj.has("summary") && !obj.get("summary").isJsonNull) { + group.summary = obj.get("summary").asString + } if (obj.has("leaderMessage") && !obj.get("leaderMessage").isJsonNull) { group.leaderMessage = obj.get("leaderMessage").asString } @@ -110,6 +113,7 @@ class GroupSerialization : JsonDeserializer, JsonSerializer { val obj = JsonObject() obj.addProperty("name", src.name) obj.addProperty("description", src.description) + obj.addProperty("summary", src.summary) obj.addProperty("logo", src.logo) obj.addProperty("type", src.type) obj.addProperty("type", src.type)