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
+