From b5a0c83b6028246297ee5973d200cbff044ada40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ptit=20l=C3=A9gume?= <67562086+PtitLegume@users.noreply.github.com> Date: Sat, 8 Aug 2026 20:39:29 +0200 Subject: [PATCH 1/2] feat(mobile): samsung flex window widgets --- .../android/app/src/main/AndroidManifest.xml | 46 +++++++++++++++++++ .../immich/widget/FlexWindowReceivers.kt | 9 ++++ .../alextran/immich/widget/MemoryReceiver.kt | 4 +- .../alextran/immich/widget/RandomReceiver.kt | 4 +- .../main/res/values/attrs_samsung_widget.xml | 9 ++++ .../app/src/main/res/values/strings.xml | 4 ++ .../main/res/xml/memory_widget_flex_2x2.xml | 19 ++++++++ .../main/res/xml/memory_widget_flex_4x2.xml | 19 ++++++++ .../main/res/xml/random_widget_flex_2x2.xml | 21 +++++++++ .../res/xml/samsung_appwidget_sub_screen.xml | 3 ++ mobile/lib/constants/constants.dart | 4 ++ 11 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt create mode 100644 mobile/android/app/src/main/res/values/attrs_samsung_widget.xml create mode 100644 mobile/android/app/src/main/res/xml/memory_widget_flex_2x2.xml create mode 100644 mobile/android/app/src/main/res/xml/memory_widget_flex_4x2.xml create mode 100644 mobile/android/app/src/main/res/xml/random_widget_flex_2x2.xml create mode 100644 mobile/android/app/src/main/res/xml/samsung_appwidget_sub_screen.xml diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 5f4de8284a..99a1a6e6b6 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -178,6 +178,52 @@ android:resource="@xml/memory_widget" /> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt new file mode 100644 index 0000000000..aae500270c --- /dev/null +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt @@ -0,0 +1,9 @@ +package app.alextran.immich.widget + +// Widget providers for the Samsung Flex Window cover screen. + +class MemoryReceiverFlex2x2 : MemoryReceiver() + +class MemoryReceiverFlex4x2 : MemoryReceiver() + +class RandomReceiverFlex2x2 : RandomReceiver() diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/MemoryReceiver.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/MemoryReceiver.kt index 63b32eb6f0..aee4398e58 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/MemoryReceiver.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/MemoryReceiver.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -class MemoryReceiver : GlanceAppWidgetReceiver() { +open class MemoryReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget = PhotoWidget() override fun onUpdate( @@ -28,7 +28,7 @@ class MemoryReceiver : GlanceAppWidgetReceiver() { override fun onReceive(context: Context, intent: Intent) { val fromMainApp = intent.getBooleanExtra(HomeWidgetPlugin.TRIGGERED_FROM_HOME_WIDGET, false) - val provider = ComponentName(context, MemoryReceiver::class.java) + val provider = ComponentName(context, javaClass) val glanceIds = AppWidgetManager.getInstance(context).getAppWidgetIds(provider) // Launch coroutine to setup a single shot if the app requested the update diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/RandomReceiver.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/RandomReceiver.kt index a7662181bc..3d4c581e52 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/RandomReceiver.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/RandomReceiver.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -class RandomReceiver : GlanceAppWidgetReceiver() { +open class RandomReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget = PhotoWidget() override fun onUpdate( @@ -28,7 +28,7 @@ class RandomReceiver : GlanceAppWidgetReceiver() { override fun onReceive(context: Context, intent: Intent) { val fromMainApp = intent.getBooleanExtra(HomeWidgetPlugin.TRIGGERED_FROM_HOME_WIDGET, false) - val provider = ComponentName(context, RandomReceiver::class.java) + val provider = ComponentName(context, javaClass) val glanceIds = AppWidgetManager.getInstance(context).getAppWidgetIds(provider) // Launch coroutine to setup a single shot if the app requested the update diff --git a/mobile/android/app/src/main/res/values/attrs_samsung_widget.xml b/mobile/android/app/src/main/res/values/attrs_samsung_widget.xml new file mode 100644 index 0000000000..27254c3866 --- /dev/null +++ b/mobile/android/app/src/main/res/values/attrs_samsung_widget.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/mobile/android/app/src/main/res/values/strings.xml b/mobile/android/app/src/main/res/values/strings.xml index d543e33116..4897b5bd1e 100644 --- a/mobile/android/app/src/main/res/values/strings.xml +++ b/mobile/android/app/src/main/res/values/strings.xml @@ -2,6 +2,10 @@ Memories Random + + Memories (2x2) + Memories (4x2) + Random (2x2) See memories from Immich. View a random image from your library or a specific album. diff --git a/mobile/android/app/src/main/res/xml/memory_widget_flex_2x2.xml b/mobile/android/app/src/main/res/xml/memory_widget_flex_2x2.xml new file mode 100644 index 0000000000..8e0379e14f --- /dev/null +++ b/mobile/android/app/src/main/res/xml/memory_widget_flex_2x2.xml @@ -0,0 +1,19 @@ + + + diff --git a/mobile/android/app/src/main/res/xml/memory_widget_flex_4x2.xml b/mobile/android/app/src/main/res/xml/memory_widget_flex_4x2.xml new file mode 100644 index 0000000000..40d2faff9c --- /dev/null +++ b/mobile/android/app/src/main/res/xml/memory_widget_flex_4x2.xml @@ -0,0 +1,19 @@ + + + diff --git a/mobile/android/app/src/main/res/xml/random_widget_flex_2x2.xml b/mobile/android/app/src/main/res/xml/random_widget_flex_2x2.xml new file mode 100644 index 0000000000..791bc03c66 --- /dev/null +++ b/mobile/android/app/src/main/res/xml/random_widget_flex_2x2.xml @@ -0,0 +1,21 @@ + + + diff --git a/mobile/android/app/src/main/res/xml/samsung_appwidget_sub_screen.xml b/mobile/android/app/src/main/res/xml/samsung_appwidget_sub_screen.xml new file mode 100644 index 0000000000..3e7c6a0f27 --- /dev/null +++ b/mobile/android/app/src/main/res/xml/samsung_appwidget_sub_screen.xml @@ -0,0 +1,3 @@ + + + diff --git a/mobile/lib/constants/constants.dart b/mobile/lib/constants/constants.dart index c2a13c3ec2..3ccab26408 100644 --- a/mobile/lib/constants/constants.dart +++ b/mobile/lib/constants/constants.dart @@ -37,9 +37,13 @@ const String kWidgetCustomHeaders = "widget_custom_headers"; // add widget identifiers here for new widgets // these are used to force a widget refresh // (iOSName, androidFQDN) +// Android-only providers reuse the iOS name of their counterpart, updateWidget rejects a null one. const List<(String, String)> kWidgetNames = [ ('com.immich.widget.random', 'app.alextran.immich.widget.RandomReceiver'), ('com.immich.widget.memory', 'app.alextran.immich.widget.MemoryReceiver'), + ('com.immich.widget.memory', 'app.alextran.immich.widget.MemoryReceiverFlex2x2'), + ('com.immich.widget.memory', 'app.alextran.immich.widget.MemoryReceiverFlex4x2'), + ('com.immich.widget.random', 'app.alextran.immich.widget.RandomReceiverFlex2x2'), ]; const int kMinMonthsToEnableScrubberSnap = 12; From e0caaf39b2e4236f2d1179cd5cf128a87913242d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ptit=20l=C3=A9gume?= <67562086+PtitLegume@users.noreply.github.com> Date: Sun, 9 Aug 2026 01:21:51 +0200 Subject: [PATCH 2/2] feat(mobile): add random 4x2 flex window widget --- .../android/app/src/main/AndroidManifest.xml | 15 +++++++++++++ .../immich/widget/FlexWindowReceivers.kt | 2 ++ .../app/src/main/res/values/strings.xml | 1 + .../main/res/xml/random_widget_flex_4x2.xml | 21 +++++++++++++++++++ mobile/lib/constants/constants.dart | 1 + 5 files changed, 40 insertions(+) create mode 100644 mobile/android/app/src/main/res/xml/random_widget_flex_4x2.xml diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 99a1a6e6b6..c6f0232bb6 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -224,6 +224,21 @@ android:resource="@xml/samsung_appwidget_sub_screen" /> + + + + + + + + diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt index aae500270c..fd43f71fcf 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/widget/FlexWindowReceivers.kt @@ -7,3 +7,5 @@ class MemoryReceiverFlex2x2 : MemoryReceiver() class MemoryReceiverFlex4x2 : MemoryReceiver() class RandomReceiverFlex2x2 : RandomReceiver() + +class RandomReceiverFlex4x2 : RandomReceiver() diff --git a/mobile/android/app/src/main/res/values/strings.xml b/mobile/android/app/src/main/res/values/strings.xml index 4897b5bd1e..89b6384ae4 100644 --- a/mobile/android/app/src/main/res/values/strings.xml +++ b/mobile/android/app/src/main/res/values/strings.xml @@ -6,6 +6,7 @@ Memories (2x2) Memories (4x2) Random (2x2) + Random (4x2) See memories from Immich. View a random image from your library or a specific album. diff --git a/mobile/android/app/src/main/res/xml/random_widget_flex_4x2.xml b/mobile/android/app/src/main/res/xml/random_widget_flex_4x2.xml new file mode 100644 index 0000000000..5baa4e01c0 --- /dev/null +++ b/mobile/android/app/src/main/res/xml/random_widget_flex_4x2.xml @@ -0,0 +1,21 @@ + + + diff --git a/mobile/lib/constants/constants.dart b/mobile/lib/constants/constants.dart index 3ccab26408..cadb896c42 100644 --- a/mobile/lib/constants/constants.dart +++ b/mobile/lib/constants/constants.dart @@ -44,6 +44,7 @@ const List<(String, String)> kWidgetNames = [ ('com.immich.widget.memory', 'app.alextran.immich.widget.MemoryReceiverFlex2x2'), ('com.immich.widget.memory', 'app.alextran.immich.widget.MemoryReceiverFlex4x2'), ('com.immich.widget.random', 'app.alextran.immich.widget.RandomReceiverFlex2x2'), + ('com.immich.widget.random', 'app.alextran.immich.widget.RandomReceiverFlex4x2'), ]; const int kMinMonthsToEnableScrubberSnap = 12;