weather: introduce display precipitation

Introduce a new datatype called DisplayPrecipitation that optimizes the
precipitation level for UI display.

This is primarily meant to fix improper precipitation displays when
values lower than 0.1 in are shown, albiet that may need to change
eventually.
This commit is contained in:
Alexander Capehart 2023-07-22 15:52:52 -06:00 committed by Hosted Weblate
parent 5ed69e8b72
commit 48655360d4
No known key found for this signature in database
GPG key ID: A3FAAA06E6569B4C
9 changed files with 314 additions and 38 deletions

View file

@ -41,7 +41,6 @@ import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.ListViewModel
import org.oxycblt.auxio.list.Menu import org.oxycblt.auxio.list.Menu
import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
@ -195,30 +194,34 @@ class AlbumDetailFragment :
} }
override fun onOpenSortMenu(anchor: View) { override fun onOpenSortMenu(anchor: View) {
openMenu(anchor, R.menu.sort_album) { findNavController().navigateSafe(AlbumDetailFragmentDirections.sort())
// Select the corresponding sort mode option // openMenu(anchor, R.menu.sort_album) {
val sort = detailModel.albumSongSort // // Select the corresponding sort mode option
unlikelyToBeNull(menu.findItem(sort.mode.itemId)).isChecked = true // val sort = detailModel.albumSongSort
// Select the corresponding sort direction option // unlikelyToBeNull(menu.findItem(sort.mode.itemId)).isChecked = true
val directionItemId = // // Select the corresponding sort direction option
when (sort.direction) { // val directionItemId =
Sort.Direction.ASCENDING -> R.id.option_sort_asc // when (sort.direction) {
Sort.Direction.DESCENDING -> R.id.option_sort_dec // Sort.Direction.ASCENDING -> R.id.option_sort_asc
} // Sort.Direction.DESCENDING -> R.id.option_sort_dec
unlikelyToBeNull(menu.findItem(directionItemId)).isChecked = true // }
setOnMenuItemClickListener { item -> // unlikelyToBeNull(menu.findItem(directionItemId)).isChecked = true
item.isChecked = !item.isChecked // setOnMenuItemClickListener { item ->
detailModel.albumSongSort = // item.isChecked = !item.isChecked
when (item.itemId) { // detailModel.albumSongSort =
// Sort direction options // when (item.itemId) {
R.id.option_sort_asc -> sort.withDirection(Sort.Direction.ASCENDING) // // Sort direction options
R.id.option_sort_dec -> sort.withDirection(Sort.Direction.DESCENDING) // R.id.option_sort_asc ->
// Any other option is a sort mode // sort.withDirection(Sort.Direction.ASCENDING)
else -> sort.withMode(unlikelyToBeNull(Sort.Mode.fromItemId(item.itemId))) // R.id.option_sort_dec ->
} // sort.withDirection(Sort.Direction.DESCENDING)
true // // Any other option is a sort mode
} // else ->
} // sort.withMode(unlikelyToBeNull(Sort.Mode.fromItemId(item.itemId)))
// }
// true
// }
// }
} }
override fun onNavigateToParentArtist() { override fun onNavigateToParentArtist() {

View file

@ -22,7 +22,6 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowInsets
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
@ -32,7 +31,6 @@ import com.google.android.material.divider.MaterialDivider
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.list.recycler.DialogRecyclerView.ViewHolder import org.oxycblt.auxio.list.recycler.DialogRecyclerView.ViewHolder
import org.oxycblt.auxio.util.getDimenPixels import org.oxycblt.auxio.util.getDimenPixels
import org.oxycblt.auxio.util.systemBarInsetsCompat
/** /**
* A [RecyclerView] intended for use in Dialogs, adding features such as: * A [RecyclerView] intended for use in Dialogs, adding features such as:
@ -76,13 +74,6 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
invalidateDividers() invalidateDividers()
} }
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
// Update the RecyclerView's padding such that the bottom insets are applied
// while still preserving bottom padding.
updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
return insets
}
override fun onScrolled(dx: Int, dy: Int) { override fun onScrolled(dx: Int, dy: Int) {
super.onScrolled(dx, dy) super.onScrolled(dx, dy)
// Scroll event occurred, need to update the dividers. // Scroll event occurred, need to update the dividers.

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2023 Auxio Project
* SortAdapter.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.list.sort
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemSortModeBinding
import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.FlexibleListAdapter
import org.oxycblt.auxio.util.inflater
class SortAdapter(var selectedMode: Sort.Mode) :
FlexibleListAdapter<Sort.Mode, SortModeViewHolder>(SortModeViewHolder.DIFF_CALLBACK) {
var currentlySelected = selectedMode
private set
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
SortModeViewHolder.from(parent)
override fun onBindViewHolder(holder: SortModeViewHolder, position: Int) {
throw NotImplementedError()
}
override fun onBindViewHolder(holder: SortModeViewHolder, position: Int, payload: List<Any>) {
val mode = getItem(position)
if (payload.isEmpty()) {
holder.bind(mode)
}
holder.setSelected(mode == currentlySelected)
}
fun setSelected(mode: Sort.Mode) {
if (mode == currentlySelected) return
val oldMode = currentList.indexOf(currentlySelected)
val newMode = currentList.indexOf(mode)
currentlySelected = selectedMode
notifyItemChanged(oldMode, PAYLOAD_SELECTION_CHANGED)
notifyItemChanged(newMode, PAYLOAD_SELECTION_CHANGED)
}
private companion object {
val PAYLOAD_SELECTION_CHANGED = Any()
}
}
class SortModeViewHolder private constructor(private val binding: ItemSortModeBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(mode: Sort.Mode) {
// TODO: Add names to sort.mode
binding.sortRadio.text = mode.toString()
}
fun setSelected(selected: Boolean) {
binding.sortRadio.isChecked = selected
}
companion object {
fun from(parent: View) =
SortModeViewHolder(ItemSortModeBinding.inflate(parent.context.inflater))
val DIFF_CALLBACK =
object : DiffUtil.ItemCallback<Sort.Mode>() {
override fun areItemsTheSame(oldItem: Sort.Mode, newItem: Sort.Mode) =
oldItem == newItem
override fun areContentsTheSame(oldItem: Sort.Mode, newItem: Sort.Mode) =
oldItem == newItem
}
}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2023 Auxio Project
* SortDialog.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.list.sort
import android.os.Bundle
import android.view.LayoutInflater
import androidx.core.view.updatePadding
import org.oxycblt.auxio.databinding.DialogSortBinding
import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.UpdateInstructions
import org.oxycblt.auxio.ui.ViewBindingBottomSheetDialogFragment
import org.oxycblt.auxio.util.systemBarInsetsCompat
class SortDialog : ViewBindingBottomSheetDialogFragment<DialogSortBinding>() {
private val sortAdapter = SortAdapter(Sort.Mode.ByName)
override fun onCreateBinding(inflater: LayoutInflater) = DialogSortBinding.inflate(inflater)
override fun onBindingCreated(binding: DialogSortBinding, savedInstanceState: Bundle?) {
super.onBindingCreated(binding, savedInstanceState)
binding.root.setOnApplyWindowInsetsListener { v, insets ->
v.updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
insets
}
binding.sortModeRecycler.adapter = sortAdapter
sortAdapter.update(listOf(Sort.Mode.ByName, Sort.Mode.ByDate), UpdateInstructions.Diff)
}
}

View file

@ -13,7 +13,7 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView <com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/menu_handle" android:id="@+id/menu_handle"
@ -70,7 +70,7 @@
tools:text="Info A" /> tools:text="Info A" />
<com.google.android.material.divider.MaterialDivider <com.google.android.material.divider.MaterialDivider
android:id="@+id/menu_divider" android:id="@+id/menu_mode_group"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium" android:layout_marginTop="@dimen/spacing_medium"
@ -85,6 +85,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:overScrollMode="never" android:overScrollMode="never"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/menu_divider" app:layout_constraintTop_toBottomOf="@+id/menu_mode_group"
tools:listitem="@layout/item_menu_option" /> tools:listitem="@layout/item_menu_option" />
</LinearLayout> </LinearLayout>

View file

@ -27,7 +27,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large" android:layout_marginStart="@dimen/spacing_large"
android:layout_marginTop="@dimen/spacing_small" android:layout_marginTop="@dimen/spacing_tiny"
android:layout_marginEnd="@dimen/spacing_large" android:layout_marginEnd="@dimen/spacing_large"
android:gravity="center" android:gravity="center"
app:layout_constraintTop_toBottomOf="@+id/dirs_mode_header" app:layout_constraintTop_toBottomOf="@+id/dirs_mode_header"

View file

@ -0,0 +1,112 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/menu_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--
Required to use a LinearLayout here for space allocation to stop the BottomSheetDialog
from flipping out and not allowing the RecyclerView to scroll fully.
-->
<TextView
android:id="@+id/sort_name"
style="@style/Widget.Auxio.TextView.Primary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/spacing_medium"
android:text="Sort By"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<org.oxycblt.auxio.list.recycler.DialogRecyclerView
android:id="@+id/sort_mode_recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
style="@style/Widget.Auxio.RecyclerView.Linear"
tools:listitem="@layout/item_sort_mode" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/dirs_mode_header"
style="@style/Widget.Auxio.TextView.Header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Direction"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/folder_mode_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_tiny"
android:gravity="center"
android:layout_marginHorizontal="@dimen/spacing_medium"
app:checkedButton="@+id/dirs_mode_exclude"
app:layout_constraintTop_toBottomOf="@+id/dirs_mode_header"
app:selectionRequired="true"
app:singleSelection="true"
tools:layout_editor_absoluteX="24dp">
<org.oxycblt.auxio.ui.RippleFixMaterialButton
android:id="@+id/dirs_mode_exclude"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/lbl_sort_asc"
tools:icon="@drawable/ic_check_24" />
<org.oxycblt.auxio.ui.RippleFixMaterialButton
android:id="@+id/dirs_mode_include"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/lbl_sort_dec" />
</com.google.android.material.button.MaterialButtonToggleGroup>
<org.oxycblt.auxio.ui.RippleFixMaterialButton
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_small"
android:text="@string/lbl_cancel"
app:layout_constraintBottom_toBottomOf="@+id/sort_save"
app:layout_constraintEnd_toStartOf="@+id/sort_save"
app:layout_constraintTop_toTopOf="@+id/sort_save" />
<org.oxycblt.auxio.ui.RippleFixMaterialButton
android:id="@+id/sort_save"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_mid_medium"
android:layout_marginTop="@dimen/spacing_mid_medium"
android:text="@string/lbl_ok"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/folder_mode_group" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View file

@ -0,0 +1,29 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:paddingTop="@dimen/spacing_tiny"
android:paddingBottom="@dimen/spacing_tiny">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/sort_radio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_mid_medium"
android:layout_marginEnd="@dimen/spacing_mid_medium"
android:clickable="false"
android:focusable="false"
android:drawableTint="?attr/colorControlNormal"
android:paddingStart="@dimen/spacing_medium"
android:textAlignment="viewStart"
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
tools:ignore="RtlSymmetry,contentDescription"
tools:text="Name" />
</FrameLayout>

View file

@ -162,6 +162,9 @@
<action <action
android:id="@+id/play_from_genre" android:id="@+id/play_from_genre"
app:destination="@id/play_from_genre_dialog" /> app:destination="@id/play_from_genre_dialog" />
<action
android:id="@+id/sort"
app:destination="@id/sort_dialog" />
</fragment> </fragment>
<fragment <fragment
@ -388,4 +391,10 @@
android:name="parcel" android:name="parcel"
app:argType="org.oxycblt.auxio.list.Menu$ForPlaylist$Parcel" /> app:argType="org.oxycblt.auxio.list.Menu$ForPlaylist$Parcel" />
</dialog> </dialog>
<dialog
android:id="@+id/sort_dialog"
android:name="org.oxycblt.auxio.list.sort.SortDialog"
android:label="sort_dialog"
tools:layout="@layout/dialog_sort" />
</navigation> </navigation>