This commit is contained in:
Mathis 2026-08-15 13:40:01 +02:00 committed by GitHub
commit 5c2761a257
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 178 additions and 4 deletions

View file

@ -178,6 +178,67 @@
android:resource="@xml/memory_widget" />
</receiver>
<!-- Samsung Flex Window size variants. -->
<receiver
android:name=".widget.MemoryReceiverFlex2x2"
android:exported="true"
android:label="@string/memory_widget_flex_2x2_title">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/memory_widget_flex_2x2" />
<meta-data
android:name="com.samsung.android.appwidget.provider"
android:resource="@xml/samsung_appwidget_sub_screen" />
</receiver>
<receiver
android:name=".widget.MemoryReceiverFlex4x2"
android:exported="true"
android:label="@string/memory_widget_flex_4x2_title">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/memory_widget_flex_4x2" />
<meta-data
android:name="com.samsung.android.appwidget.provider"
android:resource="@xml/samsung_appwidget_sub_screen" />
</receiver>
<receiver
android:name=".widget.RandomReceiverFlex2x2"
android:exported="true"
android:label="@string/random_widget_flex_2x2_title">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/random_widget_flex_2x2" />
<meta-data
android:name="com.samsung.android.appwidget.provider"
android:resource="@xml/samsung_appwidget_sub_screen" />
</receiver>
<receiver
android:name=".widget.RandomReceiverFlex4x2"
android:exported="true"
android:label="@string/random_widget_flex_4x2_title">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/random_widget_flex_4x2" />
<meta-data
android:name="com.samsung.android.appwidget.provider"
android:resource="@xml/samsung_appwidget_sub_screen" />
</receiver>
<activity android:name=".widget.configure.RandomConfigure"
android:exported="true"
android:theme="@style/Theme.Material3.DayNight.NoActionBar">

View file

@ -0,0 +1,11 @@
package app.alextran.immich.widget
// Widget providers for the Samsung Flex Window cover screen.
class MemoryReceiverFlex2x2 : MemoryReceiver()
class MemoryReceiverFlex4x2 : MemoryReceiver()
class RandomReceiverFlex2x2 : RandomReceiver()
class RandomReceiverFlex4x2 : RandomReceiver()

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Samsung cover screen widget attributes. The names are imposed by the Samsung host.
targetHost = 4 (cover screen), widgetSize = columns * 4 (2 columns = 8, 4 columns = 16).
The host only offers 2x2 and 4x2 tiles, taller ones are clamped back to 2 rows.
-->
<resources>
<attr name="targetHost" format="integer" />
<attr name="widgetSize" format="integer" />
</resources>

View file

@ -2,6 +2,11 @@
<resources>
<string name="memory_widget_title">Memories</string>
<string name="random_widget_title">Random</string>
<!-- Samsung Flex Window size variants. -->
<string name="memory_widget_flex_2x2_title">Memories (2x2)</string>
<string name="memory_widget_flex_4x2_title">Memories (4x2)</string>
<string name="random_widget_flex_2x2_title">Random (2x2)</string>
<string name="random_widget_flex_4x2_title">Random (4x2)</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>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Memories widget for the Samsung Flex Window cover screen, smallest tile of its 4x2 grid. -->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="150dp"
android:minHeight="133dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:resizeMode="none"
android:widgetCategory="keyguard"
android:updatePeriodMillis="1200000"
app:targetHost="4"
app:widgetSize="8"
tools:targetApi="31"
android:description="@string/memory_widget_description"
android:previewImage="@drawable/memory_preview"
/>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Memories widget for the Samsung Flex Window cover screen, full width of its 4x2 grid. -->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="304dp"
android:minHeight="128dp"
android:targetCellWidth="4"
android:targetCellHeight="2"
android:resizeMode="none"
android:widgetCategory="keyguard"
android:updatePeriodMillis="1200000"
app:targetHost="4"
app:widgetSize="16"
tools:targetApi="31"
android:description="@string/memory_widget_description"
android:previewImage="@drawable/memory_preview"
/>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Random widget for the Samsung Flex Window cover screen, smallest tile of its 4x2 grid. -->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="150dp"
android:minHeight="133dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:resizeMode="none"
android:widgetCategory="keyguard"
android:updatePeriodMillis="1200000"
android:configure="app.alextran.immich.widget.configure.RandomConfigure"
android:widgetFeatures="reconfigurable|configuration_optional"
app:targetHost="4"
app:widgetSize="8"
tools:targetApi="31"
android:description="@string/random_widget_description"
android:previewImage="@drawable/random_preview"
/>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Random widget for the Samsung Flex Window cover screen, full width of its 4x2 grid. -->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="304dp"
android:minHeight="128dp"
android:targetCellWidth="4"
android:targetCellHeight="2"
android:resizeMode="none"
android:widgetCategory="keyguard"
android:updatePeriodMillis="1200000"
android:configure="app.alextran.immich.widget.configure.RandomConfigure"
android:widgetFeatures="reconfigurable|configuration_optional"
app:targetHost="4"
app:widgetSize="16"
tools:targetApi="31"
android:description="@string/random_widget_description"
android:previewImage="@drawable/random_preview"
/>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Allow Immich to be used as a sub-screen widget on Samsung devices -->
<samsung-appwidget-provider display="sub_screen" />

View file

@ -37,9 +37,14 @@ 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'),
('com.immich.widget.random', 'app.alextran.immich.widget.RandomReceiverFlex4x2'),
];
const int kMinMonthsToEnableScrubberSnap = 12;