create HomeWidgetService
This commit is contained in:
parent
668f520042
commit
2a895e9245
|
@ -24,6 +24,7 @@ import 'package:photos/models/private_key_attributes.dart';
|
||||||
import 'package:photos/services/billing_service.dart';
|
import 'package:photos/services/billing_service.dart';
|
||||||
import 'package:photos/services/collections_service.dart';
|
import 'package:photos/services/collections_service.dart';
|
||||||
import 'package:photos/services/favorites_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/ignored_files_service.dart';
|
||||||
import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart';
|
import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart';
|
||||||
import 'package:photos/services/memories_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/services/sync_service.dart';
|
||||||
import 'package:photos/utils/crypto_util.dart';
|
import 'package:photos/utils/crypto_util.dart';
|
||||||
import 'package:photos/utils/file_uploader.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:photos/utils/validator_util.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import "package:tuple/tuple.dart";
|
import "package:tuple/tuple.dart";
|
||||||
|
@ -175,7 +175,7 @@ class Configuration {
|
||||||
MemoriesService.instance.clearCache();
|
MemoriesService.instance.clearCache();
|
||||||
BillingService.instance.clearCache();
|
BillingService.instance.clearCache();
|
||||||
SearchService.instance.clearCache();
|
SearchService.instance.clearCache();
|
||||||
unawaited(clearHomeWidget());
|
unawaited(HomeWidgetService.instance.clearHomeWidget());
|
||||||
Bus.instance.fire(UserLoggedOutEvent());
|
Bus.instance.fire(UserLoggedOutEvent());
|
||||||
} else {
|
} else {
|
||||||
await _preferences.setBool("auto_logout", true);
|
await _preferences.setBool("auto_logout", true);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import 'package:photos/services/collections_service.dart';
|
||||||
import "package:photos/services/entity_service.dart";
|
import "package:photos/services/entity_service.dart";
|
||||||
import 'package:photos/services/favorites_service.dart';
|
import 'package:photos/services/favorites_service.dart';
|
||||||
import 'package:photos/services/feature_flag_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_file_update_service.dart';
|
||||||
import 'package:photos/services/local_sync_service.dart';
|
import 'package:photos/services/local_sync_service.dart';
|
||||||
import "package:photos/services/location_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/ui/tools/lock_screen.dart';
|
||||||
import 'package:photos/utils/crypto_util.dart';
|
import 'package:photos/utils/crypto_util.dart';
|
||||||
import 'package:photos/utils/file_uploader.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:photos/utils/local_settings.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
@ -110,8 +110,8 @@ ThemeMode _themeMode(AdaptiveThemeMode? savedThemeMode) {
|
||||||
Future<void> _homeWidgetSync() async {
|
Future<void> _homeWidgetSync() async {
|
||||||
if (!Platform.isAndroid) return;
|
if (!Platform.isAndroid) return;
|
||||||
try {
|
try {
|
||||||
if (await countHomeWidgets() != 0) {
|
if (await HomeWidgetService.instance.countHomeWidgets() != 0) {
|
||||||
await initHomeWidget();
|
await HomeWidgetService.instance.initHomeWidget();
|
||||||
}
|
}
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
_logger.severe("Error in initSlideshowWidget", e, s);
|
_logger.severe("Error in initSlideshowWidget", e, s);
|
||||||
|
@ -210,6 +210,7 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
||||||
LocalFileUpdateService.instance.init(preferences);
|
LocalFileUpdateService.instance.init(preferences);
|
||||||
SearchService.instance.init();
|
SearchService.instance.init();
|
||||||
StorageBonusService.instance.init(preferences);
|
StorageBonusService.instance.init(preferences);
|
||||||
|
HomeWidgetService.instance.initHomeWidget();
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
PushService.instance.init().then((_) {
|
PushService.instance.init().then((_) {
|
||||||
|
|
|
@ -15,7 +15,6 @@ import 'package:photos/services/collections_service.dart';
|
||||||
import 'package:photos/services/remote_sync_service.dart';
|
import 'package:photos/services/remote_sync_service.dart';
|
||||||
import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
|
import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
|
||||||
import 'package:photos/utils/crypto_util.dart';
|
import 'package:photos/utils/crypto_util.dart';
|
||||||
import "package:photos/utils/home_widget_util.dart";
|
|
||||||
|
|
||||||
class FavoritesService {
|
class FavoritesService {
|
||||||
late Configuration _config;
|
late Configuration _config;
|
||||||
|
@ -52,7 +51,6 @@ class FavoritesService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await _warmUpCache();
|
await _warmUpCache();
|
||||||
await _checkHomeWidget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -68,12 +66,6 @@ class FavoritesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _checkHomeWidget() async {
|
|
||||||
if (await countHomeWidgets() > 0 && hasFavorites()) {
|
|
||||||
await initHomeWidget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasFavorites() {
|
bool hasFavorites() {
|
||||||
return _cachedFavUploadedIDs.isNotEmpty;
|
return _cachedFavUploadedIDs.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
156
mobile/lib/services/home_widget_service.dart
Normal file
156
mobile/lib/services/home_widget_service.dart
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
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<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 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");
|
||||||
|
throw Exception("Favorite 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();
|
||||||
|
_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 (_) {
|
||||||
|
throw Exception("Error rendering widget");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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",
|
|
||||||
);
|
|
||||||
|
|
||||||
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 (_) {
|
|
||||||
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");
|
|
||||||
}
|
|
Loading…
Reference in a new issue