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"
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
implementation 'com.google.dagger:dagger: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
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
@ -140,7 +140,7 @@ android {
buildConfigField "String", "STORE", "\"google\""
multiDexEnabled true
versionCode 2004
versionCode 2016
versionName "1.6"
}
@ -299,6 +299,12 @@ tasks.whenTaskAdded { task ->
}
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xmaxerrs" << "500"
}
}
check { findbugs { skip true } }
apply plugin: 'com.google.gms.google-services'

View file

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

View file

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

View file

@ -827,7 +827,7 @@
<string name="confirm_username">Confirm Username</string>
<string name="username_not_confirmed">Username not 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="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>

View file

@ -66,7 +66,7 @@ interface UserRepository : BaseRepository {
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void>
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>
}

View file

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

View file

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

View file

@ -1,15 +1,9 @@
package com.habitrpg.android.habitica.models.user
import android.content.Context
import android.support.annotation.StringDef
import com.google.gson.annotations.SerializedName
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.HabitRpgClass
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
@ -39,7 +33,6 @@ open class Stats : RealmObject() {
var points: Int? = null
var lvl: Int? = null
@SerializedName("class")
@HabiticaClassTypes
var habitClass: String? = null
var gp: Double? = null
var exp: Double? = null
@ -74,18 +67,6 @@ open class Stats : RealmObject() {
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 {
return when (habitClass) {
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.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.util.Log
import android.view.*
import android.widget.*
import com.habitrpg.android.habitica.R
@ -137,7 +136,7 @@ class ChallengeFormActivity : BaseActivity() {
createChallenge()
}
observable.subscribe({
compositeSubscription.add(observable.subscribe({
dialog.dismiss()
savingInProgress = false
finish()
@ -145,7 +144,7 @@ class ChallengeFormActivity : BaseActivity() {
dialog.dismiss()
savingInProgress = false
RxErrorHandler.reportError(throwable)
})
}))
} else if (item.itemId == android.R.id.home) {
finish()
return true
@ -229,7 +228,7 @@ class ChallengeFormActivity : BaseActivity() {
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())
challengeAddGemBtn.setOnClickListener { onAddGem() }
@ -323,7 +322,7 @@ class ChallengeFormActivity : BaseActivity() {
}
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()
if (groups.firstOrNull { it.id == "00000000-0000-4000-A000-000000000000" } == null) {
val tavern = Group()
@ -334,7 +333,7 @@ class ChallengeFormActivity : BaseActivity() {
locationAdapter.clear()
locationAdapter.addAll(mutableGroups)
}, RxErrorHandler.handleEmptyError())
}, RxErrorHandler.handleEmptyError()))
challengeLocationSpinner.adapter = locationAdapter
challengeLocationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
@ -365,19 +364,19 @@ class ChallengeFormActivity : BaseActivity() {
addReward.notNull { taskList.add(it) }
challengeTasks.setTasks(taskList)
challengeTasks.addItemObservable().subscribe(Consumer { t ->
compositeSubscription.add(challengeTasks.addItemObservable().subscribe(Consumer { t ->
when (t) {
addHabit -> openNewTaskActivity(Task.TYPE_HABIT, null)
addDaily -> openNewTaskActivity(Task.TYPE_DAILY, null)
addTodo -> openNewTaskActivity(Task.TYPE_TODO, null)
addReward -> openNewTaskActivity(Task.TYPE_REWARD, null)
}
}, RxErrorHandler.handleEmptyError())
}, RxErrorHandler.handleEmptyError()))
createChallengeTaskList.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
// Stop only scrolling.
return rv?.scrollState == RecyclerView.SCROLL_STATE_DRAGGING
return rv.scrollState == RecyclerView.SCROLL_STATE_DRAGGING
}
})
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) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val checkedTextView = super.getView(position, convertView, parent) as AppCompatTextView
checkedTextView.text = getItem(position).name
return checkedTextView
val checkedTextView = super.getView(position, convertView, parent) as? AppCompatTextView
checkedTextView?.text = getItem(position)?.name
return checkedTextView ?: View(context)
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val checkedTextView = super.getDropDownView(position, convertView, parent) as AppCompatCheckedTextView
checkedTextView.text = getItem(position).name
return checkedTextView
val checkedTextView = super.getDropDownView(position, convertView, parent) as? AppCompatCheckedTextView
checkedTextView?.text = getItem(position)?.name
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.components.AppComponent
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.models.user.*
import com.habitrpg.android.habitica.ui.AvatarView
@ -47,19 +48,21 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
val intent = intent
val bundle = intent.extras
isInitialSelection = bundle?.getBoolean("isInitialSelection") ?: false
currentClass = bundle.getString("currentClass")
val preferences = Preferences()
preferences.setHair(Hair())
preferences.costume = false
preferences.setSize(bundle.getString("size") ?: "slim")
preferences.setSkin(bundle.getString("skin") ?: "")
preferences.setShirt(bundle.getString("shirt") ?: "")
preferences.hair?.bangs = bundle.getInt("hairBangs")
preferences.hair?.base = bundle.getInt("hairBase")
preferences.hair?.color = bundle.getString("hairColor")
preferences.hair?.mustache = bundle.getInt("hairMustache")
preferences.hair?.beard = bundle.getInt("hairBeard")
bundle.notNull { thisBundle ->
currentClass = thisBundle.getString("currentClass")
preferences.setSize(thisBundle.getString("size") ?: "slim")
preferences.setSkin(thisBundle.getString("skin") ?: "")
preferences.setShirt(thisBundle.getString("shirt") ?: "")
preferences.hair?.bangs = thisBundle.getInt("hairBangs")
preferences.hair?.base = thisBundle.getInt("hairBase")
preferences.hair?.color = thisBundle.getString("hairColor")
preferences.hair?.mustache = thisBundle.getInt("hairMustache")
preferences.hair?.beard = thisBundle.getInt("hairBeard")
}
val healerOutfit = Outfit()
@ -94,8 +97,8 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
warriorAvatarView.setAvatar(warrior)
if (!isInitialSelection) {
userRepository.changeClass()
.subscribe(Consumer { classWasUnset = true }, RxErrorHandler.handleEmptyError())
compositeSubscription.add(userRepository.changeClass()
.subscribe(Consumer { classWasUnset = true }, RxErrorHandler.handleEmptyError()))
}
healerWrapper.setOnClickListener { healerSelected() }
@ -180,13 +183,13 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
private fun optOutOfClasses() {
shouldFinish = true
this.displayProgressDialog()
userRepository.disableClasses().subscribe(this, RxErrorHandler.handleEmptyError())
compositeSubscription.add(userRepository.disableClasses().subscribe(this, RxErrorHandler.handleEmptyError()))
}
private fun selectClass(selectedClass: String) {
shouldFinish = true
this.displayProgressDialog()
userRepository.changeClass(selectedClass).subscribe(this, RxErrorHandler.handleEmptyError())
compositeSubscription.add(userRepository.changeClass(selectedClass).subscribe(this, RxErrorHandler.handleEmptyError()))
}
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()))
distributeEvenlyButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_FLAT
distributeClassButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_CLASSBASED
@ -155,7 +155,7 @@ class StatsFragment: BaseMainFragment() {
builder.show()
}
private fun allocatePoint(@Stats.StatsTypes stat: String) {
private fun allocatePoint(stat: String) {
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.PreferenceCategory
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.models.user.User
import io.reactivex.Flowable
@ -56,12 +57,12 @@ class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.O
configurePreference(profileCategory?.findPreference(key), sharedPreferences?.getString(key, ""))
if (sharedPreferences != null) {
val observable: Flowable<User>? = when (key) {
"display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences.getString(key, ""))
"photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences.getString(key, ""))
"about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences.getString(key, ""))
"display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences.getString(key, "") ?: "")
"photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences.getString(key, "") ?: "")
"about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences.getString(key, "") ?: "")
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) {
val entry = inflater?.inflate(R.layout.item_inbox_overview, inbox_messages, false)
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
displayNameTextView?.username = message.user
displayNameTextView?.tier = message.contributor?.level ?: 0

View file

@ -8,7 +8,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.facebook.drawee.view.SimpleDraweeView
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 questRejectButton: Button? by bindView(R.id.quest_reject_button)
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)
@ -113,10 +111,10 @@ class PartyDetailFragment : BaseFragment() {
}
private fun refreshParty() {
socialRepository.retrieveGroup("party")
compositeSubscription.add(socialRepository.retrieveGroup("party")
.flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) }
.doOnComplete { refreshLayout?.isRefreshing = false }
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}
private fun updateParty(party: Group?) {
@ -211,8 +209,11 @@ class PartyDetailFragment : BaseFragment() {
val builder = AlertDialog.Builder(activity)
.setMessage(R.string.leave_party_confirmation)
.setPositiveButton(R.string.yes) { _, _ ->
socialRepository.leaveGroup(partyId)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
this.socialRepository.leaveGroup(partyId)
.flatMap { userRepository.retrieveUser(false, true) }
.subscribe(Consumer {
activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit()
}, RxErrorHandler.handleEmptyError())
}.setNegativeButton(R.string.no) { _, _ -> }
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.data.InventoryRepository
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.models.social.Group
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
@ -149,7 +150,12 @@ class PartyFragment : BaseMainFragment() {
.setPositiveButton(context?.getString(R.string.yes)) { _, _ ->
if (this.group != null) {
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() }

View file

@ -27,7 +27,7 @@ object MarkdownParser {
private val processor = AndDown()
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

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
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.TypedValue
import android.view.Gravity
import android.view.View
import android.widget.FrameLayout
@ -43,6 +47,12 @@ class UsernameLabel(context: Context?, attrs: AttributeSet?) : LinearLayout(cont
addView(textView, params)
val padding = context?.resources?.getDimension(R.dimen.spacing_small)?.toInt() ?: 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)
}
}

View file

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

View file

@ -16,12 +16,8 @@ buildscript {
classpath 'com.google.gms:google-services:4.0.1'
classpath "io.realm:realm-gradle-plugin:5.7.0"
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"
}
// Exclude the version that the android plugin depends on.
configurations.classpath.exclude group: 'com.android.tools.external.lombok'
}
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.