Add about dialog
Add an about dialog with information about this app.
This commit is contained in:
parent
4933531ca3
commit
0d32ab0f7e
29 changed files with 463 additions and 37 deletions
0
FAQ.md
Normal file
0
FAQ.md
Normal file
0
LIBRARIES.md
Normal file
0
LIBRARIES.md
Normal file
0
LICENSES.md
Normal file
0
LICENSES.md
Normal file
|
@ -51,13 +51,14 @@ dependencies {
|
||||||
// Kotlin
|
// Kotlin
|
||||||
//noinspection DifferentStdlibGradleVersion
|
//noinspection DifferentStdlibGradleVersion
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
|
||||||
// --- SUPPORT ---
|
// --- SUPPORT ---
|
||||||
|
|
||||||
// General
|
// General
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.activity:activity-ktx:1.2.0-beta01'
|
implementation 'androidx.activity:activity-ktx:1.2.0-beta02'
|
||||||
implementation 'androidx.fragment:fragment-ktx:1.3.0-beta01'
|
implementation 'androidx.fragment:fragment-ktx:1.3.0-beta02'
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
|
@ -79,6 +80,9 @@ dependencies {
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||||
|
|
||||||
|
// Opening links
|
||||||
|
implementation 'androidx.browser:browser:1.3.0'
|
||||||
|
|
||||||
// --- THIRD PARTY ---
|
// --- THIRD PARTY ---
|
||||||
|
|
||||||
// ExoPlayer
|
// ExoPlayer
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
|
<queries />
|
||||||
|
|
||||||
<!-- TODO: Backup -->
|
<!-- TODO: Backup -->
|
||||||
<application
|
<application
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.oxycblt.auxio.ui.toColor
|
||||||
// FIXME: Fix bug where fast navigation will break the animations and
|
// FIXME: Fix bug where fast navigation will break the animations and
|
||||||
// lead to nothing being displayed [Possibly Un-fixable]
|
// lead to nothing being displayed [Possibly Un-fixable]
|
||||||
// FIXME: Compat issue with Versions 5 that leads to progress bar looking off
|
// FIXME: Compat issue with Versions 5 that leads to progress bar looking off
|
||||||
|
// TODO: Try to heavily refactor edge-to-edge
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
|
@ -90,13 +90,8 @@ class CompactPlaybackFragment : Fragment() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
playbackModel.disableAnimation()
|
playbackModel.disableAnimation()
|
||||||
|
|
||||||
// Use the caveman method of getting a view as storing the binding will cause a memory
|
|
||||||
// leak.
|
|
||||||
val playbackControls = binding.playbackControls
|
|
||||||
|
|
||||||
val iconPauseToPlay = ContextCompat.getDrawable(
|
val iconPauseToPlay = ContextCompat.getDrawable(
|
||||||
requireContext(), R.drawable.ic_pause_to_play
|
requireContext(), R.drawable.ic_pause_to_play
|
||||||
) as AnimatedVectorDrawable
|
) as AnimatedVectorDrawable
|
||||||
|
@ -109,19 +104,19 @@ class CompactPlaybackFragment : Fragment() {
|
||||||
if (playbackModel.canAnimate) {
|
if (playbackModel.canAnimate) {
|
||||||
if (it) {
|
if (it) {
|
||||||
// Animate the icon transition when the playing status switches
|
// Animate the icon transition when the playing status switches
|
||||||
playbackControls?.setImageDrawable(iconPlayToPause)
|
binding.playbackControls.setImageDrawable(iconPlayToPause)
|
||||||
iconPlayToPause.start()
|
iconPlayToPause.start()
|
||||||
} else {
|
} else {
|
||||||
playbackControls?.setImageDrawable(iconPauseToPlay)
|
binding.playbackControls.setImageDrawable(iconPauseToPlay)
|
||||||
iconPauseToPlay.start()
|
iconPauseToPlay.start()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use static icons on the first firing of this observer so that the icons
|
// Use static icons on the first firing of this observer so that the icons
|
||||||
// don't animate on startup, which looks weird.
|
// don't animate on startup, which looks weird.
|
||||||
if (it) {
|
if (it) {
|
||||||
playbackControls?.setImageResource(R.drawable.ic_pause_large)
|
binding.playbackControls.setImageResource(R.drawable.ic_pause_large)
|
||||||
} else {
|
} else {
|
||||||
playbackControls?.setImageResource(R.drawable.ic_play_large)
|
binding.playbackControls.setImageResource(R.drawable.ic_play_large)
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackModel.enableAnimation()
|
playbackModel.enableAnimation()
|
||||||
|
|
|
@ -28,7 +28,9 @@ import org.oxycblt.auxio.ui.toColor
|
||||||
*/
|
*/
|
||||||
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
private val binding: FragmentPlaybackBinding by memberBinding(FragmentPlaybackBinding::inflate)
|
private val binding: FragmentPlaybackBinding by memberBinding(FragmentPlaybackBinding::inflate) {
|
||||||
|
binding.playbackSong.isSelected = false
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -199,12 +201,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
super.onStop()
|
|
||||||
|
|
||||||
binding.playbackSong.isSelected = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seeking callbacks
|
// Seeking callbacks
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
|
|
|
@ -17,7 +17,8 @@ import org.oxycblt.auxio.music.BaseModel
|
||||||
import org.oxycblt.auxio.music.Header
|
import org.oxycblt.auxio.music.Header
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.ui.isInIrregularLandscapeMode
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
|
import org.oxycblt.auxio.ui.isIrregularLandscape
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [Fragment] that contains both the user queue and the next queue, with the ability to
|
* A [Fragment] that contains both the user queue and the next queue, with the ability to
|
||||||
|
@ -49,7 +50,8 @@ class QueueFragment : Fragment() {
|
||||||
findNavController().navigateUp()
|
findNavController().navigateUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requireActivity().isInIrregularLandscapeMode()) {
|
if (!requireActivity().isIrregularLandscape() &&
|
||||||
|
SettingsManager.getInstance().edgeEnabled) {
|
||||||
setOnApplyWindowInsetsListener @Suppress("DEPRECATION") { _, insets ->
|
setOnApplyWindowInsetsListener @Suppress("DEPRECATION") { _, insets ->
|
||||||
val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
insets.getInsets(WindowInsets.Type.systemBars()).top
|
insets.getInsets(WindowInsets.Type.systemBars()).top
|
||||||
|
|
|
@ -5,7 +5,9 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentSettingsBinding
|
import org.oxycblt.auxio.databinding.FragmentSettingsBinding
|
||||||
|
import org.oxycblt.auxio.settings.ui.AboutDialog
|
||||||
|
|
||||||
class SettingsFragment : Fragment() {
|
class SettingsFragment : Fragment() {
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -15,6 +17,13 @@ class SettingsFragment : Fragment() {
|
||||||
): View {
|
): View {
|
||||||
val binding = FragmentSettingsBinding.inflate(inflater)
|
val binding = FragmentSettingsBinding.inflate(inflater)
|
||||||
|
|
||||||
|
binding.settingsToolbar.setOnMenuItemClickListener {
|
||||||
|
if (it.itemId == R.id.action_open_about) {
|
||||||
|
AboutDialog().show(childFragmentManager, "DIALOG")
|
||||||
|
true
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.recycler.DisplayMode
|
import org.oxycblt.auxio.recycler.DisplayMode
|
||||||
import org.oxycblt.auxio.settings.adapters.AccentAdapter
|
import org.oxycblt.auxio.settings.ui.AccentAdapter
|
||||||
import org.oxycblt.auxio.ui.ACCENTS
|
import org.oxycblt.auxio.ui.ACCENTS
|
||||||
import org.oxycblt.auxio.ui.accent
|
import org.oxycblt.auxio.ui.accent
|
||||||
import org.oxycblt.auxio.ui.createToast
|
import org.oxycblt.auxio.ui.createToast
|
||||||
|
|
121
app/src/main/java/org/oxycblt/auxio/settings/ui/AboutDialog.kt
Normal file
121
app/src/main/java/org/oxycblt/auxio/settings/ui/AboutDialog.kt
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
package org.oxycblt.auxio.settings.ui
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import org.oxycblt.auxio.BuildConfig
|
||||||
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.databinding.FragmentAboutBinding
|
||||||
|
import org.oxycblt.auxio.logD
|
||||||
|
import org.oxycblt.auxio.logE
|
||||||
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
|
import org.oxycblt.auxio.ui.createToast
|
||||||
|
import org.oxycblt.auxio.ui.handleTransparentSystemBars
|
||||||
|
import org.oxycblt.auxio.ui.handleTransparentSystemNavBar
|
||||||
|
import org.oxycblt.auxio.ui.isIrregularLandscape
|
||||||
|
import org.oxycblt.auxio.ui.isLandscape
|
||||||
|
import org.oxycblt.auxio.ui.toColor
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class AboutDialog : BottomSheetDialogFragment() {
|
||||||
|
override fun getTheme() = R.style.Theme_BottomSheetFix
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
val binding = FragmentAboutBinding.inflate(layoutInflater)
|
||||||
|
val musicStore = MusicStore.getInstance()
|
||||||
|
val settingsManager = SettingsManager.getInstance()
|
||||||
|
|
||||||
|
// --- UI SETUP ---
|
||||||
|
|
||||||
|
// Apply edge-to-edge to the dialog if supported/enabled.
|
||||||
|
if (settingsManager.edgeEnabled && !requireActivity().isIrregularLandscape()) {
|
||||||
|
requireDialog().window?.apply {
|
||||||
|
navigationBarColor = R.color.background.toColor(requireContext())
|
||||||
|
handleTransparentSystemNavBar(resources.configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.aboutVersion.text = BuildConfig.VERSION_NAME
|
||||||
|
|
||||||
|
binding.aboutCode.setOnClickListener { openLinkInBrowser(LINK_CODEBASE) }
|
||||||
|
binding.aboutFaq.setOnClickListener { openLinkInBrowser(LINK_FAQ) }
|
||||||
|
binding.aboutLicenses.setOnClickListener { openLinkInBrowser(LINK_LICENSES) }
|
||||||
|
|
||||||
|
binding.aboutSongCount.text = getString(
|
||||||
|
R.string.format_songs_loaded, musicStore.songs.size.toString()
|
||||||
|
)
|
||||||
|
binding.aboutAuthor.text = getString(
|
||||||
|
R.string.format_author, getString(R.string.author_oxycblt)
|
||||||
|
)
|
||||||
|
|
||||||
|
logD("Dialog created.")
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openLinkInBrowser(link: String) {
|
||||||
|
check(link in LINKS) { "Invalid link." }
|
||||||
|
|
||||||
|
try {
|
||||||
|
val tabsIntent = CustomTabsIntent.Builder()
|
||||||
|
.setShareState(CustomTabsIntent.SHARE_STATE_ON)
|
||||||
|
.setShowTitle(true)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val uri = link.toUri()
|
||||||
|
val manager = requireActivity().packageManager
|
||||||
|
val browserCandidates = manager.queryIntentActivities(tabsIntent.intent, 0)
|
||||||
|
|
||||||
|
// If there are candidates for this link, then launch it through that.
|
||||||
|
if (browserCandidates.size > 0) {
|
||||||
|
tabsIntent.launchUrl(requireActivity(), uri)
|
||||||
|
} else {
|
||||||
|
// If there are no candidates, then fallback to another list of browsers
|
||||||
|
|
||||||
|
val browserIntent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
browserIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
|
||||||
|
val fallbackCandidates = manager.queryIntentActivities(browserIntent, 0)
|
||||||
|
|
||||||
|
// If there are candidates here, then launch those.
|
||||||
|
if (fallbackCandidates.size > 0) {
|
||||||
|
requireActivity().startActivity(browserIntent)
|
||||||
|
} else {
|
||||||
|
// Otherwise they don't have a browser on their phone, meaning they should
|
||||||
|
// just see an error.
|
||||||
|
getString(R.string.error_no_browser).createToast(requireContext())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logE("Browser intent launching failed [Probably android's fault]")
|
||||||
|
e.printStackTrace()
|
||||||
|
|
||||||
|
// Sometimes people have """""Browsers""""" on their phone according to android,
|
||||||
|
// but they actually don't so here's a fallback for that.
|
||||||
|
getString(R.string.error_no_browser).createToast(requireContext())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// TODO: Change dev to master
|
||||||
|
private const val LINK_CODEBASE = "https://github.com/oxygencobalt/Auxio"
|
||||||
|
private const val LINK_FAQ = "$LINK_CODEBASE/blob/master/FAQ.md"
|
||||||
|
private const val LINK_LICENSES = "$LINK_CODEBASE/blob/master/LICENSES.md"
|
||||||
|
|
||||||
|
val LINKS = arrayOf(LINK_CODEBASE, LINK_FAQ, LINK_LICENSES)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.oxycblt.auxio.settings.adapters
|
package org.oxycblt.auxio.settings.ui
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
|
@ -22,9 +22,8 @@ import org.oxycblt.auxio.settings.SettingsManager
|
||||||
* TODO: Make edge-to-edge work in irregular mode
|
* TODO: Make edge-to-edge work in irregular mode
|
||||||
* @return True if we are in the irregular landscape mode, false if not.
|
* @return True if we are in the irregular landscape mode, false if not.
|
||||||
*/
|
*/
|
||||||
fun Activity.isInIrregularLandscapeMode(): Boolean {
|
fun Activity.isIrregularLandscape(): Boolean {
|
||||||
return SettingsManager.getInstance().edgeEnabled &&
|
return isLandscape(resources) &&
|
||||||
isLandscape(resources) &&
|
|
||||||
!isSystemBarOnBottom(this)
|
!isSystemBarOnBottom(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,3 +92,31 @@ fun Window.handleTransparentSystemBars(config: Configuration) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle only the transparent navigation bar.
|
||||||
|
*/
|
||||||
|
fun Window.handleTransparentSystemNavBar(config: Configuration) {
|
||||||
|
fun isNight() = config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
insetsController?.let { controller ->
|
||||||
|
val appearance = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
|
||||||
|
|
||||||
|
val mask = if (isNight()) 0 else appearance
|
||||||
|
|
||||||
|
controller.setSystemBarsAppearance(appearance, mask)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val flags = decorView.systemUiVisibility
|
||||||
|
|
||||||
|
decorView.systemUiVisibility =
|
||||||
|
if (isNight()) {
|
||||||
|
flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and
|
||||||
|
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
|
||||||
|
} else {
|
||||||
|
flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR or
|
||||||
|
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,20 +16,21 @@ import kotlin.reflect.KProperty
|
||||||
/**
|
/**
|
||||||
* A delegate that creates a binding that can be used as a member variable without nullability or
|
* A delegate that creates a binding that can be used as a member variable without nullability or
|
||||||
* memory leaks.
|
* memory leaks.
|
||||||
|
* @param bindingFactory The ViewBinding inflation method that should be used
|
||||||
|
* @param onDestroy Any code that should be run when the binding is destroyed.
|
||||||
*/
|
*/
|
||||||
fun <T : ViewBinding> Fragment.memberBinding(
|
fun <T : ViewBinding> Fragment.memberBinding(
|
||||||
viewBindingFactory: (LayoutInflater) -> T,
|
bindingFactory: (LayoutInflater) -> T, onDestroy: T.() -> Unit = {}
|
||||||
disposeEvents: T.() -> Unit = {}
|
) = FragmentBinderDelegate(this, bindingFactory, onDestroy)
|
||||||
) = FragmentBinderDelegate(this, viewBindingFactory, disposeEvents)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The delegate for the [binder] shortcut function.
|
* The delegate for the [memberBinding] shortcut function.
|
||||||
* Adapted from KAHelpers (https://github.com/FunkyMuse/KAHelpers/tree/master/viewbinding)
|
* Adapted from KAHelpers (https://github.com/FunkyMuse/KAHelpers/tree/master/viewbinding)
|
||||||
*/
|
*/
|
||||||
class FragmentBinderDelegate<T : ViewBinding>(
|
class FragmentBinderDelegate<T : ViewBinding>(
|
||||||
private val fragment: Fragment,
|
private val fragment: Fragment,
|
||||||
private val binder: (LayoutInflater) -> T,
|
private val inflate: (LayoutInflater) -> T,
|
||||||
private val disposeEvents: T.() -> Unit
|
private val onDestroy: T.() -> Unit
|
||||||
) : ReadOnlyProperty<Fragment, T>, LifecycleObserver {
|
) : ReadOnlyProperty<Fragment, T>, LifecycleObserver {
|
||||||
private var fragmentBinding: T? = null
|
private var fragmentBinding: T? = null
|
||||||
|
|
||||||
|
@ -46,8 +47,8 @@ class FragmentBinderDelegate<T : ViewBinding>(
|
||||||
override fun onCreate(owner: LifecycleOwner) {
|
override fun onCreate(owner: LifecycleOwner) {
|
||||||
super.onCreate(owner)
|
super.onCreate(owner)
|
||||||
|
|
||||||
viewLifecycleOwnerLiveData.observe(this@observeOwnerThroughCreation) { owner ->
|
viewLifecycleOwnerLiveData.observe(this@observeOwnerThroughCreation) {
|
||||||
owner.viewOwner()
|
it.viewOwner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -69,13 +70,13 @@ class FragmentBinderDelegate<T : ViewBinding>(
|
||||||
throw IllegalStateException("Fragment views are destroyed.")
|
throw IllegalStateException("Fragment views are destroyed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return binder(LayoutInflater.from(thisRef.requireContext())).also { fragmentBinding = it }
|
return inflate(LayoutInflater.from(thisRef.requireContext())).also { fragmentBinding = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
fragmentBinding?.disposeEvents()
|
fragmentBinding?.onDestroy()
|
||||||
fragmentBinding = null
|
fragmentBinding = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
app/src/main/res/drawable/ic_about.xml
Normal file
11
app/src/main/res/drawable/ic_about.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z"/>
|
||||||
|
</vector>
|
11
app/src/main/res/drawable/ic_author.xml
Normal file
11
app/src/main/res/drawable/ic_author.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM21.41,6.34l-3.75,-3.75 -2.53,2.54 3.75,3.75 2.53,-2.54z"/>
|
||||||
|
</vector>
|
11
app/src/main/res/drawable/ic_code.xml
Normal file
11
app/src/main/res/drawable/ic_code.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z"/>
|
||||||
|
</vector>
|
11
app/src/main/res/drawable/ic_libraries.xml
Normal file
11
app/src/main/res/drawable/ic_libraries.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M4,6L2,6v16h16v-2L4,20L4,6zM22,2L6,2v16h16L22,2zM19,11L9,11L9,9h10v2zM15,15L9,15v-2h6v2zM19,7L9,7L9,5h10v2z"/>
|
||||||
|
</vector>
|
11
app/src/main/res/drawable/ic_license.xml
Normal file
11
app/src/main/res/drawable/ic_license.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M4.01,2L4,22h16V8l-6,-6H4.01zM13,9V3.5L18.5,9H13z"/>
|
||||||
|
</vector>
|
11
app/src/main/res/drawable/ic_version.xml
Normal file
11
app/src/main/res/drawable/ic_version.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||||
|
</vector>
|
168
app/src/main/res/layout/fragment_about.xml
Normal file
168
app/src/main/res/layout/fragment_about.xml
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background"
|
||||||
|
android:theme="@style/Theme.Neutral">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/about_auxio_icon"
|
||||||
|
android:layout_width="@dimen/size_app_icon"
|
||||||
|
android:layout_height="@dimen/size_app_icon"
|
||||||
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
|
android:contentDescription="@string/description_auxio_icon"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/about_app_name"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_app_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
|
android:fontFamily="@font/inter_semibold"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/about_auxio_icon"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/about_auxio_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/about_auxio_icon" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_desc"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/margin_small"
|
||||||
|
android:text="@string/app_desc"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_auxio_icon" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/version_container"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/padding_medium"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/about_code"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_desc"
|
||||||
|
app:layout_constraintVertical_bias="0"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/about_version_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/label_version"
|
||||||
|
android:src="@drawable/ic_version"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_version_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
|
android:text="@string/label_version"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/about_version"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/about_version_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/about_version_icon" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_version"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/about_version_icon"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/about_version_icon"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_version_title"
|
||||||
|
tools:text="0.0.0" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_code"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/ui_ripple"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="@dimen/padding_medium"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="@dimen/padding_medium"
|
||||||
|
android:text="@string/label_code"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
app:drawableLeftCompat="@drawable/ic_code"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/about_faq"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/version_container" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_licenses"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/ui_ripple"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="@dimen/padding_medium"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="@dimen/padding_medium"
|
||||||
|
android:text="@string/label_licenses"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
app:drawableLeftCompat="@drawable/ic_license"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/about_song_count"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_faq" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_faq"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/ui_ripple"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="@dimen/padding_medium"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="@dimen/padding_medium"
|
||||||
|
android:text="@string/label_faq"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
app:drawableLeftCompat="@drawable/ic_about"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/about_licenses"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_code"
|
||||||
|
tools:layout_editor_absoluteX="0dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_song_count"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="@dimen/padding_medium"
|
||||||
|
android:padding="@dimen/padding_medium"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
app:drawableLeftCompat="@drawable/ic_song"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/about_author"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_licenses"
|
||||||
|
tools:text="Songs Loaded: 1616" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_author"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="@dimen/padding_medium"
|
||||||
|
android:padding="@dimen/padding_medium"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
app:drawableLeftCompat="@drawable/ic_author"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/about_song_count"
|
||||||
|
tools:text="Created by OxygenCobalt" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
|
@ -8,10 +8,11 @@
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:id="@+id/song_toolbar"
|
android:id="@+id/settings_toolbar"
|
||||||
style="@style/Toolbar.Style"
|
style="@style/Toolbar.Style"
|
||||||
android:background="?android:attr/windowBackground"
|
android:background="?android:attr/windowBackground"
|
||||||
android:elevation="@dimen/elevation_normal"
|
android:elevation="@dimen/elevation_normal"
|
||||||
|
app:menu="@menu/menu_settings"
|
||||||
app:title="@string/setting_title" />
|
app:title="@string/setting_title" />
|
||||||
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
|
9
app/src/main/res/menu/menu_settings.xml
Normal file
9
app/src/main/res/menu/menu_settings.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_open_about"
|
||||||
|
android:title="@string/label_about"
|
||||||
|
android:icon="@drawable/ic_about"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
</menu>
|
|
@ -34,6 +34,8 @@
|
||||||
<dimen name="size_play_pause">70dp</dimen>
|
<dimen name="size_play_pause">70dp</dimen>
|
||||||
<dimen name="size_play_pause_compact">36dp</dimen>
|
<dimen name="size_play_pause_compact">36dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="size_app_icon">60dp</dimen>
|
||||||
|
|
||||||
<!-- Text Size Namespace | Text Sizes -->
|
<!-- Text Size Namespace | Text Sizes -->
|
||||||
<dimen name="text_size_min">10sp</dimen>
|
<dimen name="text_size_min">10sp</dimen>
|
||||||
<dimen name="text_size_increment">2sp</dimen>
|
<dimen name="text_size_increment">2sp</dimen>
|
||||||
|
|
4
app/src/main/res/values/do_not_translate.xml
Normal file
4
app/src/main/res/values/do_not_translate.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="author_oxycblt">OxygenCobalt</string>
|
||||||
|
</resources>
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Auxio</string>
|
<string name="app_name">Auxio</string>
|
||||||
|
<string name="app_desc">A sensible and customizable music player for android.</string>
|
||||||
|
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="label_retry">Retry</string>
|
<string name="label_retry">Retry</string>
|
||||||
|
@ -36,6 +37,12 @@
|
||||||
<string name="label_channel">Music Playback</string>
|
<string name="label_channel">Music Playback</string>
|
||||||
<string name="label_service_playback">The music playback service for Auxio.</string>
|
<string name="label_service_playback">The music playback service for Auxio.</string>
|
||||||
|
|
||||||
|
<string name="label_about">About</string>
|
||||||
|
<string name="label_version">Version</string>
|
||||||
|
<string name="label_code">View on Github</string>
|
||||||
|
<string name="label_licenses">Licenses</string>
|
||||||
|
<string name="label_faq">FAQ</string>
|
||||||
|
|
||||||
<!-- Settings namespace | Settings-related labels -->
|
<!-- Settings namespace | Settings-related labels -->
|
||||||
<string name="setting_title">Settings</string>
|
<string name="setting_title">Settings</string>
|
||||||
<string name="setting_ui">Appearance</string>
|
<string name="setting_ui">Appearance</string>
|
||||||
|
@ -94,6 +101,7 @@
|
||||||
<string name="error_no_music">No music found.</string>
|
<string name="error_no_music">No music found.</string>
|
||||||
<string name="error_music_load_failed">Music loading failed.</string>
|
<string name="error_music_load_failed">Music loading failed.</string>
|
||||||
<string name="error_no_perms">Permissions to read storage are needed.</string>
|
<string name="error_no_perms">Permissions to read storage are needed.</string>
|
||||||
|
<string name="error_no_browser">Could not open link.</string>
|
||||||
|
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="hint_search_library">Search Library…</string>
|
<string name="hint_search_library">Search Library…</string>
|
||||||
|
@ -116,6 +124,8 @@
|
||||||
<string name="description_shuffle_on">Turn shuffle on</string>
|
<string name="description_shuffle_on">Turn shuffle on</string>
|
||||||
<string name="description_shuffle_off">Turn shuffle off</string>
|
<string name="description_shuffle_off">Turn shuffle off</string>
|
||||||
<string name="description_change_loop">Change Repeat Mode</string>
|
<string name="description_change_loop">Change Repeat Mode</string>
|
||||||
|
<string name="description_auxio_icon">Auxio icon</string>
|
||||||
|
<string name="description_code">Code</string>
|
||||||
|
|
||||||
<!-- Placeholder Namespace | Placeholder values -->
|
<!-- Placeholder Namespace | Placeholder values -->
|
||||||
<string name="placeholder_genre">Unknown Genre</string>
|
<string name="placeholder_genre">Unknown Genre</string>
|
||||||
|
@ -151,6 +161,8 @@
|
||||||
<string name="format_double_counts">%1$s, %2$s</string>
|
<string name="format_double_counts">%1$s, %2$s</string>
|
||||||
<string name="format_next_from">Next From: %s</string>
|
<string name="format_next_from">Next From: %s</string>
|
||||||
<string name="format_accent_summary"><b>%1$s</b>: %2$s</string>
|
<string name="format_accent_summary"><b>%1$s</b>: %2$s</string>
|
||||||
|
<string name="format_songs_loaded">Songs Loaded: %s</string>
|
||||||
|
<string name="format_author">Created by %s</string>
|
||||||
|
|
||||||
<plurals name="format_song_count">
|
<plurals name="format_song_count">
|
||||||
<item quantity="one">%s Song</item>
|
<item quantity="one">%s Song</item>
|
||||||
|
|
|
@ -167,4 +167,10 @@
|
||||||
<item name="android:paddingEnd">@dimen/padding_medium</item>
|
<item name="android:paddingEnd">@dimen/padding_medium</item>
|
||||||
<item name="android:background">@drawable/ui_small_unbounded_ripple</item>
|
<item name="android:background">@drawable/ui_small_unbounded_ripple</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Bottomsheet style -->
|
||||||
|
<style name="Theme.BottomSheetFix" parent="@style/Theme.Design.BottomSheetDialog">
|
||||||
|
<item name="android:windowIsFloating">false</item>
|
||||||
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
|
@ -1,6 +1,6 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = "1.4.20"
|
ext.kotlin_version = "1.4.21"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
|
Loading…
Reference in a new issue