Update UI

This commit is contained in:
Tommaso Berlose 2021-01-09 00:24:05 +01:00
parent c1d14f93bf
commit d32f680519
11 changed files with 187 additions and 110 deletions

View File

@ -1,11 +1,13 @@
package com.tommasoberlose.anotherwidget package com.tommasoberlose.anotherwidget
import android.Manifest
import android.app.Application import android.app.Application
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import com.chibatching.kotpref.Kotpref import com.chibatching.kotpref.Kotpref
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import net.danlew.android.joda.JodaTimeAndroid import net.danlew.android.joda.JodaTimeAndroid

View File

@ -22,6 +22,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.ui.activities.tabs.WeatherProviderActivity import com.tommasoberlose.anotherwidget.ui.activities.tabs.WeatherProviderActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@ -131,4 +132,12 @@ class MainActivity : AppCompatActivity() {
}) })
.check() .check()
} }
override fun onResume() {
super.onResume()
if (Preferences.showEvents && !checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
Preferences.showEvents = false
}
}
} }

View File

@ -59,7 +59,9 @@ class GlanceTabFragment : Fragment() {
private var dialog: GlanceSettingsDialog? = null private var dialog: GlanceSettingsDialog? = null
private lateinit var adapter: SlimAdapter private lateinit var adapter: SlimAdapter
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
private lateinit var list: ArrayList<Constants.GlanceProviderId> private val list: ArrayList<Constants.GlanceProviderId> by lazy {
GlanceProviderHelper.getGlanceProviders(requireContext())
}
private lateinit var binding: FragmentTabGlanceBinding private lateinit var binding: FragmentTabGlanceBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -81,8 +83,6 @@ class GlanceTabFragment : Fragment() {
binding.lifecycleOwner = this binding.lifecycleOwner = this
binding.viewModel = viewModel binding.viewModel = viewModel
list = GlanceProviderHelper.getGlanceProviders(requireContext())
return binding.root return binding.root
} }
@ -96,6 +96,10 @@ class GlanceTabFragment : Fragment() {
adapter = SlimAdapter.create() adapter = SlimAdapter.create()
adapter adapter
.register<String>(R.layout.glance_providers_list_ornament) { item, injector ->
injector.visibility(R.id.footer, if(item == "footer") View.VISIBLE else View.GONE)
injector.visibility(R.id.header, if(item == "header") View.VISIBLE else View.GONE)
}
.register<GlanceProvider>(R.layout.glance_provider_item) { item, injector -> .register<GlanceProvider>(R.layout.glance_provider_item) { item, injector ->
val provider = Constants.GlanceProviderId.from(item.id)!! val provider = Constants.GlanceProviderId.from(item.id)!!
injector injector
@ -212,8 +216,8 @@ class GlanceTabFragment : Fragment() {
} }
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> { Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context) val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
if (GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission( if (GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(
Manifest.permission.ACTIVITY_RECOGNITION) == true) Manifest.permission.ACTIVITY_RECOGNITION))
) { ) {
injector.text(R.id.label, injector.text(R.id.label,
if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString( if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(
@ -296,7 +300,7 @@ class GlanceTabFragment : Fragment() {
GlanceProviderHelper.saveGlanceProviderOrder( GlanceProviderHelper.saveGlanceProviderOrder(
list list
) )
adapter.updateData(list.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) }) adapter.updateData(listOf("header") + list.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) } + listOf("footer"))
} }
override fun onChildDraw( override fun onChildDraw(
@ -339,7 +343,6 @@ class GlanceTabFragment : Fragment() {
}) })
mIth.attachToRecyclerView(binding.providersList) mIth.attachToRecyclerView(binding.providersList)
adapter.updateData(list.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) })
binding.providersList.isNestedScrollingEnabled = false binding.providersList.isNestedScrollingEnabled = false
setupListener() setupListener()
@ -347,6 +350,9 @@ class GlanceTabFragment : Fragment() {
binding.scrollView.viewTreeObserver.addOnScrollChangedListener { binding.scrollView.viewTreeObserver.addOnScrollChangedListener {
viewModel.fragmentScrollY.value = binding.scrollView.scrollY viewModel.fragmentScrollY.value = binding.scrollView.scrollY
} }
adapter.updateData(listOf("header") + list.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) } + listOf("footer"))
} }
private fun subscribeUi( private fun subscribeUi(
@ -365,7 +371,7 @@ class GlanceTabFragment : Fragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, requireActivity().registerReceiver(nextAlarmChangeBroadcastReceiver,
IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
if (dialog != null) { if (dialog != null) {
dialog?.show() dialog?.show()
@ -373,7 +379,7 @@ class GlanceTabFragment : Fragment() {
} }
override fun onStop() { override fun onStop() {
activity?.unregisterReceiver(nextAlarmChangeBroadcastReceiver) requireActivity().unregisterReceiver(nextAlarmChangeBroadcastReceiver)
super.onStop() super.onStop()
} }
@ -430,7 +436,7 @@ class GlanceTabFragment : Fragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
adapter.notifyItemRangeChanged(0, adapter.data.size) adapter.notifyItemRangeChanged(0, adapter.data?.size ?: 0)
if (dialog != null) { if (dialog != null) {
dialog?.show() dialog?.show()
} }

View File

@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
@ -81,17 +82,17 @@ class PreferencesFragment : Fragment() {
viewModel.showEvents.observe(viewLifecycleOwner) { viewModel.showEvents.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.showEventsSwitch.setCheckedImmediatelyNoEvent(it)
if (it) { if (it) {
CalendarHelper.setEventUpdatesAndroidN(requireContext()) CalendarHelper.setEventUpdatesAndroidN(requireContext())
} else { } else {
CalendarHelper.removeEventUpdatesAndroidN(requireContext()) CalendarHelper.removeEventUpdatesAndroidN(requireContext())
} }
} }
checkReadEventsPermission()
} }
viewModel.showWeather.observe(viewLifecycleOwner) { viewModel.showWeather.observe(viewLifecycleOwner) {
checkLocationPermission() checkWeatherProviderConfig()
} }
viewModel.showClock.observe(viewLifecycleOwner) { viewModel.showClock.observe(viewLifecycleOwner) {
@ -113,9 +114,13 @@ class PreferencesFragment : Fragment() {
} }
binding.showEventsSwitch.setOnCheckedChangeListener { _, enabled: Boolean -> binding.showEventsSwitch.setOnCheckedChangeListener { _, enabled: Boolean ->
Preferences.showEvents = enabled if (enabled) {
if (Preferences.showEvents) { if (!requireActivity().checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
requirePermission() binding.showEventsSwitch.setCheckedImmediatelyNoEvent(false)
}
requireCalendarPermission()
} else {
Preferences.showEvents = enabled
} }
} }
@ -125,6 +130,11 @@ class PreferencesFragment : Fragment() {
binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean -> binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean ->
Preferences.showWeather = enabled Preferences.showWeather = enabled
if (enabled) {
WeatherReceiver.setUpdates(requireContext())
} else {
WeatherReceiver.removeUpdates(requireContext())
}
} }
binding.actionShowClock.setOnClickListener { binding.actionShowClock.setOnClickListener {
@ -144,29 +154,17 @@ class PreferencesFragment : Fragment() {
} }
} }
private fun checkReadEventsPermission(showEvents: Boolean = Preferences.showEvents) { private fun requireCalendarPermission() {
if (activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) == true) {
} else {
}
}
private fun updateCalendar() {
if (activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) == true) {
CalendarHelper.updateEventList(requireContext())
}
}
private fun requirePermission() {
Dexter.withContext(requireContext()) Dexter.withContext(requireContext())
.withPermissions( .withPermissions(
Manifest.permission.READ_CALENDAR Manifest.permission.READ_CALENDAR
).withListener(object: MultiplePermissionsListener { ).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) { override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let { report?.let {
if (report.areAllPermissionsGranted()){ val granted = report.areAllPermissionsGranted()
checkReadEventsPermission() Preferences.showEvents = granted
} else { if (granted) {
Preferences.showEvents = false CalendarHelper.updateEventList(requireContext())
} }
} }
} }
@ -182,16 +180,20 @@ class PreferencesFragment : Fragment() {
.check() .check()
} }
private fun checkLocationPermission() { private fun checkWeatherProviderConfig() {
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) { if (Preferences.showWeather && Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-" && !binding.weatherProviderError.isVisible) {
WeatherReceiver.setUpdates(requireContext()) binding.weatherProviderError.expand()
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") { } else {
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning)) binding.weatherProviderError.collapse()
.setPositiveButton(getString(android.R.string.ok)) {
requirePermission()
}
.show()
} }
binding.weatherProviderError.text = Preferences.weatherProviderError
if (Preferences.showWeather && Preferences.weatherProviderLocationError != "" && !binding.weatherProviderError.isVisible) {
binding.weatherProviderLocationError.expand()
} else {
binding.weatherProviderLocationError.collapse()
}
binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError
} }
private fun maintainScrollPosition(callback: () -> Unit) { private fun maintainScrollPosition(callback: () -> Unit) {

View File

@ -141,11 +141,7 @@ class WeatherFragment : Fragment() {
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") { } else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
binding.locationPermissionAlert.isVisible = true binding.locationPermissionAlert.isVisible = true
binding.locationPermissionAlert.setOnClickListener { binding.locationPermissionAlert.setOnClickListener {
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning)) requirePermission()
.setPositiveButton(getString(android.R.string.ok)) {
requirePermission()
}
.show()
} }
} else { } else {
binding.locationPermissionAlert.isVisible = false binding.locationPermissionAlert.isVisible = false
@ -169,7 +165,6 @@ class WeatherFragment : Fragment() {
} }
private fun setupListener() { private fun setupListener() {
binding.actionWeatherProvider.setOnClickListener { binding.actionWeatherProvider.setOnClickListener {
startActivityForResult( startActivityForResult(
Intent(requireContext(), WeatherProviderActivity::class.java), Intent(requireContext(), WeatherProviderActivity::class.java),

View File

@ -0,0 +1,26 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400">
<translate
android:fromYDelta="-20%"
android:toYDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<scale
android:fromXScale="105%"
android:fromYScale="105%"
android:toXScale="100%"
android:toYScale="100%"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/decelerate_interpolator"
/>
</set>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:delay="15%"
android:animationOrder="normal"
/>

View File

@ -76,7 +76,6 @@
android:id="@+id/preview" android:id="@+id/preview"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
app:cardBackgroundColor="@color/colorPrimary" app:cardBackgroundColor="@color/colorPrimary"
android:layout_marginBottom="4dp"
app:cardCornerRadius="0dp" app:cardCornerRadius="0dp"
app:cardElevation="0dp"> app:cardElevation="0dp">
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView

View File

@ -270,6 +270,35 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title" style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_weather_title"/> android:text="@string/settings_weather_title"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:textSize="14sp"
android:paddingStart="64dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:visibility="gone"
android:id="@+id/weather_provider_error"
android:textColor="@color/errorColorText"
android:letterSpacing="0"
android:fontFamily="@font/google_sans_bold"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.MaterialComponents.Button"
app:textAllCaps="false" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:textSize="14sp"
android:id="@+id/weather_provider_location_error"
android:textColor="@color/errorColorText"
android:letterSpacing="0"
android:fontFamily="@font/google_sans_bold"
android:textStyle="bold"
android:layout_marginStart="64dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Button"
app:textAllCaps="false" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="1dp" android:layout_width="1dp"

View File

@ -15,70 +15,15 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/scrollView" android:id="@+id/scrollView"
android:scrollbarThumbVertical="@color/colorPrimary"> android:scrollbarThumbVertical="@color/colorPrimary">
<LinearLayout <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_weight="1"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="8dp" android:paddingTop="8dp"
android:paddingBottom="48dp" android:paddingBottom="48dp"
android:orientation="vertical"> android:layoutAnimation="@anim/layout_animation_fall_down"
<LinearLayout android:id="@+id/providers_list" />
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/calendar_settings"
android:alpha="@{isGlanceVisible ? 1f : 1f, default=1}"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/providers"
android:paddingTop="16dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:textAppearance="@style/AnotherWidget.Settings.Header" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_marginBottom="16dp"
android:text="@string/settings_sort_glance_providers_subtitle"
android:textAppearance="@style/AnotherWidget.Settings.SubHeader"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingBottom="8dp"
android:id="@+id/providers_list" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="24dp"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/outline_info_24"
app:tint="@color/colorSecondaryText"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:layout_marginTop="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="@string/glance_info"
android:textColor="@color/colorSecondaryText"
android:letterSpacing="0"
android:fontFamily="@font/google_sans"
android:textAppearance="@style/AnotherWidget.Settings.Subtitle"
app:textAllCaps="false" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.tommasoberlose.anotherwidget.components.FixedFocusScrollView> </com.tommasoberlose.anotherwidget.components.FixedFocusScrollView>
</layout> </layout>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/header"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/providers"
android:paddingTop="16dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:textAppearance="@style/AnotherWidget.Settings.Header" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_marginBottom="16dp"
android:text="@string/settings_sort_glance_providers_subtitle"
android:textAppearance="@style/AnotherWidget.Settings.SubHeader"/>
</LinearLayout>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/footer"
android:padding="8dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="24dp"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/outline_info_24"
app:tint="@color/colorSecondaryText"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:layout_marginTop="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="@string/glance_info"
android:textColor="@color/colorSecondaryText"
android:letterSpacing="0"
android:fontFamily="@font/google_sans"
android:textAppearance="@style/AnotherWidget.Settings.Subtitle"
app:textAllCaps="false" />
</LinearLayout>
</LinearLayout>