Migrate calendar widget settings
This commit is contained in:
parent
5834e7e8c4
commit
a5cb2e3314
@ -5,7 +5,6 @@ import android.os.Bundle
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import de.mm20.launcher2.fragment.PreferencesCalendarFragment
|
|
||||||
import de.mm20.launcher2.fragment.PreferencesMainFragment
|
import de.mm20.launcher2.fragment.PreferencesMainFragment
|
||||||
import de.mm20.launcher2.fragment.PreferencesServicesFragment
|
import de.mm20.launcher2.fragment.PreferencesServicesFragment
|
||||||
import de.mm20.launcher2.fragment.PreferencesWeatherFragment
|
import de.mm20.launcher2.fragment.PreferencesWeatherFragment
|
||||||
@ -31,7 +30,6 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun getStartFragment(): Fragment {
|
private fun getStartFragment(): Fragment {
|
||||||
return when (intent.extras?.getString(FRAGMENT, "")) {
|
return when (intent.extras?.getString(FRAGMENT, "")) {
|
||||||
FRAGMENT_CALENDAR -> PreferencesCalendarFragment()
|
|
||||||
FRAGMENT_WEATHER -> PreferencesWeatherFragment()
|
FRAGMENT_WEATHER -> PreferencesWeatherFragment()
|
||||||
FRAGMENT_SERVICES -> PreferencesServicesFragment()
|
FRAGMENT_SERVICES -> PreferencesServicesFragment()
|
||||||
else -> PreferencesMainFragment()
|
else -> PreferencesMainFragment()
|
||||||
|
|||||||
@ -1,121 +0,0 @@
|
|||||||
package de.mm20.launcher2.fragment
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.widget.CheckBox
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.ScrollView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.app.ActivityCompat
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.setPadding
|
|
||||||
import androidx.preference.Preference
|
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
|
||||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
|
||||||
import com.afollestad.materialdialogs.customview.customView
|
|
||||||
import de.mm20.launcher2.R
|
|
||||||
import de.mm20.launcher2.ktx.checkPermission
|
|
||||||
import de.mm20.launcher2.ktx.dp
|
|
||||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
|
||||||
import de.mm20.launcher2.search.data.CalendarEvent
|
|
||||||
import de.mm20.launcher2.search.data.UserCalendar
|
|
||||||
|
|
||||||
class PreferencesCalendarFragment : PreferenceFragmentCompat() {
|
|
||||||
|
|
||||||
private var hasCalendarPermission = false
|
|
||||||
private val calendars = mutableListOf<UserCalendar>()
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
||||||
addPreferencesFromResource(R.xml.preferences_calendar)
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun init(requestPermission: Boolean = true) {
|
|
||||||
val context = context ?: return
|
|
||||||
hasCalendarPermission = context.checkPermission(Manifest.permission.READ_CALENDAR)
|
|
||||||
if (hasCalendarPermission) {
|
|
||||||
calendars.clear()
|
|
||||||
calendars.addAll(CalendarEvent.getCalendars(context))
|
|
||||||
val unselectedCalendars = LauncherPreferences.instance.unselectedCalendars.toMutableList()
|
|
||||||
findPreference<Preference>("calendar_calendars")?.apply {
|
|
||||||
var count = calendars.size - unselectedCalendars.size
|
|
||||||
summary = resources.getQuantityString(R.plurals.preference_calendar_calendars_summary, count, count)
|
|
||||||
isEnabled = true
|
|
||||||
setOnPreferenceClickListener {
|
|
||||||
val sheetView = LinearLayout(activity)
|
|
||||||
sheetView.setPadding((8 * context.dp).toInt())
|
|
||||||
sheetView.orientation = LinearLayout.VERTICAL
|
|
||||||
sheetView.setBackgroundColor(ContextCompat.getColor(context, R.color.bottom_sheet))
|
|
||||||
var owner = ""
|
|
||||||
val padding = (8 * context.dp).toInt()
|
|
||||||
for (c in calendars) {
|
|
||||||
if (owner != c.owner) {
|
|
||||||
owner = c.owner
|
|
||||||
val text = TextView(activity)
|
|
||||||
text.setTextColor(ContextCompat.getColor(context, R.color.text_color_secondary_normal))
|
|
||||||
text.setPadding(padding, 2 * padding, padding, padding)
|
|
||||||
text.text = owner
|
|
||||||
sheetView.addView(text)
|
|
||||||
}
|
|
||||||
val checkbox = CheckBox(activity)
|
|
||||||
checkbox.text = c.name
|
|
||||||
checkbox.buttonTintList = ColorStateList.valueOf(CalendarEvent.getDisplayColor(context, c.color))
|
|
||||||
checkbox.setPadding(padding)
|
|
||||||
checkbox.isChecked = !unselectedCalendars.contains(c.id)
|
|
||||||
checkbox.setOnCheckedChangeListener { _, checked ->
|
|
||||||
if (checked) {
|
|
||||||
unselectedCalendars.remove(c.id)
|
|
||||||
} else {
|
|
||||||
unselectedCalendars.add(c.id)
|
|
||||||
}
|
|
||||||
LauncherPreferences.instance.unselectedCalendars = unselectedCalendars
|
|
||||||
count = calendars.size - unselectedCalendars.size
|
|
||||||
summary = resources.getQuantityString(R.plurals.preference_calendar_calendars_summary, count, count)
|
|
||||||
}
|
|
||||||
sheetView.addView(checkbox)
|
|
||||||
}
|
|
||||||
val scrollView = ScrollView(context)
|
|
||||||
scrollView.isNestedScrollingEnabled = true
|
|
||||||
scrollView.addView(sheetView)
|
|
||||||
MaterialDialog(context, BottomSheet()).show {
|
|
||||||
customView(view = scrollView)
|
|
||||||
title(R.string.preference_calendar_calendars)
|
|
||||||
.negativeButton(R.string.close) {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (requestPermission) {
|
|
||||||
ActivityCompat.requestPermissions(
|
|
||||||
requireActivity(),
|
|
||||||
arrayOf(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR),
|
|
||||||
0)
|
|
||||||
}
|
|
||||||
findPreference<Preference>("calendar_calendars")?.apply {
|
|
||||||
isEnabled = false
|
|
||||||
setSummary(R.string.preference_permission_denied)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
(activity as AppCompatActivity).supportActionBar?.setTitle(R.string.preference_screen_calendarwidget)
|
|
||||||
hasCalendarPermission = requireActivity().checkPermission(Manifest.permission.READ_CALENDAR)
|
|
||||||
&& requireActivity().checkPermission(Manifest.permission.WRITE_CALENDAR)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
|
||||||
init(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -34,10 +34,6 @@ class PreferencesMainFragment : PreferenceFragmentCompat() {
|
|||||||
setSettingsScreen(PreferencesSearchFragment())
|
setSettingsScreen(PreferencesSearchFragment())
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
findPreference<Preference>("screen_calendar")?.setOnPreferenceClickListener {
|
|
||||||
setSettingsScreen(PreferencesCalendarFragment())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
findPreference<Preference>("screen_badges")?.setOnPreferenceClickListener {
|
findPreference<Preference>("screen_badges")?.setOnPreferenceClickListener {
|
||||||
setSettingsScreen(PreferencesBadgesFragment())
|
setSettingsScreen(PreferencesBadgesFragment())
|
||||||
true
|
true
|
||||||
|
|||||||
@ -1,22 +1,21 @@
|
|||||||
package de.mm20.launcher2.calendar
|
package de.mm20.launcher2.calendar
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import androidx.core.database.getStringOrNull
|
import androidx.core.database.getStringOrNull
|
||||||
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
||||||
|
import de.mm20.launcher2.ktx.checkPermission
|
||||||
import de.mm20.launcher2.permissions.PermissionGroup
|
import de.mm20.launcher2.permissions.PermissionGroup
|
||||||
import de.mm20.launcher2.permissions.PermissionsManager
|
import de.mm20.launcher2.permissions.PermissionsManager
|
||||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
|
||||||
import de.mm20.launcher2.search.data.CalendarEvent
|
import de.mm20.launcher2.search.data.CalendarEvent
|
||||||
|
import de.mm20.launcher2.search.data.UserCalendar
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
|
||||||
import kotlinx.coroutines.channels.trySendBlocking
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.get
|
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -24,6 +23,8 @@ interface CalendarRepository {
|
|||||||
fun search(query: String): Flow<List<CalendarEvent>>
|
fun search(query: String): Flow<List<CalendarEvent>>
|
||||||
|
|
||||||
fun getUpcomingEvents(): Flow<List<CalendarEvent>>
|
fun getUpcomingEvents(): Flow<List<CalendarEvent>>
|
||||||
|
|
||||||
|
suspend fun getCalendars(): List<UserCalendar>
|
||||||
}
|
}
|
||||||
|
|
||||||
class CalendarRepositoryImpl(
|
class CalendarRepositoryImpl(
|
||||||
@ -155,55 +156,59 @@ class CalendarRepositoryImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getUpcomingEvents(): Flow<List<CalendarEvent>> = channelFlow {
|
override fun getUpcomingEvents(): Flow<List<CalendarEvent>> = channelFlow {
|
||||||
val unselectedCalendars = callbackFlow {
|
dataStore.data.map { it.calendarWidget }.collectLatest { settings ->
|
||||||
val unregister =
|
hiddenItems.collectLatest { hidden ->
|
||||||
LauncherPreferences.instance.doOnPreferenceChange("unselected_calendars") {
|
val now = System.currentTimeMillis()
|
||||||
trySendBlocking(LauncherPreferences.instance.unselectedCalendars)
|
val end = now + 14 * 24 * 60 * 60 * 1000L
|
||||||
}
|
val events = withContext(Dispatchers.IO) {
|
||||||
trySendBlocking(LauncherPreferences.instance.unselectedCalendars)
|
queryCalendarEvents(
|
||||||
awaitClose {
|
query = "",
|
||||||
unregister()
|
intervalStart = now,
|
||||||
}
|
intervalEnd = end,
|
||||||
}
|
limit = 700,
|
||||||
|
excludeAllDayEvents = settings.hideAlldayEvents,
|
||||||
val hideAlldayEvents = callbackFlow {
|
excludeCalendars = settings.excludeCalendarsList
|
||||||
val unregister =
|
).filter {
|
||||||
LauncherPreferences.instance.doOnPreferenceChange("calendar_hide_allday") {
|
!hiddenItems.value.contains(it.key)
|
||||||
trySendBlocking(LauncherPreferences.instance.calendarHideAllday)
|
|
||||||
}
|
|
||||||
trySendBlocking(LauncherPreferences.instance.calendarHideAllday)
|
|
||||||
awaitClose {
|
|
||||||
unregister()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hideAlldayEvents.collectLatest { hideAllday ->
|
|
||||||
unselectedCalendars.collectLatest { unselected ->
|
|
||||||
hiddenItems.collectLatest { hidden ->
|
|
||||||
val now = System.currentTimeMillis()
|
|
||||||
val end = now + 14 * 24 * 60 * 60 * 1000L
|
|
||||||
val events = withContext(Dispatchers.IO) {
|
|
||||||
queryCalendarEvents(
|
|
||||||
query = "",
|
|
||||||
intervalStart = now,
|
|
||||||
intervalEnd = end,
|
|
||||||
limit = 700,
|
|
||||||
excludeAllDayEvents = hideAllday,
|
|
||||||
excludeCalendars = unselected
|
|
||||||
).filter {
|
|
||||||
!hiddenItems.value.contains(it.key)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
send(events)
|
|
||||||
}
|
}
|
||||||
|
send(events)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var unselectedCalendars: List<Long>
|
override suspend fun getCalendars(): List<UserCalendar> {
|
||||||
get() = LauncherPreferences.instance.unselectedCalendars
|
if (!permissionsManager.checkPermissionOnce(PermissionGroup.Calendar)) return emptyList()
|
||||||
set(value) {
|
return withContext(Dispatchers.IO) {
|
||||||
LauncherPreferences.instance.unselectedCalendars = value
|
val calendars = mutableListOf<UserCalendar>()
|
||||||
|
val uri = CalendarContract.Calendars.CONTENT_URI
|
||||||
|
val proj = arrayOf(
|
||||||
|
CalendarContract.Calendars._ID,
|
||||||
|
CalendarContract.Calendars.NAME,
|
||||||
|
CalendarContract.Calendars.ACCOUNT_NAME,
|
||||||
|
CalendarContract.Calendars.CALENDAR_COLOR,
|
||||||
|
CalendarContract.Calendars.VISIBLE,
|
||||||
|
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
|
||||||
|
)
|
||||||
|
val cursor = context.contentResolver.query(uri, proj, null, null, null)
|
||||||
|
?: return@withContext emptyList()
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
try {
|
||||||
|
calendars.add(
|
||||||
|
UserCalendar(
|
||||||
|
id = cursor.getLong(0),
|
||||||
|
name = cursor.getString(5) ?: cursor.getString(1) ?: "",
|
||||||
|
owner = cursor.getString(2),
|
||||||
|
color = cursor.getInt(3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} catch (e: NullPointerException) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.close()
|
||||||
|
calendars.sortBy { it.owner }
|
||||||
|
return@withContext calendars
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -79,41 +79,7 @@ class CalendarEvent(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object: KoinComponent {
|
companion object {
|
||||||
|
|
||||||
fun getCalendars(context: Context): List<UserCalendar> {
|
|
||||||
val calendars = mutableListOf<UserCalendar>()
|
|
||||||
val uri = CalendarContract.Calendars.CONTENT_URI
|
|
||||||
val proj = arrayOf(
|
|
||||||
CalendarContract.Calendars._ID,
|
|
||||||
CalendarContract.Calendars.NAME,
|
|
||||||
CalendarContract.Calendars.ACCOUNT_NAME,
|
|
||||||
CalendarContract.Calendars.CALENDAR_COLOR,
|
|
||||||
CalendarContract.Calendars.VISIBLE,
|
|
||||||
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
|
|
||||||
)
|
|
||||||
if (!context.checkPermission(Manifest.permission.READ_CALENDAR)) return calendars
|
|
||||||
val cursor = context.contentResolver.query(uri, proj, null, null, null)
|
|
||||||
?: return emptyList()
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
try {
|
|
||||||
calendars.add(
|
|
||||||
UserCalendar(
|
|
||||||
id = cursor.getLong(0),
|
|
||||||
name = cursor.getString(5) ?: cursor.getString(1) ?: "",
|
|
||||||
owner = cursor.getString(2),
|
|
||||||
color = cursor.getInt(3)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} catch (e: NullPointerException) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cursor.close()
|
|
||||||
calendars.sortBy { it.owner }
|
|
||||||
return calendars
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDisplayColor(context: Context, color: Int): Int {
|
fun getDisplayColor(context: Context, color: Int): Int {
|
||||||
val hsl = FloatArray(3).let {
|
val hsl = FloatArray(3).let {
|
||||||
ColorUtils.RGBToHSL(color.red, color.green, color.blue, it)
|
ColorUtils.RGBToHSL(color.red, color.green, color.blue, it)
|
||||||
|
|||||||
@ -148,15 +148,8 @@
|
|||||||
<string name="preference_dynamic_icon_bg">Dynamischer Hintergrund</string>
|
<string name="preference_dynamic_icon_bg">Dynamischer Hintergrund</string>
|
||||||
<string name="preference_dynamic_icon_bg_summary">Hintergrundfarbe an Symbol anpassen</string>
|
<string name="preference_dynamic_icon_bg_summary">Hintergrundfarbe an Symbol anpassen</string>
|
||||||
<string name="preference_category_widget">Widget</string>
|
<string name="preference_category_widget">Widget</string>
|
||||||
<string name="preference_screen_calendarwidget">Kalender</string>
|
|
||||||
<string name="preference_screen_calendar_summary">Kalender, Widgets</string>
|
<string name="preference_screen_calendar_summary">Kalender, Widgets</string>
|
||||||
<string name="preference_calendar_calendars">Kalender</string>
|
|
||||||
<string name="preference_permission_denied">Berechtigung fehlt</string>
|
<string name="preference_permission_denied">Berechtigung fehlt</string>
|
||||||
<string name="preference_calendar_hide_allday">Ganztägige Termine ausblenden</string>
|
|
||||||
<plurals name="preference_calendar_calendars_summary">
|
|
||||||
<item quantity="one">%1$d Kalender ausgewählt</item>
|
|
||||||
<item quantity="other">%1$d Kalender ausgewählt</item>
|
|
||||||
</plurals>
|
|
||||||
<string name="date_format_clock_widget">%1$s\n%2$s</string>
|
<string name="date_format_clock_widget">%1$s\n%2$s</string>
|
||||||
<string name="menu_edit_widgets">Widgets bearbeiten</string>
|
<string name="menu_edit_widgets">Widgets bearbeiten</string>
|
||||||
<string name="widget_name_weather">Wetter</string>
|
<string name="widget_name_weather">Wetter</string>
|
||||||
@ -432,6 +425,14 @@
|
|||||||
<string name="preference_music_filter_sources">Auf Musik-Apps begrenzen</string>
|
<string name="preference_music_filter_sources">Auf Musik-Apps begrenzen</string>
|
||||||
<string name="preference_music_filter_sources_summary">Mediensitzungen von Apps ignorieren, die keine Musik-Apps sind</string>
|
<string name="preference_music_filter_sources_summary">Mediensitzungen von Apps ignorieren, die keine Musik-Apps sind</string>
|
||||||
|
|
||||||
|
<string name="preference_screen_calendarwidget">Kalender</string>
|
||||||
|
<string name="preference_calendar_calendars">Kalender</string>
|
||||||
|
<string name="preference_calendar_hide_allday">Ganztägige Termine ausblenden</string>
|
||||||
|
<plurals name="preference_calendar_calendars_summary">
|
||||||
|
<item quantity="one">%1$d Kalender ausgewählt</item>
|
||||||
|
<item quantity="other">%1$d Kalender ausgewählt</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
<string name="preference_screen_search">Suche</string>
|
<string name="preference_screen_search">Suche</string>
|
||||||
<string name="preference_screen_search_summary">Konfigurieren was durchsucht werden soll</string>
|
<string name="preference_screen_search_summary">Konfigurieren was durchsucht werden soll</string>
|
||||||
<string name="preference_search_favorites">Favoriten</string>
|
<string name="preference_search_favorites">Favoriten</string>
|
||||||
|
|||||||
@ -196,11 +196,8 @@
|
|||||||
<string name="preference_dynamic_icon_bg">Dynamic background</string>
|
<string name="preference_dynamic_icon_bg">Dynamic background</string>
|
||||||
<string name="preference_dynamic_icon_bg_summary">Adjust background color to icon</string>
|
<string name="preference_dynamic_icon_bg_summary">Adjust background color to icon</string>
|
||||||
<string name="preference_category_widget">Widget</string>
|
<string name="preference_category_widget">Widget</string>
|
||||||
<string name="preference_screen_calendarwidget">Calendar</string>
|
|
||||||
<string name="preference_screen_calendar_summary">Calendars, Widget settings</string>
|
<string name="preference_screen_calendar_summary">Calendars, Widget settings</string>
|
||||||
<string name="preference_calendar_calendars">Calendars</string>
|
|
||||||
<string name="preference_permission_denied">Permission denied</string>
|
<string name="preference_permission_denied">Permission denied</string>
|
||||||
<string name="preference_calendar_hide_allday">Hide all-day events</string>
|
|
||||||
<string name="menu_edit_widgets">Edit widgets</string>
|
<string name="menu_edit_widgets">Edit widgets</string>
|
||||||
<string name="widget_name_weather">Weather</string>
|
<string name="widget_name_weather">Weather</string>
|
||||||
<string name="widget_name_calendar">Calendar</string>
|
<string name="widget_name_calendar">Calendar</string>
|
||||||
@ -237,10 +234,6 @@
|
|||||||
<string name="file_type_ebook">E-book</string>
|
<string name="file_type_ebook">E-book</string>
|
||||||
<string name="file_type_drawing">Drawing</string>
|
<string name="file_type_drawing">Drawing</string>
|
||||||
<string name="file_type_form">Form</string>
|
<string name="file_type_form">Form</string>
|
||||||
<plurals name="preference_calendar_calendars_summary">
|
|
||||||
<item quantity="one">%1$d calendar selected</item>
|
|
||||||
<item quantity="other">%1$d calendars selected</item>
|
|
||||||
</plurals>
|
|
||||||
<string name="menu_hide">Hide</string>
|
<string name="menu_hide">Hide</string>
|
||||||
<string name="menu_unhide">Don\'t hide</string>
|
<string name="menu_unhide">Don\'t hide</string>
|
||||||
<string name="menu_hidden_items">Hidden items</string>
|
<string name="menu_hidden_items">Hidden items</string>
|
||||||
@ -488,6 +481,14 @@
|
|||||||
<string name="preference_search_websearch">Web search</string>
|
<string name="preference_search_websearch">Web search</string>
|
||||||
<string name="preference_search_websearch_summary">Show shortcuts to different search engines</string>
|
<string name="preference_search_websearch_summary">Show shortcuts to different search engines</string>
|
||||||
|
|
||||||
|
<string name="preference_screen_calendarwidget">Calendar</string>
|
||||||
|
<string name="preference_calendar_calendars">Calendars</string>
|
||||||
|
<string name="preference_calendar_hide_allday">Hide all-day events</string>
|
||||||
|
<plurals name="preference_calendar_calendars_summary">
|
||||||
|
<item quantity="one">%1$d calendar selected</item>
|
||||||
|
<item quantity="other">%1$d calendars selected</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
<string name="preference_music_filter_sources">Restrict to music apps</string>
|
<string name="preference_music_filter_sources">Restrict to music apps</string>
|
||||||
<string name="preference_music_filter_sources_summary">Ignore media sessions of apps that are not music apps</string>
|
<string name="preference_music_filter_sources_summary">Ignore media sessions of apps that are not music apps</string>
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,10 @@ fun createFactorySettings(context: Context): Settings {
|
|||||||
.setFilterSources(true)
|
.setFilterSources(true)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
.setCalendarWidget(Settings.CalendarWidgetSettings
|
||||||
|
.newBuilder()
|
||||||
|
.setHideAlldayEvents(false)
|
||||||
|
)
|
||||||
.setClockWidget(Settings.ClockWidgetSettings
|
.setClockWidget(Settings.ClockWidgetSettings
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setLayout(Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical)
|
.setLayout(Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical)
|
||||||
|
|||||||
@ -103,4 +103,10 @@ message Settings {
|
|||||||
}
|
}
|
||||||
WebSearchSettings web_search = 16;
|
WebSearchSettings web_search = 16;
|
||||||
|
|
||||||
|
message CalendarWidgetSettings {
|
||||||
|
bool hide_allday_events = 1;
|
||||||
|
repeated int64 exclude_calendars = 2;
|
||||||
|
}
|
||||||
|
CalendarWidgetSettings calendar_widget = 17;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -23,6 +23,7 @@ import de.mm20.launcher2.ui.base.BaseActivity
|
|||||||
import de.mm20.launcher2.ui.locals.LocalNavController
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
import de.mm20.launcher2.ui.settings.about.AboutSettingsScreen
|
import de.mm20.launcher2.ui.settings.about.AboutSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.appearance.AppearanceSettingsScreen
|
import de.mm20.launcher2.ui.settings.appearance.AppearanceSettingsScreen
|
||||||
|
import de.mm20.launcher2.ui.settings.calendarwidget.CalendarWidgetSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.clockwidget.ClockWidgetSettingsScreen
|
import de.mm20.launcher2.ui.settings.clockwidget.ClockWidgetSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
|
import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.license.LicenseScreen
|
import de.mm20.launcher2.ui.settings.license.LicenseScreen
|
||||||
@ -98,6 +99,9 @@ class SettingsActivity : BaseActivity() {
|
|||||||
composable("settings/widgets/music") {
|
composable("settings/widgets/music") {
|
||||||
MusicWidgetSettingsScreen()
|
MusicWidgetSettingsScreen()
|
||||||
}
|
}
|
||||||
|
composable("settings/widgets/calendar") {
|
||||||
|
CalendarWidgetSettingsScreen()
|
||||||
|
}
|
||||||
composable("settings/widgets/clock") {
|
composable("settings/widgets/clock") {
|
||||||
ClockWidgetSettingsScreen()
|
ClockWidgetSettingsScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,155 @@
|
|||||||
|
package de.mm20.launcher2.ui.settings.calendarwidget
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import de.mm20.launcher2.search.data.UserCalendar
|
||||||
|
import de.mm20.launcher2.ui.R
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.Preference
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
|
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||||
|
import de.mm20.launcher2.ui.pluralResource
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CalendarWidgetSettingsScreen() {
|
||||||
|
val viewModel: CalendarWidgetSettingsScreenVM = viewModel()
|
||||||
|
PreferenceScreen(title = stringResource(R.string.preference_screen_calendarwidget)) {
|
||||||
|
item {
|
||||||
|
val excludeAllDayEvents by viewModel.excludeAllDayEvents.observeAsState()
|
||||||
|
PreferenceCategory {
|
||||||
|
SwitchPreference(
|
||||||
|
title = stringResource(R.string.preference_calendar_hide_allday),
|
||||||
|
value = excludeAllDayEvents == true,
|
||||||
|
onValueChanged = {
|
||||||
|
viewModel.setExcludeAllDayEvents(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
val calendars by viewModel.calendars.observeAsState(emptyList())
|
||||||
|
val unselectedCalendars by viewModel.unselectedCalendars.observeAsState(emptyList())
|
||||||
|
ExcludedCalendarsPreference(
|
||||||
|
calendars = calendars,
|
||||||
|
value = unselectedCalendars,
|
||||||
|
onValueChanged = {
|
||||||
|
viewModel.setUnselectedCalendars(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ExcludedCalendarsPreference(
|
||||||
|
calendars: List<UserCalendar>,
|
||||||
|
value: List<Long>,
|
||||||
|
onValueChanged: (List<Long>) -> Unit
|
||||||
|
) {
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
Preference(
|
||||||
|
title = stringResource(R.string.preference_calendar_calendars),
|
||||||
|
summary = pluralResource(
|
||||||
|
R.plurals.preference_calendar_calendars_summary,
|
||||||
|
quantity = calendars.size - value.size,
|
||||||
|
calendars.size - value.size
|
||||||
|
),
|
||||||
|
onClick = {
|
||||||
|
showDialog = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (showDialog) {
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = { showDialog = false },
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.heightIn(max = 400.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
tonalElevation = 16.dp,
|
||||||
|
shadowElevation = 16.dp,
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.preference_calendar_calendars),
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(
|
||||||
|
start = 24.dp, end = 24.dp, top = 16.dp, bottom = 8.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
items(calendars) { c ->
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
if (value.contains(c.id)) {
|
||||||
|
onValueChanged(
|
||||||
|
value.filter { it != c.id }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
onValueChanged(
|
||||||
|
value + c.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Checkbox(
|
||||||
|
checked = !value.contains(c.id),
|
||||||
|
onCheckedChange = {
|
||||||
|
if (it) {
|
||||||
|
onValueChanged(
|
||||||
|
value.filter { it != c.id }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
onValueChanged(
|
||||||
|
value + c.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colors = CheckboxDefaults.colors(
|
||||||
|
checkedColor = Color(c.color)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(text = c.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
onValueChanged(value.toList())
|
||||||
|
showDialog = false
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.End)
|
||||||
|
.padding(vertical = 12.dp, horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(android.R.string.ok),
|
||||||
|
style = MaterialTheme.typography.labelLarge
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package de.mm20.launcher2.ui.settings.calendarwidget
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.asLiveData
|
||||||
|
import androidx.lifecycle.liveData
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import de.mm20.launcher2.calendar.CalendarRepository
|
||||||
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
|
class CalendarWidgetSettingsScreenVM : ViewModel(), KoinComponent {
|
||||||
|
private val dataStore: LauncherDataStore by inject()
|
||||||
|
private val calendarRepository: CalendarRepository by inject()
|
||||||
|
|
||||||
|
val excludeAllDayEvents = dataStore.data.map { it.calendarWidget.hideAlldayEvents }.asLiveData()
|
||||||
|
fun setExcludeAllDayEvents(excludeAllDayEvents: Boolean) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
dataStore.updateData {
|
||||||
|
it.toBuilder()
|
||||||
|
.setCalendarWidget(
|
||||||
|
it.calendarWidget
|
||||||
|
.toBuilder()
|
||||||
|
.setHideAlldayEvents(excludeAllDayEvents)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val calendars = liveData {
|
||||||
|
emit(calendarRepository.getCalendars())
|
||||||
|
}
|
||||||
|
val unselectedCalendars =
|
||||||
|
dataStore.data.map { it.calendarWidget.excludeCalendarsList }.asLiveData()
|
||||||
|
|
||||||
|
fun setUnselectedCalendars(unselectedCalendars: List<Long>) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
dataStore.updateData {
|
||||||
|
it.toBuilder()
|
||||||
|
.setCalendarWidget(
|
||||||
|
it.calendarWidget.toBuilder()
|
||||||
|
.clearExcludeCalendars()
|
||||||
|
.addAllExcludeCalendars(unselectedCalendars)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,7 +40,10 @@ fun WidgetsSettingsScreen() {
|
|||||||
)
|
)
|
||||||
Preference(
|
Preference(
|
||||||
title = stringResource(R.string.preference_screen_calendarwidget),
|
title = stringResource(R.string.preference_screen_calendarwidget),
|
||||||
icon = Icons.Rounded.Today
|
icon = Icons.Rounded.Today,
|
||||||
|
onClick = {
|
||||||
|
navController?.navigate("settings/widgets/calendar")
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user