Merge crud-device

This commit is contained in:
Tommaso Berlose 2020-05-09 17:58:03 +02:00
parent 97d1caeabc
commit 26428b65da
199 changed files with 523 additions and 190 deletions

Binary file not shown.

View File

@ -18,7 +18,7 @@ android {
applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23
targetSdkVersion 29
versionCode 80
versionCode 81
versionName "2.0.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Binary file not shown.

View File

@ -1,6 +1,7 @@
package com.tommasoberlose.anotherwidget.db
import android.content.Context
import android.util.Log
import com.chibatching.kotpref.bulk
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.models.Event
@ -43,15 +44,18 @@ class EventRepository(val context: Context) {
fun getNextEvent(): Event? {
val nextEvent = getEventByEventId(Preferences.nextEventId)
return if (nextEvent != null && nextEvent.endDate > Calendar.getInstance().timeInMillis + 60 * 1000) {
return if (nextEvent != null && nextEvent.endDate > Calendar.getInstance().timeInMillis) {
nextEvent
} else {
val events = getEvents()
if (events.isNotEmpty())
events.first()
else
if (events.isNotEmpty()) {
val newNextEvent = events.first()
Preferences.nextEventId = newNextEvent!!.eventID
newNextEvent
} else {
resetNextEventData()
null
}
}
}
@ -59,7 +63,6 @@ class EventRepository(val context: Context) {
fun goToNextEvent() {
val eventList = getEvents()
if (eventList.isNotEmpty()) {
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
if (index > -1 && index < eventList.size - 1) {
@ -76,7 +79,6 @@ class EventRepository(val context: Context) {
fun goToPreviousEvent() {
val eventList = getEvents()
if (eventList.isNotEmpty()) {
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
if (index > 0) {
@ -91,7 +93,14 @@ class EventRepository(val context: Context) {
MainWidget.updateWidget(context)
}
fun getEvents(): RealmResults<Event> = realm.where(Event::class.java).greaterThan("endDate", Calendar.getInstance().timeInMillis + 60 * 1000).findAll()
fun getEvents(): RealmResults<Event> {
val now = Calendar.getInstance().timeInMillis
val list = realm.where(Event::class.java).greaterThan("endDate", now).findAll()
realm.executeTransactionAsync {
it.where(Event::class.java).lessThanOrEqualTo("endDate", now).findAll().deleteAllFromRealm()
}
return list
}
fun getEventsCount(): Int = getEvents().size
}

View File

@ -14,4 +14,12 @@ object Constants {
MEDIUM(2),
LARGE(3)
}
enum class GlanceProviderId(val id: String) {
PLAYING_SONG("PLAYING_SONG"),
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
// BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
// CUSTOM_INFO("CUSTOM_INFO"),
// GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
}
}

View File

@ -76,6 +76,7 @@ object Preferences : KotprefModel() {
// Glance
var showGlance by booleanPref(default = true)
var enabledGlanceProviderOrder by stringPref(default = "")
var customInfo by stringPref(default = "")
var showNextAlarm by booleanPref(default = false)
var isBatteryLevelLow by booleanPref(default = false)

View File

@ -0,0 +1,76 @@
package com.tommasoberlose.anotherwidget.helpers
import android.content.Context
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.models.GlanceProvider
import java.util.ArrayList
object GlanceProviderHelper {
fun getGlanceProviders(): ArrayList<Constants.GlanceProviderId> {
val enabledProviders = Preferences.enabledGlanceProviderOrder.split(",").filter { it != "" }
val providers = Constants.GlanceProviderId.values()
providers.sortWith(Comparator { p1, p2 ->
when {
enabledProviders.contains(p1.id) && enabledProviders.contains(p2.id) -> {
enabledProviders.indexOf(p1.id).compareTo(enabledProviders.indexOf(p2.id))
}
enabledProviders.contains(p1.id) -> {
-1
}
enabledProviders.contains(p2.id) -> {
1
}
else -> {
p1.id.compareTo(p2.id)
}
}
})
return ArrayList(providers.toList())
}
fun getGlanceProviderById(context: Context, providerId: Constants.GlanceProviderId): GlanceProvider? {
return when(providerId) {
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_next_alarm_title),
R.drawable.round_alarm,
context.getString(R.string.settings_show_next_alarm_subtitle)
)
}
Constants.GlanceProviderId.PLAYING_SONG -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_music_title),
R.drawable.round_music_note,
context.getString(R.string.settings_show_music_enabled_subtitle)
)
}
// Constants.GlanceProviderId.CUSTOM_INFO -> {
// GlanceProvider(providerId.id,
// context.getString(R.string.settings_show_next_alarm_title),
// R.drawable.round_event_note
// )
// }
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
// GlanceProvider(providerId.id,
// context.getString(R.string.settings_show_next_alarm_title),
// R.drawable.round_battery_charging_full
// )
// }
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
// GlanceProvider(providerId.id,
// context.getString(R.string.settings_show_next_alarm_title),
// R.drawable.round_directions_walk
// )
// }
else -> null
}
}
fun saveGlanceProviderOrder(list: ArrayList<Constants.GlanceProviderId>) {
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
}
}

View File

@ -0,0 +1,12 @@
package com.tommasoberlose.anotherwidget.models
class GlanceProvider(
val id: String,
val title: String,
val icon: Int,
val label: String = "",
val enabled: Boolean = false,
val isPermissionRequired: Boolean = false,
val isPermissionGranted: (() -> Boolean)? = null,
val requestPermission: (() -> Unit)? = null
)

View File

@ -32,7 +32,6 @@ class UpdatesReceiver : BroadcastReceiver() {
Intent.ACTION_DATE_CHANGED,
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
Actions.ACTION_TIME_UPDATE -> {
Log.d("ciao", "arrivata notifica")
MainWidget.updateWidget(context)
if (intent.hasExtra(EVENT_ID)) {
setUpdates(context, intent.getLongExtra(EVENT_ID, -1))
@ -69,7 +68,6 @@ class UpdatesReceiver : BroadcastReceiver() {
val diff = Period(now.timeInMillis, event.startDate)
if (event.startDate > now.timeInMillis) {
// Update the widget every hour till the event
Log.d("ciao", "${event.title} hours: ${diff.hours} - ${diff.minutes}")
setExactAndAllowWhileIdle(
AlarmManager.RTC,
if (event.startDate - diff.hours * 1000 * 60 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - diff.hours * 1000 * 60 * 60 else now.timeInMillis + 120000,
@ -85,10 +83,6 @@ class UpdatesReceiver : BroadcastReceiver() {
)
} else {
// Update the widget one second after the event is finished
Log.d(
"ciao",
"${event.title} end: ${Date(if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000)}"
)
val fireTime =
if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000
setExactAndAllowWhileIdle(

View File

@ -10,26 +10,36 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.models.GlanceProvider
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.android.synthetic.main.fragment_glance_settings.scrollView
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.lang.Exception
import net.idik.lib.slimadapter.SlimAdapter
import java.util.*
class GlanceTabFragment : Fragment() {
@ -38,6 +48,7 @@ class GlanceTabFragment : Fragment() {
}
private lateinit var viewModel: MainViewModel
private lateinit var adapter: SlimAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -62,6 +73,65 @@ class GlanceTabFragment : Fragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
list.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(requireContext())
list.layoutManager = mLayoutManager
adapter = SlimAdapter.create()
adapter
.register<String>(R.layout.glance_provider_item) { item, injector ->
injector
.text(R.id.title, item)
}
.register<GlanceProvider>(R.layout.glance_provider_item) { item, injector ->
injector
.text(R.id.title, item.title)
.with<ImageView>(R.id.icon) {
it.setImageDrawable(ContextCompat.getDrawable(requireContext(), item.icon))
}
.with<TextView>(R.id.label) {
it.isVisible = item.label != ""
it.text = item.label
}
}
.attachTo(list)
adapter.updateData(
GlanceProviderHelper.getGlanceProviders()
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) }
)
val mIth = ItemTouchHelper(
object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
ItemTouchHelper.LEFT
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: ViewHolder, target: ViewHolder
): Boolean {
val fromPos = viewHolder.adapterPosition
val toPos = target.adapterPosition
// move item in `fromPos` to `toPos` in adapter.
adapter.notifyItemMoved(fromPos, toPos)
val list = GlanceProviderHelper.getGlanceProviders()
Collections.swap(list, fromPos, toPos)
GlanceProviderHelper.saveGlanceProviderOrder(list)
return true
}
override fun onSwiped(
viewHolder: ViewHolder,
direction: Int
) {
// remove from adapter
}
})
mIth.attachToRecyclerView(list)
setupListener()
updateNextAlarmWarningUi()
}
@ -71,29 +141,57 @@ class GlanceTabFragment : Fragment() {
viewModel: MainViewModel
) {
// viewModel.showMusic.observe(viewLifecycleOwner, Observer {
// checkNotificationPermission()
// })
//
// viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
// updateNextAlarmWarningUi()
// })
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
binding.isGlanceVisible = it
})
viewModel.showMusic.observe(viewLifecycleOwner, Observer {
checkNotificationPermission()
})
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
updateNextAlarmWarningUi()
})
}
private fun setupListener() {
// action_show_music.setOnClickListener {
// Preferences.showMusic = !Preferences.showMusic
// }
//
// action_show_next_alarm.setOnClickListener {
// BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
// .addItem(getString(R.string.settings_visible), true)
// .addItem(getString(R.string.settings_not_visible), false)
// .addOnSelectItemListener { value ->
// Preferences.showNextAlarm = value
// }.show()
// }
action_show_glance.setOnClickListener {
Preferences.showGlance = !Preferences.showGlance
}
show_glance_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
Preferences.showGlance = enabled
}
action_show_music.setOnClickListener {
if (Preferences.showGlance) {
BottomSheetMenu<Boolean>(
requireContext(),
header = getString(R.string.settings_show_music_title)
).setSelectedValue(Preferences.showMusic)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showMusic = value
}.show()
}
}
action_show_next_alarm.setOnClickListener {
if (Preferences.showGlance) {
BottomSheetMenu<Boolean>(
requireContext(),
header = getString(R.string.settings_show_next_alarm_title)
).setSelectedValue(Preferences.showNextAlarm)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showNextAlarm = value
}.show()
}
}
}
private fun updateNextAlarmWarningUi() {
@ -106,7 +204,10 @@ class GlanceTabFragment : Fragment() {
} catch (e: Exception) {
alarm.showIntent?.creatorPackage ?: ""
}
show_next_alarm_warning.text = getString(R.string.next_alarm_warning).format(appNameOrPackage)
maintainScrollPosition {
show_next_alarm_warning.text =
getString(R.string.next_alarm_warning).format(appNameOrPackage)
}
} else {
maintainScrollPosition {
show_next_alarm_label?.text = if (Preferences.showNextAlarm) getString(R.string.settings_visible) else getString(

View File

@ -242,8 +242,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}.start()
}
widget_loader.animate().scaleX(0f).scaleY(0f).alpha(0f).setDuration(200L).start()
bitmap_container.setImageBitmap(bitmap)
widget_loader.animate().scaleX(0f).scaleY(0f).start()
widget.animate().alpha(1f).start()
}
}

View File

@ -54,6 +54,8 @@ class MainViewModel : ViewModel() {
// Glance
val showGlance = Preferences.asLiveData(Preferences::showGlance)
val showMusic = Preferences.asLiveData(Preferences::showMusic)
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
// Advanced Settings
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Some files were not shown because too many files have changed in this diff Show More