Correctly load in user data and display headers in lists

This commit is contained in:
Phillip Thelen 2022-06-03 12:51:17 +02:00
parent 97cc310460
commit 0be269ee7e
17 changed files with 163 additions and 57 deletions

View file

@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.extensions
import android.text.Html
import java.util.Locale
fun String.fromHtml(): CharSequence {
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
@ -10,3 +11,7 @@ fun String.fromHtml(): CharSequence {
Html.fromHtml(this)
}
}
fun String.localizedCapitalize(): String {
return this.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
}

View file

@ -36,6 +36,7 @@
</intent-filter>
</activity>
<activity android:name=".ui.activities.TaskListActivity" />
<activity android:name=".ui.activities.AvatarActivity" />
</application>
</manifest>

View file

@ -4,4 +4,4 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MainApplication : Application() { }
class MainApplication : Application()

View file

@ -2,5 +2,4 @@ package com.habitrpg.wearos.habitica.data.repositories
import javax.inject.Inject
class TaskLocalRepository @Inject constructor() {
}
class TaskLocalRepository @Inject constructor()

View file

@ -2,5 +2,4 @@ package com.habitrpg.wearos.habitica.data.repositories
import javax.inject.Inject
class UserLocalRepository @Inject constructor() {
}
class UserLocalRepository @Inject constructor()

View file

@ -14,23 +14,30 @@ class Items {
var gear: Gear? = null
}
@JsonClass(generateAdapter = true)
class Profile {
var name: String? = null
}
@JsonClass(generateAdapter = true)
class User: Avatar {
override val currentMount: String? = null
override val currentPet: String? = null
override val sleep: Boolean = false
override val stats: Stats? = null
override val preferences: Preferences? = null
override val flags: Flags? = null
override val gemCount: Int = 0
override val hourglassCount: Int = 0
val items: Items? = null
override var currentMount: String? = null
override var currentPet: String? = null
override var sleep: Boolean = false
override var stats: Stats? = null
override var preferences: Preferences? = null
override var flags: Flags? = null
override var gemCount: Int = 0
override var hourglassCount: Int = 0
var items: Items? = null
override val costume: Outfit?
get() = items?.gear?.costume
override val equipped: Outfit?
get() = items?.gear?.equipped
override val hasClass: Boolean = false
var profile: Profile? = null
override fun isValid(): Boolean {
return true
}

View file

@ -0,0 +1,12 @@
package com.habitrpg.wearos.habitica.ui.activities
import android.os.Bundle
import com.habitrpg.wearos.habitica.databinding.ActivityAvatarBinding
class AvatarActivity: BaseActivity<ActivityAvatarBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityAvatarBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
}
}

View file

@ -3,7 +3,6 @@ package com.habitrpg.wearos.habitica.ui.activities
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.content.res.AppCompatResources
@ -40,16 +39,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
WearableLinearLayoutManager(this@MainActivity, HabiticaScrollingLayoutCallback())
adapter = this@MainActivity.adapter
}
binding.root.post {
binding.root.setPaddingRelative(0, (binding.root.height * 0.25).toInt(), 0, (binding.root.height * 0.25).toInt())
}
}
override fun onStart() {
super.onStart()
binding.root.post {
binding.root.setPaddingRelative(0, (binding.root.height * 0.25).toInt(), 0, (binding.root.height * 0.25).toInt())
binding.root.scrollY = 0
}
adapter.data = listOf(
MenuItem(
"avatar",
@ -105,17 +101,21 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
AppCompatResources.getDrawable(this, R.drawable.ic_settings),
ContextCompat.getColor(this, R.color.blue_100)
) {
openTasklist(TaskType.REWARD)
}
)
viewModel.user.observe(this) {
Log.d("MainActivity", "onStart: ${it.currentPet}")
adapter.title = it.profile?.name ?: ""
adapter.notifyItemChanged(0)
}
}
private fun openAvatarActivity() {
startActivity(Intent(this, AvatarActivity::class.java))
}
private fun openTasklist(type: TaskType) {
val intent = Intent(this, TaskListActivity::class.java).apply {
putExtra("task_type", type.name)
putExtra("task_type", type.value)
}
startActivity(intent)
}

View file

@ -3,8 +3,9 @@ package com.habitrpg.wearos.habitica.ui.activities
import android.os.Bundle
import androidx.activity.viewModels
import androidx.wear.widget.WearableLinearLayoutManager
import com.habitrpg.common.habitica.models.tasks.TaskType
import com.habitrpg.wearos.habitica.R
import com.habitrpg.wearos.habitica.databinding.ActivityTasklistBinding
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.ui.adapters.TaskListAdapter
import com.habitrpg.wearos.habitica.ui.viewmodels.TaskListViewModel
import dagger.hilt.android.AndroidEntryPoint
@ -18,22 +19,24 @@ class TaskListActivity: BaseActivity<ActivityTasklistBinding>() {
binding = ActivityTasklistBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
binding.root.apply {
isEdgeItemsCenteringEnabled = true
layoutManager =
WearableLinearLayoutManager(this@TaskListActivity, HabiticaScrollingLayoutCallback())
adapter = this@TaskListActivity.adapter
}
adapter.data = listOf(
Task().apply { text = "Test 1" },
Task().apply { text = "Test 2" },
Task().apply { text = "Test 3" },
Task().apply { text = "Test 4" },
Task().apply { text = "Test 5" }
)
setAdapterTitle()
viewModel.tasks.observe(this) {
adapter.data = it
}
}
private fun setAdapterTitle() {
adapter.title = when (viewModel.taskType) {
TaskType.HABIT -> getString(R.string.habits)
TaskType.DAILY -> getString(R.string.dailies)
TaskType.TODO -> getString(R.string.todos)
TaskType.REWARD -> getString(R.string.rewards)
null -> ""
}
}
}

View file

@ -4,37 +4,55 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.wearos.habitica.databinding.RowHeaderBinding
import com.habitrpg.wearos.habitica.databinding.RowHubBinding
import com.habitrpg.wearos.habitica.ui.activities.MenuItem
import com.habitrpg.wearos.habitica.ui.viewHolders.BindableViewHolder
import com.habitrpg.wearos.habitica.ui.viewHolders.HeaderViewHolder
class HubAdapter: RecyclerView.Adapter<HubViewHolder>() {
class HubAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var title: String = ""
var data: List<MenuItem> = listOf()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HubViewHolder {
return HubViewHolder(RowHubBinding.inflate(parent.context.layoutInflater, parent, false).root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = parent.context.layoutInflater
return if (viewType == 0) {
HeaderViewHolder(RowHeaderBinding.inflate(inflater, parent, false).root)
} else {
HubViewHolder(RowHubBinding.inflate(inflater, parent, false).root)
}
}
override fun onBindViewHolder(holder: HubViewHolder, position: Int) {
holder.bind(data[position])
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is HubViewHolder) {
val item = data[position - 1]
holder.bind(item)
} else if (holder is HeaderViewHolder){
holder.bind(title)
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) 0 else 1
}
override fun getItemCount(): Int {
return data.size
return data.size + 1
}
}
class HubViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
class HubViewHolder(itemView: View): BindableViewHolder<MenuItem>(itemView) {
val binding = RowHubBinding.bind(itemView)
fun bind(item: MenuItem) {
binding.title.text = item.title
binding.iconView.setImageDrawable(item.icon)
binding.iconView.setColorFilter(item.color)
override fun bind(data: MenuItem) {
binding.title.text = data.title
binding.iconView.setImageDrawable(data.icon)
binding.iconView.setColorFilter(data.color)
binding.root.setOnClickListener {
item.onClick()
data.onClick()
}
}
}

View file

@ -5,31 +5,49 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.wearos.habitica.databinding.RowHabitBinding
import com.habitrpg.wearos.habitica.databinding.RowHeaderBinding
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.ui.viewHolders.BindableViewHolder
import com.habitrpg.wearos.habitica.ui.viewHolders.HeaderViewHolder
class TaskListAdapter: RecyclerView.Adapter<TaskViewHolder>() {
class TaskListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var title: String = ""
var data: List<Task> = listOf()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder {
return TaskViewHolder(RowHabitBinding.inflate(parent.context.layoutInflater, parent, false).root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = parent.context.layoutInflater
return if (viewType == 0) {
HeaderViewHolder(RowHeaderBinding.inflate(inflater, parent, false).root)
} else {
TaskViewHolder(RowHabitBinding.inflate(inflater, parent, false).root)
}
}
override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
holder.bind(data[position])
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is TaskViewHolder) {
val item = data[position - 1]
holder.bind(item)
} else if (holder is HeaderViewHolder){
holder.bind(title)
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) 0 else 1
}
override fun getItemCount(): Int {
return data.size
return data.size + 1
}
}
class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
class TaskViewHolder(itemView: View) : BindableViewHolder<Task>(itemView) {
val binding = RowHabitBinding.bind(itemView)
fun bind(task: Task) {
override fun bind(task: Task) {
binding.title.text = task.text
}
}

View file

@ -0,0 +1,8 @@
package com.habitrpg.wearos.habitica.ui.viewHolders
import android.view.View
import androidx.recyclerview.widget.RecyclerView
abstract class BindableViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(data: T)
}

View file

@ -0,0 +1,12 @@
package com.habitrpg.wearos.habitica.ui.viewHolders
import android.view.View
import com.habitrpg.wearos.habitica.databinding.RowHeaderBinding
class HeaderViewHolder(itemView: View): BindableViewHolder<String>(itemView) {
private val binding = RowHeaderBinding.bind(itemView)
override fun bind(data: String) {
binding.textView.text = data
}
}

View file

@ -3,5 +3,4 @@ package com.habitrpg.wearos.habitica.ui.viewmodels
import androidx.lifecycle.ViewModel
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
open class BaseViewModel(val userRepository: UserRepository): ViewModel() {
}
open class BaseViewModel(val userRepository: UserRepository): ViewModel()

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/spacing_medium">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="@color/white"
tools:text="Header Text"
android:textStyle="bold"
android:textSize="20sp" />
</FrameLayout>

View file

@ -21,6 +21,7 @@
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:textSize="18sp" />
</LinearLayout>
</FrameLayout>