diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ee3a1d132..e7046d210 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -181,6 +181,21 @@ PODS: - 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): + - sqlite3/common + - sqlite3/perf-threadsafe (3.45.0): + - sqlite3/common + - sqlite3/rtree (3.45.0): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - Flutter + - sqlite3 (~> 3.45.0) + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree - Toast (4.0.0) - uni_links (0.0.1): - Flutter @@ -235,6 +250,7 @@ DEPENDENCIES: - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `.symlinks/plugins/sqflite/ios`) + - 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`) @@ -264,6 +280,7 @@ SPEC REPOS: - SDWebImageWebPCoder - Sentry - SentryPrivate + - sqlite3 - Toast EXTERNAL SOURCES: @@ -343,6 +360,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" sqflite: :path: ".symlinks/plugins/sqflite/ios" + sqlite3_flutter_libs: + :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: @@ -415,6 +434,8 @@ SPEC CHECKSUMS: share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + sqlite3: f307b6291c4db7b5086c38d6237446b98a738581 + sqlite3_flutter_libs: aeb4d37509853dfa79d9b59386a2dac5dd079428 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 03a95b930..ea4cd3588 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -311,6 +311,8 @@ "${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework", "${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", + "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", + "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", "${BUILT_PRODUCTS_DIR}/uni_links/uni_links.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework", @@ -390,6 +392,8 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uni_links.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework", diff --git a/lib/db/files_db.dart b/lib/db/files_db.dart index 2e7a760b5..39ff83210 100644 --- a/lib/db/files_db.dart +++ b/lib/db/files_db.dart @@ -15,6 +15,7 @@ import "package:photos/services/filter/db_filters.dart"; import 'package:photos/utils/file_uploader_util.dart'; import 'package:sqflite/sqflite.dart'; import 'package:sqflite_migration/sqflite_migration.dart'; +import 'package:sqlite3/sqlite3.dart' as sqlite3; class FilesDB { /* @@ -100,6 +101,7 @@ class FilesDB { // only have a single app-wide reference to the database static Future? _dbFuture; + static Future? _ffiDBFuture; Future get database async { // lazily instantiate the db the first time it is accessed @@ -107,6 +109,11 @@ class FilesDB { return _dbFuture!; } + Future get ffiDB async { + _ffiDBFuture ??= _initFFIDatabase(); + return _ffiDBFuture!; + } + // this opens the database (and creates it if it doesn't exist) Future _initDatabase() async { final Directory documentsDirectory = @@ -116,6 +123,14 @@ class FilesDB { return await openDatabaseWithMigration(path, dbConfig); } + Future _initFFIDatabase() async { + final Directory documentsDirectory = + await getApplicationDocumentsDirectory(); + final String path = join(documentsDirectory.path, _databaseName); + _logger.info("DB path " + path); + return sqlite3.sqlite3.open(path); + } + // SQL code to create the database table static List createTable(String tableName) { return [ @@ -749,6 +764,40 @@ class FilesDB { ); } + Future> getFilesCreatedWithinDurationsSync( + List> durations, + Set ignoredCollectionIDs, { + int? visibility, + String order = 'ASC', + }) async { + if (durations.isEmpty) { + return []; + } + final db = await instance.ffiDB; + String whereClause = "( "; + for (int index = 0; index < durations.length; index++) { + whereClause += "($columnCreationTime >= " + + durations[index][0].toString() + + " AND $columnCreationTime < " + + durations[index][1].toString() + + ")"; + if (index != durations.length - 1) { + whereClause += " OR "; + } else if (visibility != null) { + whereClause += ' AND $columnMMdVisibility = $visibility'; + } + } + whereClause += ")"; + final results = db.select( + 'select * from $filesTable where $whereClause order by $columnCreationTime $order', + ); + final files = convertToFiles(results); + return applyDBFilters( + files, + DBFilterOptions(ignoredCollectionIDs: ignoredCollectionIDs), + ); + } + // Files which user added to a collection manually but they are not // uploaded yet or files belonging to a collection which is marked for backup Future> getFilesPendingForUpload() async { diff --git a/lib/services/memories_service.dart b/lib/services/memories_service.dart index 646113128..de68e2dab 100644 --- a/lib/services/memories_service.dart +++ b/lib/services/memories_service.dart @@ -107,7 +107,7 @@ class MemoriesService extends ChangeNotifier { } final ignoredCollections = CollectionsService.instance.archivedOrHiddenCollectionIds(); - final files = await _filesDB.getFilesCreatedWithinDurations( + final files = await _filesDB.getFilesCreatedWithinDurationsSync( durations, ignoredCollections, visibility: visibleVisibility, diff --git a/lib/ui/home/header_widget.dart b/lib/ui/home/header_widget.dart index f75d57e77..a322382f1 100644 --- a/lib/ui/home/header_widget.dart +++ b/lib/ui/home/header_widget.dart @@ -1,12 +1,9 @@ import 'package:flutter/widgets.dart'; import 'package:logging/logging.dart'; -import 'package:photos/ui/home/memories/memories_widget.dart'; +import "package:photos/ui/home/memories/memories_widget.dart"; import 'package:photos/ui/home/status_bar_widget.dart'; class HeaderWidget extends StatelessWidget { - static const _memoriesWidget = MemoriesWidget(); - static const _statusBarWidget = StatusBarWidget(); - const HeaderWidget({ Key? key, }) : super(key: key); @@ -14,13 +11,12 @@ class HeaderWidget extends StatelessWidget { @override Widget build(BuildContext context) { Logger("Header").info("Building header widget"); - const list = [ - _statusBarWidget, - _memoriesWidget, - ]; return const Column( crossAxisAlignment: CrossAxisAlignment.start, - children: list, + children: [ + StatusBarWidget(), + MemoriesWidget(), + ], ); } } diff --git a/lib/ui/home/memories/full_screen_memory.dart b/lib/ui/home/memories/full_screen_memory.dart index bacc6adda..8e8509ba4 100644 --- a/lib/ui/home/memories/full_screen_memory.dart +++ b/lib/ui/home/memories/full_screen_memory.dart @@ -154,13 +154,13 @@ class _FullScreenMemoryState extends State { automaticallyImplyLeading: false, title: ValueListenableBuilder( valueListenable: inheritedData.indexNotifier, - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: InkWell( - onTap: () { - Navigator.pop(context); - }, - child: const Icon( + child: InkWell( + onTap: () { + Navigator.pop(context); + }, + child: const Padding( + padding: EdgeInsets.fromLTRB(4, 8, 8, 8), + child: Icon( Icons.close, color: Colors.white, //same for both themes ), @@ -180,7 +180,7 @@ class _FullScreenMemoryState extends State { ) : const SizedBox.shrink(), const SizedBox( - height: 18, + height: 10, ), Row( children: [ diff --git a/lib/ui/home/memories/memories_widget.dart b/lib/ui/home/memories/memories_widget.dart index 09f279ca1..059f10b03 100644 --- a/lib/ui/home/memories/memories_widget.dart +++ b/lib/ui/home/memories/memories_widget.dart @@ -58,7 +58,10 @@ class _MemoriesWidgetState extends State { return FutureBuilder>( future: MemoriesService.instance.getMemories(), builder: (context, snapshot) { - if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) { + if (snapshot.hasData && snapshot.data!.isEmpty) { + return const SizedBox.shrink(); + } + if (snapshot.hasError || !snapshot.hasData) { return SizedBox( height: _maxHeight + 12 + 10, child: const EnteLoadingWidget(), @@ -73,7 +76,10 @@ class _MemoriesWidgetState extends State { _buildMemories(snapshot.data!), const SizedBox(height: 10), ], - ); + ).animate().fadeIn( + duration: const Duration(milliseconds: 250), + curve: Curves.easeInOutCirc, + ); } }, ); @@ -97,13 +103,7 @@ class _MemoriesWidgetState extends State { offsetOfItem: offsetOfItem, maxHeight: _maxHeight, maxWidth: _maxWidth, - ) - .animate(delay: Duration(milliseconds: 75 * itemIndex)) - .fadeIn( - duration: const Duration(milliseconds: 250), - curve: Curves.easeInOutCubic, - ) - .slideX(begin: 0.04, end: 0); + ); }, ), ); diff --git a/lib/ui/huge_listview/draggable_scrollbar.dart b/lib/ui/huge_listview/draggable_scrollbar.dart index c943c4940..f3d215c69 100644 --- a/lib/ui/huge_listview/draggable_scrollbar.dart +++ b/lib/ui/huge_listview/draggable_scrollbar.dart @@ -103,16 +103,14 @@ class DraggableScrollbarState extends State @override Widget build(BuildContext context) { - if (widget.isEnabled) { - return Stack( - children: [ - RepaintBoundary(child: widget.child), - RepaintBoundary(child: buildThumb()), - ], - ); - } else { - return widget.child; - } + return Stack( + children: [ + RepaintBoundary(child: widget.child), + widget.isEnabled + ? RepaintBoundary(child: buildThumb()) + : const SizedBox.shrink(), + ], + ); } Widget buildThumb() => Padding( diff --git a/pubspec.lock b/pubspec.lock index c7848721e..9e2e0548b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: "direct main" description: name: archive - sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" + sha256: "20071638cbe4e5964a427cfa0e86dce55d060bc7d82d56f3554095d7239a8765" url: "https://pub.dev" source: hosted - version: "3.4.9" + version: "3.4.2" args: dependency: transitive description: @@ -133,10 +133,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.0" build_resolvers: dependency: transitive description: @@ -319,10 +319,10 @@ packages: dependency: "direct main" description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" csslib: dependency: transitive description: @@ -343,10 +343,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.1" dartx: dependency: transitive description: @@ -1478,10 +1478,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: @@ -1951,6 +1951,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + sqlite3: + dependency: "direct main" + description: + name: sqlite3 + sha256: db65233e6b99e99b2548932f55a987961bc06d82a31a0665451fa0b4fff4c3fb + url: "https://pub.dev" + source: hosted + version: "2.1.0" + sqlite3_flutter_libs: + dependency: "direct main" + description: + name: sqlite3_flutter_libs + sha256: "90963b515721d6a71e96f438175cf43c979493ed14822860a300b69694c74eb6" + url: "https://pub.dev" + source: hosted + version: "0.5.19+1" stack_trace: dependency: transitive description: @@ -2436,10 +2452,10 @@ packages: dependency: transitive description: name: xmlstream - sha256: cfc14e3f256997897df9481ae630d94c2d85ada5187ebeb868bb1aabc2c977b4 + sha256: "2d10c69a9d5fc46f71798b80ee6db15bc0d5bf560fdbdd264776cbeee0c83631" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.0.0" xxh3: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4a086e039..e0bdf833b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.38+558 +version: 0.8.44+564 environment: sdk: ">=3.0.0 <4.0.0" @@ -141,6 +141,8 @@ dependencies: shared_preferences: ^2.0.5 sqflite: ^2.3.0 sqflite_migration: ^0.3.0 + sqlite3: ^2.1.0 + sqlite3_flutter_libs: ^0.5.19+1 step_progress_indicator: ^1.0.2 styled_text: ^7.0.0 syncfusion_flutter_core: ^19.2.49