From fbf6ac031d810569c66391ce0ef9ab9b0f3a3e4c Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 18 Apr 2019 11:54:32 +0200 Subject: [PATCH] Impelement new report view. Fixes #355 --- Habitica/AndroidManifest.xml | 5 + Habitica/build.gradle | 2 +- .../res/layout/activity_report_message.xml | 99 +++++++++++ .../res/layout/fragment_report_message.xml | 37 ++++ Habitica/res/menu/report_message.xml | 5 + Habitica/res/navigation/navigation.xml | 35 +++- Habitica/res/values/strings.xml | 3 + Habitica/res/values/styles.xml | 15 ++ .../android/habitica/api/ApiService.java | 4 +- .../habitica/components/AppComponent.java | 3 + .../android/habitica/data/ApiClient.kt | 3 +- .../android/habitica/data/SocialRepository.kt | 3 +- .../data/implementation/ApiClientImpl.kt | 4 +- .../implementation/SocialRepositoryImpl.kt | 14 +- .../data/local/SocialLocalRepository.kt | 1 + .../RealmSocialLocalRepository.kt | 6 + .../ui/activities/ClassSelectionActivity.kt | 10 +- .../ui/activities/FullProfileActivity.kt | 29 ++-- .../ui/activities/GroupFormActivity.kt | 8 +- .../habitica/ui/activities/LoginActivity.kt | 3 +- .../habitica/ui/activities/MainActivity.kt | 8 +- .../ui/activities/PartyInviteActivity.kt | 3 +- .../ui/activities/ReportMessageActivity.kt | 162 ++++++++++++++++++ .../adapter/social/ChatRecyclerViewAdapter.kt | 1 - .../ui/fragments/SubscriptionFragment.kt | 3 +- .../ui/fragments/social/ChatFragment.kt | 19 +- .../ui/fragments/social/ChatListFragment.kt | 20 +-- .../ui/fragments/social/InboxFragment.kt | 3 +- .../social/InboxMessageListFragment.kt | 17 +- .../habitica/ui/helpers/KeyboardUtil.kt | 5 + .../habitica/ui/viewmodels/GroupViewModel.kt | 13 -- fastlane/changelog.txt | 6 +- 32 files changed, 438 insertions(+), 111 deletions(-) create mode 100644 Habitica/res/layout/activity_report_message.xml create mode 100644 Habitica/res/layout/fragment_report_message.xml create mode 100644 Habitica/res/menu/report_message.xml create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ReportMessageActivity.kt diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml index 13f4fcc79..1bf55414c 100644 --- a/Habitica/AndroidManifest.xml +++ b/Habitica/AndroidManifest.xml @@ -229,6 +229,11 @@ + + diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 03c515109..cea2fc6c7 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -152,7 +152,7 @@ android { buildConfigField "String", "STORE", "\"google\"" multiDexEnabled true - versionCode 2091 + versionCode 2092 versionName "1.9" } diff --git a/Habitica/res/layout/activity_report_message.xml b/Habitica/res/layout/activity_report_message.xml new file mode 100644 index 000000000..21a0787e2 --- /dev/null +++ b/Habitica/res/layout/activity_report_message.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/fragment_report_message.xml b/Habitica/res/layout/fragment_report_message.xml new file mode 100644 index 000000000..e46e80ed2 --- /dev/null +++ b/Habitica/res/layout/fragment_report_message.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/menu/report_message.xml b/Habitica/res/menu/report_message.xml new file mode 100644 index 000000000..3dd8e8e07 --- /dev/null +++ b/Habitica/res/menu/report_message.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/Habitica/res/navigation/navigation.xml b/Habitica/res/navigation/navigation.xml index 5047dc638..ed9ff4fb7 100644 --- a/Habitica/res/navigation/navigation.xml +++ b/Habitica/res/navigation/navigation.xml @@ -2,7 +2,7 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 00005b26e..b36df82ba 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -887,4 +887,7 @@ Need more help? Become a %s %s Class + **Only** report a post that violates the [Community Guidelines](https://habitica.com/static/community-guidelines) and/or [Terms of Service](https://habitica.com/static/terms). Inappropriately reporting a post may give you an infraction. + Report %s for violation: + Reason for report (optional) diff --git a/Habitica/res/values/styles.xml b/Habitica/res/values/styles.xml index ecfd603d4..38090c64c 100644 --- a/Habitica/res/values/styles.xml +++ b/Habitica/res/values/styles.xml @@ -28,6 +28,17 @@ @style/AlertDialogTheme + + + + #99edecee \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java index 6da989670..0979c8a8f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java @@ -35,8 +35,6 @@ import com.habitrpg.android.habitica.models.user.Items; import com.habitrpg.android.habitica.models.user.Stats; import com.habitrpg.android.habitica.models.user.User; -import org.jetbrains.annotations.NotNull; - import java.util.List; import java.util.Map; @@ -236,7 +234,7 @@ public interface ApiService { Flowable> likeMessage(@Path("gid") String groupId, @Path("mid") String mid); @POST("groups/{gid}/chat/{mid}/flag") - Flowable> flagMessage(@Path("gid") String groupId, @Path("mid") String mid); + Flowable> flagMessage(@Path("gid") String groupId, @Path("mid") String mid, @Body Map data); @POST("groups/{gid}/chat/seen") Flowable> seenMessages(@Path("gid") String groupId); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java index 1527ef84a..e7e9653d0 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java @@ -30,6 +30,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity; import com.habitrpg.android.habitica.ui.activities.MaintenanceActivity; import com.habitrpg.android.habitica.ui.activities.PartyInviteActivity; import com.habitrpg.android.habitica.ui.activities.PrefsActivity; +import com.habitrpg.android.habitica.ui.activities.ReportMessageActivity; import com.habitrpg.android.habitica.ui.activities.SetupActivity; import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity; import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity; @@ -314,4 +315,6 @@ public interface AppComponent { void inject(@NotNull ChatBarView chatBarView); void inject(@NotNull TaskFormActivity taskFormActivity); + + void inject(@NotNull ReportMessageActivity reportMessageActivity); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt index ddc6e97a9..eb8b6e574 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt @@ -20,7 +20,6 @@ import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.models.user.User import io.reactivex.Flowable import io.reactivex.FlowableTransformer -import io.reactivex.ObservableTransformer import retrofit2.HttpException @@ -150,7 +149,7 @@ interface ApiClient { // Like returns the full chat list fun likeMessage(groupId: String, mid: String): Flowable - fun flagMessage(groupId: String, mid: String): Flowable + fun flagMessage(groupId: String, mid: String, data: MutableMap): Flowable fun seenMessages(groupId: String): Flowable diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt index ea6f4055e..899b6330c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt @@ -20,7 +20,7 @@ interface SocialRepository : BaseRepository { fun markMessagesSeen(seenGroupId: String) - fun flagMessage(chatMessage: ChatMessage): Flowable + fun flagMessage(chatMessage: ChatMessage, additionalInfo: String): Flowable fun likeMessage(chatMessage: ChatMessage): Flowable @@ -79,4 +79,5 @@ interface SocialRepository : BaseRepository { fun getGroupMembership(id: String): Flowable fun getGroupMemberships(): Flowable> + fun getChatmessage(messageID: String): Flowable } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt index 8017908e0..746fd26fd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt @@ -524,8 +524,8 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener; return apiService.likeMessage(groupId, mid).compose(configureApiCallObserver()) } - override fun flagMessage(groupId: String, mid: String): Flowable { - return apiService.flagMessage(groupId, mid).compose(configureApiCallObserver()) + override fun flagMessage(groupId: String, mid: String, data: MutableMap): Flowable { + return apiService.flagMessage(groupId, mid, data).compose(configureApiCallObserver()) } override fun seenMessages(groupId: String): Flowable { 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 3084a51f0..b2014a749 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 @@ -6,12 +6,10 @@ import com.habitrpg.android.habitica.data.local.SocialLocalRepository import com.habitrpg.android.habitica.extensions.notNull import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.AchievementResult -import com.habitrpg.android.habitica.models.auth.LocalAuthentication import com.habitrpg.android.habitica.models.inventory.Quest import com.habitrpg.android.habitica.models.members.Member import com.habitrpg.android.habitica.models.responses.PostChatMessageResult import com.habitrpg.android.habitica.models.social.* -import com.habitrpg.android.habitica.models.user.Authentication import com.habitrpg.android.habitica.models.user.User import io.reactivex.Flowable import io.reactivex.Single @@ -20,7 +18,9 @@ import io.reactivex.functions.Consumer import io.realm.RealmResults class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: ApiClient, userID: String) : BaseRepositoryImpl(localRepository, apiClient, userID), SocialRepository { - + override fun getChatmessage(messageID: String): Flowable { + return localRepository.getChatMessage(messageID) + } override fun getGroupMembership(id: String): Flowable { return localRepository.getGroupMembership(userID, id) @@ -49,10 +49,14 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap apiClient.seenMessages(seenGroupId).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } - override fun flagMessage(chatMessage: ChatMessage): Flowable { + override fun flagMessage(chatMessage: ChatMessage, additionalInfo: String): Flowable { return if (chatMessage.id == "") { Flowable.empty() - } else apiClient.flagMessage(chatMessage.groupId ?: "", chatMessage.id) + } else { + val data = mutableMapOf() + data["comment"] = additionalInfo + apiClient.flagMessage(chatMessage.groupId ?: "", chatMessage.id, data) + } } override fun likeMessage(chatMessage: ChatMessage): Flowable { 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 bf4a8bd4a..614fa3bd2 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 @@ -47,4 +47,5 @@ interface SocialLocalRepository : BaseLocalRepository { fun getInboxOverviewList(userId: String): Flowable> fun saveGroupMemberships(userID: String?, memberships: List) fun saveInboxMessages(userID: String, messages: List) + fun getChatMessage(messageID: String): Flowable } 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 ed70e77f0..91d95f00a 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 @@ -15,6 +15,12 @@ import java.util.* class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), SocialLocalRepository { + override fun getChatMessage(messageID: String): Flowable = realm.where(ChatMessage::class.java) + .equalTo("id", messageID) + .findAll() + .asFlowable() + .filter { it.isLoaded && it.isNotEmpty() } + .map { it.first() } override fun getGroupMembership(userId: String, id: String): Flowable = realm.where(GroupMembership::class.java) .equalTo("userID", userId) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt index e1fbc5ee2..04afc5d78 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt @@ -15,6 +15,7 @@ import android.widget.Button import android.widget.TextView import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import androidx.navigation.navArgs import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.UserRepository @@ -86,9 +87,9 @@ class ClassSelectionActivity : BaseActivity(), Consumer { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - val intent = intent - val bundle = intent.extras - isInitialSelection = bundle?.getBoolean("isInitialSelection") ?: false + val args = navArgs().value + isInitialSelection = args.isInitialSelection + currentClass = args.className compositeSubscription.add(userRepository.getUser().firstElement().subscribe(Consumer { it.preferences?.let {preferences -> @@ -97,9 +98,6 @@ class ClassSelectionActivity : BaseActivity(), Consumer { setAvatarViews(unmanagedPrefs) } }, RxErrorHandler.handleEmptyError())) - bundle.notNull { thisBundle -> - currentClass = thisBundle.getString("currentClass") - } if (!isInitialSelection) { compositeSubscription.add(userRepository.changeClass() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt index 5a78dbb2a..8be6920fd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt @@ -30,10 +30,7 @@ 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.adapter.social.AchievementAdapter -import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils -import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil -import com.habitrpg.android.habitica.ui.helpers.MarkdownParser -import com.habitrpg.android.habitica.ui.helpers.bindView +import com.habitrpg.android.habitica.ui.helpers.* import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType import io.reactivex.Flowable @@ -63,8 +60,8 @@ class FullProfileActivity : BaseActivity() { private val equipmentTableLayout: TableLayout by bindView(R.id.equipment_table) private val costumeTableLayout: TableLayout by bindView(R.id.costume_table) private val costumeCard: androidx.cardview.widget.CardView by bindView(R.id.profile_costume_card) - private val avatar_with_bars: View by bindView(R.id.avatar_with_bars) - private val fullprofile_scrollview: ScrollView by bindView(R.id.fullprofile_scrollview) + private val avatarWithStatsView: View by bindView(R.id.avatar_with_bars) + private val scrollView: ScrollView by bindView(R.id.fullprofile_scrollview) private val petsFoundCount: TextView by bindView(R.id.profile_pets_found_count) private val mountsTamedCount: TextView by bindView(R.id.profile_mounts_tamed_count) private val currentPetDrawee: SimpleDraweeView by bindView(R.id.current_pet_drawee) @@ -101,12 +98,12 @@ class FullProfileActivity : BaseActivity() { avatarWithBars?.valueBarLabelsToBlack() - avatar_with_bars.setBackgroundColor(ContextCompat.getColor(this, R.color.transparent)) + avatarWithStatsView.setBackgroundColor(ContextCompat.getColor(this, R.color.transparent)) attributeRows.clear() attributesCardView.setOnClickListener { toggleAttributeDetails() } - avatarWithBars = AvatarWithBarsViewModel(this, avatar_with_bars) + avatarWithBars = AvatarWithBarsViewModel(this, avatarWithStatsView) } override fun onDestroy() { @@ -144,13 +141,13 @@ class FullProfileActivity : BaseActivity() { .setPositiveButton(android.R.string.ok) { _, _ -> socialRepository.postPrivateMessage(userID, emojiEditText.text.toString()) .subscribe(Consumer { - HabiticaSnackbar.showSnackbar(this@FullProfileActivity.fullprofile_scrollview.getChildAt(0) as ViewGroup, + HabiticaSnackbar.showSnackbar(this@FullProfileActivity.scrollView.getChildAt(0) as ViewGroup, String.format(getString(R.string.profile_message_sent_to), userName), SnackbarDisplayType.NORMAL) }, RxErrorHandler.handleEmptyError()) - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() } - .setNegativeButton(android.R.string.cancel) { _, _ -> KeyboardUtil.dismissKeyboard(this) } + .setNegativeButton(android.R.string.cancel) { _, _ -> dismissKeyboard() } .create() @@ -352,12 +349,10 @@ class FullProfileActivity : BaseActivity() { addLevelAttributes(user) for (row in statsRows) { - if (row.javaClass == UserStatComputer.EquipmentRow::class.java) { - val equipmentRow = row as UserStatComputer.EquipmentRow - addEquipmentRow(equipmentTableLayout, equipmentRow.gearKey, equipmentRow.text, equipmentRow.stats) - } else if (row.javaClass == UserStatComputer.AttributeRow::class.java) { - val attributeRow2 = row as UserStatComputer.AttributeRow - addAttributeRow(getString(attributeRow2.labelId), attributeRow2.strVal, attributeRow2.intVal, attributeRow2.conVal, attributeRow2.perVal, attributeRow2.roundDown, attributeRow2.isSummary) + if (row is UserStatComputer.EquipmentRow) { + addEquipmentRow(equipmentTableLayout, row.gearKey, row.text, row.stats) + } else if (row is UserStatComputer.AttributeRow) { + addAttributeRow(getString(row.labelId), row.strVal, row.intVal, row.conVal, row.perVal, row.roundDown, row.isSummary) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt index 78f808404..5b448e679 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt @@ -60,7 +60,7 @@ class GroupFormActivity : BaseActivity() { cancelButton.setOnClickListener { finish() - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() } saveButton.setOnClickListener { @@ -92,13 +92,13 @@ class GroupFormActivity : BaseActivity() { override fun onSupportNavigateUp(): Boolean { finish() - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() return true } override fun onBackPressed() { finish() - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() } private fun finishActivitySuccessfuly() { @@ -116,7 +116,7 @@ class GroupFormActivity : BaseActivity() { resultIntent.putExtras(bundle) setResult(Activity.RESULT_OK, resultIntent) finish() - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() } companion object { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt index 76a92465c..80696cb09 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt @@ -44,6 +44,7 @@ import com.habitrpg.android.habitica.models.auth.UserAuthResponse import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil import com.habitrpg.android.habitica.ui.helpers.bindView +import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard import com.habitrpg.android.habitica.ui.views.login.LockableScrollView import com.habitrpg.android.habitica.ui.views.login.LoginBackgroundView import io.reactivex.Flowable @@ -555,7 +556,7 @@ class LoginActivity : BaseActivity(), Consumer { showAnimation.play(newGameAlphaAnimation).after(scrollViewAlphaAnimation) showAnimation.play(showLoginAlphaAnimation).after(scrollViewAlphaAnimation) showAnimation.start() - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() } private fun onForgotPasswordClicked() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt index 6bd78cb8e..d10e42221 100755 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt @@ -10,18 +10,14 @@ import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.drawable.BitmapDrawable -import android.net.Uri import android.os.Build -import android.os.Build.VERSION.SDK_INT import android.os.Bundle -import android.os.Trace import android.preference.PreferenceManager import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.tabs.TabLayout import androidx.core.content.ContextCompat import androidx.core.content.FileProvider -import androidx.drawerlayout.widget.DrawerLayout import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.Toolbar @@ -32,11 +28,11 @@ import android.widget.FrameLayout import android.widget.TextView import androidx.core.content.edit import androidx.navigation.findNavController -import androidx.navigation.fragment.NavHostFragment import com.facebook.drawee.view.SimpleDraweeView import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.perf.FirebasePerformance import com.habitrpg.android.habitica.HabiticaBaseApplication +import com.habitrpg.android.habitica.MainNavDirections import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.api.HostConfig import com.habitrpg.android.habitica.api.MaintenanceApiService @@ -51,6 +47,7 @@ import com.habitrpg.android.habitica.interactors.* import com.habitrpg.android.habitica.models.TutorialStep import com.habitrpg.android.habitica.models.responses.MaintenanceResponse import com.habitrpg.android.habitica.models.responses.TaskScoringResult +import com.habitrpg.android.habitica.models.social.Group import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.proxy.CrashlyticsProxy @@ -82,7 +79,6 @@ import io.reactivex.schedulers.Schedulers import io.realm.Realm import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe -import java.lang.IllegalStateException import java.lang.ref.WeakReference import java.util.* import javax.inject.Inject diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/PartyInviteActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/PartyInviteActivity.kt index c8f6abc22..b7ce02012 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/PartyInviteActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/PartyInviteActivity.kt @@ -23,6 +23,7 @@ import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator import com.habitrpg.android.habitica.ui.fragments.social.party.PartyInviteFragment import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil import com.habitrpg.android.habitica.ui.helpers.bindView +import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard import io.reactivex.functions.Consumer import java.util.* import javax.inject.Inject @@ -74,7 +75,7 @@ class PartyInviteActivity : BaseActivity() { if (id == R.id.action_send_invites) { setResult(Activity.RESULT_OK, createResultIntent()) - KeyboardUtil.dismissKeyboard(this) + dismissKeyboard() finish() return true } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ReportMessageActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ReportMessageActivity.kt new file mode 100644 index 000000000..95d0f47eb --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ReportMessageActivity.kt @@ -0,0 +1,162 @@ +package com.habitrpg.android.habitica.ui.activities + +import android.annotation.SuppressLint +import android.graphics.Color +import android.os.Build +import android.os.Build.VERSION_CODES +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import android.widget.TextView +import androidx.annotation.RequiresApi +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import androidx.navigation.navArgs +import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.components.AppComponent +import com.habitrpg.android.habitica.data.SocialRepository +import com.habitrpg.android.habitica.helpers.RxErrorHandler +import com.habitrpg.android.habitica.models.social.ChatMessage +import com.habitrpg.android.habitica.ui.helpers.MarkdownParser +import com.habitrpg.android.habitica.ui.helpers.bindView +import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard +import io.reactivex.functions.Consumer +import javax.inject.Inject + + +class ReportMessageActivity : BaseActivity() { + + @Inject + lateinit var socialRepository: SocialRepository + + private val toolbar: Toolbar by bindView(R.id.toolbar) + private val appBar: AppBarLayout by bindView(R.id.app_bar) + private val bottomSheetView: View by bindView(R.id.bottom_sheet) + private val contentContainer: ViewGroup by bindView(R.id.content_container) + private val dismissTouchView: View by bindView(R.id.touch_outside) + private val titleTextView: TextView by bindView(R.id.title_text_view) + private val messageTextView: TextView by bindView(R.id.message_text_view) + private val additionInfoEditText: EditText by bindView(R.id.additional_info_edittext) + private val reportExplanationTextView: TextView by bindView(R.id.report_explanation_textview) + private var raisedElevation = 0f + + private var messageID: String? = null + private var isReporting: Boolean = false + + override fun getLayoutResId(): Int { + return R.layout.activity_report_message + } + + override fun injectActivity(component: AppComponent?) { + component?.inject(this) + } + + private var chatMessage: ChatMessage? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setSupportActionBar(toolbar) + raisedElevation = appBar.elevation + setStatusBarDim(true) + + contentContainer.setOnTouchListener { _, _ -> true } + additionInfoEditText.setOnTouchListener { _, _ -> true } + dismissTouchView.setOnClickListener { finish() } + reportExplanationTextView.text = MarkdownParser.parseMarkdown(getString(R.string.report_explanation)) + + BottomSheetBehavior.from(bottomSheetView) + .setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + @SuppressLint("SwitchIntDef") + override fun onStateChanged(bottomSheet: View, newState: Int) { + when (newState) { + BottomSheetBehavior.STATE_HIDDEN -> finish() + BottomSheetBehavior.STATE_EXPANDED -> setStatusBarDim(false) + else -> setStatusBarDim(true) + } + } + + override fun onSlide(bottomSheet: View, slideOffset: Float) { + // no op + } + }) + + val args = navArgs().value + messageID = args.messageID + titleTextView.text = getString(R.string.report_message_title, args.profileName) + messageTextView.text = args.text + + messageID?.let {messageID -> + compositeSubscription.add(socialRepository.getChatmessage(messageID).subscribe(Consumer { + chatMessage = it + }, RxErrorHandler.handleEmptyError())) + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.report_message, menu) + return true + } + + @Suppress("ReturnCount") + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val id = item.itemId + + when (id) { + R.id.menu_report -> { + reportMessage() + return true + } + } + return super.onOptionsItemSelected(item) + } + + private fun reportMessage() { + if (isReporting) { + return + } + chatMessage?.let { + isReporting = true + socialRepository.flagMessage(it, additionInfoEditText.text.toString()) + .doOnError { isReporting = false } + .subscribe(Consumer { + finish() + }, RxErrorHandler.handleEmptyError()) + } + } + + private fun setStatusBarDim(dim: Boolean) { + if (dim) { + appBar.elevation = 0f + window.statusBarColor = Color.TRANSPARENT + supportActionBar?.setDisplayHomeAsUpEnabled(false) + supportActionBar?.setHomeAsUpIndicator(null) + } else { + appBar.elevation = 8f + window.statusBarColor = ContextCompat.getColor(this, R.color.gray_600) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_close) + } + + if (Build.VERSION.SDK_INT >= VERSION_CODES.M) { + setSystemBarTheme(dim) + } + } + + override fun finish() { + dismissKeyboard() + super.finish() + } + + @RequiresApi(api = Build.VERSION_CODES.M) + fun setSystemBarTheme(isDark: Boolean) { + // Fetch the current flags. + val lFlags = window.decorView.systemUiVisibility + // Update the SystemUiVisibility dependening on whether we want a Light or Dark theme. + window.decorView.systemUiVisibility = if (isDark) lFlags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() else lFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR + } +} 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 557383e95..eabea63e8 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 @@ -242,7 +242,6 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp buttonsWrapper.visibility = View.VISIBLE deleteButton.visibility = if (shouldShowDelete()) View.VISIBLE else View.GONE replyButton.visibility = if (chatMessage?.isInboxMessage == true) View.GONE else View.VISIBLE - reportButton.visibility = if (chatMessage?.uuid == userId) View.GONE else View.VISIBLE } else { buttonsWrapper.visibility = View.GONE } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.kt index f663c5ac1..c57874a3e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.kt @@ -25,6 +25,7 @@ import com.habitrpg.android.habitica.ui.activities.GiftIAPActivity import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil import com.habitrpg.android.habitica.ui.helpers.bindOptionalView import com.habitrpg.android.habitica.ui.helpers.bindView +import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionDetailsView import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView @@ -293,7 +294,7 @@ class SubscriptionFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen startActivity(intent) } .setNeutralButton(getString(R.string.action_cancel)) { dialog, _ -> - KeyboardUtil.dismissKeyboard(thisActivity) + thisActivity.dismissKeyboard() dialog.cancel() } .create() 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 07c2111f3..1a656250d 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 @@ -15,9 +15,11 @@ import androidx.core.net.toUri import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import com.habitrpg.android.habitica.MainNavDirections import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.extensions.notNull +import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.helpers.RemoteConfigManager import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.social.ChatMessage @@ -197,21 +199,8 @@ class ChatFragment constructor() : BaseFragment(), SwipeRefreshLayout.OnRefreshL } private fun showFlagConfirmationDialog(chatMessage: ChatMessage) { - val context = context - if (context != null) { - val builder = AlertDialog.Builder(context) - builder.setMessage(R.string.chat_flag_confirmation) - .setPositiveButton(R.string.flag_confirm) { _, _ -> - viewModel.flagMessage(chatMessage) { - val activity = activity as? MainActivity - activity?.floatingMenuWrapper.notNull { - showSnackbar(it, "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL) - } - } - } - .setNegativeButton(R.string.action_cancel) { _, _ -> } - builder.show() - } + val directions = MainNavDirections.actionGlobalReportMessageActivity(chatMessage.text ?: "", chatMessage.user ?: "", chatMessage.id) + MainNavigationController.navigate(directions) } private fun showDeleteConfirmationDialog(chatMessage: ChatMessage) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt index 43fd3612c..f3c51fe82 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt @@ -15,11 +15,13 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.core.net.toUri +import com.habitrpg.android.habitica.MainNavDirections import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.SocialRepository import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.extensions.notNull +import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.helpers.RemoteConfigManager import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.social.ChatMessage @@ -257,22 +259,8 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { } private fun showFlagConfirmationDialog(chatMessage: ChatMessage) { - val context = context - if (context != null) { - val builder = AlertDialog.Builder(context) - builder.setMessage(R.string.chat_flag_confirmation) - .setPositiveButton(R.string.flag_confirm) { _, _ -> - socialRepository.flagMessage(chatMessage) - .subscribe(Consumer { - val activity = activity as? MainActivity - activity?.floatingMenuWrapper.notNull { - showSnackbar(it, "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL) - } - }, RxErrorHandler.handleEmptyError()) - } - .setNegativeButton(R.string.action_cancel) { _, _ -> } - builder.show() - } + val directions = MainNavDirections.actionGlobalReportMessageActivity(chatMessage.text ?: "", chatMessage.user ?: "", chatMessage.id) + MainNavigationController.navigate(directions) } private fun showDeleteConfirmationDialog(chatMessage: ChatMessage) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt index d100c0318..7257b5550 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt @@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.modules.AppModule import com.habitrpg.android.habitica.ui.AvatarView import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil +import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard import com.habitrpg.android.habitica.ui.views.social.UsernameLabel import io.reactivex.functions.Consumer import io.realm.RealmResults @@ -94,7 +95,7 @@ class InboxFragment : BaseMainFragment(), androidx.swiperefreshlayout.widget.Swi openInboxMessages(uuidEditText?.text?.toString() ?: "", "") } .setNeutralButton(getString(R.string.action_cancel)) { dialog, _ -> - KeyboardUtil.dismissKeyboard(thisActivity) + thisActivity.dismissKeyboard() dialog.cancel() } .create() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt index 5962385c4..31709c0f6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt @@ -8,10 +8,12 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AlertDialog +import com.habitrpg.android.habitica.MainNavDirections import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.SocialRepository import com.habitrpg.android.habitica.extensions.notNull +import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.helpers.RemoteConfigManager import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.social.ChatMessage @@ -146,19 +148,8 @@ class InboxMessageListFragment : BaseMainFragment(), androidx.swiperefreshlayout } private fun showFlagConfirmationDialog(chatMessage: ChatMessage) { - val activity = getActivity() as? MainActivity ?: return - val builder = AlertDialog.Builder(activity) - builder.setMessage(R.string.chat_flag_confirmation) - .setPositiveButton(R.string.flag_confirm) { _, _ -> - socialRepository.flagMessage(chatMessage) - .subscribe(Consumer { _ -> - activity.floatingMenuWrapper.notNull { - showSnackbar(it, "Flagged message by " + chatMessage.user, HabiticaSnackbar.SnackbarDisplayType.NORMAL) - } - }, RxErrorHandler.handleEmptyError()) - } - .setNegativeButton(R.string.action_cancel) { _, _ -> } - builder.show() + val directions = MainNavDirections.actionGlobalReportMessageActivity(chatMessage.text ?: "", chatMessage.user ?: "", chatMessage.id) + MainNavigationController.navigate(directions) } private fun showDeleteConfirmationDialog(chatMessage: ChatMessage) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/KeyboardUtil.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/KeyboardUtil.kt index 6091a094a..ef9656f73 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/KeyboardUtil.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/KeyboardUtil.kt @@ -79,4 +79,9 @@ class KeyboardUtil(activity: Activity, private val contentView: View) { } } } +} + + +fun Activity.dismissKeyboard() { + KeyboardUtil.dismissKeyboard(this) } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt index 131b5dbeb..96976a55f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt @@ -3,21 +3,15 @@ package com.habitrpg.android.habitica.ui.viewmodels import android.os.Bundle import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.SocialRepository -import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.extensions.* import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.social.Group -import com.habitrpg.android.habitica.ui.activities.MainActivity -import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import io.reactivex.BackpressureStrategy import io.reactivex.Flowable -import io.reactivex.Maybe import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.disposables.CompositeDisposable import io.reactivex.functions.Consumer import io.reactivex.subjects.BehaviorSubject import io.realm.RealmResults @@ -135,13 +129,6 @@ open class GroupViewModel : BaseViewModel() { disposable.add(socialRepository.likeMessage(message).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) } - fun flagMessage(chatMessage: ChatMessage, function: () -> Unit) { - disposable.add(socialRepository.flagMessage(chatMessage) - .subscribe(Consumer { - function() - }, RxErrorHandler.handleEmptyError())) - } - fun deleteMessage(chatMessage: ChatMessage) { disposable.add(socialRepository.deleteMessage(chatMessage).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) } diff --git a/fastlane/changelog.txt b/fastlane/changelog.txt index 117e21f40..ca5a0e02d 100644 --- a/fastlane/changelog.txt +++ b/fastlane/changelog.txt @@ -1 +1,5 @@ -This update brings username and emoji autocomplete, deep linking (open https://habitica.com urls from anywhere on your device with the app), bigger emojis, party creation and many bugfixes. +- Redesigned Class selection +- Redesigned Task Form +- Optimized user and content loading +- Improved FAQ and settings +