Legit Material3 Theming 1/5 (style/colors.xml)

Chnage Source code Icon (Touches #127)
Some code cleanups
etc... (Sry I forgot what all I did)
This commit is contained in:
LooKeR 2021-12-03 00:37:13 +05:30
parent 74d3ec194c
commit 848c5ce863
24 changed files with 393 additions and 319 deletions

View File

@ -74,7 +74,7 @@ class InstallerService : Service() {
.setAutoCancel(true) .setAutoCancel(true)
.setColor( .setColor(
ContextThemeWrapper(this, R.style.Theme_Main_Light) ContextThemeWrapper(this, R.style.Theme_Main_Light)
.getColorFromAttr(android.R.attr.colorAccent).defaultColor .getColorFromAttr(R.attr.colorPrimary).defaultColor
) )
when (status) { when (status) {

View File

@ -93,7 +93,8 @@ class EditRepositoryFragment() : ScreenFragment() {
syncConnection.bind(requireContext()) syncConnection.bind(requireContext())
screenActivity.onToolbarCreated(toolbar) screenActivity.onToolbarCreated(toolbar)
toolbar.setTitle(if (repositoryId != null) R.string.edit_repository else R.string.add_repository) collapsingToolbar.title =
getString(if (repositoryId != null) R.string.edit_repository else R.string.add_repository)
saveMenuItem = toolbar.menu.add(R.string.save) saveMenuItem = toolbar.menu.add(R.string.save)
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_save)) .setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_save))
@ -179,7 +180,7 @@ class EditRepositoryFragment() : ScreenFragment() {
} catch (e: Exception) { } catch (e: Exception) {
Pair(null, null) Pair(null, null)
} }
layout.address.setText(addressText?.nullIfEmpty() ?: layout.address.hint) layout.address.setText(addressText)
layout.fingerprint.setText(fingerprintText) layout.fingerprint.setText(fingerprintText)
} else { } else {
layout.address.setText(repository.address) layout.address.setText(repository.address)

View File

@ -3,10 +3,15 @@ package com.looker.droidify.screen
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.switchmaterial.SwitchMaterial import coil.load
import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.textview.MaterialTextView
import com.looker.droidify.R import com.looker.droidify.R
import com.looker.droidify.database.Database import com.looker.droidify.database.Database
import com.looker.droidify.entity.Repository import com.looker.droidify.entity.Repository
import com.looker.droidify.utility.extension.resources.clear
import com.looker.droidify.utility.extension.resources.getColorFromAttr
import com.looker.droidify.utility.extension.resources.inflate import com.looker.droidify.utility.extension.resources.inflate
import com.looker.droidify.widget.CursorRecyclerAdapter import com.looker.droidify.widget.CursorRecyclerAdapter
@ -18,9 +23,12 @@ class RepositoriesAdapter(
enum class ViewType { REPOSITORY } enum class ViewType { REPOSITORY }
private class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val switch = itemView.findViewById<SwitchMaterial>(R.id.repository_switch)!! val item = itemView.findViewById<MaterialCardView>(R.id.repository_item)!!
val checkMark = itemView.findViewById<ShapeableImageView>(R.id.repository_state)!!
val repoName = itemView.findViewById<MaterialTextView>(R.id.repository_name)!!
val repoDesc = itemView.findViewById<MaterialTextView>(R.id.repository_description)!!
var listenSwitch = true var isEnabled = true
} }
override val viewTypeClass: Class<ViewType> override val viewTypeClass: Class<ViewType>
@ -39,15 +47,13 @@ class RepositoriesAdapter(
viewType: ViewType, viewType: ViewType,
): RecyclerView.ViewHolder { ): RecyclerView.ViewHolder {
return ViewHolder(parent.inflate(R.layout.repository_item)).apply { return ViewHolder(parent.inflate(R.layout.repository_item)).apply {
itemView.setOnClickListener { onClick(getRepository(adapterPosition)) } itemView.setOnLongClickListener {
switch.setOnCheckedChangeListener { _, isChecked -> onClick(getRepository(adapterPosition))
if (listenSwitch) { true
if (!onSwitch(getRepository(adapterPosition), isChecked)) {
listenSwitch = false
switch.isChecked = !isChecked
listenSwitch = true
}
} }
itemView.setOnClickListener {
isEnabled = !isEnabled
onSwitch(getRepository(adapterPosition), isEnabled)
} }
} }
} }
@ -55,10 +61,26 @@ class RepositoriesAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder as ViewHolder holder as ViewHolder
val repository = getRepository(position) val repository = getRepository(position)
val lastListenSwitch = holder.listenSwitch holder.repoName.text = repository.name
holder.listenSwitch = false holder.repoDesc.text = repository.description.trim()
holder.switch.isChecked = repository.enabled if (repository.enabled) {
holder.listenSwitch = lastListenSwitch holder.isEnabled = true
holder.switch.text = repository.name holder.item.setCardBackgroundColor(
holder.item.context.getColorFromAttr(R.attr.colorPrimaryContainer)
)
holder.repoName.setTextColor(holder.repoName.context.getColorFromAttr(R.attr.colorOnPrimaryContainer))
holder.repoDesc.setTextColor(holder.repoDesc.context.getColorFromAttr(R.attr.colorOnPrimaryContainer))
holder.checkMark.load(R.drawable.ic_check)
holder.checkMark.imageTintList =
holder.checkMark.context.getColorFromAttr(R.attr.colorOnPrimaryContainer)
} else {
holder.isEnabled = false
holder.item.setCardBackgroundColor(holder.item.context.getColorFromAttr(android.R.attr.colorBackground))
holder.repoName.setTextColor(holder.repoName.context.getColorFromAttr(R.attr.colorOnBackground))
holder.repoDesc.setTextColor(holder.repoDesc.context.getColorFromAttr(R.attr.colorOnBackground))
holder.checkMark.clear()
holder.checkMark.imageTintList =
holder.checkMark.context.getColorFromAttr(R.attr.colorOnBackground)
}
} }
} }

View File

@ -13,6 +13,7 @@ import com.looker.droidify.database.CursorOwner
import com.looker.droidify.service.Connection import com.looker.droidify.service.Connection
import com.looker.droidify.service.SyncService import com.looker.droidify.service.SyncService
import com.looker.droidify.utility.Utils import com.looker.droidify.utility.Utils
import com.looker.droidify.widget.RecyclerFastScroller
class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback { class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
private var recyclerView: RecyclerView? = null private var recyclerView: RecyclerView? = null
@ -37,9 +38,11 @@ class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
syncConnection.binder?.setEnabled(repository, isEnabled) == true syncConnection.binder?.setEnabled(repository, isEnabled) == true
}) })
recyclerView = this recyclerView = this
RecyclerFastScroller(this)
}) })
} }
this.toolbar = fragmentBinding.toolbar this.toolbar = fragmentBinding.toolbar
this.collapsingToolbar = fragmentBinding.collapsingToolbar
return view return view
} }
@ -49,18 +52,15 @@ class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
syncConnection.bind(requireContext()) syncConnection.bind(requireContext())
screenActivity.cursorOwner.attach(this, CursorOwner.Request.Repositories) screenActivity.cursorOwner.attach(this, CursorOwner.Request.Repositories)
toolbar.apply { screenActivity.onToolbarCreated(toolbar)
screenActivity.onToolbarCreated(this) toolbar.menu.add(R.string.add_repository)
setTitle(R.string.repositories) .setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_add))
menu.add(R.string.add_repository)
.setIcon(Utils.getToolbarIcon(this.context, R.drawable.ic_add))
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
.setOnMenuItemClickListener { .setOnMenuItemClickListener {
view.post { screenActivity.navigateAddRepository() } view.post { screenActivity.navigateAddRepository() }
true true
} }
} collapsingToolbar.title = getString(R.string.repositories)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -19,7 +19,6 @@ import com.looker.droidify.service.SyncService
import com.looker.droidify.utility.Utils import com.looker.droidify.utility.Utils
import com.looker.droidify.utility.extension.resources.getColorFromAttr import com.looker.droidify.utility.extension.resources.getColorFromAttr
import com.looker.droidify.utility.extension.resources.sizeScaled import com.looker.droidify.utility.extension.resources.sizeScaled
import io.reactivex.rxjava3.disposables.Disposable
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.* import java.util.*
@ -44,7 +43,6 @@ class RepositoryFragment() : ScreenFragment() {
private var layout: LinearLayoutCompat? = null private var layout: LinearLayoutCompat? = null
private val syncConnection = Connection(SyncService::class.java) private val syncConnection = Connection(SyncService::class.java)
private var repositoryDisposable: Disposable? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -54,7 +52,7 @@ class RepositoryFragment() : ScreenFragment() {
lifecycleScope.launch(Dispatchers.Main) { updateRepositoryView() } lifecycleScope.launch(Dispatchers.Main) { updateRepositoryView() }
screenActivity.onToolbarCreated(toolbar) screenActivity.onToolbarCreated(toolbar)
toolbar.setTitle(R.string.repository) collapsingToolbar.title = getString(R.string.repository)
toolbar.menu.apply { toolbar.menu.apply {
add(R.string.edit_repository) add(R.string.edit_repository)
@ -98,8 +96,6 @@ class RepositoryFragment() : ScreenFragment() {
layout = null layout = null
titleBinding = null titleBinding = null
syncConnection.unbind(requireContext()) syncConnection.unbind(requireContext())
repositoryDisposable?.dispose()
repositoryDisposable = null
} }
private fun updateRepositoryView() { private fun updateRepositoryView() {
@ -111,7 +107,7 @@ class RepositoryFragment() : ScreenFragment() {
} else { } else {
layout.addTitleText(R.string.address, repository.address) layout.addTitleText(R.string.address, repository.address)
if (repository.updated > 0L) { if (repository.updated > 0L) {
toolbar.title = repository.name collapsingToolbar.title = repository.name
layout.addTitleText(R.string.name, repository.name) layout.addTitleText(R.string.name, repository.name)
layout.addTitleText(R.string.description, repository.description.replace('\n', ' ')) layout.addTitleText(R.string.description, repository.description.replace('\n', ' '))
layout.addTitleText(R.string.recently_updated, run { layout.addTitleText(R.string.recently_updated, run {

View File

@ -14,6 +14,7 @@ import com.looker.droidify.R
import com.looker.droidify.content.Preferences import com.looker.droidify.content.Preferences
import com.looker.droidify.database.CursorOwner import com.looker.droidify.database.CursorOwner
import com.looker.droidify.installer.AppInstaller import com.looker.droidify.installer.AppInstaller
import com.looker.droidify.ui.appDetail.AppDetailFragment
import com.looker.droidify.utility.KParcelable import com.looker.droidify.utility.KParcelable
import com.looker.droidify.utility.extension.resources.getDrawableFromAttr import com.looker.droidify.utility.extension.resources.getDrawableFromAttr
import com.looker.droidify.utility.extension.text.nullIfEmpty import com.looker.droidify.utility.extension.text.nullIfEmpty
@ -235,7 +236,7 @@ abstract class ScreenActivity : AppCompatActivity() {
val packageName = intent.packageName val packageName = intent.packageName
if (!packageName.isNullOrEmpty()) { if (!packageName.isNullOrEmpty()) {
val fragment = currentFragment val fragment = currentFragment
if (fragment !is ProductFragment || fragment.packageName != packageName) { if (fragment !is AppDetailFragment || fragment.packageName != packageName) {
navigateProduct(packageName) navigateProduct(packageName)
} }
} }
@ -243,7 +244,7 @@ abstract class ScreenActivity : AppCompatActivity() {
} }
} }
internal fun navigateProduct(packageName: String) = pushFragment(ProductFragment(packageName)) internal fun navigateProduct(packageName: String) = pushFragment(AppDetailFragment(packageName))
internal fun navigateRepositories() = pushFragment(RepositoriesFragment()) internal fun navigateRepositories() = pushFragment(RepositoriesFragment())
internal fun navigatePreferences() = pushFragment(SettingsFragment()) internal fun navigatePreferences() = pushFragment(SettingsFragment())
internal fun navigateAddRepository() = pushFragment(EditRepositoryFragment(null)) internal fun navigateAddRepository() = pushFragment(EditRepositoryFragment(null))

View File

@ -4,18 +4,16 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.appbar.MaterialToolbar
import com.looker.droidify.databinding.FragmentBinding import com.looker.droidify.databinding.FragmentBinding
open class ScreenFragment : BaseFragment() { open class ScreenFragment : BaseFragment() {
private var _fragmentBinding: FragmentBinding? = null private var _fragmentBinding: FragmentBinding? = null
val fragmentBinding get() = _fragmentBinding!! val fragmentBinding get() = _fragmentBinding!!
lateinit var toolbar: Toolbar lateinit var toolbar: MaterialToolbar
lateinit var collapsingToolbar: CollapsingToolbarLayout lateinit var collapsingToolbar: CollapsingToolbarLayout
lateinit var appBar: AppBarLayout
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -29,7 +27,6 @@ open class ScreenFragment : BaseFragment() {
): View? { ): View? {
this.toolbar = fragmentBinding.toolbar this.toolbar = fragmentBinding.toolbar
this.collapsingToolbar = fragmentBinding.collapsingToolbar this.collapsingToolbar = fragmentBinding.collapsingToolbar
this.appBar = fragmentBinding.appbarLayout
return fragmentBinding.root return fragmentBinding.root
} }

View File

@ -48,7 +48,6 @@ class ScreenshotsAdapter(private val onClick: (Product.Screenshot) -> Unit) :
.setAllCornerSizes(radius) .setAllCornerSizes(radius)
.build() .build()
image.shapeAppearanceModel = shapeAppearanceModel image.shapeAppearanceModel = shapeAppearanceModel
image.setBackgroundColor(surfaceColor)
itemView.addView(image) itemView.addView(image)
itemView.layoutParams = RecyclerView.LayoutParams( itemView.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT,

View File

@ -45,7 +45,7 @@ class SettingsFragment : ScreenFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
preferenceBinding = PreferenceItemBinding.inflate(layoutInflater) preferenceBinding = PreferenceItemBinding.inflate(layoutInflater)
screenActivity.onToolbarCreated(toolbar) screenActivity.onToolbarCreated(toolbar)
toolbar.setTitle(R.string.settings) collapsingToolbar.title = getString(R.string.settings)
val content = fragmentBinding.fragmentContent val content = fragmentBinding.fragmentContent
val scroll = NestedScrollView(content.context) val scroll = NestedScrollView(content.context)
@ -202,8 +202,10 @@ class SettingsFragment : ScreenFragment() {
preferences[Preferences.Key.ProxyPort]?.setEnabled(enabled) preferences[Preferences.Key.ProxyPort]?.setEnabled(enabled)
} }
if (key == Preferences.Key.RootPermission) { if (key == Preferences.Key.RootPermission) {
preferences[Preferences.Key.RootPermission]?.setEnabled(Shell.getCachedShell()?.isRoot preferences[Preferences.Key.RootPermission]?.setEnabled(
?: Shell.getShell().isRoot) Shell.getCachedShell()?.isRoot
?: Shell.getShell().isRoot
)
} }
if (key == Preferences.Key.Theme) { if (key == Preferences.Key.Theme) {
requireActivity().recreate() requireActivity().recreate()
@ -217,7 +219,7 @@ class SettingsFragment : ScreenFragment() {
val text = MaterialTextView(context) val text = MaterialTextView(context)
text.typeface = TypefaceExtra.medium text.typeface = TypefaceExtra.medium
text.setTextSizeScaled(14) text.setTextSizeScaled(14)
text.setTextColor(text.context.getColorFromAttr(R.attr.colorAccent)) text.setTextColor(text.context.getColorFromAttr(R.attr.colorPrimary))
text.text = title text.text = title
resources.sizeScaled(16).let { text.setPadding(it, it, it, 0) } resources.sizeScaled(16).let { text.setPadding(it, it, it, 0) }
addView( addView(

View File

@ -115,7 +115,7 @@ class TabsFragment : ScreenFragment() {
syncConnection.bind(requireContext()) syncConnection.bind(requireContext())
screenActivity.onToolbarCreated(toolbar) screenActivity.onToolbarCreated(toolbar)
toolbar.setTitle(R.string.application_name) collapsingToolbar.title = getString(R.string.application_name)
// Move focus from SearchView to Toolbar // Move focus from SearchView to Toolbar
toolbar.isFocusableInTouchMode = true toolbar.isFocusableInTouchMode = true
@ -136,7 +136,7 @@ class TabsFragment : ScreenFragment() {
return true return true
} }
}) })
setOnSearchClickListener { appBar.setExpanded(false, true) } setOnSearchClickListener { fragmentBinding.appbarLayout.setExpanded(false, true) }
} }
toolbar.menu.apply { toolbar.menu.apply {
@ -340,16 +340,6 @@ class TabsFragment : ScreenFragment() {
} }
} }
override fun onAttachFragment(childFragment: Fragment) {
super.onAttachFragment(childFragment)
if (view != null && childFragment is AppListFragment) {
childFragment.setSearchQuery(searchQuery)
childFragment.setSection(section)
childFragment.setOrder(Preferences[Preferences.Key.SortOrder].order)
}
}
override fun onBackPressed(): Boolean { override fun onBackPressed(): Boolean {
return when { return when {
searchMenuItem?.isActionViewExpanded == true -> { searchMenuItem?.isActionViewExpanded == true -> {

View File

@ -220,7 +220,7 @@ class DownloadService : ConnectionService<DownloadService.Binder>() {
.setSmallIcon(android.R.drawable.stat_sys_warning) .setSmallIcon(android.R.drawable.stat_sys_warning)
.setColor( .setColor(
ContextThemeWrapper(this, R.style.Theme_Main_Light) ContextThemeWrapper(this, R.style.Theme_Main_Light)
.getColorFromAttr(R.attr.colorAccent).defaultColor .getColorFromAttr(R.attr.colorPrimary).defaultColor
) )
.setContentIntent( .setContentIntent(
PendingIntent.getBroadcast( PendingIntent.getBroadcast(
@ -286,7 +286,7 @@ class DownloadService : ConnectionService<DownloadService.Binder>() {
.setSmallIcon(android.R.drawable.stat_sys_download_done) .setSmallIcon(android.R.drawable.stat_sys_download_done)
.setColor( .setColor(
ContextThemeWrapper(this, R.style.Theme_Main_Light) ContextThemeWrapper(this, R.style.Theme_Main_Light)
.getColorFromAttr(android.R.attr.colorAccent).defaultColor .getColorFromAttr(R.attr.colorPrimary).defaultColor
) )
.setContentIntent(installIntent(task)) .setContentIntent(installIntent(task))
.setContentTitle(getString(R.string.downloaded_FORMAT, task.name)) .setContentTitle(getString(R.string.downloaded_FORMAT, task.name))

View File

@ -1,4 +1,4 @@
package com.looker.droidify.screen package com.looker.droidify.ui.appDetail
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ClipData import android.content.ClipData
@ -21,7 +21,6 @@ import android.view.Gravity
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.widget.LinearLayoutCompat import androidx.appcompat.widget.LinearLayoutCompat
@ -47,6 +46,7 @@ import com.looker.droidify.content.Preferences
import com.looker.droidify.content.ProductPreferences import com.looker.droidify.content.ProductPreferences
import com.looker.droidify.entity.* import com.looker.droidify.entity.*
import com.looker.droidify.network.CoilDownloader import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.screen.ScreenshotsAdapter
import com.looker.droidify.utility.KParcelable import com.looker.droidify.utility.KParcelable
import com.looker.droidify.utility.PackageItemResolver import com.looker.droidify.utility.PackageItemResolver
import com.looker.droidify.utility.Utils import com.looker.droidify.utility.Utils
@ -59,8 +59,8 @@ import java.lang.ref.WeakReference
import java.util.* import java.util.*
import kotlin.math.* import kotlin.math.*
class ProductAdapter(private val callbacks: Callbacks) : class AppDetailAdapter(private val callbacks: Callbacks) :
StableRecyclerAdapter<ProductAdapter.ViewType, RecyclerView.ViewHolder>() { StableRecyclerAdapter<AppDetailAdapter.ViewType, RecyclerView.ViewHolder>() {
interface Callbacks { interface Callbacks {
fun onActionClick(action: Action) fun onActionClick(action: Action)
@ -96,11 +96,11 @@ class ProductAdapter(private val callbacks: Callbacks) :
private enum class SectionType(val titleResId: Int, val colorAttrResId: Int) { private enum class SectionType(val titleResId: Int, val colorAttrResId: Int) {
ANTI_FEATURES(R.string.anti_features, R.attr.colorError), ANTI_FEATURES(R.string.anti_features, R.attr.colorError),
CHANGES(R.string.changes, R.attr.colorAccent), CHANGES(R.string.changes, R.attr.colorPrimary),
LINKS(R.string.links, R.attr.colorAccent), LINKS(R.string.links, R.attr.colorPrimary),
DONATE(R.string.donate, R.attr.colorAccent), DONATE(R.string.donate, R.attr.colorPrimary),
PERMISSIONS(R.string.permissions, R.attr.colorAccent), PERMISSIONS(R.string.permissions, R.attr.colorPrimary),
VERSIONS(R.string.versions, R.attr.colorAccent) VERSIONS(R.string.versions, R.attr.colorPrimary)
} }
internal enum class ExpandType { internal enum class ExpandType {
@ -129,8 +129,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
class AppInfoItem( class AppInfoItem(
val repository: Repository, val repository: Repository,
val product: Product, val product: Product
val packageName: String,
) : Item() { ) : Item() {
override val descriptor: String override val descriptor: String
get() = "app_info.${product.name}" get() = "app_info.${product.name}"
@ -329,9 +328,9 @@ class ProductAdapter(private val callbacks: Callbacks) :
val progressIcon: Drawable val progressIcon: Drawable
val defaultIcon: Drawable val defaultIcon: Drawable
val actionTintNormal = action.context.getColorFromAttr(R.attr.colorSurface) val actionTintNormal = action.context.getColorFromAttr(R.attr.colorPrimary)
val actionTintOnNormal = action.context.getColorFromAttr(R.attr.colorOnPrimary)
val actionTintCancel = action.context.getColorFromAttr(R.attr.colorError) val actionTintCancel = action.context.getColorFromAttr(R.attr.colorError)
val actionTintOnNormal = action.context.getColorFromAttr(R.attr.colorOnSurface)
val actionTintOnCancel = action.context.getColorFromAttr(R.attr.colorOnError) val actionTintOnCancel = action.context.getColorFromAttr(R.attr.colorOnError)
init { init {
@ -362,7 +361,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
} }
private class SwitchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private class SwitchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val enabled = itemView.findViewById<SwitchMaterial>(R.id.enabled)!! val enabled = itemView.findViewById<SwitchMaterial>(R.id.update_state_switch)!!
val statefulViews: Sequence<View> val statefulViews: Sequence<View>
get() = sequenceOf(itemView, enabled) get() = sequenceOf(itemView, enabled)
@ -404,7 +403,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
private class TextViewHolder(context: Context) : private class TextViewHolder(context: Context) :
RecyclerView.ViewHolder(MaterialTextView(context)) { RecyclerView.ViewHolder(MaterialTextView(context)) {
val text: TextView val text: MaterialTextView
get() = itemView as MaterialTextView get() = itemView as MaterialTextView
init { init {
@ -481,7 +480,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
val dateFormat = DateFormat.getDateFormat(itemView.context)!! val dateFormat = DateFormat.getDateFormat(itemView.context)!!
val version = itemView.findViewById<MaterialTextView>(R.id.version)!! val version = itemView.findViewById<MaterialTextView>(R.id.version)!!
val status = itemView.findViewById<MaterialTextView>(R.id.status)!! val status = itemView.findViewById<MaterialTextView>(R.id.installation_status)!!
val source = itemView.findViewById<MaterialTextView>(R.id.source)!! val source = itemView.findViewById<MaterialTextView>(R.id.source)!!
val added = itemView.findViewById<MaterialTextView>(R.id.added)!! val added = itemView.findViewById<MaterialTextView>(R.id.added)!!
val size = itemView.findViewById<MaterialTextView>(R.id.size)!! val size = itemView.findViewById<MaterialTextView>(R.id.size)!!
@ -499,21 +498,6 @@ class ProductAdapter(private val callbacks: Callbacks) :
signature, signature,
compatibility compatibility
) )
init {
status.apply {
background =
ResourcesCompat.getDrawable(
itemView.resources,
R.drawable.background_border,
itemView.context.theme
)
backgroundTintList = itemView.context.getColorFromAttr(R.attr.colorSurface)
typeface = TypefaceExtra.bold
setPadding(15, 5, 15, 5)
setTextColor(itemView.context.getColorFromAttr(R.attr.colorPrimary))
}
}
} }
private class EmptyViewHolder(context: Context) : private class EmptyViewHolder(context: Context) :
@ -568,8 +552,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
if (productRepository != null) { if (productRepository != null) {
items += Item.AppInfoItem( items += Item.AppInfoItem(
productRepository.second, productRepository.second,
productRepository.first, productRepository.first
packageName
) )
items += Item.ScreenshotItem( items += Item.ScreenshotItem(
productRepository.first.screenshots, productRepository.first.screenshots,
@ -709,8 +692,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
) )
} }
author.email.nullIfEmpty()?.let { author.email.nullIfEmpty()?.let {
linkItems += Item.LinkItem linkItems += Item.LinkItem.Typed(LinkType.EMAIL, "", Uri.parse("mailto:$it"))
.Typed(LinkType.EMAIL, "", Uri.parse("mailto:$it"))
} }
linkItems += licenses.asSequence().map { linkItems += licenses.asSequence().map {
Item.LinkItem.Typed( Item.LinkItem.Typed(
@ -887,7 +869,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
val from = items.indexOfFirst { it is Item.ReleaseItem } val from = items.indexOfFirst { it is Item.ReleaseItem }
val to = items.indexOfLast { it is Item.ReleaseItem } val to = items.indexOfLast { it is Item.ReleaseItem }
if (from in 0..to) { if (from in 0..to) {
notifyItemRangeChanged(from, to - from + 1) notifyItemRangeChanged(0, 1)
} }
} else { } else {
notifyItemChanged(index, Payload.STATUS) notifyItemChanged(index, Payload.STATUS)
@ -909,7 +891,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
): RecyclerView.ViewHolder { ): RecyclerView.ViewHolder {
return when (viewType) { return when (viewType) {
ViewType.APP_INFO -> AppInfoViewHolder(parent.inflate(R.layout.item_app_info_x)).apply { ViewType.APP_INFO -> AppInfoViewHolder(parent.inflate(R.layout.item_app_info_x)).apply {
action.setOnClickListener { this@ProductAdapter.action?.let(callbacks::onActionClick) } action.setOnClickListener { this@AppDetailAdapter.action?.let(callbacks::onActionClick) }
} }
ViewType.SCREENSHOT -> ScreenShotViewHolder(parent.inflate(R.layout.screenshot_scrollview)) ViewType.SCREENSHOT -> ScreenShotViewHolder(parent.inflate(R.layout.screenshot_scrollview))
ViewType.SWITCH -> SwitchViewHolder(parent.inflate(R.layout.switch_item)).apply { ViewType.SWITCH -> SwitchViewHolder(parent.inflate(R.layout.switch_item)).apply {
@ -1118,14 +1100,12 @@ class ProductAdapter(private val callbacks: Callbacks) :
if (status.total != null) { if (status.total != null) {
holder.progress.progress = holder.progress.progress =
(holder.progress.max.toFloat() * status.read / status.total).roundToInt() (holder.progress.max.toFloat() * status.read / status.total).roundToInt()
} } else Unit
Unit
} }
}::class }::class
} }
} }
val imageSource = product?.source?.trimAfter('/', 4).plus(".png").toUri()
val sdk = product?.displayRelease?.targetSdkVersion val sdk = product?.displayRelease?.targetSdkVersion
holder.version.doOnPreDraw { holder.version.doOnPreDraw {
@ -1143,13 +1123,9 @@ class ProductAdapter(private val callbacks: Callbacks) :
} }
val devName = product?.source?.trimAfter('/', 4).trimBefore('/', 3) val devName = product?.source?.trimAfter('/', 4).trimBefore('/', 3)
holder.devName.text = if (author.isNullOrEmpty()) devName else author holder.devName.text = if (author.isNullOrEmpty()) devName else author
when {
imageSource.toString() holder.devIcon.load(R.drawable.ic_code)
.contains("kde.org") -> holder.devIcon.setImageResource(R.drawable.ic_kde)
imageSource.toString()
.contains("gitlab") -> holder.devIcon.setImageResource(R.drawable.ic_gitlab)
imageSource.toString().contains("github") -> holder.devIcon.load(imageSource)
}
holder.dev.setOnClickListener { holder.dev.setOnClickListener {
product?.source?.let { link -> product?.source?.let { link ->
if (link.isNotEmpty()) { if (link.isNotEmpty()) {
@ -1334,30 +1310,46 @@ class ProductAdapter(private val callbacks: Callbacks) :
installedItem?.signature == item.release.signature installedItem?.signature == item.release.signature
val suggested = val suggested =
incompatibility == null && item.release.selected && item.selectedRepository incompatibility == null && item.release.selected && item.selectedRepository
val olderOrSignature = installedItem?.let {
it.versionCode > item.release.versionCode || if (suggested) {
it.signature != item.release.signature holder.itemView.apply {
} == true background = ResourcesCompat.getDrawable(
val grayOut = incompatibility != null || olderOrSignature holder.itemView.resources,
val primarySecondaryColor = context.getColorFromAttr( R.drawable.background_border,
if (grayOut) holder.itemView.context.theme
android.R.attr.textColorSecondary else android.R.attr.textColor
) )
backgroundTintList =
holder.itemView.context.getColorFromAttr(R.attr.colorSurface)
}
} else {
holder.itemView.background = null
}
holder.version.text = holder.version.text =
context.getString(R.string.version_FORMAT, item.release.version) context.getString(R.string.version_FORMAT, item.release.version)
holder.version.setTextColor(primarySecondaryColor)
holder.status.visibility = if (installed || suggested) View.VISIBLE else View.GONE holder.status.apply {
holder.status.setText( visibility = if (installed || suggested) View.VISIBLE else View.GONE
setText(
when { when {
installed -> R.string.installed installed -> R.string.installed
suggested -> R.string.suggested suggested -> R.string.suggested
else -> R.string.unknown else -> R.string.unknown
} }
) )
background =
ResourcesCompat.getDrawable(
holder.itemView.resources,
R.drawable.background_border,
context.theme
)
setPadding(15, 15, 15, 15)
backgroundTintList =
context.getColorFromAttr(R.attr.colorSecondaryContainer)
setTextColor(context.getColorFromAttr(R.attr.colorOnSecondaryContainer))
}
holder.source.text = holder.source.text =
context.getString(R.string.provided_by_FORMAT, item.repository.name) context.getString(R.string.provided_by_FORMAT, item.repository.name)
holder.added.text = holder.dateFormat.format(item.release.added) holder.added.text = holder.dateFormat.format(item.release.added)
holder.added.setTextColor(primarySecondaryColor)
holder.size.text = item.release.size.formatSize() holder.size.text = item.release.size.formatSize()
holder.signature.visibility = holder.signature.visibility =
if (item.showSignature && item.release.signature.isNotEmpty()) if (item.showSignature && item.release.signature.isNotEmpty())
@ -1466,7 +1458,7 @@ class ProductAdapter(private val callbacks: Callbacks) :
Snackbar.make(view, R.string.link_copied_to_clipboard, Snackbar.LENGTH_SHORT).show() Snackbar.make(view, R.string.link_copied_to_clipboard, Snackbar.LENGTH_SHORT).show()
} }
private class LinkSpan(private val url: String, productAdapter: ProductAdapter) : private class LinkSpan(private val url: String, productAdapter: AppDetailAdapter) :
ClickableSpan() { ClickableSpan() {
private val productAdapterReference = WeakReference(productAdapter) private val productAdapterReference = WeakReference(productAdapter)

View File

@ -1,4 +1,4 @@
package com.looker.droidify.screen package com.looker.droidify.ui.appDetail
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.ComponentName import android.content.ComponentName
@ -20,6 +20,9 @@ import com.looker.droidify.content.ProductPreferences
import com.looker.droidify.database.Database import com.looker.droidify.database.Database
import com.looker.droidify.entity.* import com.looker.droidify.entity.*
import com.looker.droidify.installer.AppInstaller import com.looker.droidify.installer.AppInstaller
import com.looker.droidify.screen.MessageDialog
import com.looker.droidify.screen.ScreenFragment
import com.looker.droidify.screen.ScreenshotsFragment
import com.looker.droidify.service.Connection import com.looker.droidify.service.Connection
import com.looker.droidify.service.DownloadService import com.looker.droidify.service.DownloadService
import com.looker.droidify.utility.RxUtils import com.looker.droidify.utility.RxUtils
@ -35,7 +38,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks { class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
companion object { companion object {
private const val EXTRA_PACKAGE_NAME = "packageName" private const val EXTRA_PACKAGE_NAME = "packageName"
private const val STATE_LAYOUT_MANAGER = "layoutManager" private const val STATE_LAYOUT_MANAGER = "layoutManager"
@ -52,14 +55,14 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
private enum class Action( private enum class Action(
val id: Int, val id: Int,
val adapterAction: ProductAdapter.Action, val adapterAction: AppDetailAdapter.Action,
) { ) {
INSTALL(1, ProductAdapter.Action.INSTALL), INSTALL(1, AppDetailAdapter.Action.INSTALL),
UPDATE(2, ProductAdapter.Action.UPDATE), UPDATE(2, AppDetailAdapter.Action.UPDATE),
LAUNCH(3, ProductAdapter.Action.LAUNCH), LAUNCH(3, AppDetailAdapter.Action.LAUNCH),
DETAILS(4, ProductAdapter.Action.DETAILS), DETAILS(4, AppDetailAdapter.Action.DETAILS),
UNINSTALL(5, ProductAdapter.Action.UNINSTALL), UNINSTALL(5, AppDetailAdapter.Action.UNINSTALL),
SHARE(6, ProductAdapter.Action.SHARE) SHARE(6, AppDetailAdapter.Action.SHARE)
} }
private class Installed( private class Installed(
@ -114,10 +117,10 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
this.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) this.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
isMotionEventSplittingEnabled = false isMotionEventSplittingEnabled = false
isVerticalScrollBarEnabled = false isVerticalScrollBarEnabled = false
val adapter = ProductAdapter(this@ProductFragment) val adapter = AppDetailAdapter(this@AppDetailFragment)
this.adapter = adapter this.adapter = adapter
addOnScrollListener(scrollListener) addOnScrollListener(scrollListener)
savedInstanceState?.getParcelable<ProductAdapter.SavedState>(STATE_ADAPTER) savedInstanceState?.getParcelable<AppDetailAdapter.SavedState>(STATE_ADAPTER)
?.let(adapter::restoreState) ?.let(adapter::restoreState)
layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER) layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER)
recyclerView = this recyclerView = this
@ -213,7 +216,7 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
} }
} }
val recyclerView = recyclerView!! val recyclerView = recyclerView!!
val adapter = recyclerView.adapter as ProductAdapter val adapter = recyclerView.adapter as AppDetailAdapter
if (firstChanged || productChanged || installedItemChanged) { if (firstChanged || productChanged || installedItemChanged) {
adapter.setProducts( adapter.setProducts(
recyclerView.context, recyclerView.context,
@ -246,7 +249,7 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
val layoutManagerState = val layoutManagerState =
layoutManagerState ?: recyclerView?.layoutManager?.onSaveInstanceState() layoutManagerState ?: recyclerView?.layoutManager?.onSaveInstanceState()
layoutManagerState?.let { outState.putParcelable(STATE_LAYOUT_MANAGER, it) } layoutManagerState?.let { outState.putParcelable(STATE_LAYOUT_MANAGER, it) }
val adapterState = (recyclerView?.adapter as? ProductAdapter)?.saveState() val adapterState = (recyclerView?.adapter as? AppDetailAdapter)?.saveState()
adapterState?.let { outState.putParcelable(STATE_ADAPTER, it) } adapterState?.let { outState.putParcelable(STATE_ADAPTER, it) }
} }
@ -297,8 +300,8 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
} }
val adapterAction = val adapterAction =
if (downloading) ProductAdapter.Action.CANCEL else primaryAction?.adapterAction if (downloading) AppDetailAdapter.Action.CANCEL else primaryAction?.adapterAction
(recyclerView?.adapter as? ProductAdapter)?.setAction(adapterAction) (recyclerView?.adapter as? AppDetailAdapter)?.setAction(adapterAction)
for (action in sequenceOf( for (action in sequenceOf(
Action.INSTALL, Action.INSTALL,
@ -344,9 +347,9 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
private suspend fun updateDownloadState(state: DownloadService.State?) { private suspend fun updateDownloadState(state: DownloadService.State?) {
val status = when (state) { val status = when (state) {
is DownloadService.State.Pending -> ProductAdapter.Status.Pending is DownloadService.State.Pending -> AppDetailAdapter.Status.Pending
is DownloadService.State.Connecting -> ProductAdapter.Status.Connecting is DownloadService.State.Connecting -> AppDetailAdapter.Status.Connecting
is DownloadService.State.Downloading -> ProductAdapter.Status.Downloading( is DownloadService.State.Downloading -> AppDetailAdapter.Status.Downloading(
state.read, state.read,
state.total state.total
) )
@ -357,7 +360,7 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
this.downloading = downloading this.downloading = downloading
updateButtons() updateButtons()
} }
(recyclerView?.adapter as? ProductAdapter)?.setStatus(status) (recyclerView?.adapter as? AppDetailAdapter)?.setStatus(status)
if (state is DownloadService.State.Success && isResumed) { if (state is DownloadService.State.Success && isResumed) {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
state.consume() state.consume()
@ -383,10 +386,10 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
} }
} }
override fun onActionClick(action: ProductAdapter.Action) { override fun onActionClick(action: AppDetailAdapter.Action) {
when (action) { when (action) {
ProductAdapter.Action.INSTALL, AppDetailAdapter.Action.INSTALL,
ProductAdapter.Action.UPDATE, AppDetailAdapter.Action.UPDATE,
-> { -> {
val installedItem = installed?.installedItem val installedItem = installed?.installedItem
lifecycleScope.launch { lifecycleScope.launch {
@ -399,7 +402,7 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
} }
Unit Unit
} }
ProductAdapter.Action.LAUNCH -> { AppDetailAdapter.Action.LAUNCH -> {
val launcherActivities = installed?.launcherActivities.orEmpty() val launcherActivities = installed?.launcherActivities.orEmpty()
if (launcherActivities.size >= 2) { if (launcherActivities.size >= 2) {
LaunchDialog(launcherActivities).show( LaunchDialog(launcherActivities).show(
@ -411,25 +414,25 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
} }
Unit Unit
} }
ProductAdapter.Action.DETAILS -> { AppDetailAdapter.Action.DETAILS -> {
startActivity( startActivity(
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.parse("package:$packageName")) .setData(Uri.parse("package:$packageName"))
) )
} }
ProductAdapter.Action.UNINSTALL -> { AppDetailAdapter.Action.UNINSTALL -> {
lifecycleScope.launch { lifecycleScope.launch {
AppInstaller.getInstance(context)?.defaultInstaller?.uninstall(packageName) AppInstaller.getInstance(context)?.defaultInstaller?.uninstall(packageName)
} }
Unit Unit
} }
ProductAdapter.Action.CANCEL -> { AppDetailAdapter.Action.CANCEL -> {
val binder = downloadConnection.binder val binder = downloadConnection.binder
if (downloading && binder != null) { if (downloading && binder != null) {
binder.cancel(packageName) binder.cancel(packageName)
} else Unit } else Unit
} }
ProductAdapter.Action.SHARE -> { AppDetailAdapter.Action.SHARE -> {
val sendIntent: Intent = Intent().apply { val sendIntent: Intent = Intent().apply {
this.action = Intent.ACTION_SEND this.action = Intent.ACTION_SEND
putExtra( putExtra(
@ -552,7 +555,7 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
return MaterialAlertDialogBuilder(requireContext()) return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.launch) .setTitle(R.string.launch)
.setItems(labels.toTypedArray()) { _, position -> .setItems(labels.toTypedArray()) { _, position ->
(parentFragment as ProductFragment) (parentFragment as AppDetailFragment)
.startLauncherActivity(names[position]) .startLauncherActivity(names[position])
} }
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@ -2,11 +2,11 @@ package com.looker.droidify.ui.appsList
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import androidx.core.content.res.ResourcesCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import coil.load import coil.load
import coil.transform.RoundedCornersTransformation import coil.transform.RoundedCornersTransformation
@ -163,16 +163,16 @@ class AppListAdapter(private val onClick: (ProductItem) -> Unit) :
if (productItem.canUpdate) { if (productItem.canUpdate) {
text = productItem.version text = productItem.version
if (background == null) { if (background == null) {
resources.sizeScaled(4).let { setPadding(it, 0, it, 0) } background =
setTextColor(holder.status.context.getColorFromAttr(android.R.attr.colorBackground)) ResourcesCompat.getDrawable(
background = GradientDrawable( holder.itemView.resources,
GradientDrawable.Orientation.TOP_BOTTOM, R.drawable.background_border,
null context.theme
).apply { )
color = setPadding(8, 15, 1, 15)
holder.status.context.getColorFromAttr(R.attr.colorAccent) backgroundTintList =
cornerRadius = holder.status.resources.sizeScaled(2).toFloat() context.getColorFromAttr(R.attr.colorSecondaryContainer)
} setTextColor(context.getColorFromAttr(R.attr.colorSecondary))
} }
} else { } else {
text = productItem.installedVersion.nullIfEmpty() ?: productItem.version text = productItem.installedVersion.nullIfEmpty() ?: productItem.version

View File

@ -2,5 +2,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/material_emphasis_disabled_background" android:color="?attr/colorOnSurface" android:state_enabled="false" /> <item android:alpha="@dimen/material_emphasis_disabled_background" android:color="?attr/colorOnSurface" android:state_enabled="false" />
<item android:color="?attr/colorPrimaryContainer" android:state_checked="true" /> <item android:color="?attr/colorPrimaryContainer" android:state_checked="true" />
<item android:color="?attr/colorOnSurfaceInverse" /> <item android:color="?attr/colorSurfaceVariant" />
</selector> </selector>

View File

@ -237,7 +237,5 @@
app:iconGravity="textStart" app:iconGravity="textStart"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_layout" app:layout_constraintTop_toBottomOf="@id/status_layout"/>
app:shapeAppearanceOverlay="@style/PillShapeAppearance" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2,7 +2,6 @@
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
style="?attr/materialCardViewFilledStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="72dp"> android:layout_height="72dp">
@ -45,10 +44,9 @@
android:id="@+id/status" android:id="@+id/status"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:maxWidth="70dp" android:maxWidth="80dp"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?textAppearanceCaption" android:textAppearance="?textAppearanceLabelMedium" />
android:textColor="?android:attr/textColorSecondary" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:baselineAligned="false" android:baselineAligned="false"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="vertical" android:orientation="vertical"
@ -15,48 +17,32 @@
android:gravity="bottom" android:gravity="bottom"
android:orientation="horizontal"> android:orientation="horizontal">
<com.google.android.material.circularreveal.CircularRevealFrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal">
tools:ignore="UselessParent">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/version" android:id="@+id/version"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true" android:singleLine="true"
android:textSize="16sp" android:textAllCaps="true"
tools:ignore="InefficientWeight" /> android:textAppearance="?textAppearanceLabelLarge" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/status" android:id="@+id/installation_status"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="1dp"
android:fontFamily="sans-serif-medium"
android:paddingStart="4dp"
android:paddingTop="1dp"
android:paddingEnd="4dp"
android:paddingBottom="1dp"
android:singleLine="true" android:singleLine="true"
android:textAllCaps="true" android:textAllCaps="true"
android:textColor="?android:attr/colorBackground" android:textAppearance="?textAppearanceLabelMedium" />
android:textSize="10sp"
tools:ignore="SmallSp" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
</com.google.android.material.circularreveal.CircularRevealFrameLayout>
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/added" android:id="@+id/added"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -109,3 +95,5 @@
android:textSize="14sp" /> android:textSize="14sp" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
</com.google.android.material.card.MaterialCardView>

View File

@ -1,10 +1,36 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.switchmaterial.SwitchMaterial xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/repository_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="54dp" android:layout_height="wrap_content"
android:id="@+id/repository_switch" android:layout_marginVertical="8dp"
android:background="?android:attr/selectableItemBackground" android:layout_marginHorizontal="@dimen/text_margin">
android:paddingStart="12dp"
android:paddingEnd="12dp" <androidx.appcompat.widget.LinearLayoutCompat
android:gravity="center_vertical" android:layout_width="match_parent"
android:orientation="horizontal"/> android:layout_height="match_parent"
android:layout_margin="@dimen/text_margin"
android:orientation="vertical"
android:paddingEnd="48dp">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/repository_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceTitleMedium" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/repository_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/repository_state"
android:layout_width="24dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginEnd="24dp"/>
</com.google.android.material.card.MaterialCardView>

View File

@ -20,7 +20,7 @@
android:layout_weight="1" android:layout_weight="1"
android:singleLine="true" android:singleLine="true"
android:text="@string/screenshots" android:text="@string/screenshots"
android:textColor="?attr/colorAccent" /> android:textColor="?attr/colorPrimary" />
<com.google.android.material.imageview.ShapeableImageView <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/screenshots_section_icon" android:id="@+id/screenshots_section_icon"
@ -28,7 +28,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_arrow_down" android:src="@drawable/ic_arrow_down"
android:tint="?attr/colorAccent" android:tint="?attr/colorPrimary"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.circularreveal.CircularRevealFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.switchmaterial.SwitchMaterial xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/update_state_switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/enabled"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="@dimen/text_margin"
android:clickable="false" android:clickable="false"
android:layout_marginHorizontal="@dimen/text_margin"
android:singleLine="true" android:singleLine="true"
android:textSize="15sp" /> android:textSize="15sp" />
</com.google.android.material.circularreveal.CircularRevealFrameLayout>

View File

@ -7,9 +7,9 @@
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tabs" android:id="@+id/tabs"
android:backgroundTint="?attr/colorSurface"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp" />
android:background="@drawable/bg_item_rounded_ripple" />
<com.google.android.material.circularreveal.CircularRevealFrameLayout <com.google.android.material.circularreveal.CircularRevealFrameLayout
android:id="@+id/section_layout" android:id="@+id/section_layout"
@ -20,7 +20,6 @@
android:id="@+id/section_change" android:id="@+id/section_change"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:background="@drawable/bg_item_rounded_ripple"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingStart="12dp" android:paddingStart="12dp"

View File

@ -17,4 +17,53 @@
<color name="darker_white">#DDDDDD</color> <color name="darker_white">#DDDDDD</color>
<color name="grey_light">#505050</color> <color name="grey_light">#505050</color>
<color name="grey_dark">#2C2C2C</color> <color name="grey_dark">#2C2C2C</color>
<color name="md_theme_light_primary">#006D3E</color>
<color name="md_theme_light_onPrimary">#FFFFFF</color>
<color name="md_theme_light_primaryContainer">#71FCAD</color>
<color name="md_theme_light_onPrimaryContainer">#00210F</color>
<color name="md_theme_light_secondary">#924C00</color>
<color name="md_theme_light_onSecondary">#FFFFFF</color>
<color name="md_theme_light_secondaryContainer">#FFDCC1</color>
<color name="md_theme_light_onSecondaryContainer">#2F1400</color>
<color name="md_theme_light_error">#BA1B1B</color>
<color name="md_theme_light_errorContainer">#FFDAD4</color>
<color name="md_theme_light_onError">#FFFFFF</color>
<color name="md_theme_light_onErrorContainer">#410001</color>
<color name="md_theme_light_background">#FBFDF8</color>
<color name="md_theme_light_onBackground">#191C1A</color>
<color name="md_theme_light_surface">#E8F5E9</color>
<color name="md_theme_light_onSurface">#191C1A</color>
<color name="md_theme_light_surfaceVariant">#DDE5DC</color>
<color name="md_theme_light_onSurfaceVariant">#414942</color>
<color name="md_theme_light_outline">#707971</color>
<color name="md_theme_light_inverseOnSurface">#EFF1EC</color>
<color name="md_theme_light_inverseSurface">#2E312E</color>
<color name="md_theme_light_primaryInverse">#51DF93</color>
<color name="md_theme_dark_primary">#51DF93</color>
<color name="md_theme_dark_onPrimary">#00391D</color>
<color name="md_theme_dark_primaryContainer">#00522D</color>
<color name="md_theme_dark_onPrimaryContainer">#71FCAD</color>
<color name="md_theme_dark_secondary">#FFB77B</color>
<color name="md_theme_dark_onSecondary">#4E2600</color>
<color name="md_theme_dark_secondaryContainer">#6F3800</color>
<color name="md_theme_dark_onSecondaryContainer">#FFDCC1</color>
<color name="md_theme_dark_error">#FFB4A9</color>
<color name="md_theme_dark_errorContainer">#930006</color>
<color name="md_theme_dark_onError">#680003</color>
<color name="md_theme_dark_onErrorContainer">#FFDAD4</color>
<color name="md_theme_dark_background">#191C1A</color>
<color name="md_theme_dark_onBackground">#E1E3DE</color>
<color name="md_theme_dark_surface">#191C1A</color>
<color name="md_theme_dark_onSurface">#E1E3DE</color>
<color name="md_theme_dark_surfaceVariant">#414942</color>
<color name="md_theme_dark_onSurfaceVariant">#C0C9C0</color>
<color name="md_theme_dark_outline">#8A938A</color>
<color name="md_theme_dark_inverseOnSurface">#191C1A</color>
<color name="md_theme_dark_inverseSurface">#E1E3DE</color>
<color name="md_theme_dark_primaryInverse">#006D3E</color>
<color name="seed">#51DF93</color>
<color name="error">#BA1B1B</color>
</resources> </resources>

View File

@ -6,21 +6,28 @@
</style> </style>
<style name="Theme.Main.Light" parent="Theme.Material3.Light.NoActionBar"> <style name="Theme.Main.Light" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/green300</item> <item name="colorPrimary">@color/md_theme_light_primary</item>
<item name="colorPrimaryContainer">@color/green100</item> <item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
<item name="colorOnPrimary">@color/black</item> <item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
<item name="colorSurface">@color/green50</item> <item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
<item name="colorOnSurface">@color/black</item> <item name="colorSecondary">@color/md_theme_light_secondary</item>
<item name="android:colorBackground">@color/white</item> <item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
<item name="colorOnBackground">@color/grey_dark</item> <item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
<item name="colorAccent">@color/accent_light</item> <item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
<item name="colorError">@color/error_light</item> <item name="colorError">@color/md_theme_light_error</item>
<item name="colorOutline">@color/green75</item> <item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
<item name="colorControlActivated">@color/green300</item> <item name="colorOnError">@color/md_theme_light_onError</item>
<item name="android:textColor">@color/black</item> <item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
<item name="android:textColorPrimary">@color/green900</item> <item name="android:colorBackground">@color/md_theme_light_background</item>
<item name="android:textColorSecondary">@color/grey_light</item> <item name="colorOnBackground">@color/md_theme_light_onBackground</item>
<item name="android:overScrollMode">never</item> <item name="colorSurface">@color/md_theme_light_surface</item>
<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_light_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_light_primaryInverse</item>
<item name="android:statusBarColor">@color/green50</item> <item name="android:statusBarColor">@color/green50</item>
<item name="android:navigationBarColor">@android:color/transparent</item> <item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item> <item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
@ -34,26 +41,33 @@
<item name="textInputStyle">@style/Theme.EditText</item> <item name="textInputStyle">@style/Theme.EditText</item>
<item name="materialAlertDialogTheme">@style/Theme.Alert</item> <item name="materialAlertDialogTheme">@style/Theme.Alert</item>
<item name="appBarLayoutStyle">@style/Theme.AppBarLayout</item> <item name="appBarLayoutStyle">@style/Theme.AppBarLayout</item>
<item name="materialCardViewFilledStyle">@style/Theme.Card</item> <item name="materialCardViewStyle">@style/Theme.Card</item>
<item name="collapsingToolbarLayoutLargeStyle">@style/Theme.CollapsingToolbar</item> <item name="collapsingToolbarLayoutLargeStyle">@style/Theme.CollapsingToolbar</item>
</style> </style>
<style name="Theme.Main.Dark" parent="Theme.Material3.Dark.NoActionBar"> <style name="Theme.Main.Dark" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/green200</item> <item name="colorPrimary">@color/md_theme_dark_primary</item>
<item name="colorPrimaryContainer">@color/green900</item> <item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
<item name="colorOnPrimary">@color/black</item> <item name="colorPrimaryContainer">@color/md_theme_dark_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_theme_dark_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_theme_dark_secondary</item>
<item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_dark_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_dark_onSecondaryContainer</item>
<item name="colorError">@color/md_theme_dark_error</item>
<item name="colorErrorContainer">@color/md_theme_dark_errorContainer</item>
<item name="colorOnError">@color/md_theme_dark_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_dark_onErrorContainer</item>
<item name="android:colorBackground">@color/md_theme_dark_background</item>
<item name="colorOnBackground">@color/md_theme_dark_onBackground</item>
<item name="colorSurface">@color/grey_dark</item> <item name="colorSurface">@color/grey_dark</item>
<item name="colorOnSurface">@color/green50</item> <item name="colorOnSurface">@color/md_theme_dark_onSurface</item>
<item name="android:colorBackground">@color/black</item> <item name="colorSurfaceVariant">@color/md_theme_dark_surfaceVariant</item>
<item name="colorOnBackground">@color/green200</item> <item name="colorOnSurfaceVariant">@color/md_theme_dark_onSurfaceVariant</item>
<item name="colorAccent">@color/accent_dark</item> <item name="colorOutline">@color/md_theme_dark_outline</item>
<item name="colorError">@color/error_dark</item> <item name="colorOnSurfaceInverse">@color/md_theme_dark_inverseOnSurface</item>
<item name="colorOutline">@color/green50</item> <item name="colorSurfaceInverse">@color/md_theme_dark_inverseSurface</item>
<item name="colorControlActivated">@color/green200</item> <item name="colorPrimaryInverse">@color/md_theme_dark_primaryInverse</item>
<item name="android:textColor">@color/white</item>
<item name="android:textColorPrimary">@color/green200</item>
<item name="android:textColorSecondary">@color/darker_white</item>
<item name="android:overScrollMode">never</item>
<item name="android:statusBarColor">@color/grey_dark</item> <item name="android:statusBarColor">@color/grey_dark</item>
<item name="android:navigationBarColor">@android:color/transparent</item> <item name="android:navigationBarColor">@android:color/transparent</item>
@ -66,26 +80,33 @@
<item name="textInputStyle">@style/Theme.EditText</item> <item name="textInputStyle">@style/Theme.EditText</item>
<item name="materialAlertDialogTheme">@style/Theme.Alert</item> <item name="materialAlertDialogTheme">@style/Theme.Alert</item>
<item name="appBarLayoutStyle">@style/Theme.AppBarLayout</item> <item name="appBarLayoutStyle">@style/Theme.AppBarLayout</item>
<item name="materialCardViewFilledStyle">@style/Theme.Card</item> <item name="materialCardViewStyle">@style/Theme.Card</item>
<item name="collapsingToolbarLayoutLargeStyle">@style/Theme.CollapsingToolbar</item> <item name="collapsingToolbarLayoutLargeStyle">@style/Theme.CollapsingToolbar</item>
</style> </style>
<style name="Theme.Main.Amoled" parent="Theme.Material3.Dark.NoActionBar"> <style name="Theme.Main.Amoled" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/green100</item> <item name="colorPrimary">@color/md_theme_dark_primary</item>
<item name="colorPrimaryContainer">@color/green900</item> <item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
<item name="colorOnPrimary">@color/black</item> <item name="colorPrimaryContainer">@color/md_theme_dark_primaryContainer</item>
<item name="colorSurface">@color/black</item> <item name="colorOnPrimaryContainer">@color/md_theme_dark_onPrimaryContainer</item>
<item name="colorOnSurface">@color/green50</item> <item name="colorSecondary">@color/md_theme_dark_secondary</item>
<item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_dark_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_dark_onSecondaryContainer</item>
<item name="colorError">@color/md_theme_dark_error</item>
<item name="colorErrorContainer">@color/md_theme_dark_errorContainer</item>
<item name="colorOnError">@color/md_theme_dark_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_dark_onErrorContainer</item>
<item name="colorSurface">@color/md_theme_dark_surface</item>
<item name="colorOnSurface">@color/md_theme_dark_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_dark_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_dark_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_dark_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_dark_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_dark_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_dark_primaryInverse</item>
<item name="android:colorBackground">@color/pitch_black</item> <item name="android:colorBackground">@color/pitch_black</item>
<item name="colorOnBackground">@color/green50</item> <item name="colorOnBackground">@color/green50</item>
<item name="colorAccent">@color/accent_dark</item>
<item name="colorError">@color/error_dark</item>
<item name="colorOutline">@color/green50</item>
<item name="colorControlActivated">@color/green100</item>
<item name="android:textColor">@color/white</item>
<item name="android:textColorPrimary">@color/green100</item>
<item name="android:textColorSecondary">@color/darker_white</item>
<item name="android:overScrollMode">never</item>
<item name="android:statusBarColor">@color/black</item> <item name="android:statusBarColor">@color/black</item>
<item name="android:navigationBarColor">@android:color/transparent</item> <item name="android:navigationBarColor">@android:color/transparent</item>
@ -98,7 +119,7 @@
<item name="textInputStyle">@style/Theme.EditText</item> <item name="textInputStyle">@style/Theme.EditText</item>
<item name="materialAlertDialogTheme">@style/Theme.Alert</item> <item name="materialAlertDialogTheme">@style/Theme.Alert</item>
<item name="appBarLayoutStyle">@style/Theme.AppBarLayout</item> <item name="appBarLayoutStyle">@style/Theme.AppBarLayout</item>
<item name="materialCardViewFilledStyle">@style/Theme.Card</item> <item name="materialCardViewStyle">@style/Theme.Card</item>
<item name="collapsingToolbarLayoutLargeStyle">@style/Theme.CollapsingToolbar</item> <item name="collapsingToolbarLayoutLargeStyle">@style/Theme.CollapsingToolbar</item>
</style> </style>
@ -118,12 +139,9 @@
<style name="Theme.Toolbar" parent="Widget.Material3.Toolbar.Surface"> <style name="Theme.Toolbar" parent="Widget.Material3.Toolbar.Surface">
<item name="layout_collapseMode">pin</item> <item name="layout_collapseMode">pin</item>
<item name="android:backgroundTint">?attr/colorSurface</item> <item name="android:backgroundTint">?attr/colorSurface</item>
<item name="android:background">@drawable/bottom_corner</item>
</style> </style>
<style name="Theme.Tab" parent="Widget.Material3.TabLayout"> <style name="Theme.Tab" parent="Widget.Material3.TabLayout">
<item name="tabTextColor">@color/tab_text_color</item>
<item name="tabIndicatorColor">?android:attr/textColorPrimary</item>
<item name="tabTextAppearance">?attr/textAppearanceBody1</item> <item name="tabTextAppearance">?attr/textAppearanceBody1</item>
</style> </style>