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

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

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

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

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

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

@ -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>

@ -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"
/>

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

@ -270,6 +270,35 @@
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.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
android:layout_width="1dp"

@ -15,70 +15,15 @@
android:layout_height="match_parent"
android:id="@+id/scrollView"
android:scrollbarThumbVertical="@color/colorPrimary">
<LinearLayout
<androidx.recyclerview.widget.RecyclerView
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:paddingBottom="48dp"
android:orientation="vertical">
<LinearLayout
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>
android:layoutAnimation="@anim/layout_animation_fall_down"
android:id="@+id/providers_list" />
</com.tommasoberlose.anotherwidget.components.FixedFocusScrollView>
</layout>

@ -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>