Material3 polishing (#4673)

see commit messages for a list of changes

closes #4692
This commit is contained in:
Konrad Pozniak 2024-10-11 08:51:34 +02:00 committed by GitHub
parent 2dd6d9db5c
commit 20bd90faae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 209 additions and 188 deletions

View File

@ -16,6 +16,7 @@
package com.keylesspalace.tusky package com.keylesspalace.tusky
import android.app.Dialog
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -29,6 +30,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.keylesspalace.tusky.databinding.FragmentAccountsInListBinding import com.keylesspalace.tusky.databinding.FragmentAccountsInListBinding
import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding
import com.keylesspalace.tusky.entity.TimelineAccount import com.keylesspalace.tusky.entity.TimelineAccount
@ -39,7 +41,6 @@ import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.loadAvatar import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel
import com.keylesspalace.tusky.viewmodel.State import com.keylesspalace.tusky.viewmodel.State
@ -50,13 +51,13 @@ import kotlinx.coroutines.launch
private typealias AccountInfo = Pair<TimelineAccount, Boolean> private typealias AccountInfo = Pair<TimelineAccount, Boolean>
@AndroidEntryPoint @AndroidEntryPoint
class AccountsInListFragment : DialogFragment(R.layout.fragment_accounts_in_list) { class AccountsInListFragment : DialogFragment() {
@Inject @Inject
lateinit var preferences: SharedPreferences lateinit var preferences: SharedPreferences
private val viewModel: AccountsInListViewModel by viewModels() private val viewModel: AccountsInListViewModel by viewModels()
private val binding by viewBinding(FragmentAccountsInListBinding::bind) private lateinit var binding: FragmentAccountsInListBinding
private lateinit var listId: String private lateinit var listId: String
private lateinit var listName: String private lateinit var listName: String
@ -65,7 +66,6 @@ class AccountsInListFragment : DialogFragment(R.layout.fragment_accounts_in_list
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.TuskyDialogFragmentStyle)
val args = requireArguments() val args = requireArguments()
listId = args.getString(LIST_ID_ARG)!! listId = args.getString(LIST_ID_ARG)!!
listName = args.getString(LIST_NAME_ARG)!! listName = args.getString(LIST_NAME_ARG)!!
@ -73,6 +73,12 @@ class AccountsInListFragment : DialogFragment(R.layout.fragment_accounts_in_list
viewModel.load(listId) viewModel.load(listId)
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return MaterialAlertDialogBuilder(requireContext())
.setView(createView())
.create()
}
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
dialog?.apply { dialog?.apply {
@ -84,17 +90,18 @@ class AccountsInListFragment : DialogFragment(R.layout.fragment_accounts_in_list
} }
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { private fun createView(): View {
binding = FragmentAccountsInListBinding.inflate(layoutInflater)
val adapter = Adapter() val adapter = Adapter()
val searchAdapter = SearchAdapter() val searchAdapter = SearchAdapter()
binding.accountsRecycler.layoutManager = LinearLayoutManager(view.context) binding.accountsRecycler.layoutManager = LinearLayoutManager(binding.root.context)
binding.accountsRecycler.adapter = adapter binding.accountsRecycler.adapter = adapter
binding.accountsSearchRecycler.layoutManager = LinearLayoutManager(view.context) binding.accountsSearchRecycler.layoutManager = LinearLayoutManager(binding.root.context)
binding.accountsSearchRecycler.adapter = searchAdapter binding.accountsSearchRecycler.adapter = searchAdapter
viewLifecycleOwner.lifecycleScope.launch { lifecycleScope.launch {
viewModel.state.collect { state -> viewModel.state.collect { state ->
adapter.submitList(state.accounts.getOrDefault(emptyList())) adapter.submitList(state.accounts.getOrDefault(emptyList()))
@ -122,6 +129,7 @@ class AccountsInListFragment : DialogFragment(R.layout.fragment_accounts_in_list
return true return true
} }
}) })
return binding.root
} }
private fun setupSearchView(searchAdapter: SearchAdapter, state: State) { private fun setupSearchView(searchAdapter: SearchAdapter, state: State) {

View File

@ -19,11 +19,8 @@ import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.widget.FrameLayout
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.view.updatePadding
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
@ -31,7 +28,6 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager import androidx.transition.TransitionManager
import at.connyduck.sparkbutton.helpers.Utils
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.transition.MaterialArcMotion import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform import com.google.android.material.transition.MaterialContainerTransform
@ -41,6 +37,7 @@ import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent import com.keylesspalace.tusky.appstore.MainTabsChangedEvent
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding
import com.keylesspalace.tusky.databinding.DialogAddHashtagBinding
import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
@ -231,18 +228,12 @@ class TabPreferenceActivity : BaseActivity(), ItemInteractionListener, ListSelec
} }
private fun showAddHashtagDialog(tab: TabData? = null, tabPosition: Int = 0) { private fun showAddHashtagDialog(tab: TabData? = null, tabPosition: Int = 0) {
val frameLayout = FrameLayout(this) val dialogBinding = DialogAddHashtagBinding.inflate(layoutInflater)
val padding = Utils.dpToPx(this, 8) val editText = dialogBinding.addHashtagEditText
frameLayout.updatePadding(left = padding, right = padding)
val editText = AppCompatEditText(this)
editText.setHint(R.string.edit_hashtag_hint)
editText.setText("")
frameLayout.addView(editText)
val dialog = MaterialAlertDialogBuilder(this) val dialog = MaterialAlertDialogBuilder(this)
.setTitle(R.string.add_hashtag_title) .setTitle(R.string.add_hashtag_title)
.setView(frameLayout) .setView(dialogBinding.root)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.action_save) { _, _ -> .setPositiveButton(R.string.action_save) { _, _ ->
val input = editText.text.toString().trim() val input = editText.text.toString().trim()

View File

@ -66,7 +66,6 @@ class ListSelectionFragment : DialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.TuskyDialogFragmentStyle)
accountId = requireArguments().getString(ARG_ACCOUNT_ID) accountId = requireArguments().getString(ARG_ACCOUNT_ID)
} }

View File

@ -15,15 +15,14 @@
package com.keylesspalace.tusky.components.compose.dialog package com.keylesspalace.tusky.components.compose.dialog
import android.app.Dialog
import android.content.Context import android.content.Context
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.text.InputFilter import android.text.InputFilter
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
@ -32,11 +31,11 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition import com.bumptech.glide.request.transition.Transition
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.DialogImageDescriptionBinding import com.keylesspalace.tusky.databinding.DialogImageDescriptionBinding
import com.keylesspalace.tusky.util.getParcelableCompat import com.keylesspalace.tusky.util.getParcelableCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding
// https://github.com/tootsuite/mastodon/blob/c6904c0d3766a2ea8a81ab025c127169ecb51373/app/models/media_attachment.rb#L32 // https://github.com/tootsuite/mastodon/blob/c6904c0d3766a2ea8a81ab025c127169ecb51373/app/models/media_attachment.rb#L32
private const val MEDIA_DESCRIPTION_CHARACTER_LIMIT = 1500 private const val MEDIA_DESCRIPTION_CHARACTER_LIMIT = 1500
@ -44,22 +43,23 @@ private const val MEDIA_DESCRIPTION_CHARACTER_LIMIT = 1500
class CaptionDialog : DialogFragment() { class CaptionDialog : DialogFragment() {
private lateinit var listener: Listener private lateinit var listener: Listener
private val binding by viewBinding(DialogImageDescriptionBinding::bind) private lateinit var binding: DialogImageDescriptionBinding
private var animatable: Animatable? = null private var animatable: Animatable? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
super.onCreate(savedInstanceState) val localId = arguments?.getInt(LOCAL_ID_ARG) ?: error("Missing localId")
setStyle(STYLE_NORMAL, R.style.TuskyDialogFragmentStyle) return MaterialAlertDialogBuilder(requireContext())
.setView(createView(savedInstanceState))
.setPositiveButton(android.R.string.ok) { _, _ ->
listener.onUpdateDescription(localId, binding.imageDescriptionText.text.toString())
}
.setNegativeButton(android.R.string.cancel, null)
.create()
} }
override fun onCreateView( private fun createView(savedInstanceState: Bundle?): View {
inflater: LayoutInflater, binding = DialogImageDescriptionBinding.inflate(layoutInflater)
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.dialog_image_description, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val imageView = binding.imageDescriptionView val imageView = binding.imageDescriptionView
imageView.maxZoom = 6f imageView.maxZoom = 6f
val imageDescriptionText = binding.imageDescriptionText val imageDescriptionText = binding.imageDescriptionText
@ -79,15 +79,6 @@ class CaptionDialog : DialogFragment() {
binding.imageDescriptionText.setText(it) binding.imageDescriptionText.setText(it)
} }
binding.cancelButton.setOnClickListener {
dismiss()
}
val localId = arguments?.getInt(LOCAL_ID_ARG) ?: error("Missing localId")
binding.okButton.setOnClickListener {
listener.onUpdateDescription(localId, binding.imageDescriptionText.text.toString())
dismiss()
}
isCancelable = true isCancelable = true
dialog?.setCanceledOnTouchOutside(false) // Dialog is full screen anyway. But without this, taps in navbar while keyboard is up can dismiss the dialog. dialog?.setCanceledOnTouchOutside(false) // Dialog is full screen anyway. But without this, taps in navbar while keyboard is up can dismiss the dialog.
@ -109,15 +100,15 @@ class CaptionDialog : DialogFragment() {
if (resource is Animatable) { if (resource is Animatable) {
resource.callback = object : Drawable.Callback { resource.callback = object : Drawable.Callback {
override fun invalidateDrawable(who: Drawable) { override fun invalidateDrawable(who: Drawable) {
view.invalidate() imageView.invalidate()
} }
override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) { override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) {
view.postDelayed(what, `when`) imageView.postDelayed(what, `when`)
} }
override fun unscheduleDrawable(who: Drawable, what: Runnable) { override fun unscheduleDrawable(who: Drawable, what: Runnable) {
view.removeCallbacks(what) imageView.removeCallbacks(what)
} }
} }
resource.start() resource.start()
@ -131,6 +122,7 @@ class CaptionDialog : DialogFragment() {
imageView.hide() imageView.hide()
} }
}) })
return binding.root
} }
override fun onStart() { override fun onStart() {

View File

@ -1,14 +1,10 @@
package com.keylesspalace.tusky.components.followedtags package com.keylesspalace.tusky.components.followedtags
import android.app.Dialog
import android.content.DialogInterface
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.WindowManager import android.view.WindowManager
import android.widget.AutoCompleteTextView
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.paging.LoadState import androidx.paging.LoadState
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
@ -22,6 +18,7 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.StatusListActivity import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter
import com.keylesspalace.tusky.databinding.ActivityFollowedTagsBinding import com.keylesspalace.tusky.databinding.ActivityFollowedTagsBinding
import com.keylesspalace.tusky.databinding.DialogFollowHashtagBinding
import com.keylesspalace.tusky.interfaces.HashtagActionListener import com.keylesspalace.tusky.interfaces.HashtagActionListener
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.copyToClipboard import com.keylesspalace.tusky.util.copyToClipboard
@ -61,8 +58,7 @@ class FollowedTagsActivity :
} }
binding.fab.setOnClickListener { binding.fab.setOnClickListener {
val dialog: DialogFragment = FollowTagDialog.newInstance() showDialog()
dialog.show(supportFragmentManager, "dialog")
} }
setupAdapter().let { adapter -> setupAdapter().let { adapter ->
@ -179,44 +175,34 @@ class FollowedTagsActivity :
) )
} }
private fun showDialog() {
val dialogBinding = DialogFollowHashtagBinding.inflate(layoutInflater)
dialogBinding.hashtagAutoCompleteTextView.setAdapter(
ComposeAutoCompleteAdapter(
this,
animateAvatar = false,
animateEmojis = false,
showBotBadge = false
)
)
dialogBinding.hashtagAutoCompleteTextView.requestFocus()
dialogBinding.hashtagAutoCompleteTextView.setSelection(dialogBinding.hashtagAutoCompleteTextView.length())
val dialog = MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_follow_hashtag_title)
.setView(dialogBinding.root)
.setPositiveButton(android.R.string.ok) { _, _ ->
follow(
dialogBinding.hashtagAutoCompleteTextView.text.toString().removePrefix("#")
)
}
.setNegativeButton(android.R.string.cancel, null)
.create()
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
}
companion object { companion object {
const val TAG = "FollowedTagsActivity" const val TAG = "FollowedTagsActivity"
} }
class FollowTagDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val layout = layoutInflater.inflate(R.layout.dialog_follow_hashtag, null)
val autoCompleteTextView = layout.findViewById<AutoCompleteTextView>(R.id.hashtag)!!
autoCompleteTextView.setAdapter(
ComposeAutoCompleteAdapter(
requireActivity() as FollowedTagsActivity,
animateAvatar = false,
animateEmojis = false,
showBotBadge = false
)
)
autoCompleteTextView.requestFocus()
autoCompleteTextView.setSelection(autoCompleteTextView.length())
return MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_follow_hashtag_title)
.setView(layout)
.setPositiveButton(android.R.string.ok) { _, _ ->
(requireActivity() as FollowedTagsActivity).follow(
autoCompleteTextView.text.toString().removePrefix("#")
)
}
.setNegativeButton(android.R.string.cancel) { _: DialogInterface, _: Int -> }
.create()
}
override fun onStart() {
super.onStart()
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
}
companion object {
fun newInstance(): FollowTagDialog = FollowTagDialog()
}
}
} }

View File

@ -433,7 +433,7 @@ class NotificationsFragment :
} }
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_multiple_choice, notificationTypeList) val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_multiple_choice, notificationTypeList)
val window = PopupWindow(requireContext()) val window = PopupWindow(requireContext(), null, com.google.android.material.R.attr.listPopupWindowStyle)
val menuBinding = NotificationsFilterBinding.inflate(LayoutInflater.from(requireContext()), binding.root as ViewGroup, false) val menuBinding = NotificationsFilterBinding.inflate(LayoutInflater.from(requireContext()), binding.root as ViewGroup, false)
menuBinding.buttonApply.setOnClickListener { menuBinding.buttonApply.setOnClickListener {

View File

@ -25,8 +25,6 @@ import com.keylesspalace.tusky.components.report.ReportViewModel
import com.keylesspalace.tusky.components.report.Screen import com.keylesspalace.tusky.components.report.Screen
import com.keylesspalace.tusky.databinding.FragmentReportDoneBinding import com.keylesspalace.tusky.databinding.FragmentReportDoneBinding
import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -49,11 +47,11 @@ class ReportDoneFragment : Fragment(R.layout.fragment_report_done) {
viewModel.muteState.collect { viewModel.muteState.collect {
if (it == null) return@collect if (it == null) return@collect
if (it !is Loading) { if (it !is Loading) {
binding.buttonMute.show() binding.buttonMute.visibility = View.VISIBLE
binding.progressMute.show() binding.progressMute.visibility = View.GONE
} else { } else {
binding.buttonMute.hide() binding.buttonMute.visibility = View.INVISIBLE
binding.progressMute.hide() binding.progressMute.visibility = View.VISIBLE
} }
binding.buttonMute.setText( binding.buttonMute.setText(
@ -69,11 +67,11 @@ class ReportDoneFragment : Fragment(R.layout.fragment_report_done) {
viewModel.blockState.collect { viewModel.blockState.collect {
if (it == null) return@collect if (it == null) return@collect
if (it !is Loading) { if (it !is Loading) {
binding.buttonBlock.show() binding.buttonBlock.visibility = View.VISIBLE
binding.progressBlock.show() binding.progressBlock.visibility = View.GONE
} else { } else {
binding.buttonBlock.hide() binding.buttonBlock.visibility = View.INVISIBLE
binding.progressBlock.hide() binding.progressBlock.visibility = View.VISIBLE
} }
binding.buttonBlock.setText( binding.buttonBlock.setText(
when (it.data) { when (it.data) {

View File

@ -15,6 +15,8 @@ import com.keylesspalace.tusky.databinding.ViewBackgroundMessageBinding
import com.keylesspalace.tusky.util.addDrawables import com.keylesspalace.tusky.util.addDrawables
import com.keylesspalace.tusky.util.getDrawableRes import com.keylesspalace.tusky.util.getDrawableRes
import com.keylesspalace.tusky.util.getErrorString import com.keylesspalace.tusky.util.getErrorString
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
/** /**
@ -61,7 +63,7 @@ class BackgroundMessageView @JvmOverloads constructor(
binding.imageView.setImageResource(imageRes) binding.imageView.setImageResource(imageRes)
binding.button.setOnClickListener(clickListener) binding.button.setOnClickListener(clickListener)
binding.button.visible(clickListener != null) binding.button.visible(clickListener != null)
binding.helpText.visible(false) binding.helpTextCard.hide()
} }
fun showHelp(@StringRes helpRes: Int) { fun showHelp(@StringRes helpRes: Int) {
@ -72,6 +74,6 @@ class BackgroundMessageView @JvmOverloads constructor(
binding.helpText.setText(textWithDrawables, TextView.BufferType.SPANNABLE) binding.helpText.setText(textWithDrawables, TextView.BufferType.SPANNABLE)
binding.helpText.visible(true) binding.helpTextCard.show()
} }
} }

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="1dp"
android:left="-1dp"
android:right="-1dp"
android:top="1dp">
<shape android:shape="rectangle">
<solid android:color="?attr/colorBackgroundAccent"/>
<stroke android:width="1dp" android:color="?attr/dividerColor"/>
</shape>
</item>
</layer-list>

View File

@ -59,7 +59,7 @@
app:layout_constraintTop_toBottomOf="@id/textReported" app:layout_constraintTop_toBottomOf="@id/textReported"
app:layout_constraintVertical_chainStyle="packed" /> app:layout_constraintVertical_chainStyle="packed" />
<com.google.android.material.progressindicator.LinearProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progressMute" android:id="@+id/progressMute"
style="@style/Widget.Material3.CircularProgressIndicator.Small" style="@style/Widget.Material3.CircularProgressIndicator.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -83,7 +83,7 @@
app:layout_constraintTop_toBottomOf="@id/buttonMute" app:layout_constraintTop_toBottomOf="@id/buttonMute"
app:layout_constraintVertical_chainStyle="packed" /> app:layout_constraintVertical_chainStyle="packed" />
<com.google.android.material.progressindicator.LinearProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progressBlock" android:id="@+id/progressBlock"
style="@style/Widget.Material3.CircularProgressIndicator.Small" style="@style/Widget.Material3.CircularProgressIndicator.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -34,6 +34,8 @@
android:layout_height="48dp" android:layout_height="48dp"
android:orientation="horizontal" android:orientation="horizontal"
app:contentInsetStart="0dp" app:contentInsetStart="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
app:contentInsetStartWithNavigation="0dp" app:contentInsetStartWithNavigation="0dp"
app:navigationContentDescription="@string/action_open_drawer"> app:navigationContentDescription="@string/action_open_drawer">

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingTop="16dp"
android:paddingRight="20dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/addHashtagInputLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/edit_hashtag_hint"
app:endIconMode="none">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/addHashtagEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textNoSuggestions"
android:lines="1" />
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>

View File

@ -1,34 +1,43 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="24dp"> android:paddingLeft="20dp"
android:paddingTop="16dp"
android:paddingRight="20dp">
<EditText <com.google.android.material.textfield.TextInputLayout
android:id="@+id/phraseEditText" android:id="@+id/phraseInputLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/filter_add_description" android:hint="@string/filter_add_description"
android:inputType="text" app:layout_constraintTop_toTopOf="parent">
android:importantForAutofill="no"
app:layout_constraintTop_toTopOf="parent" <com.google.android.material.textfield.TextInputEditText
/> android:id="@+id/phraseEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<CheckBox <CheckBox
android:id="@+id/phraseWholeWord" android:id="@+id/phraseWholeWord"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/filter_dialog_whole_word" android:text="@string/filter_dialog_whole_word"
app:layout_constraintTop_toBottomOf="@id/phraseEditText"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
/> app:layout_constraintTop_toBottomOf="@id/phraseInputLayout" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.1" android:lineSpacingMultiplier="1.1"
app:layout_constraintTop_toBottomOf="@id/phraseWholeWord"
app:layout_constraintLeft_toLeftOf="parent"
android:text="@string/filter_dialog_whole_word_description" android:text="@string/filter_dialog_whole_word_description"
/> app:layout_constraintLeft_toLeftOf="parent"
</androidx.constraintlayout.widget.ConstraintLayout> app:layout_constraintTop_toBottomOf="@id/phraseWholeWord" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,16 +1,28 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingLeft="20dp"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> android:paddingTop="16dp"
android:paddingRight="20dp">
<!-- textNoSuggestions is to disable spell check, it will auto-complete --> <com.google.android.material.textfield.TextInputLayout
<AutoCompleteTextView android:id="@+id/hashtagAutoCompleteInputLayout"
android:id="@+id/hashtag" style="@style/Widget.Material3.TextInputLayout.OutlinedBox.Dense.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="textNoSuggestions" android:hint="@string/dialog_follow_hashtag_hint"
android:hint="@string/dialog_follow_hashtag_hint" /> app:endIconMode="none">
<!-- textNoSuggestions is to disable spell check, it will auto-complete -->
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/hashtagAutoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textNoSuggestions"
android:lines="1" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout> </LinearLayout>

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout 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"
@ -17,7 +16,6 @@
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
style="@style/TuskyTextInput" style="@style/TuskyTextInput"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
@ -39,27 +37,4 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal"
android:gravity="end"
android:layout_marginStart="?dialogPreferredPadding"
android:layout_marginEnd="?dialogPreferredPadding">
<Button
android:id="@+id/cancelButton"
style="@style/TuskyButton.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@android:string/cancel" />
<Button
android:id="@+id/okButton"
style="@style/TuskyButton.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@android:string/ok" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -1,13 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="200dp" android:layout_width="200dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"> android:orientation="vertical">
<ListView <ListView
android:id="@+id/listView" android:id="@+id/listView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" /> android:layout_weight="1" />
<Button <Button
android:id="@+id/buttonApply" android:id="@+id/buttonApply"
style="@style/TuskyButton.TextButton" style="@style/TuskyButton.TextButton"
@ -16,4 +18,5 @@
android:layout_weight="0" android:layout_weight="0"
android:text="@string/filter_apply" android:text="@string/filter_apply"
android:textSize="?attr/status_text_medium" /> android:textSize="?attr/status_text_medium" />
</LinearLayout> </LinearLayout>

View File

@ -1,24 +1,32 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" <merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
tools:parentTag="android.widget.LinearLayout"> tools:parentTag="android.widget.LinearLayout">
<TextView <com.google.android.material.card.MaterialCardView
android:id="@+id/helpText" android:id="@+id/helpTextCard"
android:visibility="gone" style="@style/Widget.Material3.CardView.Filled"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.1" android:layout_margin="8dp"
android:textColor="@color/textColorPrimary" android:visibility="gone"
android:background="@drawable/help_message_background" app:cardBackgroundColor="?attr/colorSurface">
android:layout_marginTop="16dp"
android:padding="16dp" <TextView
android:textAlignment="viewStart" android:id="@+id/helpText"
android:textSize="?attr/status_text_medium" /> android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:lineSpacingMultiplier="1.1"
android:textColor="@color/textColorPrimary"
android:textSize="?attr/status_text_medium"
tools:text="@string/help_empty_home" />
</com.google.android.material.card.MaterialCardView>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -43,8 +51,8 @@
android:drawablePadding="16dp" android:drawablePadding="16dp"
android:lineSpacingMultiplier="1.1" android:lineSpacingMultiplier="1.1"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp" android:paddingTop="16dp"
android:paddingRight="16dp"
android:text="@string/error_network" android:text="@string/error_network"
android:textAlignment="center" android:textAlignment="center"
android:textSize="?attr/status_text_medium" /> android:textSize="?attr/status_text_medium" />
@ -54,8 +62,10 @@
style="@style/TuskyButton.Outlined" style="@style/TuskyButton.Outlined"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
android:text="@string/action_retry" /> android:text="@string/action_retry" />
</LinearLayout> </LinearLayout>
</merge> </merge>

View File

@ -99,6 +99,9 @@
<item name="alertDialogTheme">@style/TuskyDialogOverlay</item> <item name="alertDialogTheme">@style/TuskyDialogOverlay</item>
<item name="dialogCornerRadius">16dp</item> <item name="dialogCornerRadius">16dp</item>
<item name="materialTimePickerTheme">@style/TuskyTimePickerOverlay</item>
<item name="materialCalendarTheme">@style/TuskyDatePickerOverlay</item>
<item name="minTouchTargetSize">32dp</item> <!-- this affects RadioButton size --> <item name="minTouchTargetSize">32dp</item> <!-- this affects RadioButton size -->
<item name="elevationOverlayEnabled">false</item> <!-- disable the automatic tinting of surfaces with elevation in dark mode --> <item name="elevationOverlayEnabled">false</item> <!-- disable the automatic tinting of surfaces with elevation in dark mode -->
@ -120,12 +123,21 @@
<item name="windowBackgroundColor">@color/black</item> <item name="windowBackgroundColor">@color/black</item>
<item name="colorSurface">@color/tusky_grey_10</item> <item name="colorSurface">@color/tusky_grey_10</item>
<item name="colorSurfaceVariant">@color/tusky_grey_10</item>
<item name="colorSurfaceContainerLowest">@color/tusky_grey_10</item>
<item name="colorSurfaceContainerLow">@color/tusky_grey_10</item>
<item name="colorSurfaceContainer">@color/tusky_grey_10</item>
<item name="colorSurfaceContainerHigh">@color/tusky_grey_10</item>
<item name="colorSurfaceContainerHighest">@color/tusky_grey_10</item>
<item name="iconColor">@color/tusky_grey_40</item> <item name="iconColor">@color/tusky_grey_40</item>
<item name="colorBackgroundHighlight">@color/tusky_grey_40</item> <item name="colorBackgroundHighlight">@color/tusky_grey_40</item>
<item name="colorBackgroundAccent">@color/tusky_grey_20</item> <item name="colorBackgroundAccent">@color/tusky_grey_20</item>
<item name="dividerColor">@color/tusky_grey_20</item> <item name="dividerColor">@color/tusky_grey_20</item>
<item name="colorOutlineVariant">@color/tusky_grey_20</item>
</style> </style>
<style name="TuskyBlackTheme" parent="TuskyBlackThemeBase" /> <style name="TuskyBlackTheme" parent="TuskyBlackThemeBase" />
@ -143,13 +155,22 @@
<style name="TuskyDialog" parent="@style/MaterialAlertDialog.Material3"> <style name="TuskyDialog" parent="@style/MaterialAlertDialog.Material3">
<item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.Large</item> <item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.Large</item>
<item name="backgroundTint">@color/colorBackground</item> <item name="backgroundTint">@color/colorBackground</item>
<item name="buttonBarNeutralButtonStyle">@style/TuskyButton.TextButton</item>
<item name="buttonBarPositiveButtonStyle">@style/TuskyButton.TextButton</item>
<item name="buttonBarNegativeButtonStyle">@style/TuskyButton.TextButton</item>
</style> </style>
<style name="TuskyDialogFragmentStyle" parent="@style/ThemeOverlay.Material3.Dialog"> <style name="TuskyTimePickerOverlay" parent="@style/ThemeOverlay.MaterialComponents.TimePicker">
<item name="dialogCornerRadius">8dp</item> <item name="materialTimePickerStyle">@style/TuskyTimePicker</item>
</style>
<style name="TuskyTimePicker" parent="@style/Widget.Material3.MaterialTimePicker">
<item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.Large</item>
<item name="backgroundTint">@color/colorBackground</item>
</style>
<style name="TuskyDatePickerOverlay" parent="@style/ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="materialCalendarStyle">@style/TuskyDatePicker</item>
</style>
<style name="TuskyDatePicker" parent="@style/Widget.Material3.MaterialCalendar">
<item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.Large</item>
<item name="backgroundTint">@color/colorBackground</item>
</style> </style>
<style name="TuskyTabAppearance" parent="Widget.Material3.TabLayout"> <style name="TuskyTabAppearance" parent="Widget.Material3.TabLayout">