Fix various username bugs

This commit is contained in:
Phillip Thelen 2018-11-06 14:04:27 +01:00
parent b065cf0acc
commit 8c15df4d8a
36 changed files with 301 additions and 153 deletions

View file

@ -1,3 +1,6 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "fastlane" gem "fastlane"
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

150
Gemfile.lock Normal file
View file

@ -0,0 +1,150 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3)
babosa (1.0.2)
claide (1.0.2)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
declarative (0.0.10)
declarative-option (0.1.0)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.5.0)
emoji_regex (0.1.1)
excon (0.62.0)
faraday (0.15.3)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.4)
fastlane (2.107.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 2.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (~> 0.1)
excon (>= 0.45.0, < 1.0.0)
faraday (~> 0.9)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.9)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.21.2, < 0.24.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
mini_magick (~> 4.5.1)
multi_json
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
public_suffix (~> 2.0.0)
rubyzip (>= 1.2.2, < 2.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 1.6.2, < 2.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.6.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-increment_version_code (0.4.3)
gh_inspector (1.1.3)
google-api-client (0.23.9)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
googleauth (0.6.7)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
json (2.1.0)
jwt (2.1.0)
memoist (0.16.0)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mini_magick (4.5.1)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
naturally (2.2.0)
os (1.0.0)
plist (3.4.0)
public_suffix (2.0.5)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
rubyzip (1.2.2)
security (0.1.3)
signet (0.11.0)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.5)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (1.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.6.0)
tty-screen (0.6.5)
tty-spinner (0.8.0)
tty-cursor (>= 0.5.0)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.0)
word_wrap (1.0.0)
xcodeproj (1.7.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.6)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
fastlane
fastlane-plugin-increment_version_code
BUNDLED WITH
1.16.4

View file

@ -58,7 +58,7 @@ dependencies {
//Dependency Injection //Dependency Injection
implementation 'com.google.dagger:dagger:2.17' implementation 'com.google.dagger:dagger:2.17'
kapt 'com.google.dagger:dagger-compiler:2.17' kapt 'com.google.dagger:dagger-compiler:2.17'
compileOnly 'org.glassfish:javax.annotation:10.0-b28' compileOnly 'javax.annotation:javax.annotation-api:1.3.1'
//App Compatibility and Material Design //App Compatibility and Material Design
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:design:28.0.0'
@ -140,7 +140,7 @@ android {
buildConfigField "String", "STORE", "\"google\"" buildConfigField "String", "STORE", "\"google\""
multiDexEnabled true multiDexEnabled true
versionCode 2004 versionCode 2016
versionName "1.6" versionName "1.6"
} }
@ -299,6 +299,12 @@ tasks.whenTaskAdded { task ->
} }
} }
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xmaxerrs" << "500"
}
}
check { findbugs { skip true } } check { findbugs { skip true } }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'

View file

@ -12,13 +12,15 @@
--> -->
<!-- Layout used for PreferenceCategory in a PreferenceActivity. --> <!-- Layout used for PreferenceCategory in a PreferenceActivity. -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/title" android:id="@android:id/title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dip" android:layout_marginBottom="16dip"
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:background="@color/transparent" android:background="@color/transparent"
android:textColor="@color/brand_300" android:textColor="@color/gray_300"
android:paddingLeft="48dip" android:paddingLeft="32dip"
android:paddingRight="48dip" android:paddingRight="32dip"
android:paddingTop="16dip" /> android:paddingTop="16dip"
tools:text="Title" />

View file

@ -97,7 +97,8 @@
android:id="@+id/message_text" android:id="@+id/message_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:lineSpacingMultiplier="1.0" android:lineSpacingMultiplier="1.0"
tools:text="This is the chat message" tools:text="This is the chat message"
android:textColor="@color/gray_10"/> android:textColor="@color/gray_10"/>

View file

@ -827,7 +827,7 @@
<string name="confirm_username">Confirm Username</string> <string name="confirm_username">Confirm Username</string>
<string name="username_not_confirmed">Username not confirmed</string> <string name="username_not_confirmed">Username not confirmed</string>
<string name="username_confirmed">Username Confirmed</string> <string name="username_confirmed">Username Confirmed</string>
<string name="username_level">%s ・Lvl %d</string> <string name="username_level">\@%s ・Lvl %d</string>
<string name="enter_recipient_username">Enter a Recipient\'s username</string> <string name="enter_recipient_username">Enter a Recipient\'s username</string>
<string name="username_copied">Username copied to clipboard</string> <string name="username_copied">Username copied to clipboard</string>
<string name="verification_pet">One of these Veteran Pets will be waiting for you after youve finished confirming!</string> <string name="verification_pet">One of these Veteran Pets will be waiting for you after youve finished confirming!</string>

View file

@ -66,7 +66,7 @@ interface UserRepository : BaseRepository {
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void> fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void>
fun verifyUsername(username: String): Flowable<VerifyUsernameResponse> fun verifyUsername(username: String): Flowable<VerifyUsernameResponse>
fun allocatePoint(user: User?, @Stats.StatsTypes stat: String): Flowable<Stats> fun allocatePoint(user: User?, stat: String): Flowable<Stats>
fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats> fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
} }

View file

@ -208,8 +208,8 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
override fun getInboxOverviewList(userId: String): Flowable<RealmResults<ChatMessage>> { override fun getInboxOverviewList(userId: String): Flowable<RealmResults<ChatMessage>> {
return realm.where(ChatMessage::class.java) return realm.where(ChatMessage::class.java)
.equalTo("isInboxMessage", true) .equalTo("isInboxMessage", true)
.distinct("uuid")
.sort("timestamp", Sort.DESCENDING) .sort("timestamp", Sort.DESCENDING)
.distinct("uuid")
.findAll() .findAll()
.asFlowable() .asFlowable()
.filter { it.isLoaded } .filter { it.isLoaded }

View file

@ -31,7 +31,6 @@ open class Task : RealmObject, Parcelable {
var notes: String? = null var notes: String? = null
@TaskTypes @TaskTypes
var type: String = "" var type: String = ""
@Stats.StatsTypes
var attribute: String? = Stats.STRENGTH var attribute: String? = Stats.STRENGTH
var value: Double = 0.0 var value: Double = 0.0
var tags: RealmList<Tag>? = RealmList() var tags: RealmList<Tag>? = RealmList()

View file

@ -1,15 +1,9 @@
package com.habitrpg.android.habitica.models.user package com.habitrpg.android.habitica.models.user
import android.content.Context import android.content.Context
import android.support.annotation.StringDef
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.HabitRpgClass import com.habitrpg.android.habitica.models.HabitRpgClass
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
@ -39,7 +33,6 @@ open class Stats : RealmObject() {
var points: Int? = null var points: Int? = null
var lvl: Int? = null var lvl: Int? = null
@SerializedName("class") @SerializedName("class")
@HabiticaClassTypes
var habitClass: String? = null var habitClass: String? = null
var gp: Double? = null var gp: Double? = null
var exp: Double? = null var exp: Double? = null
@ -74,18 +67,6 @@ open class Stats : RealmObject() {
buffs?.per ?: 0f > 0 buffs?.per ?: 0f > 0
} }
@StringDef(Stats.STRENGTH, Stats.INTELLIGENCE, Stats.CONSTITUTION, Stats.PERCEPTION)
@Retention(RetentionPolicy.SOURCE)
annotation class StatsTypes
@StringDef(Stats.WARRIOR, Stats.MAGE, Stats.HEALER, Stats.ROGUE)
@Retention(RetentionPolicy.SOURCE)
annotation class HabiticaClassTypes
@StringDef(Stats.AUTO_ALLOCATE_FLAT, Stats.AUTO_ALLOCATE_CLASSBASED, Stats.AUTO_ALLOCATE_TASKBASED)
@Retention(RetentionPolicy.SOURCE)
annotation class AutoAllocationTypes
fun getTranslatedClassName(context: Context): String { fun getTranslatedClassName(context: Context): String {
return when (habitClass) { return when (habitClass) {
HEALER -> context.getString(R.string.healer) HEALER -> context.getString(R.string.healer)

View file

@ -13,7 +13,6 @@ import android.support.v7.widget.AppCompatCheckedTextView
import android.support.v7.widget.AppCompatTextView import android.support.v7.widget.AppCompatTextView
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.util.Log
import android.view.* import android.view.*
import android.widget.* import android.widget.*
import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.R
@ -137,7 +136,7 @@ class ChallengeFormActivity : BaseActivity() {
createChallenge() createChallenge()
} }
observable.subscribe({ compositeSubscription.add(observable.subscribe({
dialog.dismiss() dialog.dismiss()
savingInProgress = false savingInProgress = false
finish() finish()
@ -145,7 +144,7 @@ class ChallengeFormActivity : BaseActivity() {
dialog.dismiss() dialog.dismiss()
savingInProgress = false savingInProgress = false
RxErrorHandler.reportError(throwable) RxErrorHandler.reportError(throwable)
}) }))
} else if (item.itemId == android.R.id.home) { } else if (item.itemId == android.R.id.home) {
finish() finish()
return true return true
@ -229,7 +228,7 @@ class ChallengeFormActivity : BaseActivity() {
fillControlsByChallenge() fillControlsByChallenge()
} }
userRepository.getUser(userId).subscribe(Consumer { this.user = it }, RxErrorHandler.handleEmptyError()) compositeSubscription.add(userRepository.getUser(userId).subscribe(Consumer { this.user = it }, RxErrorHandler.handleEmptyError()))
gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem()) gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem())
challengeAddGemBtn.setOnClickListener { onAddGem() } challengeAddGemBtn.setOnClickListener { onAddGem() }
@ -323,7 +322,7 @@ class ChallengeFormActivity : BaseActivity() {
} }
locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
socialRepository.getGroups("guild").subscribe(Consumer { groups -> compositeSubscription.add(socialRepository.getGroups("guild").subscribe(Consumer { groups ->
val mutableGroups = groups.toMutableList() val mutableGroups = groups.toMutableList()
if (groups.firstOrNull { it.id == "00000000-0000-4000-A000-000000000000" } == null) { if (groups.firstOrNull { it.id == "00000000-0000-4000-A000-000000000000" } == null) {
val tavern = Group() val tavern = Group()
@ -334,7 +333,7 @@ class ChallengeFormActivity : BaseActivity() {
locationAdapter.clear() locationAdapter.clear()
locationAdapter.addAll(mutableGroups) locationAdapter.addAll(mutableGroups)
}, RxErrorHandler.handleEmptyError()) }, RxErrorHandler.handleEmptyError()))
challengeLocationSpinner.adapter = locationAdapter challengeLocationSpinner.adapter = locationAdapter
challengeLocationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { challengeLocationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
@ -365,19 +364,19 @@ class ChallengeFormActivity : BaseActivity() {
addReward.notNull { taskList.add(it) } addReward.notNull { taskList.add(it) }
challengeTasks.setTasks(taskList) challengeTasks.setTasks(taskList)
challengeTasks.addItemObservable().subscribe(Consumer { t -> compositeSubscription.add(challengeTasks.addItemObservable().subscribe(Consumer { t ->
when (t) { when (t) {
addHabit -> openNewTaskActivity(Task.TYPE_HABIT, null) addHabit -> openNewTaskActivity(Task.TYPE_HABIT, null)
addDaily -> openNewTaskActivity(Task.TYPE_DAILY, null) addDaily -> openNewTaskActivity(Task.TYPE_DAILY, null)
addTodo -> openNewTaskActivity(Task.TYPE_TODO, null) addTodo -> openNewTaskActivity(Task.TYPE_TODO, null)
addReward -> openNewTaskActivity(Task.TYPE_REWARD, null) addReward -> openNewTaskActivity(Task.TYPE_REWARD, null)
} }
}, RxErrorHandler.handleEmptyError()) }, RxErrorHandler.handleEmptyError()))
createChallengeTaskList.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() { createChallengeTaskList.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean { override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
// Stop only scrolling. // Stop only scrolling.
return rv?.scrollState == RecyclerView.SCROLL_STATE_DRAGGING return rv.scrollState == RecyclerView.SCROLL_STATE_DRAGGING
} }
}) })
createChallengeTaskList.adapter = challengeTasks createChallengeTaskList.adapter = challengeTasks
@ -493,15 +492,15 @@ class ChallengeFormActivity : BaseActivity() {
private inner class GroupArrayAdapter internal constructor(context: Context) : ArrayAdapter<Group>(context, android.R.layout.simple_spinner_item) { private inner class GroupArrayAdapter internal constructor(context: Context) : ArrayAdapter<Group>(context, android.R.layout.simple_spinner_item) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val checkedTextView = super.getView(position, convertView, parent) as AppCompatTextView val checkedTextView = super.getView(position, convertView, parent) as? AppCompatTextView
checkedTextView.text = getItem(position).name checkedTextView?.text = getItem(position)?.name
return checkedTextView return checkedTextView ?: View(context)
} }
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val checkedTextView = super.getDropDownView(position, convertView, parent) as AppCompatCheckedTextView val checkedTextView = super.getDropDownView(position, convertView, parent) as? AppCompatCheckedTextView
checkedTextView.text = getItem(position).name checkedTextView?.text = getItem(position)?.name
return checkedTextView return checkedTextView ?: View(context)
} }
} }

View file

@ -7,6 +7,7 @@ import android.view.View
import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.user.* import com.habitrpg.android.habitica.models.user.*
import com.habitrpg.android.habitica.ui.AvatarView import com.habitrpg.android.habitica.ui.AvatarView
@ -47,19 +48,21 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
val intent = intent val intent = intent
val bundle = intent.extras val bundle = intent.extras
isInitialSelection = bundle?.getBoolean("isInitialSelection") ?: false isInitialSelection = bundle?.getBoolean("isInitialSelection") ?: false
currentClass = bundle.getString("currentClass")
val preferences = Preferences() val preferences = Preferences()
preferences.setHair(Hair()) preferences.setHair(Hair())
preferences.costume = false preferences.costume = false
preferences.setSize(bundle.getString("size") ?: "slim") bundle.notNull { thisBundle ->
preferences.setSkin(bundle.getString("skin") ?: "") currentClass = thisBundle.getString("currentClass")
preferences.setShirt(bundle.getString("shirt") ?: "") preferences.setSize(thisBundle.getString("size") ?: "slim")
preferences.hair?.bangs = bundle.getInt("hairBangs") preferences.setSkin(thisBundle.getString("skin") ?: "")
preferences.hair?.base = bundle.getInt("hairBase") preferences.setShirt(thisBundle.getString("shirt") ?: "")
preferences.hair?.color = bundle.getString("hairColor") preferences.hair?.bangs = thisBundle.getInt("hairBangs")
preferences.hair?.mustache = bundle.getInt("hairMustache") preferences.hair?.base = thisBundle.getInt("hairBase")
preferences.hair?.beard = bundle.getInt("hairBeard") preferences.hair?.color = thisBundle.getString("hairColor")
preferences.hair?.mustache = thisBundle.getInt("hairMustache")
preferences.hair?.beard = thisBundle.getInt("hairBeard")
}
val healerOutfit = Outfit() val healerOutfit = Outfit()
@ -94,8 +97,8 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
warriorAvatarView.setAvatar(warrior) warriorAvatarView.setAvatar(warrior)
if (!isInitialSelection) { if (!isInitialSelection) {
userRepository.changeClass() compositeSubscription.add(userRepository.changeClass()
.subscribe(Consumer { classWasUnset = true }, RxErrorHandler.handleEmptyError()) .subscribe(Consumer { classWasUnset = true }, RxErrorHandler.handleEmptyError()))
} }
healerWrapper.setOnClickListener { healerSelected() } healerWrapper.setOnClickListener { healerSelected() }
@ -180,13 +183,13 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
private fun optOutOfClasses() { private fun optOutOfClasses() {
shouldFinish = true shouldFinish = true
this.displayProgressDialog() this.displayProgressDialog()
userRepository.disableClasses().subscribe(this, RxErrorHandler.handleEmptyError()) compositeSubscription.add(userRepository.disableClasses().subscribe(this, RxErrorHandler.handleEmptyError()))
} }
private fun selectClass(selectedClass: String) { private fun selectClass(selectedClass: String) {
shouldFinish = true shouldFinish = true
this.displayProgressDialog() this.displayProgressDialog()
userRepository.changeClass(selectedClass).subscribe(this, RxErrorHandler.handleEmptyError()) compositeSubscription.add(userRepository.changeClass(selectedClass).subscribe(this, RxErrorHandler.handleEmptyError()))
} }
private fun displayProgressDialog() { private fun displayProgressDialog() {

View file

@ -142,7 +142,7 @@ class StatsFragment: BaseMainFragment() {
} }
} }
private fun changeAutoAllocationMode(@Stats.AutoAllocationTypes allocationMode: String) { private fun changeAutoAllocationMode(allocationMode: String) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.allocationMode", allocationMode).subscribe(Consumer {}, RxErrorHandler.handleEmptyError())) compositeSubscription.add(userRepository.updateUser(user, "preferences.allocationMode", allocationMode).subscribe(Consumer {}, RxErrorHandler.handleEmptyError()))
distributeEvenlyButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_FLAT distributeEvenlyButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_FLAT
distributeClassButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_CLASSBASED distributeClassButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_CLASSBASED
@ -155,7 +155,7 @@ class StatsFragment: BaseMainFragment() {
builder.show() builder.show()
} }
private fun allocatePoint(@Stats.StatsTypes stat: String) { private fun allocatePoint(stat: String) {
compositeSubscription.add(userRepository.allocatePoint(user, stat).subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) compositeSubscription.add(userRepository.allocatePoint(user, stat).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
} }

View file

@ -6,6 +6,7 @@ import android.support.v7.preference.EditTextPreference
import android.support.v7.preference.Preference import android.support.v7.preference.Preference
import android.support.v7.preference.PreferenceCategory import android.support.v7.preference.PreferenceCategory
import com.habitrpg.android.habitica.HabiticaBaseApplication import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.models.user.User
import io.reactivex.Flowable import io.reactivex.Flowable
@ -56,12 +57,12 @@ class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.O
configurePreference(profileCategory?.findPreference(key), sharedPreferences?.getString(key, "")) configurePreference(profileCategory?.findPreference(key), sharedPreferences?.getString(key, ""))
if (sharedPreferences != null) { if (sharedPreferences != null) {
val observable: Flowable<User>? = when (key) { val observable: Flowable<User>? = when (key) {
"display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences.getString(key, "")) "display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences.getString(key, "") ?: "")
"photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences.getString(key, "")) "photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences.getString(key, "") ?: "")
"about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences.getString(key, "")) "about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences.getString(key, "") ?: "")
else -> null else -> null
} }
observable?.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) observable?.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()).notNull { compositeSubscription.add(it) }
} }
} }

View file

@ -129,7 +129,8 @@ class InboxFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshListener,
for (message in messages) { for (message in messages) {
val entry = inflater?.inflate(R.layout.item_inbox_overview, inbox_messages, false) val entry = inflater?.inflate(R.layout.item_inbox_overview, inbox_messages, false)
val avatarView = entry?.findViewById(R.id.avatar_view) as? AvatarView val avatarView = entry?.findViewById(R.id.avatar_view) as? AvatarView
message.userStyles?.let { avatarView?.setAvatar(it) } //message.userStyles?.let { avatarView?.setAvatar(it) }
avatarView?.visibility = View.GONE
val displayNameTextView = entry?.findViewById(R.id.display_name_textview) as? UsernameLabel val displayNameTextView = entry?.findViewById(R.id.display_name_textview) as? UsernameLabel
displayNameTextView?.username = message.user displayNameTextView?.username = message.user
displayNameTextView?.tier = message.contributor?.level ?: 0 displayNameTextView?.tier = message.contributor?.level ?: 0

View file

@ -8,7 +8,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView import com.facebook.drawee.view.SimpleDraweeView
import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.R
@ -65,7 +64,6 @@ class PartyDetailFragment : BaseFragment() {
private val questAcceptButton: Button? by bindView(R.id.quest_accept_button) private val questAcceptButton: Button? by bindView(R.id.quest_accept_button)
private val questRejectButton: Button? by bindView(R.id.quest_reject_button) private val questRejectButton: Button? by bindView(R.id.quest_reject_button)
private val questProgressView: OldQuestProgressView? by bindView(R.id.quest_progress_view) private val questProgressView: OldQuestProgressView? by bindView(R.id.quest_progress_view)
private val questParticipantList: LinearLayout? by bindView(R.id.quest_participant_list)
private val leaveButton: Button? by bindView(R.id.leave_button) private val leaveButton: Button? by bindView(R.id.leave_button)
@ -113,10 +111,10 @@ class PartyDetailFragment : BaseFragment() {
} }
private fun refreshParty() { private fun refreshParty() {
socialRepository.retrieveGroup("party") compositeSubscription.add(socialRepository.retrieveGroup("party")
.flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) } .flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) }
.doOnComplete { refreshLayout?.isRefreshing = false } .doOnComplete { refreshLayout?.isRefreshing = false }
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
} }
private fun updateParty(party: Group?) { private fun updateParty(party: Group?) {
@ -211,8 +209,11 @@ class PartyDetailFragment : BaseFragment() {
val builder = AlertDialog.Builder(activity) val builder = AlertDialog.Builder(activity)
.setMessage(R.string.leave_party_confirmation) .setMessage(R.string.leave_party_confirmation)
.setPositiveButton(R.string.yes) { _, _ -> .setPositiveButton(R.string.yes) { _, _ ->
socialRepository.leaveGroup(partyId) this.socialRepository.leaveGroup(partyId)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) .flatMap { userRepository.retrieveUser(false, true) }
.subscribe(Consumer {
activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit()
}, RxErrorHandler.handleEmptyError())
}.setNegativeButton(R.string.no) { _, _ -> } }.setNegativeButton(R.string.no) { _, _ -> }
builder.show() builder.show()
} }

View file

@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.SocialRepository import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.social.Group import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
@ -149,7 +150,12 @@ class PartyFragment : BaseMainFragment() {
.setPositiveButton(context?.getString(R.string.yes)) { _, _ -> .setPositiveButton(context?.getString(R.string.yes)) { _, _ ->
if (this.group != null) { if (this.group != null) {
this.socialRepository.leaveGroup(this.group?.id ?: "") this.socialRepository.leaveGroup(this.group?.id ?: "")
.subscribe(Consumer { activity?.supportFragmentManager?.beginTransaction()?.remove(this@PartyFragment)?.commit() }, RxErrorHandler.handleEmptyError()) .flatMap { userRepository.retrieveUser(false, true) }
.subscribe(Consumer {
parentFragment.notNull { fragment ->
activity?.supportFragmentManager?.beginTransaction()?.remove(fragment)?.commit()
}
}, RxErrorHandler.handleEmptyError())
} }
} }
.setNegativeButton(context?.getString(R.string.no)) { dialog, _ -> dialog.dismiss() } .setNegativeButton(context?.getString(R.string.no)) { dialog, _ -> dialog.dismiss() }

View file

@ -27,7 +27,7 @@ object MarkdownParser {
private val processor = AndDown() private val processor = AndDown()
private val regex = Pattern.compile("@(?:\\w+)") private val regex = Pattern.compile("@(?:\\w+)")
private val colorSpan = UsernameSpan() private val colorSpan = ForegroundColorSpan(Color.parseColor("#6133b4"))
/** /**
* Parses formatted markdown and returns it as styled CharSequence * Parses formatted markdown and returns it as styled CharSequence

View file

@ -1,76 +0,0 @@
package com.habitrpg.android.habitica.ui.helpers;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Parcel;
import android.support.annotation.NonNull;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;
public class UsernameSpan extends MetricAffectingSpan implements ParcelableSpan {
private final int color = Color.parseColor("#6133b4");
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
writeToParcelInternal(dest, flags);
}
private void writeToParcelInternal(@NonNull Parcel dest, int flags) {
dest.writeInt(color);
}
public void updateDrawState(@NonNull TextPaint textPaint) {
textPaint.setColor(color);
apply(textPaint);
}
@Override
public int getSpanTypeId() {
return 0;
}
@Override
public void updateMeasureState(@NonNull TextPaint textPaint) {
apply(textPaint);
}
private static void apply(Paint paint) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int want = oldStyle | Typeface.BOLD;
Typeface tf;
if (old == null) {
tf = Typeface.defaultFromStyle(want);
} else {
tf = Typeface.create(old, want);
}
int fake = want & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}

View file

@ -1,7 +1,11 @@
package com.habitrpg.android.habitica.ui.views.social package com.habitrpg.android.habitica.ui.views.social
import android.content.Context import android.content.Context
import android.os.Build
import android.support.v4.content.ContextCompat
import android.support.v4.content.res.ResourcesCompat
import android.util.AttributeSet import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
@ -43,6 +47,12 @@ class UsernameLabel(context: Context?, attrs: AttributeSet?) : LinearLayout(cont
addView(textView, params) addView(textView, params)
val padding = context?.resources?.getDimension(R.dimen.spacing_small)?.toInt() ?: 0 val padding = context?.resources?.getDimension(R.dimen.spacing_small)?.toInt() ?: 0
textView.setPadding(0, 0, padding, 0) textView.setPadding(0, 0, padding, 0)
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
textView.setTextAppearance(R.style.Body1)
} else {
textView.setTextAppearance(context, R.style.Body1)
}
addView(tierIconView, params) addView(tierIconView, params)
} }
} }

View file

@ -61,6 +61,10 @@ class ChatMessageDeserializer : JsonDeserializer<ChatMessage> {
message.user = obj.get("user").asString message.user = obj.get("user").asString
} }
if (obj.has("username")) {
message.username = obj.get("username").asString
}
if (obj.has("sent")) { if (obj.has("sent")) {
message.sent = obj.get("sent").asBoolean message.sent = obj.get("sent").asBoolean
} }

View file

@ -16,12 +16,8 @@ buildscript {
classpath 'com.google.gms:google-services:4.0.1' classpath 'com.google.gms:google-services:4.0.1'
classpath "io.realm:realm-gradle-plugin:5.7.0" classpath "io.realm:realm-gradle-plugin:5.7.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
classpath "gradle.plugin.io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0.RC4-3" classpath "gradle.plugin.io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0.RC4-3"
} }
// Exclude the version that the android plugin depends on.
configurations.classpath.exclude group: 'com.android.tools.external.lombok'
} }
apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'io.gitlab.arturbosch.detekt'

5
fastlane/Pluginfile Normal file
View file

@ -0,0 +1,5 @@
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
gem 'fastlane-plugin-increment_version_code'

44
fastlane/README.md Normal file
View file

@ -0,0 +1,44 @@
fastlane documentation
================
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```
xcode-select --install
```
Install _fastlane_ using
```
[sudo] gem install fastlane -NV
```
or alternatively using `brew cask install fastlane`
# Available Actions
## Android
### android test
```
fastlane android test
```
Runs all the tests
### android alpha
```
fastlane android alpha
```
Submit a new Alpha Build to Google Play
### android beta
```
fastlane android beta
```
Submit a new Beta Build to Google Play
### android deploy
```
fastlane android deploy
```
Deploy a new version to the Google Play
----
This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.

View file

@ -0,0 +1 @@
This update brings improvements to challenges and task notes as well as fixes for various bugs.