[FEAT] Home Widget for Favorites Album (#1703)

This commit is contained in:
Ashil 2024-03-01 11:40:52 +05:30 committed by GitHub
commit e26141033c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 740 additions and 332 deletions

3
.vscode/settings.json.example vendored Normal file
View file

@ -0,0 +1,3 @@
{
"dart.flutterSdkPath": "thirdparty/flutter/bin"
}

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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++) {

View 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");
}

View 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;
}
}

View file

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

File diff suppressed because it is too large Load diff

View file

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