[FEAT] Home Widget for Favorites Album (#1703)
This commit is contained in:
commit
e26141033c
25 changed files with 740 additions and 332 deletions
3
.vscode/settings.json.example
vendored
Normal file
3
.vscode/settings.json.example
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"dart.flutterSdkPath": "thirdparty/flutter/bin"
|
||||
}
|
|
@ -64,7 +64,7 @@ You can alternatively install the build from PlayStore or F-Droid.
|
|||
|
||||
## 🧑💻 Building from source
|
||||
|
||||
1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install)
|
||||
1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install) or set the Path of Flutter SDK to `thirdparty/flutter/bin` of photos-app directory after step 3.
|
||||
2. Clone this repository with `git clone git@github.com:ente-io/photos-app.git`
|
||||
3. Pull in all submodules with `git submodule update --init --recursive`
|
||||
4. Enable repo git hooks `git config core.hooksPath hooks`
|
||||
|
|
|
@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
compileSdkVersion 34
|
||||
ndkVersion "26.0.10792818"
|
||||
|
||||
sourceSets {
|
||||
|
@ -57,7 +57,7 @@ android {
|
|||
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : file(System.getenv("SIGNING_KEY_PATH"))
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : System.getenv("SIGNING_KEY_PATH") ? file(System.getenv("SIGNING_KEY_PATH")) : null
|
||||
keyAlias keystoreProperties['keyAlias'] ? keystoreProperties['keyAlias'] : System.getenv("SIGNING_KEY_ALIAS")
|
||||
keyPassword keystoreProperties['keyPassword'] ? keystoreProperties['keyPassword'] : System.getenv("SIGNING_KEY_PASSWORD")
|
||||
storePassword keystoreProperties['storePassword'] ? keystoreProperties['storePassword'] : System.getenv("SIGNING_STORE_PASSWORD")
|
||||
|
|
|
@ -85,6 +85,13 @@
|
|||
android:value="https://2235e5c99219488ea93da34b9ac1cb68@sentry.ente.io/4" />
|
||||
<meta-data android:name="firebase_analytics_collection_deactivated"
|
||||
android:value="true" />
|
||||
<receiver android:name="SlideshowWidgetProvider" android:label="Favorites" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/slideshow_widget" />
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
<!-- Android 11: https://developer.android.com/preview/privacy/package-visibility -->
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package io.ente.photos
|
||||
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity;
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||
|
||||
class MainActivity: FlutterFragmentActivity() {
|
||||
class MainActivity : FlutterFragmentActivity() {
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
GeneratedPluginRegistrant.registerWith(flutterEngine)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package io.ente.photos
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.ContextCompat
|
||||
import es.antonborri.home_widget.HomeWidgetLaunchIntent
|
||||
import es.antonborri.home_widget.HomeWidgetProvider
|
||||
import java.io.File
|
||||
|
||||
class SlideshowWidgetProvider : HomeWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray,
|
||||
widgetData: SharedPreferences
|
||||
) {
|
||||
appWidgetIds.forEach { widgetId ->
|
||||
val views =
|
||||
RemoteViews(context.packageName, R.layout.slideshow_layout).apply {
|
||||
// Open App on Widget Click
|
||||
val pendingIntent =
|
||||
HomeWidgetLaunchIntent.getActivity(
|
||||
context,
|
||||
MainActivity::class.java
|
||||
)
|
||||
setOnClickPendingIntent(R.id.widget_container, pendingIntent)
|
||||
|
||||
// Show Images saved with `renderFlutterWidget`
|
||||
val imagePath = widgetData.getString("slideshow", null)
|
||||
var imageExists: Boolean = false
|
||||
if (imagePath != null) {
|
||||
val imageFile = File(imagePath)
|
||||
imageExists = imageFile.exists()
|
||||
}
|
||||
if (imageExists) {
|
||||
Log.d("SlideshowWidgetProvider", "Image exists: $imagePath")
|
||||
setViewVisibility(R.id.widget_img, View.VISIBLE)
|
||||
setViewVisibility(R.id.widget_placeholder, View.GONE)
|
||||
|
||||
val bitmap: Bitmap = BitmapFactory.decodeFile(imagePath)
|
||||
setImageViewBitmap(R.id.widget_img, bitmap)
|
||||
} else {
|
||||
Log.d("SlideshowWidgetProvider", "Image doesn't exists")
|
||||
setViewVisibility(R.id.widget_img, View.GONE)
|
||||
setViewVisibility(R.id.widget_placeholder, View.VISIBLE)
|
||||
|
||||
val drawable =
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_launcher_foreground
|
||||
)
|
||||
val bitmap = (drawable as BitmapDrawable).bitmap
|
||||
setImageViewBitmap(R.id.widget_placeholder, bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
appWidgetManager.updateAppWidget(widgetId, views)
|
||||
}
|
||||
}
|
||||
}
|
5
android/app/src/main/res/drawable/widget_background.xml
Normal file
5
android/app/src/main/res/drawable/widget_background.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF"/>
|
||||
<corners android:radius="16dp"/>
|
||||
</shape>
|
28
android/app/src/main/res/layout/slideshow_layout.xml
Normal file
28
android/app/src/main/res/layout/slideshow_layout.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/widget_container">
|
||||
<ImageView
|
||||
android:id="@+id/widget_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"
|
||||
android:visibility="visible"
|
||||
tools:visibility="visible"
|
||||
android:background="@drawable/widget_background"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/widget_img"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"
|
||||
android:visibility="visible"
|
||||
tools:visibility="visible"
|
||||
/>
|
||||
</LinearLayout>
|
9
android/app/src/main/res/xml/slideshow_widget.xml
Normal file
9
android/app/src/main/res/xml/slideshow_widget.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="100dp"
|
||||
android:minHeight="100dp"
|
||||
android:updatePeriodMillis="900000"
|
||||
android:initialLayout="@layout/slideshow_layout"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:widgetCategory="home_screen">
|
||||
</appwidget-provider>
|
136
ios/Podfile.lock
136
ios/Podfile.lock
|
@ -10,30 +10,30 @@ PODS:
|
|||
- Flutter
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (10.9.0):
|
||||
- FirebaseCore (= 10.9.0)
|
||||
- Firebase/Messaging (10.9.0):
|
||||
- Firebase/CoreOnly (10.18.0):
|
||||
- FirebaseCore (= 10.18.0)
|
||||
- Firebase/Messaging (10.18.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 10.9.0)
|
||||
- firebase_core (2.13.1):
|
||||
- Firebase/CoreOnly (= 10.9.0)
|
||||
- FirebaseMessaging (~> 10.18.0)
|
||||
- firebase_core (2.24.2):
|
||||
- Firebase/CoreOnly (= 10.18.0)
|
||||
- Flutter
|
||||
- firebase_messaging (14.6.2):
|
||||
- Firebase/Messaging (= 10.9.0)
|
||||
- firebase_messaging (14.7.10):
|
||||
- Firebase/Messaging (= 10.18.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseCore (10.9.0):
|
||||
- FirebaseCore (10.18.0):
|
||||
- FirebaseCoreInternal (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Logger (~> 7.8)
|
||||
- FirebaseCoreInternal (10.19.0):
|
||||
- GoogleUtilities/Environment (~> 7.12)
|
||||
- GoogleUtilities/Logger (~> 7.12)
|
||||
- FirebaseCoreInternal (10.21.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- FirebaseInstallations (10.19.0):
|
||||
- FirebaseInstallations (10.21.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebaseMessaging (10.9.0):
|
||||
- FirebaseMessaging (10.18.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleDataTransport (~> 9.2)
|
||||
|
@ -70,9 +70,6 @@ PODS:
|
|||
- fluttertoast (0.0.2):
|
||||
- Flutter
|
||||
- Toast
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- GoogleDataTransport (9.3.0):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
|
@ -94,6 +91,8 @@ PODS:
|
|||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- home_widget (0.0.1):
|
||||
- Flutter
|
||||
- image_editor_common (1.0.0):
|
||||
- Flutter
|
||||
- in_app_purchase_storekit (0.0.1):
|
||||
|
@ -158,23 +157,23 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- PromisesObjC (2.3.1)
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- receive_sharing_intent (0.0.1):
|
||||
- receive_sharing_intent (1.6.7):
|
||||
- Flutter
|
||||
- screen_brightness_ios (0.1.0):
|
||||
- Flutter
|
||||
- SDWebImage (5.18.7):
|
||||
- SDWebImage/Core (= 5.18.7)
|
||||
- SDWebImage/Core (5.18.7)
|
||||
- SDWebImageWebPCoder (0.14.2):
|
||||
- SDWebImage (5.18.11):
|
||||
- SDWebImage/Core (= 5.18.11)
|
||||
- SDWebImage/Core (5.18.11)
|
||||
- SDWebImageWebPCoder (0.14.5):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.17)
|
||||
- Sentry/HybridSDK (8.9.1):
|
||||
- SentryPrivate (= 8.9.1)
|
||||
- Sentry/HybridSDK (8.18.0):
|
||||
- SentryPrivate (= 8.18.0)
|
||||
- sentry_flutter (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (= 8.9.1)
|
||||
- SentryPrivate (8.9.1)
|
||||
- Sentry/HybridSDK (= 8.18.0)
|
||||
- SentryPrivate (8.18.0)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
|
@ -182,15 +181,15 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FMDB (>= 2.7.5)
|
||||
- sqlite3 (3.45.0):
|
||||
- sqlite3/common (= 3.45.0)
|
||||
- sqlite3/common (3.45.0)
|
||||
- sqlite3/fts5 (3.45.0):
|
||||
- FlutterMacOS
|
||||
- sqlite3 (3.45.1):
|
||||
- sqlite3/common (= 3.45.1)
|
||||
- sqlite3/common (3.45.1)
|
||||
- sqlite3/fts5 (3.45.1):
|
||||
- sqlite3/common
|
||||
- sqlite3/perf-threadsafe (3.45.0):
|
||||
- sqlite3/perf-threadsafe (3.45.1):
|
||||
- sqlite3/common
|
||||
- sqlite3/rtree (3.45.0):
|
||||
- sqlite3/rtree (3.45.1):
|
||||
- sqlite3/common
|
||||
- sqlite3_flutter_libs (0.0.1):
|
||||
- Flutter
|
||||
|
@ -198,13 +197,14 @@ PODS:
|
|||
- sqlite3/fts5
|
||||
- sqlite3/perf-threadsafe
|
||||
- sqlite3/rtree
|
||||
- Toast (4.0.0)
|
||||
- Toast (4.1.0)
|
||||
- uni_links (0.0.1):
|
||||
- Flutter
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- video_player_avfoundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- video_thumbnail (0.0.1):
|
||||
- Flutter
|
||||
- libwebp
|
||||
|
@ -212,6 +212,8 @@ PODS:
|
|||
- Flutter
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- workmanager (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
||||
|
@ -231,6 +233,7 @@ DEPENDENCIES:
|
|||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- flutter_sodium (from `.symlinks/plugins/flutter_sodium/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- home_widget (from `.symlinks/plugins/home_widget/ios`)
|
||||
- image_editor_common (from `.symlinks/plugins/image_editor_common/ios`)
|
||||
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||
|
@ -252,14 +255,15 @@ DEPENDENCIES:
|
|||
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
|
||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
|
||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
|
||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||
- video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`)
|
||||
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
|
@ -268,7 +272,6 @@ SPEC REPOS:
|
|||
- FirebaseCoreInternal
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- FMDB
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- libwebp
|
||||
|
@ -321,6 +324,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/flutter_sodium/ios"
|
||||
fluttertoast:
|
||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||
home_widget:
|
||||
:path: ".symlinks/plugins/home_widget/ios"
|
||||
image_editor_common:
|
||||
:path: ".symlinks/plugins/image_editor_common/ios"
|
||||
in_app_purchase_storekit:
|
||||
|
@ -364,7 +369,7 @@ EXTERNAL SOURCES:
|
|||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
:path: ".symlinks/plugins/sqflite/darwin"
|
||||
sqlite3_flutter_libs:
|
||||
:path: ".symlinks/plugins/sqlite3_flutter_libs/ios"
|
||||
uni_links:
|
||||
|
@ -372,27 +377,29 @@ EXTERNAL SOURCES:
|
|||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
video_player_avfoundation:
|
||||
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
||||
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
||||
video_thumbnail:
|
||||
:path: ".symlinks/plugins/video_thumbnail/ios"
|
||||
volume_controller:
|
||||
:path: ".symlinks/plugins/volume_controller/ios"
|
||||
wakelock_plus:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
workmanager:
|
||||
:path: ".symlinks/plugins/workmanager/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
background_fetch: 896944864b038d2837fc750d470e9841e1e6a363
|
||||
battery_info: 09f5c9ee65394f2291c8c6227bedff345b8a730c
|
||||
connectivity_plus: 53efb943fc2882c8512d84c45707bcabc4c36076
|
||||
device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||
Firebase: bd152f0f3d278c4060c5c71359db08ebcfd5a3e2
|
||||
firebase_core: ce64b0941c6d87c6ef5022ae9116a158236c8c94
|
||||
firebase_messaging: 42912365e62efc1ea3e00724e5eecba6068ddb88
|
||||
FirebaseCore: b68d3616526ec02e4d155166bbafb8eca64af557
|
||||
FirebaseCoreInternal: b444828ea7cfd594fca83046b95db98a2be4f290
|
||||
FirebaseInstallations: 033d199474164db20c8350736842a94fe717b960
|
||||
FirebaseMessaging: 6b7052cc3da7bc8e5f72bef871243e8f04a14eed
|
||||
Firebase: 414ad272f8d02dfbf12662a9d43f4bba9bec2a06
|
||||
firebase_core: 0af4a2b24f62071f9bf283691c0ee41556dcb3f5
|
||||
firebase_messaging: 90e8a6db84b6e1e876cebce4f30f01dc495e7014
|
||||
FirebaseCore: 2322423314d92f946219c8791674d2f3345b598f
|
||||
FirebaseCoreInternal: 43c1788eaeee9d1b97caaa751af567ce11010d00
|
||||
FirebaseInstallations: 390ea1d10a4d02b20c965cbfd527ee9b3b412acb
|
||||
FirebaseMessaging: 9bc34a98d2e0237e1b121915120d4d48ddcf301e
|
||||
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b
|
||||
|
@ -403,15 +410,15 @@ SPEC CHECKSUMS:
|
|||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
flutter_sodium: c84426b4de738514b5b66cfdeb8a06634e72fe0b
|
||||
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
|
||||
GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34
|
||||
home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57
|
||||
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
|
||||
in_app_purchase_storekit: 4fb7ee9e824b1f09107fbfbbce8c4b276366dc43
|
||||
in_app_purchase_storekit: 9e9931234f0adcf71ae323f8c83785b96030edf1
|
||||
integration_test: 13825b8a9334a850581300559b8839134b124670
|
||||
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
|
||||
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
|
||||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||
local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac
|
||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
||||
media_extension: 6d30dc1431ebaa63f43c397c37917b1a0a597a4c
|
||||
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
||||
|
@ -425,30 +432,31 @@ SPEC CHECKSUMS:
|
|||
onnxruntime-objc: ae7acec7a3d03eaf072d340afed7a35635c1c2a6
|
||||
open_mail_app: 794172f6a22cd16319d3ddaf45e945b2f74952b0
|
||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||
photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604
|
||||
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1
|
||||
receive_sharing_intent: 9ca20ae908f83c36ddaaaa8c9bd30ce4700495e8
|
||||
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
|
||||
SDWebImage: f9258c58221ed854cfa0e2b80ee4033710b1c6d3
|
||||
SDWebImageWebPCoder: 633b813fca24f1de5e076bcd7f720c038b23892b
|
||||
Sentry: e3203780941722a1fcfee99e351de14244c7f806
|
||||
sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c
|
||||
SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13
|
||||
SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457
|
||||
SDWebImageWebPCoder: c94f09adbca681822edad9e532ac752db713eabf
|
||||
Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e
|
||||
sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364
|
||||
SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085
|
||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||
sqlite3: f307b6291c4db7b5086c38d6237446b98a738581
|
||||
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
sqlite3: 73b7fc691fdc43277614250e04d183740cb15078
|
||||
sqlite3_flutter_libs: aeb4d37509853dfa79d9b59386a2dac5dd079428
|
||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||
Toast: ec33c32b8688982cecc6348adeae667c1b9938da
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126
|
||||
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
||||
video_player_avfoundation: e9e6f9cae7d7a6d9b43519b0aab382bca60fcfd1
|
||||
video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1
|
||||
volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
|
||||
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
|
||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||
|
||||
PODFILE CHECKSUM: c1a8f198a245ed1f10e40b617efdb129b021b225
|
||||
|
||||
|
|
|
@ -16,10 +16,20 @@
|
|||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
DA6BE5E826B3BC8600656280 /* BuildFile in Resources */ = {isa = PBXBuildFile; };
|
||||
DA6BE5E826B3BC8600656280 /* (null) in Resources */ = {isa = PBXBuildFile; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
6DACD84B2B755B0800BA9516 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -40,6 +50,8 @@
|
|||
2772189F270F596900FFE3CC /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
6A1E2DBA51995DADEC1ED952 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
6DACD83C2B755B0600BA9516 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||
6DACD83E2B755B0600BA9516 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -140,6 +152,8 @@
|
|||
children = (
|
||||
274DC65025920DD100F526A4 /* StoreKit.framework */,
|
||||
F82DAEEB9A7D9FD00E0FFA1E /* Pods_Runner.framework */,
|
||||
6DACD83C2B755B0600BA9516 /* WidgetKit.framework */,
|
||||
6DACD83E2B755B0600BA9516 /* SwiftUI.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -152,6 +166,7 @@
|
|||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
CA5A2D2FAC2FC326D78201AE /* [CP] Check Pods Manifest.lock */,
|
||||
6DACD84B2B755B0800BA9516 /* Embed Foundation Extensions */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
|
@ -175,6 +190,7 @@
|
|||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1520;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "The Chromium Authors";
|
||||
TargetAttributes = {
|
||||
|
@ -213,7 +229,7 @@
|
|||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
DA6BE5E826B3BC8600656280 /* BuildFile in Resources */,
|
||||
DA6BE5E826B3BC8600656280 /* (null) in Resources */,
|
||||
277218A0270F596900FFE3CC /* GoogleService-Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -259,7 +275,6 @@
|
|||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework",
|
||||
|
@ -289,6 +304,7 @@
|
|||
"${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_sodium/flutter_sodium.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/home_widget/home_widget.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/image_editor_common/image_editor_common.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/in_app_purchase_storekit/in_app_purchase_storekit.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
|
||||
|
@ -320,6 +336,7 @@
|
|||
"${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/volume_controller/volume_controller.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/wakelock_plus/wakelock_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/workmanager/workmanager.framework",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/media_kit_libs_ios_video/Ass.framework/Ass",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/media_kit_libs_ios_video/Avcodec.framework/Avcodec",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/media_kit_libs_ios_video/Avfilter.framework/Avfilter",
|
||||
|
@ -341,7 +358,6 @@
|
|||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework",
|
||||
|
@ -371,6 +387,7 @@
|
|||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_sodium.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/home_widget.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_editor_common.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/in_app_purchase_storekit.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
|
||||
|
@ -402,6 +419,7 @@
|
|||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/volume_controller.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/workmanager.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Ass.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Avcodec.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Avfilter.framework",
|
||||
|
@ -527,7 +545,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MACH_O_TYPE = mh_execute;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -559,6 +577,7 @@
|
|||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Ente Photos";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -629,7 +648,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MACH_O_TYPE = mh_execute;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
|
@ -687,7 +706,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MACH_O_TYPE = mh_execute;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -720,6 +739,7 @@
|
|||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Ente Photos";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -758,6 +778,7 @@
|
|||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Ente Photos";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import UIKit
|
||||
import Flutter
|
||||
import UIKit
|
||||
import workmanager
|
||||
|
||||
@UIApplicationMain
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
|
@ -7,22 +8,21 @@ import Flutter
|
|||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
var flutter_native_splash = 1
|
||||
UIApplication.shared.isStatusBarHidden = false
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
|
||||
}
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
override func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
}
|
||||
override func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
signal(SIGPIPE, SIG_IGN)
|
||||
}
|
||||
|
||||
override func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
}
|
||||
}
|
||||
override func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
signal(SIGPIPE, SIG_IGN)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,5 +8,9 @@
|
|||
<array>
|
||||
<string>webcredentials:web.ente.io</string>
|
||||
</array>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.io.ente.frame.SlideshowWidget</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import "dart:async";
|
||||
import 'dart:convert';
|
||||
import "dart:io";
|
||||
import 'dart:typed_data';
|
||||
|
@ -31,6 +32,7 @@ import 'package:photos/services/search_service.dart';
|
|||
import 'package:photos/services/sync_service.dart';
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
import 'package:photos/utils/file_uploader.dart';
|
||||
import "package:photos/utils/home_widget_util.dart";
|
||||
import 'package:photos/utils/validator_util.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import "package:tuple/tuple.dart";
|
||||
|
@ -174,6 +176,7 @@ class Configuration {
|
|||
MemoriesService.instance.clearCache();
|
||||
BillingService.instance.clearCache();
|
||||
SearchService.instance.clearCache();
|
||||
unawaited(clearHomeWidget());
|
||||
Bus.instance.fire(UserLoggedOutEvent());
|
||||
} else {
|
||||
await _preferences.setBool("auto_logout", true);
|
||||
|
|
|
@ -67,6 +67,8 @@ const galleryGridSpacing = 2.0;
|
|||
|
||||
const kSearchSectionLimit = 7;
|
||||
|
||||
const iOSGroupID = "group.io.ente.frame.SlideshowWidget";
|
||||
|
||||
const blackThumbnailBase64 = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEB' +
|
||||
'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQ' +
|
||||
'EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARC' +
|
||||
|
|
|
@ -46,8 +46,10 @@ import 'package:photos/ui/tools/app_lock.dart';
|
|||
import 'package:photos/ui/tools/lock_screen.dart';
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
import 'package:photos/utils/file_uploader.dart';
|
||||
import "package:photos/utils/home_widget_util.dart";
|
||||
import 'package:photos/utils/local_settings.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import "package:workmanager/workmanager.dart";
|
||||
|
||||
final _logger = Logger("main");
|
||||
|
||||
|
@ -61,14 +63,54 @@ const kBGPushTimeout = Duration(seconds: 28);
|
|||
const kFGTaskDeathTimeoutInMicroseconds = 5000000;
|
||||
const kBackgroundLockLatency = Duration(seconds: 3);
|
||||
|
||||
@pragma("vm:entry-point")
|
||||
void initSlideshowWidget() {
|
||||
Workmanager().executeTask(
|
||||
(taskName, inputData) async {
|
||||
try {
|
||||
if (await countHomeWidgets() != 0) {
|
||||
await _init(true, via: 'runViaSlideshowWidget');
|
||||
await initHomeWidget();
|
||||
}
|
||||
return true;
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error in initSlideshowWidget", e, s);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> initWorkmanager() async {
|
||||
await Workmanager()
|
||||
.initialize(initSlideshowWidget, isInDebugMode: kDebugMode);
|
||||
await Workmanager().registerPeriodicTask(
|
||||
"slideshow-widget",
|
||||
"updateSlideshowWidget",
|
||||
initialDelay: const Duration(seconds: 10),
|
||||
frequency: const Duration(
|
||||
minutes: 15,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void main() async {
|
||||
debugRepaintRainbowEnabled = false;
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
MediaKit.ensureInitialized();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
unawaited(
|
||||
initWorkmanager().catchError((e, s) {
|
||||
_logger.severe("Error in initWorkmanager", e, s);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
final savedThemeMode = await AdaptiveTheme.getThemeMode();
|
||||
await _runInForeground(savedThemeMode);
|
||||
unawaited(BackgroundFetch.registerHeadlessTask(_headlessTaskHandler));
|
||||
FlutterDisplayMode.setHighRefreshRate().ignore();
|
||||
if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate().ignore();
|
||||
}
|
||||
|
||||
Future<void> _runInForeground(AdaptiveThemeMode? savedThemeMode) async {
|
||||
|
@ -77,6 +119,7 @@ Future<void> _runInForeground(AdaptiveThemeMode? savedThemeMode) async {
|
|||
await _init(false, via: 'mainMethod');
|
||||
final Locale locale = await getLocale();
|
||||
unawaited(_scheduleFGSync('appStart in FG'));
|
||||
|
||||
runApp(
|
||||
AppLock(
|
||||
builder: (args) =>
|
||||
|
|
|
@ -210,6 +210,11 @@ class FavoritesService {
|
|||
return _collectionsService.getCollectionByID(_cachedFavoritesCollectionID!);
|
||||
}
|
||||
|
||||
Future<int?> getFavoriteCollectionID() async {
|
||||
final collection = await _getFavoritesCollection();
|
||||
return collection?.id;
|
||||
}
|
||||
|
||||
Future<int> _getOrCreateFavoriteCollectionID() async {
|
||||
if (_cachedFavoritesCollectionID != null) {
|
||||
return _cachedFavoritesCollectionID!;
|
||||
|
|
|
@ -120,11 +120,13 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|||
debugPrint(
|
||||
"TabChange going from $_selectedTabIndex to ${event.selectedIndex} souce: ${event.source}",
|
||||
);
|
||||
_pageController.animateToPage(
|
||||
event.selectedIndex,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
if (_pageController.hasClients) {
|
||||
_pageController.animateToPage(
|
||||
event.selectedIndex,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
_subscriptionPurchaseEvent =
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import "package:flutter/foundation.dart";
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
|
|
@ -31,6 +31,7 @@ class _NoResultWidgetState extends State<NoResultWidget> {
|
|||
InheritedAllSectionsExamples.of(context)
|
||||
.allSectionsExamplesFuture
|
||||
.then((value) {
|
||||
if (value.isEmpty) return;
|
||||
for (int i = 0; i < searchTypes.length; i++) {
|
||||
final querySuggestions = <String>[];
|
||||
for (int j = 0; j < 2 && j < value[i].length; j++) {
|
||||
|
|
136
lib/utils/home_widget_util.dart
Normal file
136
lib/utils/home_widget_util.dart
Normal file
|
@ -0,0 +1,136 @@
|
|||
import "dart:math";
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import 'package:home_widget/home_widget.dart' as hw;
|
||||
import "package:logging/logging.dart";
|
||||
import "package:photos/core/configuration.dart";
|
||||
import "package:photos/core/constants.dart";
|
||||
import "package:photos/db/files_db.dart";
|
||||
import "package:photos/models/file/file_type.dart";
|
||||
import "package:photos/services/favorites_service.dart";
|
||||
import "package:photos/utils/file_util.dart";
|
||||
import "package:photos/utils/preload_util.dart";
|
||||
|
||||
Future<int> countHomeWidgets() async {
|
||||
return await hw.HomeWidget.getWidgetCount(
|
||||
name: 'SlideshowWidgetProvider',
|
||||
androidName: 'SlideshowWidgetProvider',
|
||||
qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider',
|
||||
iOSName: 'SlideshowWidget',
|
||||
) ??
|
||||
0;
|
||||
}
|
||||
|
||||
Future<void> initHomeWidget() async {
|
||||
final Logger logger = Logger("initHomeWidget");
|
||||
final user = Configuration.instance.getUserID();
|
||||
|
||||
if (user == null) {
|
||||
await clearHomeWidget();
|
||||
throw Exception("User not found");
|
||||
}
|
||||
|
||||
final collectionID =
|
||||
await FavoritesService.instance.getFavoriteCollectionID();
|
||||
if (collectionID == null) {
|
||||
await clearHomeWidget();
|
||||
throw Exception("Collection not found");
|
||||
}
|
||||
|
||||
try {
|
||||
await hw.HomeWidget.setAppGroupId(iOSGroupID);
|
||||
final res = await FilesDB.instance.getFilesInCollection(
|
||||
collectionID,
|
||||
galleryLoadStartTime,
|
||||
galleryLoadEndTime,
|
||||
);
|
||||
|
||||
final previousGeneratedId =
|
||||
await hw.HomeWidget.getWidgetData<int>("home_widget_last_img");
|
||||
final files = res.files.where(
|
||||
(element) =>
|
||||
element.generatedID != previousGeneratedId &&
|
||||
element.fileType == FileType.image,
|
||||
);
|
||||
final randomNumber = Random().nextInt(files.length);
|
||||
final randomFile = files.elementAt(randomNumber);
|
||||
final fullImage = await getFileFromServer(randomFile);
|
||||
if (fullImage == null) throw Exception("File not found");
|
||||
|
||||
Image img = Image.file(fullImage);
|
||||
var imgProvider = img.image;
|
||||
await PreloadImage.loadImage(imgProvider);
|
||||
|
||||
img = Image.file(fullImage);
|
||||
imgProvider = img.image;
|
||||
|
||||
final image = await decodeImageFromList(await fullImage.readAsBytes());
|
||||
final width = image.width.toDouble();
|
||||
final height = image.height.toDouble();
|
||||
final size = min(min(width, height), 1024.0);
|
||||
|
||||
final widget = ClipRRect(
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black,
|
||||
image: DecorationImage(image: imgProvider, fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await hw.HomeWidget.renderFlutterWidget(
|
||||
widget,
|
||||
logicalSize: Size(size, size),
|
||||
key: "slideshow",
|
||||
);
|
||||
|
||||
await hw.HomeWidget.updateWidget(
|
||||
name: 'SlideshowWidgetProvider',
|
||||
androidName: 'SlideshowWidgetProvider',
|
||||
qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider',
|
||||
iOSName: 'SlideshowWidget',
|
||||
);
|
||||
|
||||
if (randomFile.generatedID != null) {
|
||||
await hw.HomeWidget.saveWidgetData<int>(
|
||||
"home_widget_last_img",
|
||||
randomFile.generatedID!,
|
||||
);
|
||||
}
|
||||
|
||||
logger.info(
|
||||
">>> SlideshowWidget rendered with size ${width}x$height",
|
||||
);
|
||||
} catch (_) {
|
||||
throw Exception("Error rendering widget");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> clearHomeWidget() async {
|
||||
final previousGeneratedId =
|
||||
await hw.HomeWidget.getWidgetData<int>("home_widget_last_img");
|
||||
if (previousGeneratedId == null) return;
|
||||
|
||||
final Logger logger = Logger("clearHomeWidget");
|
||||
|
||||
logger.info("Clearing SlideshowWidget");
|
||||
await hw.HomeWidget.saveWidgetData(
|
||||
"slideshow",
|
||||
null,
|
||||
);
|
||||
|
||||
await hw.HomeWidget.updateWidget(
|
||||
name: 'SlideshowWidgetProvider',
|
||||
androidName: 'SlideshowWidgetProvider',
|
||||
qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider',
|
||||
iOSName: 'SlideshowWidget',
|
||||
);
|
||||
await hw.HomeWidget.saveWidgetData<int>(
|
||||
"home_widget_last_img",
|
||||
null,
|
||||
);
|
||||
logger.info(">>> SlideshowWidget cleared");
|
||||
}
|
43
lib/utils/preload_util.dart
Normal file
43
lib/utils/preload_util.dart
Normal file
|
@ -0,0 +1,43 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class PreloadImage {
|
||||
static Future<void> loadImage(ImageProvider provider) {
|
||||
final config = ImageConfiguration(
|
||||
bundle: rootBundle,
|
||||
devicePixelRatio: 1,
|
||||
platform: defaultTargetPlatform,
|
||||
);
|
||||
final Completer<void> completer = Completer();
|
||||
final ImageStream stream = provider.resolve(config);
|
||||
|
||||
late final ImageStreamListener listener;
|
||||
|
||||
listener = ImageStreamListener(
|
||||
(ImageInfo image, bool sync) {
|
||||
debugPrint("Image ${image.debugLabel} finished loading");
|
||||
completer.complete();
|
||||
stream.removeListener(listener);
|
||||
},
|
||||
onError: (dynamic exception, StackTrace? stackTrace) {
|
||||
completer.complete();
|
||||
stream.removeListener(listener);
|
||||
FlutterError.reportError(
|
||||
FlutterErrorDetails(
|
||||
context: ErrorDescription('image failed to load'),
|
||||
library: 'image resource service',
|
||||
exception: exception,
|
||||
stack: stackTrace,
|
||||
silent: true,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
stream.addListener(listener);
|
||||
return completer.future;
|
||||
}
|
||||
}
|
|
@ -108,8 +108,8 @@ Future<List<EnteFile>> convertIncomingSharedMediaToFile(
|
|||
) async {
|
||||
final List<EnteFile> localFiles = [];
|
||||
for (var media in sharedMedia) {
|
||||
if (!(media.type == SharedMediaType.IMAGE ||
|
||||
media.type == SharedMediaType.VIDEO)) {
|
||||
if (!(media.type == SharedMediaType.image ||
|
||||
media.type == SharedMediaType.video)) {
|
||||
_logger.warning(
|
||||
"ignore unsupported file type ${media.type.toString()} path: ${media.path}",
|
||||
);
|
||||
|
@ -149,7 +149,7 @@ Future<List<EnteFile>> convertIncomingSharedMediaToFile(
|
|||
enteFile.localID = sharedMediaIdentifier + enteFile.title!;
|
||||
enteFile.collectionID = collectionID;
|
||||
enteFile.fileType =
|
||||
media.type == SharedMediaType.IMAGE ? FileType.image : FileType.video;
|
||||
media.type == SharedMediaType.image ? FileType.image : FileType.video;
|
||||
if (enteFile.fileType == FileType.image) {
|
||||
final exifTime = await getCreationTimeFromEXIF(ioFile, null);
|
||||
if (exifTime != null) {
|
||||
|
|
459
pubspec.lock
459
pubspec.lock
File diff suppressed because it is too large
Load diff
35
pubspec.yaml
35
pubspec.yaml
|
@ -13,6 +13,8 @@ description: ente photos application
|
|||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
|
||||
version: 0.8.64+584
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
||||
|
@ -89,6 +91,10 @@ dependencies:
|
|||
fluttertoast: ^8.0.6
|
||||
freezed_annotation: ^2.2.0
|
||||
google_nav_bar: ^5.0.5
|
||||
home_widget:
|
||||
git:
|
||||
url: https://github.com/prateekmedia/FlutterHomeWidget
|
||||
ref: main
|
||||
html_unescape: ^2.0.0
|
||||
http: ^1.1.0
|
||||
image: ^4.0.17
|
||||
|
@ -129,13 +135,13 @@ dependencies:
|
|||
path: #dart
|
||||
path_provider: ^2.1.1
|
||||
pedantic: ^1.9.2
|
||||
photo_manager: ^2.5.0
|
||||
photo_manager: ^2.8.1
|
||||
photo_view: ^0.14.0
|
||||
pinput: ^1.2.2
|
||||
pointycastle: ^3.7.3
|
||||
provider: ^6.0.0
|
||||
quiver: ^3.0.1
|
||||
receive_sharing_intent: ^1.4.5
|
||||
receive_sharing_intent: ^1.6.7
|
||||
scrollable_positioned_list: ^0.3.5
|
||||
sentry: ^7.9.0
|
||||
sentry_flutter: ^7.9.0
|
||||
|
@ -169,12 +175,13 @@ dependencies:
|
|||
wallpaper_manager_flutter: ^0.0.2
|
||||
wechat_assets_picker: ^8.6.3
|
||||
widgets_to_image: ^0.0.2
|
||||
workmanager: ^0.5.2
|
||||
|
||||
dependency_overrides:
|
||||
# current fork of tfite_flutter_helper depends on ffi: ^1.x.x
|
||||
# but we need ffi: ^2.0.1 for newer packages. The original tfite_flutter_helper
|
||||
#
|
||||
ffi: ^2.0.1
|
||||
ffi: ^2.0.0
|
||||
video_player:
|
||||
git:
|
||||
url: https://github.com/ente-io/packages.git
|
||||
|
@ -185,8 +192,6 @@ dependency_overrides:
|
|||
flutter_intl:
|
||||
enabled: true
|
||||
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.7
|
||||
flutter_driver:
|
||||
|
@ -237,16 +242,16 @@ flutter:
|
|||
- assets/models/scenes/
|
||||
- assets/models/clip/
|
||||
fonts:
|
||||
- family: Inter
|
||||
fonts:
|
||||
- asset: fonts/Inter-Regular.ttf
|
||||
- asset: fonts/Inter-Medium.ttf
|
||||
- asset: fonts/Inter-Light.ttf
|
||||
- asset: fonts/Inter-SemiBold.ttf
|
||||
- asset: fonts/Inter-Bold.ttf
|
||||
- family: Montserrat
|
||||
fonts:
|
||||
- asset: fonts/Montserrat-Bold.ttf
|
||||
- family: Inter
|
||||
fonts:
|
||||
- asset: fonts/Inter-Regular.ttf
|
||||
- asset: fonts/Inter-Medium.ttf
|
||||
- asset: fonts/Inter-Light.ttf
|
||||
- asset: fonts/Inter-SemiBold.ttf
|
||||
- asset: fonts/Inter-Bold.ttf
|
||||
- family: Montserrat
|
||||
fonts:
|
||||
- asset: fonts/Montserrat-Bold.ttf
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
|
|
Loading…
Add table
Reference in a new issue