mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
finish minor refactoring and add some polish :)
This commit is contained in:
parent
403b5dd930
commit
9d19c5e3f3
@ -146,7 +146,8 @@
|
||||
<!-- Widgets -->
|
||||
<receiver
|
||||
android:name=".widget.RandomReceiver"
|
||||
android:exported="true">
|
||||
android:exported="true"
|
||||
android:label="@string/random_widget_title">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
@ -157,7 +158,8 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widget.MemoryReceiver"
|
||||
android:exported="true">
|
||||
android:exported="true"
|
||||
android:label="@string/memory_widget_title">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
@ -194,7 +194,8 @@ class ImageDownloadWorker(
|
||||
val memory = memories.random()
|
||||
asset = memory.assets.random()
|
||||
|
||||
subtitle = "${today.year - memory.data.year} years ago"
|
||||
val yearDiff = today.year - memory.data.year
|
||||
subtitle = "$yearDiff ${if (yearDiff == 1) "year" else "years"} ago"
|
||||
} else {
|
||||
val filters = SearchFilters(AssetType.IMAGE, size=1)
|
||||
asset = api.fetchSearchResults(filters).first()
|
||||
|
@ -1,7 +1,6 @@
|
||||
package app.alextran.immich.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import com.google.gson.Gson
|
||||
@ -13,11 +12,8 @@ import java.io.OutputStreamWriter
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.net.URLEncoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
|
||||
|
||||
class ImmichAPI(cfg: ServerConfig) {
|
||||
|
||||
|
@ -1,10 +1,16 @@
|
||||
package app.alextran.immich.widget
|
||||
|
||||
import HomeWidgetGlanceWidgetReceiver
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.glance.appwidget.GlanceAppWidgetReceiver
|
||||
import es.antonborri.home_widget.HomeWidgetPlugin
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MemoryReceiver : HomeWidgetGlanceWidgetReceiver<PhotoWidget>() {
|
||||
class MemoryReceiver : GlanceAppWidgetReceiver() {
|
||||
override val glanceAppWidget = PhotoWidget()
|
||||
|
||||
override fun onUpdate(
|
||||
@ -18,5 +24,23 @@ class MemoryReceiver : HomeWidgetGlanceWidgetReceiver<PhotoWidget>() {
|
||||
ImageDownloadWorker.enqueuePeriodic(context, widgetID, WidgetType.MEMORIES)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val fromMainApp = intent.getBooleanExtra(HomeWidgetPlugin.TRIGGERED_FROM_HOME_WIDGET, false)
|
||||
|
||||
// Launch coroutine to setup a single shot if the app requested the update
|
||||
if (fromMainApp) {
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
val provider = ComponentName(context, MemoryReceiver::class.java)
|
||||
val glanceIds = AppWidgetManager.getInstance(context).getAppWidgetIds(provider)
|
||||
|
||||
glanceIds.forEach { widgetID ->
|
||||
ImageDownloadWorker.singleShot(context, widgetID, WidgetType.MEMORIES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,7 @@ val kDeeplinkURL = stringPreferencesKey("deeplink")
|
||||
|
||||
const val kWorkerWidgetType = "widgetType"
|
||||
const val kWorkerWidgetID = "widgetId"
|
||||
const val kTriggeredFromApp = "triggeredFromApp"
|
||||
|
||||
fun imageFilename(id: String): String {
|
||||
return "widget_image_$id.jpg"
|
||||
|
@ -3,6 +3,9 @@ package app.alextran.immich.widget
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.*
|
||||
import androidx.core.net.toUri
|
||||
@ -14,6 +17,7 @@ import androidx.glance.layout.*
|
||||
import androidx.glance.state.GlanceStateDefinition
|
||||
import androidx.glance.state.PreferencesGlanceStateDefinition
|
||||
import androidx.glance.text.Text
|
||||
import androidx.glance.text.TextAlign
|
||||
import androidx.glance.text.TextStyle
|
||||
import androidx.glance.unit.ColorProvider
|
||||
import app.alextran.immich.R
|
||||
@ -29,6 +33,7 @@ class PhotoWidget : GlanceAppWidget() {
|
||||
val imageUUID = prefs[kImageUUID]
|
||||
val subtitle = prefs[kSubtitleText]
|
||||
val deeplinkURL = prefs[kDeeplinkURL]?.toUri()
|
||||
val widgetState = prefs[kWidgetState]
|
||||
var bitmap: Bitmap? = null
|
||||
|
||||
if (imageUUID != null) {
|
||||
@ -44,7 +49,7 @@ class PhotoWidget : GlanceAppWidget() {
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.fillMaxSize()
|
||||
.background(Color.White)
|
||||
.background(GlanceTheme.colors.background)
|
||||
.clickable {
|
||||
val intent = Intent(Intent.ACTION_VIEW, deeplinkURL ?: "immich://".toUri())
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
@ -81,10 +86,39 @@ class PhotoWidget : GlanceAppWidget() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Column(
|
||||
modifier = GlanceModifier.fillMaxSize(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
provider = ImageProvider(R.drawable.splash),
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
if (widgetState == WidgetState.LOG_IN.toString()) {
|
||||
Box(
|
||||
modifier = GlanceModifier.fillMaxWidth().padding(16.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("Log in to your Immich server", style = TextStyle(textAlign = TextAlign.Center, color = GlanceTheme.colors.primary))
|
||||
}
|
||||
} else {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = GlanceModifier.fillMaxWidth().padding(16.dp)
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = GlanceModifier.size(12.dp)
|
||||
)
|
||||
|
||||
Spacer(modifier = GlanceModifier.width(8.dp))
|
||||
|
||||
Text("Loading widget...", style = TextStyle(textAlign = TextAlign.Center, color = GlanceTheme.colors.primary))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,16 @@
|
||||
package app.alextran.immich.widget
|
||||
|
||||
import HomeWidgetGlanceWidgetReceiver
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.content.Intent
|
||||
import es.antonborri.home_widget.HomeWidgetPlugin
|
||||
import androidx.glance.appwidget.GlanceAppWidgetReceiver
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RandomReceiver : HomeWidgetGlanceWidgetReceiver<PhotoWidget>() {
|
||||
class RandomReceiver : GlanceAppWidgetReceiver() {
|
||||
override val glanceAppWidget = PhotoWidget()
|
||||
|
||||
override fun onUpdate(
|
||||
@ -19,5 +24,23 @@ class RandomReceiver : HomeWidgetGlanceWidgetReceiver<PhotoWidget>() {
|
||||
ImageDownloadWorker.enqueuePeriodic(context, widgetID, WidgetType.RANDOM)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val fromMainApp = intent.getBooleanExtra(HomeWidgetPlugin.TRIGGERED_FROM_HOME_WIDGET, false)
|
||||
|
||||
// Launch coroutine to setup a single shot if the app requested the update
|
||||
if (fromMainApp) {
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
val provider = ComponentName(context, RandomReceiver::class.java)
|
||||
val glanceIds = AppWidgetManager.getInstance(context).getAppWidgetIds(provider)
|
||||
|
||||
glanceIds.forEach { widgetID ->
|
||||
ImageDownloadWorker.singleShot(context, widgetID, WidgetType.MEMORIES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
@Composable
|
||||
fun LightDarkTheme(
|
||||
useDarkTheme: Boolean = isSystemInDarkTheme(), // ← This line is key
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 240 KiB |
Binary file not shown.
After Width: | Height: | Size: 244 KiB |
8
mobile/android/app/src/main/res/values/strings.xml
Normal file
8
mobile/android/app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="memory_widget_title">Memories</string>
|
||||
<string name="random_widget_title">Random</string>
|
||||
|
||||
<string name="memory_widget_description">See memories from Immich.</string>
|
||||
<string name="random_widget_description">View a random image from your library or a specific album.</string>
|
||||
</resources>
|
@ -4,4 +4,6 @@
|
||||
android:minHeight="110dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="1200000"
|
||||
android:description="@string/memory_widget_description"
|
||||
android:previewImage="@drawable/memory_preview"
|
||||
/>
|
||||
|
@ -8,4 +8,6 @@
|
||||
android:configure="app.alextran.immich.widget.configure.RandomConfigure"
|
||||
android:widgetFeatures="reconfigurable|configuration_optional"
|
||||
tools:targetApi="28"
|
||||
android:description="@string/random_widget_description"
|
||||
android:previewImage="@drawable/random_preview"
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user