From 27dc2f981e8199a252afc8a812a4c565d28f4cd9 Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Sat, 15 Jun 2024 00:28:31 +0200 Subject: [PATCH 1/9] feat: create merge statistic service and repository to track success rate --- lib/bootstrap.dart | 20 +++++ lib/src/core/gen/objectbox-model.json | 26 +++++- lib/src/core/gen/objectbox.g.dart | 71 ++++++++++++++- .../merge/data/data_sources/data_sources.dart | 1 + .../local_merge_settings_service.dart | 3 +- .../local_merge_statistics_service.dart | 17 ++++ .../merge_statistics_service.dart | 21 +++++ .../object_box_merge_statistics_service.dart | 41 +++++++++ .../data/models/local_merge_statistics.dart | 34 ++++++++ .../features/merge/data/models/models.dart | 1 + .../merge_statistics_repository_impl.dart | 52 +++++++++++ .../merge/data/repositories/repositories.dart | 1 + .../merge/domain/entities/entities.dart | 1 + .../merge/domain/entities/merge_settings.dart | 14 +++ .../domain/entities/merge_statistics.dart | 34 ++++++++ .../merge_statistics_repository.dart | 14 +++ .../domain/repositories/repositories.dart | 1 + .../get_merge_statistics_use_case.dart | 20 +++++ .../save_merge_statistics_use_case.dart | 20 +++++ .../merge/domain/use_cases/use_cases.dart | 2 + .../save_bottom_sheet_cubit.dart | 86 ++++++++++++++++++- .../merge/presentation/pages/merge_page.dart | 2 + 22 files changed, 477 insertions(+), 5 deletions(-) create mode 100644 lib/src/features/merge/data/data_sources/merge_statistics_service/local_merge_statistics_service.dart create mode 100644 lib/src/features/merge/data/data_sources/merge_statistics_service/merge_statistics_service.dart create mode 100644 lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart create mode 100644 lib/src/features/merge/data/models/local_merge_statistics.dart create mode 100644 lib/src/features/merge/data/repositories/merge_statistics_repository_impl.dart create mode 100644 lib/src/features/merge/domain/entities/merge_statistics.dart create mode 100644 lib/src/features/merge/domain/repositories/merge_statistics_repository.dart create mode 100644 lib/src/features/merge/domain/use_cases/get_merge_statistics_use_case.dart create mode 100644 lib/src/features/merge/domain/use_cases/save_merge_statistics_use_case.dart diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index a8195ea..0c1d330 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -132,6 +132,26 @@ Future setup() async { repository: getIt(), ), ) + ..registerLazySingleton( + () => ObjectBoxMergeStatisticsService( + service: getIt(), + ), + ) + ..registerLazySingleton( + () => MergeStatisticsRepositoryImpl( + localService: getIt(), + ), + ) + ..registerLazySingleton( + () => GetMergeStatisticsUseCase( + repository: getIt(), + ), + ) + ..registerLazySingleton( + () => SaveMergeStatisticsUseCase( + repository: getIt(), + ), + ) ..registerLazySingleton( () => packageInfo, ) diff --git a/lib/src/core/gen/objectbox-model.json b/lib/src/core/gen/objectbox-model.json index d97ebd0..f72c066 100644 --- a/lib/src/core/gen/objectbox-model.json +++ b/lib/src/core/gen/objectbox-model.json @@ -60,9 +60,33 @@ } ], "relations": [] + }, + { + "id": "3:6752277543447190155", + "lastPropertyId": "3:4991885907385683044", + "name": "LocalMergeStatistics", + "properties": [ + { + "id": "1:5740094858668497488", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:3379488580577270059", + "name": "successMerges", + "type": 6 + }, + { + "id": "3:4991885907385683044", + "name": "failedMerges", + "type": 6 + } + ], + "relations": [] } ], - "lastEntityId": "2:4520518054235479906", + "lastEntityId": "3:6752277543447190155", "lastIndexId": "0:0", "lastRelationId": "0:0", "lastSequenceId": "0:0", diff --git a/lib/src/core/gen/objectbox.g.dart b/lib/src/core/gen/objectbox.g.dart index 6dbc30a..34db1ee 100644 --- a/lib/src/core/gen/objectbox.g.dart +++ b/lib/src/core/gen/objectbox.g.dart @@ -17,6 +17,7 @@ import 'package:objectbox_flutter_libs/objectbox_flutter_libs.dart'; import '../../../src/app/data/models/local_theme_configuration.dart'; import '../../../src/features/merge/data/models/local_merge_settings.dart'; +import '../../../src/features/merge/data/models/local_merge_statistics.dart'; export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file @@ -78,6 +79,30 @@ final _entities = [ flags: 0) ], relations: [], + backlinks: []), + obx_int.ModelEntity( + id: const obx_int.IdUid(3, 6752277543447190155), + name: 'LocalMergeStatistics', + lastPropertyId: const obx_int.IdUid(3, 4991885907385683044), + flags: 0, + properties: [ + obx_int.ModelProperty( + id: const obx_int.IdUid(1, 5740094858668497488), + name: 'id', + type: 6, + flags: 1), + obx_int.ModelProperty( + id: const obx_int.IdUid(2, 3379488580577270059), + name: 'successMerges', + type: 6, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(3, 4991885907385683044), + name: 'failedMerges', + type: 6, + flags: 0) + ], + relations: [], backlinks: []) ]; @@ -116,7 +141,7 @@ Future openStore( obx_int.ModelDefinition getObjectBoxModel() { final model = obx_int.ModelInfo( entities: _entities, - lastEntityId: const obx_int.IdUid(2, 4520518054235479906), + lastEntityId: const obx_int.IdUid(3, 6752277543447190155), lastIndexId: const obx_int.IdUid(0, 0), lastRelationId: const obx_int.IdUid(0, 0), lastSequenceId: const obx_int.IdUid(0, 0), @@ -197,6 +222,35 @@ obx_int.ModelDefinition getObjectBoxModel() { ..mainColor = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 8, ''); + return object; + }), + LocalMergeStatistics: obx_int.EntityDefinition( + model: _entities[2], + toOneRelations: (LocalMergeStatistics object) => [], + toManyRelations: (LocalMergeStatistics object) => {}, + getId: (LocalMergeStatistics object) => object.id, + setId: (LocalMergeStatistics object, int id) { + object.id = id; + }, + objectToFB: (LocalMergeStatistics object, fb.Builder fbb) { + fbb.startTable(4); + fbb.addInt64(0, object.id); + fbb.addInt64(1, object.successMerges); + fbb.addInt64(2, object.failedMerges); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (obx.Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + + final object = LocalMergeStatistics() + ..id = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) + ..successMerges = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0) + ..failedMerges = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0); + return object; }) }; @@ -241,3 +295,18 @@ class LocalThemeConfiguration_ { static final mainColor = obx.QueryStringProperty( _entities[1].properties[2]); } + +/// [LocalMergeStatistics] entity fields to define ObjectBox queries. +class LocalMergeStatistics_ { + /// see [LocalMergeStatistics.id] + static final id = obx.QueryIntegerProperty( + _entities[2].properties[0]); + + /// see [LocalMergeStatistics.successMerges] + static final successMerges = obx.QueryIntegerProperty( + _entities[2].properties[1]); + + /// see [LocalMergeStatistics.failedMerges] + static final failedMerges = obx.QueryIntegerProperty( + _entities[2].properties[2]); +} diff --git a/lib/src/features/merge/data/data_sources/data_sources.dart b/lib/src/features/merge/data/data_sources/data_sources.dart index adc5598..f018035 100644 --- a/lib/src/features/merge/data/data_sources/data_sources.dart +++ b/lib/src/features/merge/data/data_sources/data_sources.dart @@ -3,3 +3,4 @@ // in the LICENSE file. export 'merge_settings_service/merge_settings_service.dart'; +export 'merge_statistics_service/merge_statistics_service.dart'; diff --git a/lib/src/features/merge/data/data_sources/merge_settings_service/local_merge_settings_service.dart b/lib/src/features/merge/data/data_sources/merge_settings_service/local_merge_settings_service.dart index ce4980a..c67bf32 100644 --- a/lib/src/features/merge/data/data_sources/merge_settings_service/local_merge_settings_service.dart +++ b/lib/src/features/merge/data/data_sources/merge_settings_service/local_merge_settings_service.dart @@ -8,8 +8,7 @@ import 'package:vmerge/src/features/merge/merge.dart'; /// An interface that inherits from [MergeSettingsService] and defines the /// requirements for implementations that use a local service. /// -/// The [LocalMergeSettings] type is the model -/// type. +/// The [LocalMergeSettings] type is the model type. /// {@endtemplate} abstract interface class LocalMergeSettingsService implements MergeSettingsService { diff --git a/lib/src/features/merge/data/data_sources/merge_statistics_service/local_merge_statistics_service.dart b/lib/src/features/merge/data/data_sources/merge_statistics_service/local_merge_statistics_service.dart new file mode 100644 index 0000000..206dc4f --- /dev/null +++ b/lib/src/features/merge/data/data_sources/merge_statistics_service/local_merge_statistics_service.dart @@ -0,0 +1,17 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/features/merge/merge.dart'; + +/// {@template local_merge_statistics_service} +/// An interface that inherits from [MergeStatisticsService] and defines the +/// requirements for implementations that use a local service. +/// +/// The [LocalMergeStatistics] type is the model type. +/// {@endtemplate} +abstract interface class LocalMergeStatisticsService + implements MergeStatisticsService { + /// {@macro local_merge_statistics_service} + const LocalMergeStatisticsService(); +} diff --git a/lib/src/features/merge/data/data_sources/merge_statistics_service/merge_statistics_service.dart b/lib/src/features/merge/data/data_sources/merge_statistics_service/merge_statistics_service.dart new file mode 100644 index 0000000..bd62d7c --- /dev/null +++ b/lib/src/features/merge/data/data_sources/merge_statistics_service/merge_statistics_service.dart @@ -0,0 +1,21 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +export 'local_merge_statistics_service.dart'; +export 'object_box_merge_statistics_service.dart'; + +/// {@template merge_statistics_service} +/// An interface that defines the requirements for implementations that provide +/// merge statistics. +/// +/// The [M] type is the model type. +/// {@endtemplate} +abstract interface class MergeStatisticsService { + /// {@macro merge_statistics_service} + const MergeStatisticsService(); + + Future getMergeStatistics(); + + Future saveMergeStatistics(M statistics); +} diff --git a/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart b/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart new file mode 100644 index 0000000..fc10eff --- /dev/null +++ b/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart @@ -0,0 +1,41 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/bootstrap.dart'; +import 'package:vmerge/src/features/merge/merge.dart'; + +final class ObjectBoxMergeStatisticsService + implements LocalMergeStatisticsService { + /// {@macro object_box_merge_statistics_service} + const ObjectBoxMergeStatisticsService({required ObjectBoxService service}) + : _service = service; + + final ObjectBoxService _service; + + /// Gets the [LocalMergeStatistics]. + @override + Future getMergeStatistics() async { + final box = _service.store.box(); + final query = box.query().build(); + final entities = query.find(); + final statistics = entities.first; + query.close(); + + return statistics; + } + + /// Saves the [LocalMergeStatistics]. + @override + Future saveMergeStatistics(LocalMergeStatistics statistics) async { + final box = _service.store.box(); + final query = box.query().build(); + final entities = query.find(); + final oldStatistics = entities.firstOrNull; + query.close(); + + if (oldStatistics != null) statistics.id = oldStatistics.id; + + box.put(statistics); + } +} diff --git a/lib/src/features/merge/data/models/local_merge_statistics.dart b/lib/src/features/merge/data/models/local_merge_statistics.dart new file mode 100644 index 0000000..6c41767 --- /dev/null +++ b/lib/src/features/merge/data/models/local_merge_statistics.dart @@ -0,0 +1,34 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/core/core.dart'; +import 'package:vmerge/src/features/merge/domain/domain.dart'; + +@Entity() +final class LocalMergeStatistics implements DataModel { + LocalMergeStatistics(); + + LocalMergeStatistics.fromArgs({ + required this.successMerges, + required this.failedMerges, + }); + + LocalMergeStatistics.fromEntity(MergeStatistics entity) + : this.fromArgs( + successMerges: entity.successMerges, + failedMerges: entity.failedMerges, + ); + + int id = 0; + int successMerges = 0; + int failedMerges = 0; + + @override + MergeStatistics toEntity() { + return MergeStatistics( + successMerges: successMerges, + failedMerges: failedMerges, + ); + } +} diff --git a/lib/src/features/merge/data/models/models.dart b/lib/src/features/merge/data/models/models.dart index 9b481e7..59642d7 100644 --- a/lib/src/features/merge/data/models/models.dart +++ b/lib/src/features/merge/data/models/models.dart @@ -3,3 +3,4 @@ // in the LICENSE file. export 'local_merge_settings.dart'; +export 'local_merge_statistics.dart'; diff --git a/lib/src/features/merge/data/repositories/merge_statistics_repository_impl.dart b/lib/src/features/merge/data/repositories/merge_statistics_repository_impl.dart new file mode 100644 index 0000000..aed185e --- /dev/null +++ b/lib/src/features/merge/data/repositories/merge_statistics_repository_impl.dart @@ -0,0 +1,52 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/core/core.dart'; +import 'package:vmerge/src/features/merge/merge.dart'; + +final class MergeStatisticsRepositoryImpl implements MergeStatisticsRepository { + const MergeStatisticsRepositoryImpl({ + required LocalMergeStatisticsService localService, + }) : _localService = localService; + + final LocalMergeStatisticsService _localService; + + @override + Future> getMergeStatistics() async { + try { + final localMergeStatistics = await _localService.getMergeStatistics(); + final mergeStatistics = localMergeStatistics.toEntity(); + return DataSuccess(mergeStatistics); + } catch (error, stackTrace) { + return DataFailure( + Failure( + 'Could not get merge statistics!', + error: error, + name: '$MergeStatisticsRepositoryImpl', + stackTrace: stackTrace, + ), + ); + } + } + + @override + Future> saveMergeStatistics( + MergeStatistics statistics, + ) async { + try { + final localMergeStatistics = LocalMergeStatistics.fromEntity(statistics); + await _localService.saveMergeStatistics(localMergeStatistics); + return const DataSuccess(null); + } catch (error, stackTrace) { + return DataFailure( + Failure( + 'Could not save merge statistics!', + error: error, + name: '$MergeStatisticsRepositoryImpl', + stackTrace: stackTrace, + ), + ); + } + } +} diff --git a/lib/src/features/merge/data/repositories/repositories.dart b/lib/src/features/merge/data/repositories/repositories.dart index 4f9e7ea..175d2cf 100644 --- a/lib/src/features/merge/data/repositories/repositories.dart +++ b/lib/src/features/merge/data/repositories/repositories.dart @@ -3,3 +3,4 @@ // in the LICENSE file. export 'merge_settings_repository_impl.dart'; +export 'merge_statistics_repository_impl.dart'; diff --git a/lib/src/features/merge/domain/entities/entities.dart b/lib/src/features/merge/domain/entities/entities.dart index a96a31e..758e296 100644 --- a/lib/src/features/merge/domain/entities/entities.dart +++ b/lib/src/features/merge/domain/entities/entities.dart @@ -3,4 +3,5 @@ // in the LICENSE file. export 'merge_settings.dart'; +export 'merge_statistics.dart'; export 'video_metadata.dart'; diff --git a/lib/src/features/merge/domain/entities/merge_settings.dart b/lib/src/features/merge/domain/entities/merge_settings.dart index 62b84b8..e908cd9 100644 --- a/lib/src/features/merge/domain/entities/merge_settings.dart +++ b/lib/src/features/merge/domain/entities/merge_settings.dart @@ -32,6 +32,20 @@ final class MergeSettings extends DomainEntity { videoResolution, videoAspectRatio, ]; + + MergeSettings copyWith({ + bool? isAudioOn, + PlaybackSpeed? playbackSpeed, + VideoResolution? videoResolution, + VideoAspectRatio? videoAspectRatio, + }) { + return MergeSettings( + isAudioOn: isAudioOn ?? this.isAudioOn, + playbackSpeed: playbackSpeed ?? this.playbackSpeed, + videoResolution: videoResolution ?? this.videoResolution, + videoAspectRatio: videoAspectRatio ?? this.videoAspectRatio, + ); + } } enum PlaybackSpeed { diff --git a/lib/src/features/merge/domain/entities/merge_statistics.dart b/lib/src/features/merge/domain/entities/merge_statistics.dart new file mode 100644 index 0000000..9e5c011 --- /dev/null +++ b/lib/src/features/merge/domain/entities/merge_statistics.dart @@ -0,0 +1,34 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/core/core.dart'; + +final class MergeStatistics extends DomainEntity { + const MergeStatistics({ + required this.successMerges, + required this.failedMerges, + }); + + final int successMerges; + final int failedMerges; + + @override + String toString() { + return 'MergeStatistics(successMerges: $successMerges, failedMerges: ' + '$failedMerges)'; + } + + @override + List get props => [ + successMerges, + failedMerges, + ]; + + MergeStatistics copyWith({int? successMerges, int? failedMerges}) { + return MergeStatistics( + successMerges: successMerges ?? this.successMerges, + failedMerges: failedMerges ?? this.failedMerges, + ); + } +} diff --git a/lib/src/features/merge/domain/repositories/merge_statistics_repository.dart b/lib/src/features/merge/domain/repositories/merge_statistics_repository.dart new file mode 100644 index 0000000..5afdc17 --- /dev/null +++ b/lib/src/features/merge/domain/repositories/merge_statistics_repository.dart @@ -0,0 +1,14 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/core/core.dart'; +import 'package:vmerge/src/features/merge/merge.dart'; + +abstract interface class MergeStatisticsRepository { + const MergeStatisticsRepository(); + + Future> getMergeStatistics(); + + Future> saveMergeStatistics(MergeStatistics statistics); +} diff --git a/lib/src/features/merge/domain/repositories/repositories.dart b/lib/src/features/merge/domain/repositories/repositories.dart index d6a3b62..1985eb6 100644 --- a/lib/src/features/merge/domain/repositories/repositories.dart +++ b/lib/src/features/merge/domain/repositories/repositories.dart @@ -3,3 +3,4 @@ // in the LICENSE file. export 'merge_settings_repository.dart'; +export 'merge_statistics_repository.dart'; diff --git a/lib/src/features/merge/domain/use_cases/get_merge_statistics_use_case.dart b/lib/src/features/merge/domain/use_cases/get_merge_statistics_use_case.dart new file mode 100644 index 0000000..ccee7c8 --- /dev/null +++ b/lib/src/features/merge/domain/use_cases/get_merge_statistics_use_case.dart @@ -0,0 +1,20 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/core/core.dart'; +import 'package:vmerge/src/features/merge/merge.dart'; + +final class GetMergeStatisticsUseCase + implements UseCase, void> { + const GetMergeStatisticsUseCase({ + required MergeStatisticsRepository repository, + }) : _repository = repository; + + final MergeStatisticsRepository _repository; + + @override + Future> call({void params}) { + return _repository.getMergeStatistics(); + } +} diff --git a/lib/src/features/merge/domain/use_cases/save_merge_statistics_use_case.dart b/lib/src/features/merge/domain/use_cases/save_merge_statistics_use_case.dart new file mode 100644 index 0000000..6124156 --- /dev/null +++ b/lib/src/features/merge/domain/use_cases/save_merge_statistics_use_case.dart @@ -0,0 +1,20 @@ +// Copyright 2024 BBK Development. All rights reserved. +// Use of this source code is governed by a GPL-style license that can be found +// in the LICENSE file. + +import 'package:vmerge/src/core/core.dart'; +import 'package:vmerge/src/features/merge/merge.dart'; + +final class SaveMergeStatisticsUseCase + implements UseCase, MergeStatistics> { + const SaveMergeStatisticsUseCase({ + required MergeStatisticsRepository repository, + }) : _repository = repository; + + final MergeStatisticsRepository _repository; + + @override + Future> call({required MergeStatistics params}) { + return _repository.saveMergeStatistics(params); + } +} diff --git a/lib/src/features/merge/domain/use_cases/use_cases.dart b/lib/src/features/merge/domain/use_cases/use_cases.dart index 60aba21..777686f 100644 --- a/lib/src/features/merge/domain/use_cases/use_cases.dart +++ b/lib/src/features/merge/domain/use_cases/use_cases.dart @@ -3,4 +3,6 @@ // in the LICENSE file. export 'get_merge_settings_use_case.dart'; +export 'get_merge_statistics_use_case.dart'; export 'save_merge_settings_use_case.dart'; +export 'save_merge_statistics_use_case.dart'; diff --git a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart index cdbb3c9..b1e06e2 100644 --- a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart +++ b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart @@ -3,6 +3,7 @@ // in the LICENSE file. import 'dart:async'; +import 'dart:developer'; import 'dart:io'; import 'package:bloc/bloc.dart'; @@ -10,6 +11,7 @@ import 'package:ffmpeg_service/ffmpeg_service.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; +import 'package:vmerge/src/core/core.dart'; import 'package:vmerge/src/features/merge/merge.dart'; import 'package:wakelock_service/wakelock_service.dart'; @@ -17,8 +19,12 @@ final class SaveBottomSheetCubit extends Cubit { SaveBottomSheetCubit({ required FFmpegService ffmpegService, required WakelockService wakelockService, + required GetMergeStatisticsUseCase getMergeStatisticsUseCase, + required SaveMergeStatisticsUseCase saveMergeStatisticsUseCase, }) : _ffmpegService = ffmpegService, _wakelockService = wakelockService, + _getMergeStatisticsUseCase = getMergeStatisticsUseCase, + _saveMergeStatisticsUseCase = saveMergeStatisticsUseCase, super( const SaveBottomSheetInitial( videoMetadatas: [], @@ -27,8 +33,15 @@ final class SaveBottomSheetCubit extends Cubit { final FFmpegService _ffmpegService; final WakelockService _wakelockService; + final GetMergeStatisticsUseCase _getMergeStatisticsUseCase; + final SaveMergeStatisticsUseCase _saveMergeStatisticsUseCase; - void init(List videoMetadatas) { + static const _defaultMergeStatistics = MergeStatistics( + successMerges: 0, + failedMerges: 0, + ); + + Future init(List videoMetadatas) async { emit(SaveBottomSheetInitial(videoMetadatas: videoMetadatas)); } @@ -39,6 +52,8 @@ final class SaveBottomSheetCubit extends Cubit { int? outputHeight, bool? forceFirstAspectRatio, }) async { + final statistics = await _getMergeStatistics(); + final Directory appDocsDir; try { appDocsDir = await getApplicationDocumentsDirectory(); @@ -50,6 +65,11 @@ final class SaveBottomSheetCubit extends Cubit { stackTrace: stackTrace, ), ); + unawaited( + _saveMergeStatistics( + statistics.copyWith(failedMerges: statistics.failedMerges + 1), + ), + ); return; } @@ -81,6 +101,11 @@ final class SaveBottomSheetCubit extends Cubit { stackTrace: stackTrace, ), ); + unawaited( + _saveMergeStatistics( + statistics.copyWith(failedMerges: statistics.failedMerges + 1), + ), + ); unawaited(_wakelockService.disable()); return; } @@ -107,6 +132,11 @@ final class SaveBottomSheetCubit extends Cubit { stackTrace: stackTrace, ), ); + unawaited( + _saveMergeStatistics( + statistics.copyWith(failedMerges: statistics.failedMerges + 1), + ), + ); return; } on FFmpegServiceInsufficientVideosException catch (error, stackTrace) { emit( @@ -117,6 +147,11 @@ final class SaveBottomSheetCubit extends Cubit { stackTrace: stackTrace, ), ); + unawaited( + _saveMergeStatistics( + statistics.copyWith(failedMerges: statistics.failedMerges + 1), + ), + ); return; } on FFmpegServiceMergeException catch (error, stackTrace) { emit( @@ -126,6 +161,11 @@ final class SaveBottomSheetCubit extends Cubit { stackTrace: stackTrace, ), ); + unawaited( + _saveMergeStatistics( + statistics.copyWith(failedMerges: statistics.failedMerges + 1), + ), + ); return; } finally { unawaited(_wakelockService.disable()); @@ -145,10 +185,20 @@ final class SaveBottomSheetCubit extends Cubit { stackTrace: stackTrace, ), ); + unawaited( + _saveMergeStatistics( + statistics.copyWith(failedMerges: statistics.failedMerges + 1), + ), + ); return; } emit(const SaveBottomSheetSuccess()); + unawaited( + _saveMergeStatistics( + statistics.copyWith(successMerges: statistics.successMerges + 1), + ), + ); } Future cancelMerge() async { @@ -157,6 +207,40 @@ final class SaveBottomSheetCubit extends Cubit { emit(const SaveBottomSheetCancelled()); await _ffmpegService.cancelMerge(); } + + Future _getMergeStatistics() async { + final dataState = await _getMergeStatisticsUseCase(); + + switch (dataState) { + case DataSuccess(): + return dataState.data; + case DataFailure(): + log( + dataState.message, + name: dataState.name, + error: dataState.error, + stackTrace: dataState.stackTrace, + ); + await _saveMergeStatistics(_defaultMergeStatistics); + return _defaultMergeStatistics; + } + } + + Future _saveMergeStatistics(MergeStatistics statistics) async { + final dataState = await _saveMergeStatisticsUseCase(params: statistics); + + switch (dataState) { + case DataSuccess(): + break; + case DataFailure(): + log( + dataState.message, + name: dataState.name, + error: dataState.error, + stackTrace: dataState.stackTrace, + ); + } + } } /// The minimum duration a status should be displayed for. diff --git a/lib/src/features/merge/presentation/pages/merge_page.dart b/lib/src/features/merge/presentation/pages/merge_page.dart index 6c819dd..cff39af 100644 --- a/lib/src/features/merge/presentation/pages/merge_page.dart +++ b/lib/src/features/merge/presentation/pages/merge_page.dart @@ -57,6 +57,8 @@ class MergePage extends StatelessWidget { create: (_) => SaveBottomSheetCubit( ffmpegService: getIt(), wakelockService: getIt(), + getMergeStatisticsUseCase: getIt(), + saveMergeStatisticsUseCase: getIt(), ), ), ], From f64d219197a8f1264eeb8e16682feb7a3ff5c44a Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 01:15:18 +0200 Subject: [PATCH 2/9] build(deps): add in_app_review_service as a dependency --- pubspec.lock | 27 ++++++++++++++++++++++++++- pubspec.yaml | 4 ++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index e4d8755..97e9f40 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -509,6 +509,31 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + in_app_review: + dependency: transitive + description: + name: in_app_review + sha256: "99869244d09adc76af16bf8fd731dd13cef58ecafd5917847589c49f378cbb30" + url: "https://pub.dev" + source: hosted + version: "2.0.9" + in_app_review_platform_interface: + dependency: transitive + description: + name: in_app_review_platform_interface + sha256: fed2c755f2125caa9ae10495a3c163aa7fab5af3585a9c62ef4a6920c5b45f10 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + in_app_review_service: + dependency: "direct main" + description: + path: "." + ref: "v1.0.0" + resolved-ref: "1b11f4c1f16f3d1bc5f5a0040708375e3bf71f5e" + url: "https://github.com/BBKDevelopment/In-App-Review-Service.git" + source: git + version: "1.0.0" intl: dependency: "direct main" description: @@ -1224,4 +1249,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.4.0 <4.0.0" - flutter: ">=3.19.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 53ed366..7f80c10 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,10 @@ dependencies: flutter_svg: ^2.0.10+1 get_it: ^7.7.0 image_gallery_saver: ^2.0.3 + in_app_review_service: + git: + url: https://github.com/BBKDevelopment/In-App-Review-Service.git + ref: v1.0.0 intl: 0.19.0 launch_review_service: git: From 2a13c014f7125f89fad3f6d326bb874be55f4edf Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 01:16:40 +0200 Subject: [PATCH 3/9] build(deps): remove launch_review_service from dependencies --- pubspec.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 7f80c10..e6c10bf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,10 +31,6 @@ dependencies: url: https://github.com/BBKDevelopment/In-App-Review-Service.git ref: v1.0.0 intl: 0.19.0 - launch_review_service: - git: - url: https://github.com/BBKDevelopment/Launch-Review-Service.git - ref: v1.0.0 modal_bottom_sheet: ^3.0.0 objectbox: ^2.5.1 objectbox_flutter_libs: ^2.5.1 From fc19904be965c85e47038c45f247ef1542ee00fe Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 01:16:59 +0200 Subject: [PATCH 4/9] build(deps): remove launch_review_service from dependencies --- pubspec.lock | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 97e9f40..0d7d7b4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -566,23 +566,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" - launch_review: - dependency: transitive - description: - name: launch_review - sha256: "04cdaf752033cefd53bc0fa9c22105801ef53791a93d8b6cdd00fcb3c1c1604b" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - launch_review_service: - dependency: "direct main" - description: - path: "." - ref: "v1.0.0" - resolved-ref: a85533d94d4308ee3f50268db225c60ea2080bac - url: "https://github.com/BBKDevelopment/Launch-Review-Service.git" - source: git - version: "1.0.0" leak_tracker: dependency: transitive description: From f2045455f3ee5af6277127b609acab4780bd2bab Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 01:49:07 +0200 Subject: [PATCH 5/9] refactor: replace launch_review_service with in_app_review_service everywhere --- lib/bootstrap.dart | 6 +++--- lib/src/core/l10n/app_localizations.dart | 12 ++++++------ lib/src/core/l10n/app_localizations_en.dart | 8 ++++---- lib/src/core/l10n/arb/app_en.arb | 2 +- .../features/more/presentation/pages/more_page.dart | 2 +- .../more/presentation/widgets/more_page_option.dart | 8 ++++---- pubspec.lock | 6 +++--- pubspec.yaml | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index 0c1d330..a102004 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -12,7 +12,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:get_it/get_it.dart'; -import 'package:launch_review_service/launch_review_service.dart'; +import 'package:in_app_review_service/in_app_review_service.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; @@ -155,8 +155,8 @@ Future setup() async { ..registerLazySingleton( () => packageInfo, ) - ..registerLazySingleton( - () => LaunchReviewService(androidAppId: getIt().packageName), + ..registerLazySingleton( + InAppReviewService.new, ) ..registerLazySingleton( () => const UrlLauncherService(), diff --git a/lib/src/core/l10n/app_localizations.dart b/lib/src/core/l10n/app_localizations.dart index 18d7224..231c8d1 100644 --- a/lib/src/core/l10n/app_localizations.dart +++ b/lib/src/core/l10n/app_localizations.dart @@ -212,6 +212,12 @@ abstract class AppLocalizations { /// **'Could not open privacy policy! Please check your internet connection and try again.'** String get couldNotOpenPrivacyPolicyMessage; + /// No description provided for @couldNotOpenStoreListingMessage. + /// + /// In en, this message translates to: + /// **'Could not open store listing! Please check your internet connection and try again.'** + String get couldNotOpenStoreListingMessage; + /// No description provided for @couldNotOpenTermsAndConditionsMessage. /// /// In en, this message translates to: @@ -236,12 +242,6 @@ abstract class AppLocalizations { /// **'Could not launch email service! Please check your internet connection and try again.'** String get couldNotLaunchEmailServiceMessage; - /// No description provided for @couldNotLaunchReviewServiceMessage. - /// - /// In en, this message translates to: - /// **'Could not launch review service! Please check your internet connection and try again.'** - String get couldNotLaunchReviewServiceMessage; - /// No description provided for @couldNotSeekVideoPositionMessage. /// /// In en, this message translates to: diff --git a/lib/src/core/l10n/app_localizations_en.dart b/lib/src/core/l10n/app_localizations_en.dart index 3bffa1b..75525ff 100644 --- a/lib/src/core/l10n/app_localizations_en.dart +++ b/lib/src/core/l10n/app_localizations_en.dart @@ -71,6 +71,10 @@ class AppLocalizationsEn extends AppLocalizations { String get couldNotOpenPrivacyPolicyMessage => 'Could not open privacy policy! Please check your internet connection and try again.'; + @override + String get couldNotOpenStoreListingMessage => + 'Could not open store listing! Please check your internet connection and try again.'; + @override String get couldNotOpenTermsAndConditionsMessage => 'Could not open terms and conditions! Please check your internet connection and try again.'; @@ -87,10 +91,6 @@ class AppLocalizationsEn extends AppLocalizations { String get couldNotLaunchEmailServiceMessage => 'Could not launch email service! Please check your internet connection and try again.'; - @override - String get couldNotLaunchReviewServiceMessage => - 'Could not launch review service! Please check your internet connection and try again.'; - @override String get couldNotSeekVideoPositionMessage => 'Could not seek video position! Please try again later.'; diff --git a/lib/src/core/l10n/arb/app_en.arb b/lib/src/core/l10n/arb/app_en.arb index 98ce329..a26939f 100644 --- a/lib/src/core/l10n/arb/app_en.arb +++ b/lib/src/core/l10n/arb/app_en.arb @@ -20,11 +20,11 @@ "couldNotLoadVideosMessage": "Could not load videos! Please confirm that video files are valid.", "couldNotOpenAssetPickerMessage": "Could not open the asset picker! Please grant the necessary permissions.", "couldNotOpenPrivacyPolicyMessage": "Could not open privacy policy! Please check your internet connection and try again.", + "couldNotOpenStoreListingMessage": "Could not open store listing! Please check your internet connection and try again.", "couldNotOpenTermsAndConditionsMessage": "Could not open terms and conditions! Please check your internet connection and try again.", "couldNotPauseVideoMessage": "Could not pause video! Please try again later.", "couldNotPlayVideoMessage": "Could not play video! Please confirm that video files are valid.", "couldNotLaunchEmailServiceMessage": "Could not launch email service! Please check your internet connection and try again.", - "couldNotLaunchReviewServiceMessage": "Could not launch review service! Please check your internet connection and try again.", "couldNotSeekVideoPositionMessage": "Could not seek video position! Please try again later.", "couldNotSetVideoSpeedMessage": "Could not set video playback speed! Please try again later.", "cyan": "Cyan", diff --git a/lib/src/features/more/presentation/pages/more_page.dart b/lib/src/features/more/presentation/pages/more_page.dart index ad5bdd8..0425735 100644 --- a/lib/src/features/more/presentation/pages/more_page.dart +++ b/lib/src/features/more/presentation/pages/more_page.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:launch_review_service/launch_review_service.dart'; +import 'package:in_app_review_service/in_app_review_service.dart'; import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher_service/url_launcher_service.dart'; diff --git a/lib/src/features/more/presentation/widgets/more_page_option.dart b/lib/src/features/more/presentation/widgets/more_page_option.dart index b26decc..6ef61a1 100644 --- a/lib/src/features/more/presentation/widgets/more_page_option.dart +++ b/lib/src/features/more/presentation/widgets/more_page_option.dart @@ -60,11 +60,11 @@ class _MorePageOption extends StatelessWidget { }, ); case MorePageOption.rateUs: - getIt() - .launch() - .onError((error, stackTrace) { + getIt() + .openStoreListing() + .onError((error, stackTrace) { context.read().caught( - message: l10n.couldNotLaunchReviewServiceMessage, + message: l10n.couldNotOpenStoreListingMessage, error: error, stackTrace: stackTrace, ); diff --git a/pubspec.lock b/pubspec.lock index 0d7d7b4..8cf16e9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -529,11 +529,11 @@ packages: dependency: "direct main" description: path: "." - ref: "v1.0.0" - resolved-ref: "1b11f4c1f16f3d1bc5f5a0040708375e3bf71f5e" + ref: "v1.0.1" + resolved-ref: ad4c30c7f6ed404bc70c54decae94fc41db471a9 url: "https://github.com/BBKDevelopment/In-App-Review-Service.git" source: git - version: "1.0.0" + version: "1.0.1" intl: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index e6c10bf..43e4cc5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,7 +29,7 @@ dependencies: in_app_review_service: git: url: https://github.com/BBKDevelopment/In-App-Review-Service.git - ref: v1.0.0 + ref: v1.0.1 intl: 0.19.0 modal_bottom_sheet: ^3.0.0 objectbox: ^2.5.1 From b09ac09b81dd690839e5caed45f04c9d7893bffc Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 21:30:55 +0200 Subject: [PATCH 6/9] feat: implement InAppReviewService to request a review --- lib/src/core/gen/objectbox-model.json | 15 +++-- lib/src/core/gen/objectbox.g.dart | 40 ++++++------ .../data/models/local_merge_statistics.dart | 16 ++--- .../domain/entities/merge_statistics.dart | 22 +++---- .../save_bottom_sheet_cubit.dart | 64 +++++++++++++++---- .../merge/presentation/pages/merge_page.dart | 2 + 6 files changed, 102 insertions(+), 57 deletions(-) diff --git a/lib/src/core/gen/objectbox-model.json b/lib/src/core/gen/objectbox-model.json index f72c066..8d0c4be 100644 --- a/lib/src/core/gen/objectbox-model.json +++ b/lib/src/core/gen/objectbox-model.json @@ -63,7 +63,7 @@ }, { "id": "3:6752277543447190155", - "lastPropertyId": "3:4991885907385683044", + "lastPropertyId": "5:7060629709470016846", "name": "LocalMergeStatistics", "properties": [ { @@ -73,13 +73,13 @@ "flags": 1 }, { - "id": "2:3379488580577270059", - "name": "successMerges", + "id": "4:7986270554451540890", + "name": "successMergeCount", "type": 6 }, { - "id": "3:4991885907385683044", - "name": "failedMerges", + "id": "5:7060629709470016846", + "name": "failedMergeCount", "type": 6 } ], @@ -94,7 +94,10 @@ "modelVersionParserMinimum": 5, "retiredEntityUids": [], "retiredIndexUids": [], - "retiredPropertyUids": [], + "retiredPropertyUids": [ + 3379488580577270059, + 4991885907385683044 + ], "retiredRelationUids": [], "version": 1 } \ No newline at end of file diff --git a/lib/src/core/gen/objectbox.g.dart b/lib/src/core/gen/objectbox.g.dart index 34db1ee..9a884d6 100644 --- a/lib/src/core/gen/objectbox.g.dart +++ b/lib/src/core/gen/objectbox.g.dart @@ -83,7 +83,7 @@ final _entities = [ obx_int.ModelEntity( id: const obx_int.IdUid(3, 6752277543447190155), name: 'LocalMergeStatistics', - lastPropertyId: const obx_int.IdUid(3, 4991885907385683044), + lastPropertyId: const obx_int.IdUid(5, 7060629709470016846), flags: 0, properties: [ obx_int.ModelProperty( @@ -92,13 +92,13 @@ final _entities = [ type: 6, flags: 1), obx_int.ModelProperty( - id: const obx_int.IdUid(2, 3379488580577270059), - name: 'successMerges', + id: const obx_int.IdUid(4, 7986270554451540890), + name: 'successMergeCount', type: 6, flags: 0), obx_int.ModelProperty( - id: const obx_int.IdUid(3, 4991885907385683044), - name: 'failedMerges', + id: const obx_int.IdUid(5, 7060629709470016846), + name: 'failedMergeCount', type: 6, flags: 0) ], @@ -147,7 +147,7 @@ obx_int.ModelDefinition getObjectBoxModel() { lastSequenceId: const obx_int.IdUid(0, 0), retiredEntityUids: const [], retiredIndexUids: const [], - retiredPropertyUids: const [], + retiredPropertyUids: const [3379488580577270059, 4991885907385683044], retiredRelationUids: const [], modelVersion: 5, modelVersionParserMinimum: 5, @@ -233,10 +233,10 @@ obx_int.ModelDefinition getObjectBoxModel() { object.id = id; }, objectToFB: (LocalMergeStatistics object, fb.Builder fbb) { - fbb.startTable(4); + fbb.startTable(6); fbb.addInt64(0, object.id); - fbb.addInt64(1, object.successMerges); - fbb.addInt64(2, object.failedMerges); + fbb.addInt64(3, object.successMergeCount); + fbb.addInt64(4, object.failedMergeCount); fbb.finish(fbb.endTable()); return object.id; }, @@ -246,10 +246,10 @@ obx_int.ModelDefinition getObjectBoxModel() { final object = LocalMergeStatistics() ..id = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) - ..successMerges = - const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0) - ..failedMerges = - const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0); + ..successMergeCount = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 10, 0) + ..failedMergeCount = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 12, 0); return object; }) @@ -302,11 +302,13 @@ class LocalMergeStatistics_ { static final id = obx.QueryIntegerProperty( _entities[2].properties[0]); - /// see [LocalMergeStatistics.successMerges] - static final successMerges = obx.QueryIntegerProperty( - _entities[2].properties[1]); + /// see [LocalMergeStatistics.successMergeCount] + static final successMergeCount = + obx.QueryIntegerProperty( + _entities[2].properties[1]); - /// see [LocalMergeStatistics.failedMerges] - static final failedMerges = obx.QueryIntegerProperty( - _entities[2].properties[2]); + /// see [LocalMergeStatistics.failedMergeCount] + static final failedMergeCount = + obx.QueryIntegerProperty( + _entities[2].properties[2]); } diff --git a/lib/src/features/merge/data/models/local_merge_statistics.dart b/lib/src/features/merge/data/models/local_merge_statistics.dart index 6c41767..2198cc3 100644 --- a/lib/src/features/merge/data/models/local_merge_statistics.dart +++ b/lib/src/features/merge/data/models/local_merge_statistics.dart @@ -10,25 +10,25 @@ final class LocalMergeStatistics implements DataModel { LocalMergeStatistics(); LocalMergeStatistics.fromArgs({ - required this.successMerges, - required this.failedMerges, + required this.successMergeCount, + required this.failedMergeCount, }); LocalMergeStatistics.fromEntity(MergeStatistics entity) : this.fromArgs( - successMerges: entity.successMerges, - failedMerges: entity.failedMerges, + successMergeCount: entity.successMergeCount, + failedMergeCount: entity.failedMergeCount, ); int id = 0; - int successMerges = 0; - int failedMerges = 0; + int successMergeCount = 0; + int failedMergeCount = 0; @override MergeStatistics toEntity() { return MergeStatistics( - successMerges: successMerges, - failedMerges: failedMerges, + successMergeCount: successMergeCount, + failedMergeCount: failedMergeCount, ); } } diff --git a/lib/src/features/merge/domain/entities/merge_statistics.dart b/lib/src/features/merge/domain/entities/merge_statistics.dart index 9e5c011..449c5a3 100644 --- a/lib/src/features/merge/domain/entities/merge_statistics.dart +++ b/lib/src/features/merge/domain/entities/merge_statistics.dart @@ -6,29 +6,29 @@ import 'package:vmerge/src/core/core.dart'; final class MergeStatistics extends DomainEntity { const MergeStatistics({ - required this.successMerges, - required this.failedMerges, + required this.successMergeCount, + required this.failedMergeCount, }); - final int successMerges; - final int failedMerges; + final int successMergeCount; + final int failedMergeCount; @override String toString() { - return 'MergeStatistics(successMerges: $successMerges, failedMerges: ' - '$failedMerges)'; + return 'MergeStatistics(successMergeCount: $successMergeCount, ' + 'failedMergeCount: $failedMergeCount)'; } @override List get props => [ - successMerges, - failedMerges, + successMergeCount, + failedMergeCount, ]; - MergeStatistics copyWith({int? successMerges, int? failedMerges}) { + MergeStatistics copyWith({int? successMergeCount, int? failedMergeCount}) { return MergeStatistics( - successMerges: successMerges ?? this.successMerges, - failedMerges: failedMerges ?? this.failedMerges, + successMergeCount: successMergeCount ?? this.successMergeCount, + failedMergeCount: failedMergeCount ?? this.failedMergeCount, ); } } diff --git a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart index b1e06e2..4a00c1e 100644 --- a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart +++ b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart @@ -9,6 +9,7 @@ import 'dart:io'; import 'package:bloc/bloc.dart'; import 'package:ffmpeg_service/ffmpeg_service.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:in_app_review_service/in_app_review_service.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:vmerge/src/core/core.dart'; @@ -21,10 +22,12 @@ final class SaveBottomSheetCubit extends Cubit { required WakelockService wakelockService, required GetMergeStatisticsUseCase getMergeStatisticsUseCase, required SaveMergeStatisticsUseCase saveMergeStatisticsUseCase, + required InAppReviewService inAppReviewService, }) : _ffmpegService = ffmpegService, _wakelockService = wakelockService, _getMergeStatisticsUseCase = getMergeStatisticsUseCase, _saveMergeStatisticsUseCase = saveMergeStatisticsUseCase, + _inAppReviewService = inAppReviewService, super( const SaveBottomSheetInitial( videoMetadatas: [], @@ -35,10 +38,11 @@ final class SaveBottomSheetCubit extends Cubit { final WakelockService _wakelockService; final GetMergeStatisticsUseCase _getMergeStatisticsUseCase; final SaveMergeStatisticsUseCase _saveMergeStatisticsUseCase; + final InAppReviewService _inAppReviewService; static const _defaultMergeStatistics = MergeStatistics( - successMerges: 0, - failedMerges: 0, + successMergeCount: 0, + failedMergeCount: 0, ); Future init(List videoMetadatas) async { @@ -67,7 +71,9 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith(failedMerges: statistics.failedMerges + 1), + statistics.copyWith( + failedMergeCount: statistics.failedMergeCount + 1, + ), ), ); return; @@ -103,7 +109,9 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith(failedMerges: statistics.failedMerges + 1), + statistics.copyWith( + failedMergeCount: statistics.failedMergeCount + 1, + ), ), ); unawaited(_wakelockService.disable()); @@ -134,7 +142,9 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith(failedMerges: statistics.failedMerges + 1), + statistics.copyWith( + failedMergeCount: statistics.failedMergeCount + 1, + ), ), ); return; @@ -149,7 +159,9 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith(failedMerges: statistics.failedMerges + 1), + statistics.copyWith( + failedMergeCount: statistics.failedMergeCount + 1, + ), ), ); return; @@ -163,7 +175,9 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith(failedMerges: statistics.failedMerges + 1), + statistics.copyWith( + failedMergeCount: statistics.failedMergeCount + 1, + ), ), ); return; @@ -187,18 +201,20 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith(failedMerges: statistics.failedMerges + 1), + statistics.copyWith( + failedMergeCount: statistics.failedMergeCount + 1, + ), ), ); return; } - emit(const SaveBottomSheetSuccess()); - unawaited( - _saveMergeStatistics( - statistics.copyWith(successMerges: statistics.successMerges + 1), - ), + final newStatistics = statistics.copyWith( + successMergeCount: statistics.successMergeCount + 1, ); + unawaited(_saveMergeStatistics(newStatistics)); + unawaited(_requestReview(newStatistics)); + emit(const SaveBottomSheetSuccess()); } Future cancelMerge() async { @@ -241,6 +257,28 @@ final class SaveBottomSheetCubit extends Cubit { ); } } + + Future _requestReview(MergeStatistics statistics) async { + final totalMergeCount = + statistics.successMergeCount + statistics.failedMergeCount; + // If the user has not merged at least 2 videos, don't request review. + if (totalMergeCount < 2) return; + + final successRate = statistics.successMergeCount / totalMergeCount; + // If the success rate is less than 90%, don't request review. + if (successRate < 0.9) return; + + try { + await _inAppReviewService.requestReview(); + } on RequestReviewException catch (error, stackTrace) { + log( + 'Could not request review!', + name: '$SaveBottomSheetCubit', + error: error, + stackTrace: stackTrace, + ); + } + } } /// The minimum duration a status should be displayed for. diff --git a/lib/src/features/merge/presentation/pages/merge_page.dart b/lib/src/features/merge/presentation/pages/merge_page.dart index cff39af..2cf086e 100644 --- a/lib/src/features/merge/presentation/pages/merge_page.dart +++ b/lib/src/features/merge/presentation/pages/merge_page.dart @@ -11,6 +11,7 @@ import 'package:android_intent_plus/flag.dart'; import 'package:ffmpeg_service/ffmpeg_service.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:in_app_review_service/in_app_review_service.dart'; import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; import 'package:video_player/video_player.dart'; import 'package:video_player_service/video_player_service.dart'; @@ -59,6 +60,7 @@ class MergePage extends StatelessWidget { wakelockService: getIt(), getMergeStatisticsUseCase: getIt(), saveMergeStatisticsUseCase: getIt(), + inAppReviewService: getIt(), ), ), ], From 8e6b9e57b51e66439a2411bfc7fdf2133d472a51 Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 21:55:31 +0200 Subject: [PATCH 7/9] refactor: update ObjectBoxMergeStatisticsService to create clean box if not available --- .../object_box_merge_statistics_service.dart | 12 +++++-- .../save_bottom_sheet_cubit.dart | 36 +++++++++---------- .../merge/presentation/pages/merge_page.dart | 2 +- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart b/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart index fc10eff..45a656e 100644 --- a/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart +++ b/lib/src/features/merge/data/data_sources/merge_statistics_service/object_box_merge_statistics_service.dart @@ -19,6 +19,12 @@ final class ObjectBoxMergeStatisticsService final box = _service.store.box(); final query = box.query().build(); final entities = query.find(); + + if (entities.isEmpty) { + query.close(); + return saveMergeStatistics(LocalMergeStatistics()); + } + final statistics = entities.first; query.close(); @@ -27,7 +33,9 @@ final class ObjectBoxMergeStatisticsService /// Saves the [LocalMergeStatistics]. @override - Future saveMergeStatistics(LocalMergeStatistics statistics) async { + Future saveMergeStatistics( + LocalMergeStatistics statistics, + ) async { final box = _service.store.box(); final query = box.query().build(); final entities = query.find(); @@ -36,6 +44,6 @@ final class ObjectBoxMergeStatisticsService if (oldStatistics != null) statistics.id = oldStatistics.id; - box.put(statistics); + return box.putAndGetAsync(statistics); } } diff --git a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart index 4a00c1e..1d20af6 100644 --- a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart +++ b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart @@ -20,9 +20,9 @@ final class SaveBottomSheetCubit extends Cubit { SaveBottomSheetCubit({ required FFmpegService ffmpegService, required WakelockService wakelockService, + required InAppReviewService inAppReviewService, required GetMergeStatisticsUseCase getMergeStatisticsUseCase, required SaveMergeStatisticsUseCase saveMergeStatisticsUseCase, - required InAppReviewService inAppReviewService, }) : _ffmpegService = ffmpegService, _wakelockService = wakelockService, _getMergeStatisticsUseCase = getMergeStatisticsUseCase, @@ -36,14 +36,9 @@ final class SaveBottomSheetCubit extends Cubit { final FFmpegService _ffmpegService; final WakelockService _wakelockService; + final InAppReviewService _inAppReviewService; final GetMergeStatisticsUseCase _getMergeStatisticsUseCase; final SaveMergeStatisticsUseCase _saveMergeStatisticsUseCase; - final InAppReviewService _inAppReviewService; - - static const _defaultMergeStatistics = MergeStatistics( - successMergeCount: 0, - failedMergeCount: 0, - ); Future init(List videoMetadatas) async { emit(SaveBottomSheetInitial(videoMetadatas: videoMetadatas)); @@ -71,7 +66,7 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith( + statistics?.copyWith( failedMergeCount: statistics.failedMergeCount + 1, ), ), @@ -109,7 +104,7 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith( + statistics?.copyWith( failedMergeCount: statistics.failedMergeCount + 1, ), ), @@ -142,7 +137,7 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith( + statistics?.copyWith( failedMergeCount: statistics.failedMergeCount + 1, ), ), @@ -159,7 +154,7 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith( + statistics?.copyWith( failedMergeCount: statistics.failedMergeCount + 1, ), ), @@ -175,7 +170,7 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith( + statistics?.copyWith( failedMergeCount: statistics.failedMergeCount + 1, ), ), @@ -201,7 +196,7 @@ final class SaveBottomSheetCubit extends Cubit { ); unawaited( _saveMergeStatistics( - statistics.copyWith( + statistics?.copyWith( failedMergeCount: statistics.failedMergeCount + 1, ), ), @@ -209,7 +204,7 @@ final class SaveBottomSheetCubit extends Cubit { return; } - final newStatistics = statistics.copyWith( + final newStatistics = statistics?.copyWith( successMergeCount: statistics.successMergeCount + 1, ); unawaited(_saveMergeStatistics(newStatistics)); @@ -224,7 +219,7 @@ final class SaveBottomSheetCubit extends Cubit { await _ffmpegService.cancelMerge(); } - Future _getMergeStatistics() async { + Future _getMergeStatistics() async { final dataState = await _getMergeStatisticsUseCase(); switch (dataState) { @@ -237,12 +232,13 @@ final class SaveBottomSheetCubit extends Cubit { error: dataState.error, stackTrace: dataState.stackTrace, ); - await _saveMergeStatistics(_defaultMergeStatistics); - return _defaultMergeStatistics; + return null; } } - Future _saveMergeStatistics(MergeStatistics statistics) async { + Future _saveMergeStatistics(MergeStatistics? statistics) async { + if (statistics == null) return; + final dataState = await _saveMergeStatisticsUseCase(params: statistics); switch (dataState) { @@ -258,7 +254,9 @@ final class SaveBottomSheetCubit extends Cubit { } } - Future _requestReview(MergeStatistics statistics) async { + Future _requestReview(MergeStatistics? statistics) async { + if (statistics == null) return; + final totalMergeCount = statistics.successMergeCount + statistics.failedMergeCount; // If the user has not merged at least 2 videos, don't request review. diff --git a/lib/src/features/merge/presentation/pages/merge_page.dart b/lib/src/features/merge/presentation/pages/merge_page.dart index 2cf086e..4b7f2eb 100644 --- a/lib/src/features/merge/presentation/pages/merge_page.dart +++ b/lib/src/features/merge/presentation/pages/merge_page.dart @@ -58,9 +58,9 @@ class MergePage extends StatelessWidget { create: (_) => SaveBottomSheetCubit( ffmpegService: getIt(), wakelockService: getIt(), + inAppReviewService: getIt(), getMergeStatisticsUseCase: getIt(), saveMergeStatisticsUseCase: getIt(), - inAppReviewService: getIt(), ), ), ], From 7ce35fe8f80c41dbfefbc5441ad3d607679c17d9 Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Wed, 19 Jun 2024 22:12:04 +0200 Subject: [PATCH 8/9] refactor: update ObjectBoxMergeSettingsService to create clean box if not available --- .../object_box_merge_settings_service.dart | 12 ++++++-- .../data/models/local_merge_settings.dart | 19 +++++++----- .../data/models/local_merge_statistics.dart | 13 ++++---- .../settings_bottom_sheet_cubit.dart | 30 +++++-------------- 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/lib/src/features/merge/data/data_sources/merge_settings_service/object_box_merge_settings_service.dart b/lib/src/features/merge/data/data_sources/merge_settings_service/object_box_merge_settings_service.dart index 59abb14..16e060e 100644 --- a/lib/src/features/merge/data/data_sources/merge_settings_service/object_box_merge_settings_service.dart +++ b/lib/src/features/merge/data/data_sources/merge_settings_service/object_box_merge_settings_service.dart @@ -22,6 +22,12 @@ final class ObjectBoxMergeSettingsService implements LocalMergeSettingsService { final box = _service.store.box(); final query = box.query().build(); final entities = query.find(); + + if (entities.isEmpty) { + query.close(); + return saveMergeSettings(LocalMergeSettings()); + } + final settings = entities.first; query.close(); @@ -30,7 +36,9 @@ final class ObjectBoxMergeSettingsService implements LocalMergeSettingsService { /// Saves the [LocalMergeSettings]. @override - Future saveMergeSettings(LocalMergeSettings settings) async { + Future saveMergeSettings( + LocalMergeSettings settings, + ) async { final box = _service.store.box(); final query = box.query().build(); final entities = query.find(); @@ -39,6 +47,6 @@ final class ObjectBoxMergeSettingsService implements LocalMergeSettingsService { if (oldSettings != null) settings.id = oldSettings.id; - box.put(settings); + return box.putAndGetAsync(settings); } } diff --git a/lib/src/features/merge/data/models/local_merge_settings.dart b/lib/src/features/merge/data/models/local_merge_settings.dart index b8c0528..380342e 100644 --- a/lib/src/features/merge/data/models/local_merge_settings.dart +++ b/lib/src/features/merge/data/models/local_merge_settings.dart @@ -7,14 +7,19 @@ import 'package:vmerge/src/features/merge/merge.dart'; @Entity() final class LocalMergeSettings implements DataModel { - LocalMergeSettings(); + LocalMergeSettings() + : id = 0, + isSoundOn = true, + playbackSpeed = PlaybackSpeed.one.toString(), + videoResolution = VideoResolution.original.toString(), + videoAspectRatio = VideoAspectRatio.firstVideo.toString(); LocalMergeSettings.fromArgs({ required this.isSoundOn, required this.playbackSpeed, required this.videoResolution, required this.videoAspectRatio, - }); + }) : id = 0; LocalMergeSettings.fromEntity(MergeSettings entity) : this.fromArgs( @@ -24,11 +29,11 @@ final class LocalMergeSettings implements DataModel { videoAspectRatio: entity.videoAspectRatio.toString(), ); - int id = 0; - bool isSoundOn = false; - String playbackSpeed = ''; - String videoResolution = ''; - String videoAspectRatio = ''; + int id; + bool isSoundOn; + String playbackSpeed; + String videoResolution; + String videoAspectRatio; @override MergeSettings toEntity() { diff --git a/lib/src/features/merge/data/models/local_merge_statistics.dart b/lib/src/features/merge/data/models/local_merge_statistics.dart index 2198cc3..cbc27ae 100644 --- a/lib/src/features/merge/data/models/local_merge_statistics.dart +++ b/lib/src/features/merge/data/models/local_merge_statistics.dart @@ -7,12 +7,15 @@ import 'package:vmerge/src/features/merge/domain/domain.dart'; @Entity() final class LocalMergeStatistics implements DataModel { - LocalMergeStatistics(); + LocalMergeStatistics() + : id = 0, + successMergeCount = 0, + failedMergeCount = 0; LocalMergeStatistics.fromArgs({ required this.successMergeCount, required this.failedMergeCount, - }); + }) : id = 0; LocalMergeStatistics.fromEntity(MergeStatistics entity) : this.fromArgs( @@ -20,9 +23,9 @@ final class LocalMergeStatistics implements DataModel { failedMergeCount: entity.failedMergeCount, ); - int id = 0; - int successMergeCount = 0; - int failedMergeCount = 0; + int id; + int successMergeCount; + int failedMergeCount; @override MergeStatistics toEntity() { diff --git a/lib/src/features/merge/presentation/cubits/settings_bottom_sheet_cubit/settings_bottom_sheet_cubit.dart b/lib/src/features/merge/presentation/cubits/settings_bottom_sheet_cubit/settings_bottom_sheet_cubit.dart index 59b4b4c..65e9fd8 100644 --- a/lib/src/features/merge/presentation/cubits/settings_bottom_sheet_cubit/settings_bottom_sheet_cubit.dart +++ b/lib/src/features/merge/presentation/cubits/settings_bottom_sheet_cubit/settings_bottom_sheet_cubit.dart @@ -14,39 +14,26 @@ final class SettingsBottomSheetCubit extends Cubit { required SaveMergeSettingsUseCase saveMergeSettingsUseCase, }) : _getMergeSettingsUseCase = getMergeSettingsUseCase, _saveMergeSettingsUseCase = saveMergeSettingsUseCase, - super( - SettingsBottomSheetLoaded( - isAudioOn: _defaultMergeSettings.isAudioOn, - playbackSpeed: _defaultMergeSettings.playbackSpeed, - videoResolution: _defaultMergeSettings.videoResolution, - videoAspectRatio: _defaultMergeSettings.videoAspectRatio, - ), - ); + super(const SettingsBottomSheetInitial()); final GetMergeSettingsUseCase _getMergeSettingsUseCase; final SaveMergeSettingsUseCase _saveMergeSettingsUseCase; - static const _defaultMergeSettings = MergeSettings( - isAudioOn: true, - playbackSpeed: PlaybackSpeed.one, - videoResolution: VideoResolution.original, - videoAspectRatio: VideoAspectRatio.firstVideo, - ); - Future init() async { final settings = await _getMergeSettings(); emit( SettingsBottomSheetLoaded( - isAudioOn: settings.isAudioOn, - playbackSpeed: settings.playbackSpeed, - videoResolution: settings.videoResolution, - videoAspectRatio: settings.videoAspectRatio, + isAudioOn: settings?.isAudioOn ?? true, + playbackSpeed: settings?.playbackSpeed ?? PlaybackSpeed.one, + videoResolution: settings?.videoResolution ?? VideoResolution.original, + videoAspectRatio: + settings?.videoAspectRatio ?? VideoAspectRatio.firstVideo, ), ); } - Future _getMergeSettings() async { + Future _getMergeSettings() async { final dataState = await _getMergeSettingsUseCase(); switch (dataState) { @@ -59,8 +46,7 @@ final class SettingsBottomSheetCubit extends Cubit { error: dataState.error, stackTrace: dataState.stackTrace, ); - await _saveMergeSettings(_defaultMergeSettings); - return _defaultMergeSettings; + return null; } } From dc69b50420156e589bf5f3e63ac526cce897f56c Mon Sep 17 00:00:00 2001 From: Bulent Baris Kilic Date: Thu, 20 Jun 2024 00:22:40 +0200 Subject: [PATCH 9/9] refactor: update init method signature in SaveBottomSheetCubit --- .../cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart index 1d20af6..09645e8 100644 --- a/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart +++ b/lib/src/features/merge/presentation/cubits/save_bottom_sheet_cubit/save_bottom_sheet_cubit.dart @@ -40,7 +40,7 @@ final class SaveBottomSheetCubit extends Cubit { final GetMergeStatisticsUseCase _getMergeStatisticsUseCase; final SaveMergeStatisticsUseCase _saveMergeStatisticsUseCase; - Future init(List videoMetadatas) async { + void init(List videoMetadatas) { emit(SaveBottomSheetInitial(videoMetadatas: videoMetadatas)); }