From 15c2dbaa0dbf5ac36fa50b1b3f65478aaf0117bc Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 9 Aug 2025 01:41:51 +0800 Subject: [PATCH] :bug: Fix developer --- lib/models/developer.dart | 20 ++- lib/models/developer.freezed.dart | 287 ++++++++++++++++++++++++++++++ lib/models/developer.g.dart | 16 ++ lib/screens/developers/hub.dart | 41 +++-- lib/screens/developers/hub.g.dart | 6 +- lib/widgets/app_scaffold.dart | 2 +- 6 files changed, 346 insertions(+), 26 deletions(-) diff --git a/lib/models/developer.dart b/lib/models/developer.dart index 037de9a..7f6f54e 100644 --- a/lib/models/developer.dart +++ b/lib/models/developer.dart @@ -1,14 +1,26 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:island/models/publisher.dart'; part 'developer.freezed.dart'; part 'developer.g.dart'; +@freezed +sealed class SnDeveloper with _$SnDeveloper { + const factory SnDeveloper({ + required String id, + required String publisherId, + SnPublisher? publisher, + }) = _SnDeveloper; + + factory SnDeveloper.fromJson(Map json) => + _$SnDeveloperFromJson(json); +} + @freezed sealed class DeveloperStats with _$DeveloperStats { - const factory DeveloperStats({ - @Default(0) int totalCustomApps, - }) = _DeveloperStats; + const factory DeveloperStats({@Default(0) int totalCustomApps}) = + _DeveloperStats; factory DeveloperStats.fromJson(Map json) => _$DeveloperStatsFromJson(json); -} \ No newline at end of file +} diff --git a/lib/models/developer.freezed.dart b/lib/models/developer.freezed.dart index 8107e57..d71be37 100644 --- a/lib/models/developer.freezed.dart +++ b/lib/models/developer.freezed.dart @@ -12,6 +12,293 @@ part of 'developer.dart'; // dart format off T _$identity(T value) => value; +/// @nodoc +mixin _$SnDeveloper { + + String get id; String get publisherId; SnPublisher? get publisher; +/// Create a copy of SnDeveloper +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SnDeveloperCopyWith get copyWith => _$SnDeveloperCopyWithImpl(this as SnDeveloper, _$identity); + + /// Serializes this SnDeveloper to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnDeveloper&&(identical(other.id, id) || other.id == id)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisher, publisher) || other.publisher == publisher)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,publisherId,publisher); + +@override +String toString() { + return 'SnDeveloper(id: $id, publisherId: $publisherId, publisher: $publisher)'; +} + + +} + +/// @nodoc +abstract mixin class $SnDeveloperCopyWith<$Res> { + factory $SnDeveloperCopyWith(SnDeveloper value, $Res Function(SnDeveloper) _then) = _$SnDeveloperCopyWithImpl; +@useResult +$Res call({ + String id, String publisherId, SnPublisher? publisher +}); + + +$SnPublisherCopyWith<$Res>? get publisher; + +} +/// @nodoc +class _$SnDeveloperCopyWithImpl<$Res> + implements $SnDeveloperCopyWith<$Res> { + _$SnDeveloperCopyWithImpl(this._self, this._then); + + final SnDeveloper _self; + final $Res Function(SnDeveloper) _then; + +/// Create a copy of SnDeveloper +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? publisherId = null,Object? publisher = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable +as String,publisher: freezed == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable +as SnPublisher?, + )); +} +/// Create a copy of SnDeveloper +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnPublisherCopyWith<$Res>? get publisher { + if (_self.publisher == null) { + return null; + } + + return $SnPublisherCopyWith<$Res>(_self.publisher!, (value) { + return _then(_self.copyWith(publisher: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [SnDeveloper]. +extension SnDeveloperPatterns on SnDeveloper { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _SnDeveloper value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _SnDeveloper() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _SnDeveloper value) $default,){ +final _that = this; +switch (_that) { +case _SnDeveloper(): +return $default(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _SnDeveloper value)? $default,){ +final _that = this; +switch (_that) { +case _SnDeveloper() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String publisherId, SnPublisher? publisher)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _SnDeveloper() when $default != null: +return $default(_that.id,_that.publisherId,_that.publisher);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String publisherId, SnPublisher? publisher) $default,) {final _that = this; +switch (_that) { +case _SnDeveloper(): +return $default(_that.id,_that.publisherId,_that.publisher);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String publisherId, SnPublisher? publisher)? $default,) {final _that = this; +switch (_that) { +case _SnDeveloper() when $default != null: +return $default(_that.id,_that.publisherId,_that.publisher);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _SnDeveloper implements SnDeveloper { + const _SnDeveloper({required this.id, required this.publisherId, this.publisher}); + factory _SnDeveloper.fromJson(Map json) => _$SnDeveloperFromJson(json); + +@override final String id; +@override final String publisherId; +@override final SnPublisher? publisher; + +/// Create a copy of SnDeveloper +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$SnDeveloperCopyWith<_SnDeveloper> get copyWith => __$SnDeveloperCopyWithImpl<_SnDeveloper>(this, _$identity); + +@override +Map toJson() { + return _$SnDeveloperToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnDeveloper&&(identical(other.id, id) || other.id == id)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisher, publisher) || other.publisher == publisher)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,publisherId,publisher); + +@override +String toString() { + return 'SnDeveloper(id: $id, publisherId: $publisherId, publisher: $publisher)'; +} + + +} + +/// @nodoc +abstract mixin class _$SnDeveloperCopyWith<$Res> implements $SnDeveloperCopyWith<$Res> { + factory _$SnDeveloperCopyWith(_SnDeveloper value, $Res Function(_SnDeveloper) _then) = __$SnDeveloperCopyWithImpl; +@override @useResult +$Res call({ + String id, String publisherId, SnPublisher? publisher +}); + + +@override $SnPublisherCopyWith<$Res>? get publisher; + +} +/// @nodoc +class __$SnDeveloperCopyWithImpl<$Res> + implements _$SnDeveloperCopyWith<$Res> { + __$SnDeveloperCopyWithImpl(this._self, this._then); + + final _SnDeveloper _self; + final $Res Function(_SnDeveloper) _then; + +/// Create a copy of SnDeveloper +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? publisherId = null,Object? publisher = freezed,}) { + return _then(_SnDeveloper( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable +as String,publisher: freezed == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable +as SnPublisher?, + )); +} + +/// Create a copy of SnDeveloper +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnPublisherCopyWith<$Res>? get publisher { + if (_self.publisher == null) { + return null; + } + + return $SnPublisherCopyWith<$Res>(_self.publisher!, (value) { + return _then(_self.copyWith(publisher: value)); + }); +} +} + + /// @nodoc mixin _$DeveloperStats { diff --git a/lib/models/developer.g.dart b/lib/models/developer.g.dart index 84235ea..7fa257c 100644 --- a/lib/models/developer.g.dart +++ b/lib/models/developer.g.dart @@ -6,6 +6,22 @@ part of 'developer.dart'; // JsonSerializableGenerator // ************************************************************************** +_SnDeveloper _$SnDeveloperFromJson(Map json) => _SnDeveloper( + id: json['id'] as String, + publisherId: json['publisher_id'] as String, + publisher: + json['publisher'] == null + ? null + : SnPublisher.fromJson(json['publisher'] as Map), +); + +Map _$SnDeveloperToJson(_SnDeveloper instance) => + { + 'id': instance.id, + 'publisher_id': instance.publisherId, + 'publisher': instance.publisher?.toJson(), + }; + _DeveloperStats _$DeveloperStatsFromJson(Map json) => _DeveloperStats( totalCustomApps: (json['total_custom_apps'] as num?)?.toInt() ?? 0, diff --git a/lib/screens/developers/hub.dart b/lib/screens/developers/hub.dart index a85ebe7..581fe12 100644 --- a/lib/screens/developers/hub.dart +++ b/lib/screens/developers/hub.dart @@ -30,12 +30,12 @@ Future developerStats(Ref ref, String? uname) async { } @riverpod -Future> developers(Ref ref) async { +Future> developers(Ref ref) async { final client = ref.watch(apiClientProvider); final resp = await client.get('/develop/developers'); return resp.data - .map((e) => SnPublisher.fromJson(e)) - .cast() + .map((e) => SnDeveloper.fromJson(e)) + .cast() .toList(); } @@ -74,25 +74,25 @@ class DeveloperHubScreen extends HookConsumerWidget { } final developers = ref.watch(developersProvider); - final currentDeveloper = useState( + final currentDeveloper = useState( developers.value?.firstOrNull, ); - final List> developersMenu = developers.when( + final List> developersMenu = developers.when( data: (data) => data .map( - (item) => DropdownMenuItem( + (item) => DropdownMenuItem( value: item, child: ListTile( minTileHeight: 48, leading: ProfilePictureWidget( radius: 16, - fileId: item.picture?.id, + fileId: item.publisher?.picture?.id, ), - title: Text(item.nick), - subtitle: Text('@${item.name}'), + title: Text(item.publisher!.nick), + subtitle: Text('@${item.publisher!.name}'), trailing: currentDeveloper.value?.id == item.id ? const Icon(Icons.check) @@ -107,7 +107,7 @@ class DeveloperHubScreen extends HookConsumerWidget { ); final developerStats = ref.watch( - developerStatsProvider(currentDeveloper.value?.name), + developerStatsProvider(currentDeveloper.value?.publisher?.name), ); return AppScaffold( @@ -117,7 +117,7 @@ class DeveloperHubScreen extends HookConsumerWidget { title: Text('developerHub').tr(), actions: [ DropdownButtonHideUnderline( - child: DropdownButton2( + child: DropdownButton2( alignment: Alignment.centerRight, value: currentDeveloper.value, hint: CircleAvatar( @@ -139,7 +139,7 @@ class DeveloperHubScreen extends HookConsumerWidget { ...developersMenu.map( (e) => ProfilePictureWidget( radius: 16, - fileId: e.value?.picture?.id, + fileId: e.value?.publisher?.picture?.id, ).center().padding(right: 8), ), ]; @@ -193,10 +193,12 @@ class DeveloperHubScreen extends HookConsumerWidget { ...(developers.value?.map( (developer) => ListTile( leading: ProfilePictureWidget( - file: developer.picture, + file: developer.publisher?.picture, + ), + title: Text(developer.publisher!.nick), + subtitle: Text( + '@${developer.publisher!.name}', ), - title: Text(developer.nick), - subtitle: Text('@${developer.name}'), onTap: () { currentDeveloper.value = developer; }, @@ -243,7 +245,8 @@ class DeveloperHubScreen extends HookConsumerWidget { context.pushNamed( 'developerApps', pathParameters: { - 'name': currentDeveloper.value!.name, + 'name': + currentDeveloper.value!.publisher!.name, }, ); }, @@ -257,7 +260,9 @@ class DeveloperHubScreen extends HookConsumerWidget { error: err, onRetry: () { ref.invalidate( - developerStatsProvider(currentDeveloper.value?.name), + developerStatsProvider( + currentDeveloper.value?.publisher!.name, + ), ); }, ), @@ -354,7 +359,7 @@ class _DeveloperEnrollmentSheet extends HookConsumerWidget { ? Center( child: Text( - 'noPublishersToEnroll', + 'noDevelopersToEnroll', textAlign: TextAlign.center, ).tr(), ) diff --git a/lib/screens/developers/hub.g.dart b/lib/screens/developers/hub.g.dart index 44d93c1..d287526 100644 --- a/lib/screens/developers/hub.g.dart +++ b/lib/screens/developers/hub.g.dart @@ -149,12 +149,12 @@ class _DeveloperStatsProviderElement String? get uname => (origin as DeveloperStatsProvider).uname; } -String _$developersHash() => r'04f25db31f511f651a5add128d56631236ed0b39'; +String _$developersHash() => r'252341098617ac398ce133994453f318dd3edbd2'; /// See also [developers]. @ProviderFor(developers) final developersProvider = - AutoDisposeFutureProvider>.internal( + AutoDisposeFutureProvider>.internal( developers, name: r'developersProvider', debugGetCreateSourceHash: @@ -167,6 +167,6 @@ final developersProvider = @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element -typedef DevelopersRef = AutoDisposeFutureProviderRef>; +typedef DevelopersRef = AutoDisposeFutureProviderRef>; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/widgets/app_scaffold.dart b/lib/widgets/app_scaffold.dart index d24efea..d4fa359 100644 --- a/lib/widgets/app_scaffold.dart +++ b/lib/widgets/app_scaffold.dart @@ -331,7 +331,7 @@ class _WebSocketIndicator extends HookConsumerWidget { final user = ref.watch(userInfoProvider); final websocketState = ref.watch(websocketStateProvider); final indicatorHeight = - MediaQuery.of(context).padding.top + (isDesktop ? 27.5 : 20); + MediaQuery.of(context).padding.top + (isDesktop ? 27.5 : 25); Color indicatorColor; String indicatorText;