Compare commits

...

9 commits

Author SHA1 Message Date
ashilkn 9385b30159 init home widget on app init only if app init is from foreground 2024-03-11 18:46:33 +05:30
ashilkn 56bc0437fc update assets of home widget's default state 2024-03-11 17:31:43 +05:30
ashilkn 7ce67b33b3 refactor + minor changes 2024-03-11 16:49:20 +05:30
ashilkn 93559e452a refactor 2024-03-11 16:39:45 +05:30
ashilkn 2a895e9245 create HomeWidgetService 2024-03-11 16:39:09 +05:30
Prateek Sunal 668f520042 fix: schedule first after 15 minutes 2024-03-11 00:25:28 +05:30
Prateek Sunal 08a433bb6f fix: widget doesn't gets updated 2024-03-11 00:23:36 +05:30
Prateek Sunal 150da15683 fix: init home widget on favorites fetch 2024-03-11 00:01:53 +05:30
Prateek Sunal 7ddb80c64e feat: upscale images to 8x 2024-03-10 23:57:18 +05:30
10 changed files with 173 additions and 153 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 343 KiB

View file

@ -24,6 +24,7 @@ import 'package:photos/models/private_key_attributes.dart';
import 'package:photos/services/billing_service.dart';
import 'package:photos/services/collections_service.dart';
import 'package:photos/services/favorites_service.dart';
import "package:photos/services/home_widget_service.dart";
import 'package:photos/services/ignored_files_service.dart';
import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart';
import 'package:photos/services/memories_service.dart';
@ -31,7 +32,6 @@ 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";
@ -175,7 +175,7 @@ class Configuration {
MemoriesService.instance.clearCache();
BillingService.instance.clearCache();
SearchService.instance.clearCache();
unawaited(clearHomeWidget());
unawaited(HomeWidgetService.instance.clearHomeWidget());
Bus.instance.fire(UserLoggedOutEvent());
} else {
await _preferences.setBool("auto_logout", true);

View file

@ -27,6 +27,7 @@ import 'package:photos/services/collections_service.dart';
import "package:photos/services/entity_service.dart";
import 'package:photos/services/favorites_service.dart';
import 'package:photos/services/feature_flag_service.dart';
import 'package:photos/services/home_widget_service.dart';
import 'package:photos/services/local_file_update_service.dart';
import 'package:photos/services/local_sync_service.dart';
import "package:photos/services/location_service.dart";
@ -46,7 +47,6 @@ 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';
@ -110,8 +110,8 @@ ThemeMode _themeMode(AdaptiveThemeMode? savedThemeMode) {
Future<void> _homeWidgetSync() async {
if (!Platform.isAndroid) return;
try {
if (await countHomeWidgets() != 0) {
await initHomeWidget();
if (await HomeWidgetService.instance.countHomeWidgets() != 0) {
await HomeWidgetService.instance.initHomeWidget();
}
} catch (e, s) {
_logger.severe("Error in initSlideshowWidget", e, s);
@ -210,6 +210,10 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
LocalFileUpdateService.instance.init(preferences);
SearchService.instance.init();
StorageBonusService.instance.init(preferences);
if (!isBackground) {
unawaited(HomeWidgetService.instance.initHomeWidget());
}
if (Platform.isIOS) {
// ignore: unawaited_futures
PushService.instance.init().then((_) {
@ -275,9 +279,15 @@ Future<void> _scheduleHeartBeat(
}
Future<void> _scheduleFGHomeWidgetSync() async {
Future.delayed(kFGHomeWidgetSyncFrequency, () async {
unawaited(_homeWidgetSyncPeriodic());
});
}
Future<void> _homeWidgetSyncPeriodic() async {
await _homeWidgetSync();
Future.delayed(kFGHomeWidgetSyncFrequency, () async {
unawaited(_scheduleFGHomeWidgetSync());
unawaited(_homeWidgetSyncPeriodic());
});
}

View file

@ -0,0 +1,157 @@
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";
class HomeWidgetService {
final Logger _logger = Logger((HomeWidgetService).toString());
HomeWidgetService._privateConstructor();
static final HomeWidgetService instance =
HomeWidgetService._privateConstructor();
Future<void> initHomeWidget() async {
final isLoggedIn = Configuration.instance.isLoggedIn();
if (!isLoggedIn) {
await clearHomeWidget();
_logger.info("user not logged in");
return;
}
final collectionID =
await FavoritesService.instance.getFavoriteCollectionID();
if (collectionID == null) {
await clearHomeWidget();
_logger.info("Favorite collection not found");
return;
}
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");
if (res.files.length == 1 &&
res.files[0].generatedID == previousGeneratedId) {
_logger
.info("Only one image found and it's the same as the previous one");
return;
}
if (res.files.isEmpty) {
await clearHomeWidget();
_logger.info("No images found");
return;
}
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",
);
if (randomFile.generatedID != null) {
await hw.HomeWidget.saveWidgetData<int>(
"home_widget_last_img",
randomFile.generatedID!,
);
}
await hw.HomeWidget.updateWidget(
name: 'SlideshowWidgetProvider',
androidName: 'SlideshowWidgetProvider',
qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider',
iOSName: 'SlideshowWidget',
);
_logger.info(
">>> SlideshowWidget rendered with size ${width}x$height",
);
} catch (e) {
_logger.severe("Error rendering widget", e);
}
}
Future<int> countHomeWidgets() async {
return await hw.HomeWidget.getWidgetCount(
name: 'SlideshowWidgetProvider',
androidName: 'SlideshowWidgetProvider',
qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider',
iOSName: 'SlideshowWidget',
) ??
0;
}
Future<void> clearHomeWidget() async {
final previousGeneratedId =
await hw.HomeWidget.getWidgetData<int>("home_widget_last_img");
if (previousGeneratedId == null) return;
_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

@ -1,147 +0,0 @@
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");
if (res.files.length == 1 &&
res.files[0].generatedID == previousGeneratedId) {
logger.info("Only one image found and it's the same as the previous one");
return;
}
if (res.files.isEmpty) {
await clearHomeWidget();
return;
}
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");
}