From 43d3c71653b0f3f8b78bf9507e451f12f7e988a9 Mon Sep 17 00:00:00 2001 From: Ryo Takeuchi Date: Sat, 5 Oct 2024 17:50:02 +0900 Subject: [PATCH] =?UTF-8?q?feat(model):=20=E3=82=A2=E3=83=97=E3=83=AA?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=81=AE=E3=83=A2?= =?UTF-8?q?=E3=83=87=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/mobile/lib/config/remote_config.dart | 4 +- .../initializer/app_config_initializer.dart | 4 +- core/model/lib/config.dart | 1 + core/model/lib/src/config/app_config.dart | 5 +- .../lib/src/config/app_config.freezed.dart | 31 ++- core/model/lib/src/config/app_version.dart | 46 +++++ .../lib/src/config/app_version.freezed.dart | 181 ++++++++++++++++++ core/model/lib/src/config/update_version.dart | 33 ++-- .../src/config/update_version.freezed.dart | 56 ++++-- .../component/app_config_tile_content.dart | 4 +- 10 files changed, 319 insertions(+), 46 deletions(-) create mode 100644 core/model/lib/src/config/app_version.dart create mode 100644 core/model/lib/src/config/app_version.freezed.dart diff --git a/app/mobile/lib/config/remote_config.dart b/app/mobile/lib/config/remote_config.dart index 6fab2de7..05e27893 100644 --- a/app/mobile/lib/config/remote_config.dart +++ b/app/mobile/lib/config/remote_config.dart @@ -27,7 +27,7 @@ UpdateVersion _resolveUpdateVersion(FirebaseRemoteConfig firebaseRemoteConfig) { firebaseRemoteConfig.getString(appVersionsKey), ); return UpdateVersion( - force: updateVersions['force'] as String, - optional: updateVersions['optional'] as String, + force: AppVersion.parse(updateVersions['force'] as String), + optional: AppVersion.parse(updateVersions['optional'] as String), ); } diff --git a/app/mobile/lib/initializer/app_config_initializer.dart b/app/mobile/lib/initializer/app_config_initializer.dart index b2f90fa2..79654de2 100644 --- a/app/mobile/lib/initializer/app_config_initializer.dart +++ b/app/mobile/lib/initializer/app_config_initializer.dart @@ -1,6 +1,6 @@ +import 'package:app_mobile/env.dart'; import 'package:core_model/config.dart'; import 'package:flutter/services.dart'; -import 'package:app_mobile/env.dart'; import 'package:package_info_plus/package_info_plus.dart'; Future initializeAppConfig() async { @@ -15,7 +15,7 @@ Future initializeAppConfig() async { flavor: flavor, appName: packageInfo.appName, packageName: packageInfo.packageName, - version: packageInfo.version, + version: AppVersion.parse(packageInfo.version), buildNumber: packageInfo.buildNumber, buildSignature: packageInfo.buildSignature, installerStore: packageInfo.installerStore, diff --git a/core/model/lib/config.dart b/core/model/lib/config.dart index 067e5a36..da48f36c 100644 --- a/core/model/lib/config.dart +++ b/core/model/lib/config.dart @@ -1,4 +1,5 @@ export 'src/config/app_config.dart'; +export 'src/config/app_version.dart'; export 'src/config/flavor.dart'; export 'src/config/remote_config.dart'; export 'src/config/update_version.dart'; diff --git a/core/model/lib/src/config/app_config.dart b/core/model/lib/src/config/app_config.dart index 8f5676a7..182e7859 100644 --- a/core/model/lib/src/config/app_config.dart +++ b/core/model/lib/src/config/app_config.dart @@ -1,3 +1,4 @@ +import 'package:core_model/src/config/app_version.dart'; import 'package:core_model/src/config/flavor.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -19,7 +20,7 @@ class AppConfig with _$AppConfig { const factory AppConfig({ required String appName, required String packageName, - required String version, + required AppVersion version, required String buildNumber, required String buildSignature, required Flavor flavor, @@ -33,7 +34,7 @@ class AppConfig with _$AppConfig { const fakeAppConfig = AppConfig( appName: 'Fake App', packageName: 'com.example.fake_app', - version: '1.0.0', + version: AppVersion(major: 1, minor: 0, patch: 0), buildNumber: '1', buildSignature: '1', flavor: Flavor.dev, diff --git a/core/model/lib/src/config/app_config.freezed.dart b/core/model/lib/src/config/app_config.freezed.dart index 97ab60d7..4a5d8cec 100644 --- a/core/model/lib/src/config/app_config.freezed.dart +++ b/core/model/lib/src/config/app_config.freezed.dart @@ -18,7 +18,7 @@ final _privateConstructorUsedError = UnsupportedError( mixin _$AppConfig { String get appName => throw _privateConstructorUsedError; String get packageName => throw _privateConstructorUsedError; - String get version => throw _privateConstructorUsedError; + AppVersion get version => throw _privateConstructorUsedError; String get buildNumber => throw _privateConstructorUsedError; String get buildSignature => throw _privateConstructorUsedError; Flavor get flavor => throw _privateConstructorUsedError; @@ -41,13 +41,15 @@ abstract class $AppConfigCopyWith<$Res> { $Res call( {String appName, String packageName, - String version, + AppVersion version, String buildNumber, String buildSignature, Flavor flavor, String? installerStore, String backendUrl, String websiteUrl}); + + $AppVersionCopyWith<$Res> get version; } /// @nodoc @@ -87,7 +89,7 @@ class _$AppConfigCopyWithImpl<$Res, $Val extends AppConfig> version: null == version ? _value.version : version // ignore: cast_nullable_to_non_nullable - as String, + as AppVersion, buildNumber: null == buildNumber ? _value.buildNumber : buildNumber // ignore: cast_nullable_to_non_nullable @@ -114,6 +116,16 @@ class _$AppConfigCopyWithImpl<$Res, $Val extends AppConfig> as String, ) as $Val); } + + /// Create a copy of AppConfig + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $AppVersionCopyWith<$Res> get version { + return $AppVersionCopyWith<$Res>(_value.version, (value) { + return _then(_value.copyWith(version: value) as $Val); + }); + } } /// @nodoc @@ -127,13 +139,16 @@ abstract class _$$AppConfigImplCopyWith<$Res> $Res call( {String appName, String packageName, - String version, + AppVersion version, String buildNumber, String buildSignature, Flavor flavor, String? installerStore, String backendUrl, String websiteUrl}); + + @override + $AppVersionCopyWith<$Res> get version; } /// @nodoc @@ -171,7 +186,7 @@ class __$$AppConfigImplCopyWithImpl<$Res> version: null == version ? _value.version : version // ignore: cast_nullable_to_non_nullable - as String, + as AppVersion, buildNumber: null == buildNumber ? _value.buildNumber : buildNumber // ignore: cast_nullable_to_non_nullable @@ -219,7 +234,7 @@ class _$AppConfigImpl implements _AppConfig { @override final String packageName; @override - final String version; + final AppVersion version; @override final String buildNumber; @override @@ -286,7 +301,7 @@ abstract class _AppConfig implements AppConfig { const factory _AppConfig( {required final String appName, required final String packageName, - required final String version, + required final AppVersion version, required final String buildNumber, required final String buildSignature, required final Flavor flavor, @@ -299,7 +314,7 @@ abstract class _AppConfig implements AppConfig { @override String get packageName; @override - String get version; + AppVersion get version; @override String get buildNumber; @override diff --git a/core/model/lib/src/config/app_version.dart b/core/model/lib/src/config/app_version.dart new file mode 100644 index 00000000..1a11d41c --- /dev/null +++ b/core/model/lib/src/config/app_version.dart @@ -0,0 +1,46 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'app_version.freezed.dart'; + +/// アプリバージョン +/// +/// {@category Model} +@freezed +class AppVersion with _$AppVersion { + const factory AppVersion({ + required int major, + required int minor, + required int patch, + }) = _AppVersion; + + factory AppVersion.parse(String version) { + final versionList = version.split('.').map(int.parse).toList(); + return AppVersion( + major: versionList[0], + minor: versionList[1], + patch: versionList[2], + ); + } + + const AppVersion._(); + + String get value => '$major.$minor.$patch'; + + int compareTo(AppVersion other) { + if (major != other.major) { + return major.compareTo(other.major); + } + if (minor != other.minor) { + return minor.compareTo(other.minor); + } + return patch.compareTo(other.patch); + } + + bool operator >(AppVersion other) => compareTo(other) > 0; + + bool operator <(AppVersion other) => compareTo(other) < 0; + + bool operator >=(AppVersion other) => compareTo(other) >= 0; + + bool operator <=(AppVersion other) => compareTo(other) <= 0; +} diff --git a/core/model/lib/src/config/app_version.freezed.dart b/core/model/lib/src/config/app_version.freezed.dart new file mode 100644 index 00000000..7bcd6b32 --- /dev/null +++ b/core/model/lib/src/config/app_version.freezed.dart @@ -0,0 +1,181 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'app_version.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$AppVersion { + int get major => throw _privateConstructorUsedError; + int get minor => throw _privateConstructorUsedError; + int get patch => throw _privateConstructorUsedError; + + /// Create a copy of AppVersion + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AppVersionCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AppVersionCopyWith<$Res> { + factory $AppVersionCopyWith( + AppVersion value, $Res Function(AppVersion) then) = + _$AppVersionCopyWithImpl<$Res, AppVersion>; + @useResult + $Res call({int major, int minor, int patch}); +} + +/// @nodoc +class _$AppVersionCopyWithImpl<$Res, $Val extends AppVersion> + implements $AppVersionCopyWith<$Res> { + _$AppVersionCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AppVersion + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? major = null, + Object? minor = null, + Object? patch = null, + }) { + return _then(_value.copyWith( + major: null == major + ? _value.major + : major // ignore: cast_nullable_to_non_nullable + as int, + minor: null == minor + ? _value.minor + : minor // ignore: cast_nullable_to_non_nullable + as int, + patch: null == patch + ? _value.patch + : patch // ignore: cast_nullable_to_non_nullable + as int, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$AppVersionImplCopyWith<$Res> + implements $AppVersionCopyWith<$Res> { + factory _$$AppVersionImplCopyWith( + _$AppVersionImpl value, $Res Function(_$AppVersionImpl) then) = + __$$AppVersionImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({int major, int minor, int patch}); +} + +/// @nodoc +class __$$AppVersionImplCopyWithImpl<$Res> + extends _$AppVersionCopyWithImpl<$Res, _$AppVersionImpl> + implements _$$AppVersionImplCopyWith<$Res> { + __$$AppVersionImplCopyWithImpl( + _$AppVersionImpl _value, $Res Function(_$AppVersionImpl) _then) + : super(_value, _then); + + /// Create a copy of AppVersion + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? major = null, + Object? minor = null, + Object? patch = null, + }) { + return _then(_$AppVersionImpl( + major: null == major + ? _value.major + : major // ignore: cast_nullable_to_non_nullable + as int, + minor: null == minor + ? _value.minor + : minor // ignore: cast_nullable_to_non_nullable + as int, + patch: null == patch + ? _value.patch + : patch // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$AppVersionImpl extends _AppVersion { + const _$AppVersionImpl( + {required this.major, required this.minor, required this.patch}) + : super._(); + + @override + final int major; + @override + final int minor; + @override + final int patch; + + @override + String toString() { + return 'AppVersion(major: $major, minor: $minor, patch: $patch)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AppVersionImpl && + (identical(other.major, major) || other.major == major) && + (identical(other.minor, minor) || other.minor == minor) && + (identical(other.patch, patch) || other.patch == patch)); + } + + @override + int get hashCode => Object.hash(runtimeType, major, minor, patch); + + /// Create a copy of AppVersion + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AppVersionImplCopyWith<_$AppVersionImpl> get copyWith => + __$$AppVersionImplCopyWithImpl<_$AppVersionImpl>(this, _$identity); +} + +abstract class _AppVersion extends AppVersion { + const factory _AppVersion( + {required final int major, + required final int minor, + required final int patch}) = _$AppVersionImpl; + const _AppVersion._() : super._(); + + @override + int get major; + @override + int get minor; + @override + int get patch; + + /// Create a copy of AppVersion + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AppVersionImplCopyWith<_$AppVersionImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/core/model/lib/src/config/update_version.dart b/core/model/lib/src/config/update_version.dart index 5dd7cc77..f1007bfb 100644 --- a/core/model/lib/src/config/update_version.dart +++ b/core/model/lib/src/config/update_version.dart @@ -1,3 +1,4 @@ +import 'package:core_model/src/config/app_version.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'update_version.freezed.dart'; @@ -8,31 +9,31 @@ part 'update_version.freezed.dart'; @freezed abstract class UpdateVersion implements _$UpdateVersion { const factory UpdateVersion({ - required String force, - required String optional, + required AppVersion force, + required AppVersion optional, }) = _UpdateVersion; const UpdateVersion._(); - bool forceUpdatable(String version) => _updatable(version, force); + bool forceUpdatable(AppVersion version) => _updatable(version, force); - bool optionalUpdatable(String version) => _updatable(version, optional); + bool optionalUpdatable(AppVersion version) => _updatable(version, optional); - bool _updatable(String currentVersion, String updateVersion) { - final currentVersionList = - currentVersion.split('.').map(int.parse).toList(); - final updateVersionList = updateVersion.split('.').map(int.parse).toList(); - for (var i = 0; i < currentVersionList.length; i++) { - if (currentVersionList[i] < updateVersionList[i]) { - return true; - } - } - return false; + bool _updatable(AppVersion currentVersion, AppVersion updateVersion) { + return currentVersion < updateVersion; } } /// FakeUpdateVersion const fakeUpdateVersion = UpdateVersion( - force: '1.0.0', - optional: '1.0.0', + force: AppVersion( + major: 1, + minor: 0, + patch: 0, + ), + optional: AppVersion( + major: 1, + minor: 0, + patch: 0, + ), ); diff --git a/core/model/lib/src/config/update_version.freezed.dart b/core/model/lib/src/config/update_version.freezed.dart index 4cf4234b..55146488 100644 --- a/core/model/lib/src/config/update_version.freezed.dart +++ b/core/model/lib/src/config/update_version.freezed.dart @@ -16,8 +16,8 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$UpdateVersion { - String get force => throw _privateConstructorUsedError; - String get optional => throw _privateConstructorUsedError; + AppVersion get force => throw _privateConstructorUsedError; + AppVersion get optional => throw _privateConstructorUsedError; /// Create a copy of UpdateVersion /// with the given fields replaced by the non-null parameter values. @@ -32,7 +32,10 @@ abstract class $UpdateVersionCopyWith<$Res> { UpdateVersion value, $Res Function(UpdateVersion) then) = _$UpdateVersionCopyWithImpl<$Res, UpdateVersion>; @useResult - $Res call({String force, String optional}); + $Res call({AppVersion force, AppVersion optional}); + + $AppVersionCopyWith<$Res> get force; + $AppVersionCopyWith<$Res> get optional; } /// @nodoc @@ -57,13 +60,33 @@ class _$UpdateVersionCopyWithImpl<$Res, $Val extends UpdateVersion> force: null == force ? _value.force : force // ignore: cast_nullable_to_non_nullable - as String, + as AppVersion, optional: null == optional ? _value.optional : optional // ignore: cast_nullable_to_non_nullable - as String, + as AppVersion, ) as $Val); } + + /// Create a copy of UpdateVersion + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $AppVersionCopyWith<$Res> get force { + return $AppVersionCopyWith<$Res>(_value.force, (value) { + return _then(_value.copyWith(force: value) as $Val); + }); + } + + /// Create a copy of UpdateVersion + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $AppVersionCopyWith<$Res> get optional { + return $AppVersionCopyWith<$Res>(_value.optional, (value) { + return _then(_value.copyWith(optional: value) as $Val); + }); + } } /// @nodoc @@ -74,7 +97,12 @@ abstract class _$$UpdateVersionImplCopyWith<$Res> __$$UpdateVersionImplCopyWithImpl<$Res>; @override @useResult - $Res call({String force, String optional}); + $Res call({AppVersion force, AppVersion optional}); + + @override + $AppVersionCopyWith<$Res> get force; + @override + $AppVersionCopyWith<$Res> get optional; } /// @nodoc @@ -97,11 +125,11 @@ class __$$UpdateVersionImplCopyWithImpl<$Res> force: null == force ? _value.force : force // ignore: cast_nullable_to_non_nullable - as String, + as AppVersion, optional: null == optional ? _value.optional : optional // ignore: cast_nullable_to_non_nullable - as String, + as AppVersion, )); } } @@ -113,9 +141,9 @@ class _$UpdateVersionImpl extends _UpdateVersion { : super._(); @override - final String force; + final AppVersion force; @override - final String optional; + final AppVersion optional; @override String toString() { @@ -146,14 +174,14 @@ class _$UpdateVersionImpl extends _UpdateVersion { abstract class _UpdateVersion extends UpdateVersion { const factory _UpdateVersion( - {required final String force, - required final String optional}) = _$UpdateVersionImpl; + {required final AppVersion force, + required final AppVersion optional}) = _$UpdateVersionImpl; const _UpdateVersion._() : super._(); @override - String get force; + AppVersion get force; @override - String get optional; + AppVersion get optional; /// Create a copy of UpdateVersion /// with the given fields replaced by the non-null parameter values. diff --git a/feature/settings/lib/src/ui/page/settings/component/app_config_tile_content.dart b/feature/settings/lib/src/ui/page/settings/component/app_config_tile_content.dart index 891f7af5..592f8c27 100644 --- a/feature/settings/lib/src/ui/page/settings/component/app_config_tile_content.dart +++ b/feature/settings/lib/src/ui/page/settings/component/app_config_tile_content.dart @@ -18,9 +18,9 @@ final class AppConfigTileContent extends ConsumerWidget { // アプリバージョン Text(l10n.settingsAppConfigAppVersion), if (kIsWeb) - Text(appConfig.version) + Text(appConfig.version.value) else - Text('${appConfig.version} (${appConfig.buildNumber})'), + Text('${appConfig.version.value} (${appConfig.buildNumber})'), // パッケージ名 if (kDebugMode)