Bringup notes widget

This commit is contained in:
MM20 2023-04-23 22:34:20 +02:00
parent e17c8d0f63
commit d98dcdf286
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
9 changed files with 155 additions and 0 deletions

View File

@ -74,6 +74,7 @@ import de.mm20.launcher2.widgets.AppWidget
import de.mm20.launcher2.widgets.CalendarWidget
import de.mm20.launcher2.widgets.FavoritesWidget
import de.mm20.launcher2.widgets.MusicWidget
import de.mm20.launcher2.widgets.NotesWidget
import de.mm20.launcher2.widgets.WeatherWidget
import de.mm20.launcher2.widgets.Widget
import org.koin.androidx.compose.get
@ -110,6 +111,7 @@ fun ConfigureWidgetSheet(
is CalendarWidget -> ConfigureCalendarWidget(widget, onWidgetUpdated)
is FavoritesWidget -> ConfigureFavoritesWidget(widget, onWidgetUpdated)
is MusicWidget -> ConfigureMusicWidget()
is NotesWidget -> ConfigureNotesWidget(widget, onWidgetUpdated)
}
}
@ -304,6 +306,7 @@ fun ColumnScope.ConfigureAppWidget(
is MusicWidget -> it.copy(id = widget.id)
is CalendarWidget -> it.copy(id = widget.id)
is FavoritesWidget -> it.copy(id = widget.id)
is NotesWidget -> it.copy(id = widget.id)
}
onWidgetUpdated(updatedWidget)
replaceWidget = false
@ -537,4 +540,12 @@ fun ColumnScope.ConfigureCalendarWidget(
text = stringResource(R.string.widget_config_calendar_no_calendars)
)
}
}
@Composable
fun ConfigureNotesWidget(
widget: NotesWidget,
onWidgetUpdated: (NotesWidget) -> Unit
) {
}

View File

@ -30,6 +30,7 @@ import androidx.compose.material.icons.rounded.LightMode
import androidx.compose.material.icons.rounded.MusicNote
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StickyNote2
import androidx.compose.material.icons.rounded.Today
import androidx.compose.material.icons.rounded.Widgets
import androidx.compose.material.icons.rounded.Work
@ -64,6 +65,7 @@ import de.mm20.launcher2.widgets.AppWidget
import de.mm20.launcher2.widgets.AppWidgetConfig
import de.mm20.launcher2.widgets.FavoritesWidget
import de.mm20.launcher2.widgets.MusicWidget
import de.mm20.launcher2.widgets.NotesWidget
import de.mm20.launcher2.widgets.WeatherWidget
import de.mm20.launcher2.widgets.Widget
import java.util.UUID
@ -287,6 +289,7 @@ fun WidgetPickerSheet(
CalendarWidget.Type -> CalendarWidget(id)
MusicWidget.Type -> MusicWidget(id)
FavoritesWidget.Type -> FavoritesWidget(id)
NotesWidget.Type -> NotesWidget(id)
else -> return@OutlinedCard
}
onWidgetSelected(widget)
@ -302,6 +305,7 @@ fun WidgetPickerSheet(
CalendarWidget.Type -> Icons.Rounded.Today
MusicWidget.Type -> Icons.Rounded.MusicNote
FavoritesWidget.Type -> Icons.Rounded.Star
NotesWidget.Type -> Icons.Rounded.StickyNote2
else -> Icons.Rounded.Widgets
},
contentDescription = null,

View File

@ -45,11 +45,13 @@ import de.mm20.launcher2.ui.launcher.widgets.calendar.CalendarWidget
import de.mm20.launcher2.ui.launcher.widgets.external.ExternalWidget
import de.mm20.launcher2.ui.launcher.widgets.favorites.FavoritesWidget
import de.mm20.launcher2.ui.launcher.widgets.music.MusicWidget
import de.mm20.launcher2.ui.launcher.widgets.notes.NotesWidget
import de.mm20.launcher2.ui.launcher.widgets.weather.WeatherWidget
import de.mm20.launcher2.widgets.AppWidget
import de.mm20.launcher2.widgets.CalendarWidget
import de.mm20.launcher2.widgets.FavoritesWidget
import de.mm20.launcher2.widgets.MusicWidget
import de.mm20.launcher2.widgets.NotesWidget
import de.mm20.launcher2.widgets.WeatherWidget
import de.mm20.launcher2.widgets.Widget
@ -107,6 +109,7 @@ fun WidgetItem(
is MusicWidget -> stringResource(R.string.widget_name_music)
is CalendarWidget -> stringResource(R.string.widget_name_calendar)
is FavoritesWidget -> stringResource(R.string.widget_name_favorites)
is NotesWidget -> stringResource(R.string.widget_name_notes)
is AppWidget -> remember(widget.config.widgetId) {
appWidget?.loadLabel(
context.packageManager
@ -155,6 +158,10 @@ fun WidgetItem(
FavoritesWidget(widget)
}
is NotesWidget -> {
NotesWidget(widget)
}
is AppWidget -> {
val widgetInfo = remember(widget.config.widgetId) {
AppWidgetManager.getInstance(context)
@ -193,6 +200,7 @@ fun WidgetItem(
is MusicWidget -> it.copy(id = widget.id)
is CalendarWidget -> it.copy(id = widget.id)
is FavoritesWidget -> it.copy(id = widget.id)
is NotesWidget -> it.copy(id = widget.id)
}
onWidgetUpdate(updatedWidget)
replaceWidget = false

View File

@ -0,0 +1,37 @@
package de.mm20.launcher2.ui.launcher.widgets.notes
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.widgets.NotesWidget
@Composable
fun NotesWidget(widget: NotesWidget) {
val viewModel: NotesWidgetVM = viewModel(key = "notes-widget-${widget.id}", factory = NotesWidgetVM.Factory)
LaunchedEffect(widget) {
viewModel.updateWidget(widget)
}
val text by viewModel.noteText
BasicTextField(
value = text,
onValueChange = { viewModel.setText(it) },
modifier = Modifier.fillMaxWidth().padding(16.dp),
textStyle = MaterialTheme.typography.bodyMedium.copy(
color = LocalContentColor.current,
),
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
)
}

View File

@ -0,0 +1,48 @@
package de.mm20.launcher2.ui.launcher.widgets.notes
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import de.mm20.launcher2.services.widgets.WidgetsService
import de.mm20.launcher2.widgets.NotesWidget
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class NotesWidgetVM(
private val widgetsService: WidgetsService,
) : ViewModel() {
private val widget = MutableStateFlow<NotesWidget?>(null)
val noteText = mutableStateOf(widget.value?.config?.storedText ?: "")
fun updateWidget(widget: NotesWidget) {
val oldId = this.widget.value?.id
this.widget.value = widget
if (widget.id != oldId) noteText.value = widget.config.storedText
}
private var updateJob: Job? = null
fun setText(text: String) {
noteText.value = text
updateJob?.cancel()
val widget = widget.value ?: return
updateJob = viewModelScope.launch {
delay(1000)
widgetsService.updateWidget(widget.copy(config = widget.config.copy(storedText = text)))
}
}
companion object: KoinComponent {
val Factory = viewModelFactory {
initializer {
NotesWidgetVM(get())
}
}
}
}

View File

@ -219,6 +219,7 @@
<string name="widget_name_calendar">Calendar</string>
<string name="widget_name_music">Music</string>
<string name="widget_name_favorites">Favorites</string>
<string name="widget_name_notes">Note</string>
<string name="widget_name_unknown">Unknown app widget</string>
<string name="widget_add_widget">Add widget</string>
<!-- Add a third party widget (=a standard Android app widget) -->

View File

@ -0,0 +1,31 @@
package de.mm20.launcher2.widgets
import de.mm20.launcher2.database.entities.PartialWidgetEntity
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.UUID
@Serializable
data class NotesWidgetConfig(
val storedText: String = "",
val quickActions: Boolean = true,
)
data class NotesWidget(
override val id: UUID,
val config: NotesWidgetConfig = NotesWidgetConfig(),
) : Widget() {
override fun toDatabaseEntity(): PartialWidgetEntity {
return PartialWidgetEntity(
id = id,
type = Type,
config = Json.encodeToString(config),
)
}
companion object {
const val Type = "notes"
}
}

View File

@ -54,6 +54,12 @@ sealed class Widget {
config,
)
}
NotesWidget.Type -> {
val config: NotesWidgetConfig =
Json.decodeFromStringOrNull(entity.config?.takeIf { it.isNotBlank() })
?: NotesWidgetConfig()
NotesWidget(entity.id, config)
}
else -> null
}

View File

@ -8,6 +8,7 @@ import androidx.core.content.getSystemService
import de.mm20.launcher2.widgets.CalendarWidget
import de.mm20.launcher2.widgets.FavoritesWidget
import de.mm20.launcher2.widgets.MusicWidget
import de.mm20.launcher2.widgets.NotesWidget
import de.mm20.launcher2.widgets.WeatherWidget
import de.mm20.launcher2.widgets.Widget
import de.mm20.launcher2.widgets.WidgetRepository
@ -56,6 +57,10 @@ class WidgetsService(
type = FavoritesWidget.Type,
label = context.getString(R.string.widget_name_favorites),
),
BuiltInWidgetInfo(
type = NotesWidget.Type,
label = context.getString(R.string.widget_name_notes),
),
)
}
@ -63,6 +68,10 @@ class WidgetsService(
widgetRepository.create(widget, position, parentId)
}
fun updateWidget(widget: Widget) {
widgetRepository.update(widget)
}
fun getWidgets() = widgetRepository.get()
fun isFavoritesWidgetFirst(): Flow<Boolean> {