Compare commits
	
		
			3 Commits
		
	
	
		
			abf395ff9a
			...
			d1e8234b93
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d1e8234b93 | |||
| a03d6015a6 | |||
| 246ac52d0a | 
| @@ -914,5 +914,17 @@ | ||||
|     "other": "{} articles" | ||||
|   }, | ||||
|   "webFeedSubscribed": "The feed has been subscribed", | ||||
|   "webFeedUnsubscribed": "The feed has been unsubscribed" | ||||
|   "webFeedUnsubscribed": "The feed has been unsubscribed", | ||||
|   "appDetails": "App Details", | ||||
|   "secrets": "Secrets", | ||||
|   "appNotFound": "App not found.", | ||||
|   "secretCopied": "Secret copied to clipboard.", | ||||
|   "deleteSecret": "Delete Secret", | ||||
|   "deleteSecretHint": "Are you sure you want to delete this secret? This action cannot be undone.", | ||||
|   "generateSecret": "Generate New Secret", | ||||
|   "createdAt": "Created at {}", | ||||
|   "newSecretGenerated": "New Secret Generated", | ||||
|   "copySecretHint": "Please copy this secret and store it somewhere safe. You will not be able to see it again.", | ||||
|   "expiresIn": "Expires In (seconds)", | ||||
|   "isOidc": "OIDC Compliant" | ||||
| } | ||||
| @@ -843,5 +843,17 @@ | ||||
|   "socialCreditsLevelPoor": "糟糕", | ||||
|   "socialCreditsLevelNormal": "正常", | ||||
|   "socialCreditsLevelGood": "良好", | ||||
|   "socialCreditsLevelExcellent": "优秀" | ||||
|   "socialCreditsLevelExcellent": "优秀", | ||||
|   "appDetails": "应用详情", | ||||
|   "secrets": "密钥", | ||||
|   "appNotFound": "应用未找到。", | ||||
|   "secretCopied": "密钥已复制到剪贴板。", | ||||
|   "deleteSecret": "删除密钥", | ||||
|   "deleteSecretHint": "您确定要删除此密钥吗?此操作无法撤销。", | ||||
|   "generateSecret": "生成新密钥", | ||||
|   "createdAt": "创建于 {}", | ||||
|   "newSecretGenerated": "已生成新密钥", | ||||
|   "copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。", | ||||
|   "expiresIn": "过期时间(秒)", | ||||
|   "isOidc": "OIDC 兼容" | ||||
| } | ||||
|   | ||||
| @@ -811,5 +811,17 @@ | ||||
|     "filesListAdditional": { | ||||
|         "one": "+{} 個文件被摺疊", | ||||
|         "other": "+{} 個文件被摺疊" | ||||
|     } | ||||
|     }, | ||||
|     "appDetails": "應用程式詳情", | ||||
|     "secrets": "密鑰", | ||||
|     "appNotFound": "找不到應用程式。", | ||||
|     "secretCopied": "密鑰已複製到剪貼簿。", | ||||
|     "deleteSecret": "刪除密鑰", | ||||
|     "deleteSecretHint": "您確定要刪除此密鑰嗎?此操作無法復原。", | ||||
|     "generateSecret": "產生新密鑰", | ||||
|     "createdAt": "建立於 {}", | ||||
|     "newSecretGenerated": "已產生新密鑰", | ||||
|     "copySecretHint": "請複製此密鑰並將其存放在安全的地方。您將無法再次看到它。", | ||||
|     "expiresIn": "過期時間(秒)", | ||||
|     "isOidc": "OIDC 相容" | ||||
| } | ||||
							
								
								
									
										19
									
								
								lib/models/custom_app_secret.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/models/custom_app_secret.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | ||||
|  | ||||
| part 'custom_app_secret.freezed.dart'; | ||||
| part 'custom_app_secret.g.dart'; | ||||
|  | ||||
| @freezed | ||||
| sealed class CustomAppSecret with _$CustomAppSecret { | ||||
|   const factory CustomAppSecret({ | ||||
|     required String id, | ||||
|     required String? secret, | ||||
|     required DateTime createdAt, | ||||
|     String? description, | ||||
|     int? expiresIn, | ||||
|     bool? isOidc, | ||||
|   }) = _CustomAppSecret; | ||||
|  | ||||
|   factory CustomAppSecret.fromJson(Map<String, dynamic> json) => | ||||
|       _$CustomAppSecretFromJson(json); | ||||
| } | ||||
							
								
								
									
										286
									
								
								lib/models/custom_app_secret.freezed.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								lib/models/custom_app_secret.freezed.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,286 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
| // coverage:ignore-file | ||||
| // 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 'custom_app_secret.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // FreezedGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| // dart format off | ||||
| T _$identity<T>(T value) => value; | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$CustomAppSecret { | ||||
|  | ||||
|  String get id; String? get secret; DateTime get createdAt; String? get description; int? get expiresIn; bool? get isOidc; | ||||
| /// Create a copy of CustomAppSecret | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $CustomAppSecretCopyWith<CustomAppSecret> get copyWith => _$CustomAppSecretCopyWithImpl<CustomAppSecret>(this as CustomAppSecret, _$identity); | ||||
|  | ||||
|   /// Serializes this CustomAppSecret to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is CustomAppSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiresIn, expiresIn) || other.expiresIn == expiresIn)&&(identical(other.isOidc, isOidc) || other.isOidc == isOidc)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,secret,createdAt,description,expiresIn,isOidc); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'CustomAppSecret(id: $id, secret: $secret, createdAt: $createdAt, description: $description, expiresIn: $expiresIn, isOidc: $isOidc)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $CustomAppSecretCopyWith<$Res>  { | ||||
|   factory $CustomAppSecretCopyWith(CustomAppSecret value, $Res Function(CustomAppSecret) _then) = _$CustomAppSecretCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$CustomAppSecretCopyWithImpl<$Res> | ||||
|     implements $CustomAppSecretCopyWith<$Res> { | ||||
|   _$CustomAppSecretCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final CustomAppSecret _self; | ||||
|   final $Res Function(CustomAppSecret) _then; | ||||
|  | ||||
| /// Create a copy of CustomAppSecret | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? secret = freezed,Object? createdAt = null,Object? description = freezed,Object? expiresIn = freezed,Object? isOidc = freezed,}) { | ||||
|   return _then(_self.copyWith( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,secret: freezed == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable | ||||
| as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable | ||||
| as String?,expiresIn: freezed == expiresIn ? _self.expiresIn : expiresIn // ignore: cast_nullable_to_non_nullable | ||||
| as int?,isOidc: freezed == isOidc ? _self.isOidc : isOidc // ignore: cast_nullable_to_non_nullable | ||||
| as bool?, | ||||
|   )); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Adds pattern-matching-related methods to [CustomAppSecret]. | ||||
| extension CustomAppSecretPatterns on CustomAppSecret { | ||||
| /// 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 extends Object?>(TResult Function( _CustomAppSecret value)?  $default,{required TResult orElse(),}){ | ||||
| final _that = this; | ||||
| switch (_that) { | ||||
| case _CustomAppSecret() 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 extends Object?>(TResult Function( _CustomAppSecret value)  $default,){ | ||||
| final _that = this; | ||||
| switch (_that) { | ||||
| case _CustomAppSecret(): | ||||
| 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 extends Object?>(TResult? Function( _CustomAppSecret value)?  $default,){ | ||||
| final _that = this; | ||||
| switch (_that) { | ||||
| case _CustomAppSecret() 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 extends Object?>(TResult Function( String id,  String? secret,  DateTime createdAt,  String? description,  int? expiresIn,  bool? isOidc)?  $default,{required TResult orElse(),}) {final _that = this; | ||||
| switch (_that) { | ||||
| case _CustomAppSecret() when $default != null: | ||||
| return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);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 extends Object?>(TResult Function( String id,  String? secret,  DateTime createdAt,  String? description,  int? expiresIn,  bool? isOidc)  $default,) {final _that = this; | ||||
| switch (_that) { | ||||
| case _CustomAppSecret(): | ||||
| return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);} | ||||
| } | ||||
| /// 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 extends Object?>(TResult? Function( String id,  String? secret,  DateTime createdAt,  String? description,  int? expiresIn,  bool? isOidc)?  $default,) {final _that = this; | ||||
| switch (_that) { | ||||
| case _CustomAppSecret() when $default != null: | ||||
| return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);case _: | ||||
|   return null; | ||||
|  | ||||
| } | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class _CustomAppSecret implements CustomAppSecret { | ||||
|   const _CustomAppSecret({required this.id, required this.secret, required this.createdAt, this.description, this.expiresIn, this.isOidc}); | ||||
|   factory _CustomAppSecret.fromJson(Map<String, dynamic> json) => _$CustomAppSecretFromJson(json); | ||||
|  | ||||
| @override final  String id; | ||||
| @override final  String? secret; | ||||
| @override final  DateTime createdAt; | ||||
| @override final  String? description; | ||||
| @override final  int? expiresIn; | ||||
| @override final  bool? isOidc; | ||||
|  | ||||
| /// Create a copy of CustomAppSecret | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| _$CustomAppSecretCopyWith<_CustomAppSecret> get copyWith => __$CustomAppSecretCopyWithImpl<_CustomAppSecret>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$CustomAppSecretToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _CustomAppSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiresIn, expiresIn) || other.expiresIn == expiresIn)&&(identical(other.isOidc, isOidc) || other.isOidc == isOidc)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,secret,createdAt,description,expiresIn,isOidc); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'CustomAppSecret(id: $id, secret: $secret, createdAt: $createdAt, description: $description, expiresIn: $expiresIn, isOidc: $isOidc)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class _$CustomAppSecretCopyWith<$Res> implements $CustomAppSecretCopyWith<$Res> { | ||||
|   factory _$CustomAppSecretCopyWith(_CustomAppSecret value, $Res Function(_CustomAppSecret) _then) = __$CustomAppSecretCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class __$CustomAppSecretCopyWithImpl<$Res> | ||||
|     implements _$CustomAppSecretCopyWith<$Res> { | ||||
|   __$CustomAppSecretCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final _CustomAppSecret _self; | ||||
|   final $Res Function(_CustomAppSecret) _then; | ||||
|  | ||||
| /// Create a copy of CustomAppSecret | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? secret = freezed,Object? createdAt = null,Object? description = freezed,Object? expiresIn = freezed,Object? isOidc = freezed,}) { | ||||
|   return _then(_CustomAppSecret( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,secret: freezed == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable | ||||
| as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable | ||||
| as String?,expiresIn: freezed == expiresIn ? _self.expiresIn : expiresIn // ignore: cast_nullable_to_non_nullable | ||||
| as int?,isOidc: freezed == isOidc ? _self.isOidc : isOidc // ignore: cast_nullable_to_non_nullable | ||||
| as bool?, | ||||
|   )); | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| // dart format on | ||||
							
								
								
									
										27
									
								
								lib/models/custom_app_secret.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lib/models/custom_app_secret.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'custom_app_secret.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // JsonSerializableGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| _CustomAppSecret _$CustomAppSecretFromJson(Map<String, dynamic> json) => | ||||
|     _CustomAppSecret( | ||||
|       id: json['id'] as String, | ||||
|       secret: json['secret'] as String?, | ||||
|       createdAt: DateTime.parse(json['created_at'] as String), | ||||
|       description: json['description'] as String?, | ||||
|       expiresIn: (json['expires_in'] as num?)?.toInt(), | ||||
|       isOidc: json['is_oidc'] as bool?, | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$CustomAppSecretToJson(_CustomAppSecret instance) => | ||||
|     <String, dynamic>{ | ||||
|       'id': instance.id, | ||||
|       'secret': instance.secret, | ||||
|       'created_at': instance.createdAt.toIso8601String(), | ||||
|       'description': instance.description, | ||||
|       'expires_in': instance.expiresIn, | ||||
|       'is_oidc': instance.isOidc, | ||||
|     }; | ||||
| @@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/screens/about.dart'; | ||||
| import 'package:island/screens/account/credits.dart'; | ||||
| import 'package:island/screens/developers/app_detail.dart'; | ||||
| import 'package:island/screens/developers/bot_detail.dart'; | ||||
| import 'package:island/screens/developers/edit_app.dart'; | ||||
| import 'package:island/screens/developers/edit_bot.dart'; | ||||
| @@ -349,6 +350,16 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|                           id: state.pathParameters['id']!, | ||||
|                         ), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     name: 'developerAppDetail', | ||||
|                     path: 'apps/:appId', | ||||
|                     builder: | ||||
|                         (context, state) => AppDetailScreen( | ||||
|                           publisherName: state.pathParameters['name']!, | ||||
|                           projectId: state.pathParameters['projectId']!, | ||||
|                           appId: state.pathParameters['appId']!, | ||||
|                         ), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     name: 'developerBotDetail', | ||||
|                     path: 'bots/:botId', | ||||
|   | ||||
							
								
								
									
										131
									
								
								lib/screens/developers/app_detail.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								lib/screens/developers/app_detail.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/custom_app.dart'; | ||||
| import 'package:island/screens/developers/app_secrets.dart'; | ||||
| import 'package:island/screens/developers/apps.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/content/cloud_files.dart'; | ||||
| import 'package:island/widgets/response.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| class AppDetailScreen extends HookConsumerWidget { | ||||
|   final String publisherName; | ||||
|   final String projectId; | ||||
|   final String appId; | ||||
|  | ||||
|   const AppDetailScreen({ | ||||
|     super.key, | ||||
|     required this.publisherName, | ||||
|     required this.projectId, | ||||
|     required this.appId, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final tabController = useTabController(initialLength: 2); | ||||
|     final appData = ref.watch(customAppProvider(publisherName, projectId, appId)); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar( | ||||
|         title: Text(appData.value?.name ?? 'appDetails'.tr()), | ||||
|         actions: [ | ||||
|           IconButton( | ||||
|             icon: const Icon(Symbols.edit), | ||||
|             onPressed: appData.value == null | ||||
|                 ? null | ||||
|                 : () { | ||||
|                     context.pushNamed( | ||||
|                       'developerAppEdit', | ||||
|                       pathParameters: { | ||||
|                         'name': publisherName, | ||||
|                         'projectId': projectId, | ||||
|                         'id': appId, | ||||
|                       }, | ||||
|                     ); | ||||
|                   }, | ||||
|           ), | ||||
|         ], | ||||
|         bottom: TabBar( | ||||
|           controller: tabController, | ||||
|           tabs: [Tab(text: 'overview'.tr()), Tab(text: 'secrets'.tr())], | ||||
|         ), | ||||
|       ), | ||||
|       body: appData.when( | ||||
|         data: (app) { | ||||
|           return TabBarView( | ||||
|             controller: tabController, | ||||
|             physics: const NeverScrollableScrollPhysics(), | ||||
|             children: [ | ||||
|               _AppOverview(app: app), | ||||
|               AppSecretsScreen( | ||||
|                 publisherName: publisherName, | ||||
|                 projectId: projectId, | ||||
|                 appId: appId, | ||||
|               ), | ||||
|             ], | ||||
|           ); | ||||
|         }, | ||||
|         loading: () => const Center(child: CircularProgressIndicator()), | ||||
|         error: (err, stack) => ResponseErrorWidget( | ||||
|           error: err, | ||||
|           onRetry: () => ref.invalidate( | ||||
|             customAppProvider(publisherName, projectId, appId), | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _AppOverview extends StatelessWidget { | ||||
|   final CustomApp app; | ||||
|   const _AppOverview({required this.app}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return SingleChildScrollView( | ||||
|       child: Column( | ||||
|         children: [ | ||||
|           AspectRatio( | ||||
|             aspectRatio: 16 / 7, | ||||
|             child: Stack( | ||||
|               clipBehavior: Clip.none, | ||||
|               fit: StackFit.expand, | ||||
|               children: [ | ||||
|                 Container( | ||||
|                   color: Theme.of(context).colorScheme.surfaceContainer, | ||||
|                   child: app.background != null | ||||
|                       ? CloudFileWidget( | ||||
|                           item: app.background!, | ||||
|                           fit: BoxFit.cover, | ||||
|                         ) | ||||
|                       : const SizedBox.shrink(), | ||||
|                 ), | ||||
|                 Positioned( | ||||
|                   left: 20, | ||||
|                   bottom: -32, | ||||
|                   child: ProfilePictureWidget( | ||||
|                     fileId: app.picture?.id, | ||||
|                     radius: 40, | ||||
|                     fallbackIcon: Symbols.apps, | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ).padding(bottom: 32), | ||||
|           ListTile(title: Text('name'.tr()), subtitle: Text(app.name)), | ||||
|           ListTile(title: Text('slug'.tr()), subtitle: Text(app.slug)), | ||||
|           if (app.description?.isNotEmpty ?? false) | ||||
|             ListTile( | ||||
|               title: Text('description'.tr()), | ||||
|               subtitle: Text(app.description!), | ||||
|             ), | ||||
|         ], | ||||
|       ).padding(bottom: 24), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										252
									
								
								lib/screens/developers/app_secrets.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								lib/screens/developers/app_secrets.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,252 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/custom_app_secret.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/services/time.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/content/sheet.dart'; | ||||
| import 'package:island/widgets/response.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
|  | ||||
| part 'app_secrets.g.dart'; | ||||
|  | ||||
| @riverpod | ||||
| Future<List<CustomAppSecret>> customAppSecrets( | ||||
|   Ref ref, | ||||
|   String publisherName, | ||||
|   String projectId, | ||||
|   String appId, | ||||
| ) async { | ||||
|   final client = ref.watch(apiClientProvider); | ||||
|   final resp = await client.get( | ||||
|     '/develop/developers/$publisherName/projects/$projectId/apps/$appId/secrets', | ||||
|   ); | ||||
|   return (resp.data as List) | ||||
|       .map((e) => CustomAppSecret.fromJson(e)) | ||||
|       .cast<CustomAppSecret>() | ||||
|       .toList(); | ||||
| } | ||||
|  | ||||
| class AppSecretsScreen extends HookConsumerWidget { | ||||
|   final String publisherName; | ||||
|   final String projectId; | ||||
|   final String appId; | ||||
|  | ||||
|   const AppSecretsScreen({ | ||||
|     super.key, | ||||
|     required this.publisherName, | ||||
|     required this.projectId, | ||||
|     required this.appId, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final secrets = ref.watch( | ||||
|       customAppSecretsProvider(publisherName, projectId, appId), | ||||
|     ); | ||||
|  | ||||
|     void showNewSecretSheet(String newSecret) { | ||||
|       showModalBottomSheet( | ||||
|         context: context, | ||||
|         isScrollControlled: true, | ||||
|         builder: | ||||
|             (context) => SheetScaffold( | ||||
|               titleText: 'newSecretGenerated'.tr(), | ||||
|               child: Padding( | ||||
|                 padding: const EdgeInsets.all(20.0), | ||||
|                 child: Column( | ||||
|                   crossAxisAlignment: CrossAxisAlignment.stretch, | ||||
|                   mainAxisSize: MainAxisSize.min, | ||||
|                   children: [ | ||||
|                     Text('copySecretHint'.tr()), | ||||
|                     const SizedBox(height: 16), | ||||
|                     Container( | ||||
|                       padding: const EdgeInsets.all(12), | ||||
|                       decoration: BoxDecoration( | ||||
|                         color: Theme.of(context).colorScheme.surfaceContainer, | ||||
|                         borderRadius: BorderRadius.circular(8), | ||||
|                       ), | ||||
|                       child: SelectableText(newSecret), | ||||
|                     ), | ||||
|                     const SizedBox(height: 20), | ||||
|                     FilledButton.icon( | ||||
|                       onPressed: () { | ||||
|                         Clipboard.setData(ClipboardData(text: newSecret)); | ||||
|                       }, | ||||
|                       icon: const Icon(Symbols.copy_all), | ||||
|                       label: Text('copy'.tr()), | ||||
|                     ), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|       ).whenComplete(() { | ||||
|         ref.invalidate( | ||||
|           customAppSecretsProvider(publisherName, projectId, appId), | ||||
|         ); | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     void createSecret() { | ||||
|       showModalBottomSheet( | ||||
|         context: context, | ||||
|         isScrollControlled: true, | ||||
|         builder: (context) { | ||||
|           return HookBuilder( | ||||
|             builder: (context) { | ||||
|               final descriptionController = useTextEditingController(); | ||||
|               final expiresInController = useTextEditingController(); | ||||
|               final isOidc = useState(false); | ||||
|  | ||||
|               return SheetScaffold( | ||||
|                 titleText: 'generateSecret'.tr(), | ||||
|                 child: Padding( | ||||
|                   padding: const EdgeInsets.all(20.0), | ||||
|                   child: Column( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.stretch, | ||||
|                     mainAxisSize: MainAxisSize.min, | ||||
|                     children: [ | ||||
|                       TextFormField( | ||||
|                         controller: descriptionController, | ||||
|                         decoration: InputDecoration( | ||||
|                           labelText: 'description'.tr(), | ||||
|                         ), | ||||
|                         autofocus: true, | ||||
|                       ), | ||||
|                       const SizedBox(height: 20), | ||||
|                       TextFormField( | ||||
|                         controller: expiresInController, | ||||
|                         decoration: InputDecoration( | ||||
|                           labelText: 'expiresIn'.tr(), | ||||
|                         ), | ||||
|                         keyboardType: TextInputType.number, | ||||
|                       ), | ||||
|                       const SizedBox(height: 20), | ||||
|                       SwitchListTile( | ||||
|                         title: Text('isOidc'.tr()), | ||||
|                         value: isOidc.value, | ||||
|                         onChanged: (value) => isOidc.value = value, | ||||
|                       ), | ||||
|                       const SizedBox(height: 20), | ||||
|                       FilledButton.icon( | ||||
|                         onPressed: () async { | ||||
|                           final description = descriptionController.text; | ||||
|                           final expiresIn = int.tryParse( | ||||
|                             expiresInController.text, | ||||
|                           ); | ||||
|                           Navigator.pop(context); // Close the sheet | ||||
|                           try { | ||||
|                             final client = ref.read(apiClientProvider); | ||||
|                             final resp = await client.post( | ||||
|                               '/develop/developers/$publisherName/projects/$projectId/apps/$appId/secrets', | ||||
|                               data: { | ||||
|                                 'description': description, | ||||
|                                 'expires_in': expiresIn, | ||||
|                                 'is_oidc': isOidc.value, | ||||
|                               }, | ||||
|                             ); | ||||
|                             final newSecret = CustomAppSecret.fromJson( | ||||
|                               resp.data, | ||||
|                             ); | ||||
|                             if (newSecret.secret != null) { | ||||
|                               showNewSecretSheet(newSecret.secret!); | ||||
|                             } | ||||
|                           } catch (e) { | ||||
|                             showErrorAlert(e.toString()); | ||||
|                           } | ||||
|                         }, | ||||
|                         icon: const Icon(Symbols.add), | ||||
|                         label: Text('create'.tr()), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|               ); | ||||
|             }, | ||||
|           ); | ||||
|         }, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return secrets.when( | ||||
|       data: (data) { | ||||
|         return RefreshIndicator( | ||||
|           onRefresh: | ||||
|               () => ref.refresh( | ||||
|                 customAppSecretsProvider( | ||||
|                   publisherName, | ||||
|                   projectId, | ||||
|                   appId, | ||||
|                 ).future, | ||||
|               ), | ||||
|           child: Column( | ||||
|             children: [ | ||||
|               ListTile( | ||||
|                 leading: const Icon(Symbols.add), | ||||
|                 title: Text('generateSecret'.tr()), | ||||
|                 onTap: createSecret, | ||||
|               ), | ||||
|               const Divider(height: 1), | ||||
|               Expanded( | ||||
|                 child: ListView.builder( | ||||
|                   padding: EdgeInsets.zero, | ||||
|                   itemCount: data.length, | ||||
|                   itemBuilder: (context, index) { | ||||
|                     final secret = data[index]; | ||||
|                     return ListTile( | ||||
|                       title: Text(secret.description ?? secret.id), | ||||
|                       subtitle: Text( | ||||
|                         'createdAt'.tr(args: [secret.createdAt.formatSystem()]), | ||||
|                       ), | ||||
|                       trailing: Row( | ||||
|                         mainAxisSize: MainAxisSize.min, | ||||
|                         children: [ | ||||
|                           IconButton( | ||||
|                             icon: const Icon(Symbols.delete, color: Colors.red), | ||||
|                             onPressed: () { | ||||
|                               showConfirmAlert( | ||||
|                                 'deleteSecretHint'.tr(), | ||||
|                                 'deleteSecret'.tr(), | ||||
|                               ).then((confirm) { | ||||
|                                 if (confirm) { | ||||
|                                   final client = ref.read(apiClientProvider); | ||||
|                                   client.delete( | ||||
|                                     '/develop/developers/$publisherName/projects/$projectId/apps/$appId/secrets/${secret.id}', | ||||
|                                   ); | ||||
|                                   ref.invalidate( | ||||
|                                     customAppSecretsProvider( | ||||
|                                       publisherName, | ||||
|                                       projectId, | ||||
|                                       appId, | ||||
|                                     ), | ||||
|                                   ); | ||||
|                                 } | ||||
|                               }); | ||||
|                             }, | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ); | ||||
|                   }, | ||||
|                 ), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|       loading: () => const Center(child: CircularProgressIndicator()), | ||||
|       error: | ||||
|           (err, stack) => ResponseErrorWidget( | ||||
|             error: err, | ||||
|             onRetry: | ||||
|                 () => ref.invalidate( | ||||
|                   customAppSecretsProvider(publisherName, projectId, appId), | ||||
|                 ), | ||||
|           ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										188
									
								
								lib/screens/developers/app_secrets.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								lib/screens/developers/app_secrets.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'app_secrets.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // RiverpodGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$customAppSecretsHash() => r'1bc62ad812487883ce739793b22a76168d656752'; | ||||
|  | ||||
| /// Copied from Dart SDK | ||||
| class _SystemHash { | ||||
|   _SystemHash._(); | ||||
|  | ||||
|   static int combine(int hash, int value) { | ||||
|     // ignore: parameter_assignments | ||||
|     hash = 0x1fffffff & (hash + value); | ||||
|     // ignore: parameter_assignments | ||||
|     hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); | ||||
|     return hash ^ (hash >> 6); | ||||
|   } | ||||
|  | ||||
|   static int finish(int hash) { | ||||
|     // ignore: parameter_assignments | ||||
|     hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); | ||||
|     // ignore: parameter_assignments | ||||
|     hash = hash ^ (hash >> 11); | ||||
|     return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// See also [customAppSecrets]. | ||||
| @ProviderFor(customAppSecrets) | ||||
| const customAppSecretsProvider = CustomAppSecretsFamily(); | ||||
|  | ||||
| /// See also [customAppSecrets]. | ||||
| class CustomAppSecretsFamily extends Family<AsyncValue<List<CustomAppSecret>>> { | ||||
|   /// See also [customAppSecrets]. | ||||
|   const CustomAppSecretsFamily(); | ||||
|  | ||||
|   /// See also [customAppSecrets]. | ||||
|   CustomAppSecretsProvider call( | ||||
|     String publisherName, | ||||
|     String projectId, | ||||
|     String appId, | ||||
|   ) { | ||||
|     return CustomAppSecretsProvider(publisherName, projectId, appId); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   CustomAppSecretsProvider getProviderOverride( | ||||
|     covariant CustomAppSecretsProvider provider, | ||||
|   ) { | ||||
|     return call(provider.publisherName, provider.projectId, provider.appId); | ||||
|   } | ||||
|  | ||||
|   static const Iterable<ProviderOrFamily>? _dependencies = null; | ||||
|  | ||||
|   @override | ||||
|   Iterable<ProviderOrFamily>? get dependencies => _dependencies; | ||||
|  | ||||
|   static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null; | ||||
|  | ||||
|   @override | ||||
|   Iterable<ProviderOrFamily>? get allTransitiveDependencies => | ||||
|       _allTransitiveDependencies; | ||||
|  | ||||
|   @override | ||||
|   String? get name => r'customAppSecretsProvider'; | ||||
| } | ||||
|  | ||||
| /// See also [customAppSecrets]. | ||||
| class CustomAppSecretsProvider | ||||
|     extends AutoDisposeFutureProvider<List<CustomAppSecret>> { | ||||
|   /// See also [customAppSecrets]. | ||||
|   CustomAppSecretsProvider(String publisherName, String projectId, String appId) | ||||
|     : this._internal( | ||||
|         (ref) => customAppSecrets( | ||||
|           ref as CustomAppSecretsRef, | ||||
|           publisherName, | ||||
|           projectId, | ||||
|           appId, | ||||
|         ), | ||||
|         from: customAppSecretsProvider, | ||||
|         name: r'customAppSecretsProvider', | ||||
|         debugGetCreateSourceHash: | ||||
|             const bool.fromEnvironment('dart.vm.product') | ||||
|                 ? null | ||||
|                 : _$customAppSecretsHash, | ||||
|         dependencies: CustomAppSecretsFamily._dependencies, | ||||
|         allTransitiveDependencies: | ||||
|             CustomAppSecretsFamily._allTransitiveDependencies, | ||||
|         publisherName: publisherName, | ||||
|         projectId: projectId, | ||||
|         appId: appId, | ||||
|       ); | ||||
|  | ||||
|   CustomAppSecretsProvider._internal( | ||||
|     super._createNotifier, { | ||||
|     required super.name, | ||||
|     required super.dependencies, | ||||
|     required super.allTransitiveDependencies, | ||||
|     required super.debugGetCreateSourceHash, | ||||
|     required super.from, | ||||
|     required this.publisherName, | ||||
|     required this.projectId, | ||||
|     required this.appId, | ||||
|   }) : super.internal(); | ||||
|  | ||||
|   final String publisherName; | ||||
|   final String projectId; | ||||
|   final String appId; | ||||
|  | ||||
|   @override | ||||
|   Override overrideWith( | ||||
|     FutureOr<List<CustomAppSecret>> Function(CustomAppSecretsRef provider) | ||||
|     create, | ||||
|   ) { | ||||
|     return ProviderOverride( | ||||
|       origin: this, | ||||
|       override: CustomAppSecretsProvider._internal( | ||||
|         (ref) => create(ref as CustomAppSecretsRef), | ||||
|         from: from, | ||||
|         name: null, | ||||
|         dependencies: null, | ||||
|         allTransitiveDependencies: null, | ||||
|         debugGetCreateSourceHash: null, | ||||
|         publisherName: publisherName, | ||||
|         projectId: projectId, | ||||
|         appId: appId, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   AutoDisposeFutureProviderElement<List<CustomAppSecret>> createElement() { | ||||
|     return _CustomAppSecretsProviderElement(this); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return other is CustomAppSecretsProvider && | ||||
|         other.publisherName == publisherName && | ||||
|         other.projectId == projectId && | ||||
|         other.appId == appId; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   int get hashCode { | ||||
|     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||
|     hash = _SystemHash.combine(hash, publisherName.hashCode); | ||||
|     hash = _SystemHash.combine(hash, projectId.hashCode); | ||||
|     hash = _SystemHash.combine(hash, appId.hashCode); | ||||
|  | ||||
|     return _SystemHash.finish(hash); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||
| // ignore: unused_element | ||||
| mixin CustomAppSecretsRef | ||||
|     on AutoDisposeFutureProviderRef<List<CustomAppSecret>> { | ||||
|   /// The parameter `publisherName` of this provider. | ||||
|   String get publisherName; | ||||
|  | ||||
|   /// The parameter `projectId` of this provider. | ||||
|   String get projectId; | ||||
|  | ||||
|   /// The parameter `appId` of this provider. | ||||
|   String get appId; | ||||
| } | ||||
|  | ||||
| class _CustomAppSecretsProviderElement | ||||
|     extends AutoDisposeFutureProviderElement<List<CustomAppSecret>> | ||||
|     with CustomAppSecretsRef { | ||||
|   _CustomAppSecretsProviderElement(super.provider); | ||||
|  | ||||
|   @override | ||||
|   String get publisherName => | ||||
|       (origin as CustomAppSecretsProvider).publisherName; | ||||
|   @override | ||||
|   String get projectId => (origin as CustomAppSecretsProvider).projectId; | ||||
|   @override | ||||
|   String get appId => (origin as CustomAppSecretsProvider).appId; | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| @@ -14,6 +14,20 @@ import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| part 'apps.g.dart'; | ||||
|  | ||||
| @riverpod | ||||
| Future<CustomApp> customApp( | ||||
|   Ref ref, | ||||
|   String publisherName, | ||||
|   String projectId, | ||||
|   String appId, | ||||
| ) async { | ||||
|   final client = ref.watch(apiClientProvider); | ||||
|   final resp = await client.get( | ||||
|     '/develop/developers/$publisherName/projects/$projectId/apps/$appId', | ||||
|   ); | ||||
|   return CustomApp.fromJson(resp.data); | ||||
| } | ||||
|  | ||||
| @riverpod | ||||
| Future<List<CustomApp>> customApps( | ||||
|   Ref ref, | ||||
| @@ -81,6 +95,18 @@ class CustomAppsScreen extends HookConsumerWidget { | ||||
|               final app = data[index]; | ||||
|               return Card( | ||||
|                 margin: const EdgeInsets.all(8.0), | ||||
|                 clipBehavior: Clip.antiAlias, | ||||
|                 child: InkWell( | ||||
|                   onTap: () { | ||||
|                     context.pushNamed( | ||||
|                       'developerAppDetail', | ||||
|                       pathParameters: { | ||||
|                         'name': publisherName, | ||||
|                         'projectId': projectId, | ||||
|                         'appId': app.id, | ||||
|                       }, | ||||
|                     ); | ||||
|                   }, | ||||
|                   child: Column( | ||||
|                     children: [ | ||||
|                       SizedBox( | ||||
| @@ -164,7 +190,10 @@ class CustomAppsScreen extends HookConsumerWidget { | ||||
|                                     '/develop/developers/$publisherName/projects/$projectId/apps/${app.id}', | ||||
|                                   ); | ||||
|                                   ref.invalidate( | ||||
|                                   customAppsProvider(publisherName, projectId), | ||||
|                                     customAppsProvider( | ||||
|                                       publisherName, | ||||
|                                       projectId, | ||||
|                                     ), | ||||
|                                   ); | ||||
|                                 } | ||||
|                               }); | ||||
| @@ -174,6 +203,7 @@ class CustomAppsScreen extends HookConsumerWidget { | ||||
|                       ), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|               ); | ||||
|             }, | ||||
|           ), | ||||
|   | ||||
| @@ -6,7 +6,7 @@ part of 'apps.dart'; | ||||
| // RiverpodGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$customAppsHash() => r'450bedaf4220b8963cb44afeb14d4c0e80f01b11'; | ||||
| String _$customAppHash() => r'be05431ba8bf06fd20ee988a61c3663a68e15fc9'; | ||||
|  | ||||
| /// Copied from Dart SDK | ||||
| class _SystemHash { | ||||
| @@ -29,6 +29,148 @@ class _SystemHash { | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// See also [customApp]. | ||||
| @ProviderFor(customApp) | ||||
| const customAppProvider = CustomAppFamily(); | ||||
|  | ||||
| /// See also [customApp]. | ||||
| class CustomAppFamily extends Family<AsyncValue<CustomApp>> { | ||||
|   /// See also [customApp]. | ||||
|   const CustomAppFamily(); | ||||
|  | ||||
|   /// See also [customApp]. | ||||
|   CustomAppProvider call(String publisherName, String projectId, String appId) { | ||||
|     return CustomAppProvider(publisherName, projectId, appId); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   CustomAppProvider getProviderOverride(covariant CustomAppProvider provider) { | ||||
|     return call(provider.publisherName, provider.projectId, provider.appId); | ||||
|   } | ||||
|  | ||||
|   static const Iterable<ProviderOrFamily>? _dependencies = null; | ||||
|  | ||||
|   @override | ||||
|   Iterable<ProviderOrFamily>? get dependencies => _dependencies; | ||||
|  | ||||
|   static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null; | ||||
|  | ||||
|   @override | ||||
|   Iterable<ProviderOrFamily>? get allTransitiveDependencies => | ||||
|       _allTransitiveDependencies; | ||||
|  | ||||
|   @override | ||||
|   String? get name => r'customAppProvider'; | ||||
| } | ||||
|  | ||||
| /// See also [customApp]. | ||||
| class CustomAppProvider extends AutoDisposeFutureProvider<CustomApp> { | ||||
|   /// See also [customApp]. | ||||
|   CustomAppProvider(String publisherName, String projectId, String appId) | ||||
|     : this._internal( | ||||
|         (ref) => | ||||
|             customApp(ref as CustomAppRef, publisherName, projectId, appId), | ||||
|         from: customAppProvider, | ||||
|         name: r'customAppProvider', | ||||
|         debugGetCreateSourceHash: | ||||
|             const bool.fromEnvironment('dart.vm.product') | ||||
|                 ? null | ||||
|                 : _$customAppHash, | ||||
|         dependencies: CustomAppFamily._dependencies, | ||||
|         allTransitiveDependencies: CustomAppFamily._allTransitiveDependencies, | ||||
|         publisherName: publisherName, | ||||
|         projectId: projectId, | ||||
|         appId: appId, | ||||
|       ); | ||||
|  | ||||
|   CustomAppProvider._internal( | ||||
|     super._createNotifier, { | ||||
|     required super.name, | ||||
|     required super.dependencies, | ||||
|     required super.allTransitiveDependencies, | ||||
|     required super.debugGetCreateSourceHash, | ||||
|     required super.from, | ||||
|     required this.publisherName, | ||||
|     required this.projectId, | ||||
|     required this.appId, | ||||
|   }) : super.internal(); | ||||
|  | ||||
|   final String publisherName; | ||||
|   final String projectId; | ||||
|   final String appId; | ||||
|  | ||||
|   @override | ||||
|   Override overrideWith( | ||||
|     FutureOr<CustomApp> Function(CustomAppRef provider) create, | ||||
|   ) { | ||||
|     return ProviderOverride( | ||||
|       origin: this, | ||||
|       override: CustomAppProvider._internal( | ||||
|         (ref) => create(ref as CustomAppRef), | ||||
|         from: from, | ||||
|         name: null, | ||||
|         dependencies: null, | ||||
|         allTransitiveDependencies: null, | ||||
|         debugGetCreateSourceHash: null, | ||||
|         publisherName: publisherName, | ||||
|         projectId: projectId, | ||||
|         appId: appId, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   AutoDisposeFutureProviderElement<CustomApp> createElement() { | ||||
|     return _CustomAppProviderElement(this); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return other is CustomAppProvider && | ||||
|         other.publisherName == publisherName && | ||||
|         other.projectId == projectId && | ||||
|         other.appId == appId; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   int get hashCode { | ||||
|     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||
|     hash = _SystemHash.combine(hash, publisherName.hashCode); | ||||
|     hash = _SystemHash.combine(hash, projectId.hashCode); | ||||
|     hash = _SystemHash.combine(hash, appId.hashCode); | ||||
|  | ||||
|     return _SystemHash.finish(hash); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||
| // ignore: unused_element | ||||
| mixin CustomAppRef on AutoDisposeFutureProviderRef<CustomApp> { | ||||
|   /// The parameter `publisherName` of this provider. | ||||
|   String get publisherName; | ||||
|  | ||||
|   /// The parameter `projectId` of this provider. | ||||
|   String get projectId; | ||||
|  | ||||
|   /// The parameter `appId` of this provider. | ||||
|   String get appId; | ||||
| } | ||||
|  | ||||
| class _CustomAppProviderElement | ||||
|     extends AutoDisposeFutureProviderElement<CustomApp> | ||||
|     with CustomAppRef { | ||||
|   _CustomAppProviderElement(super.provider); | ||||
|  | ||||
|   @override | ||||
|   String get publisherName => (origin as CustomAppProvider).publisherName; | ||||
|   @override | ||||
|   String get projectId => (origin as CustomAppProvider).projectId; | ||||
|   @override | ||||
|   String get appId => (origin as CustomAppProvider).appId; | ||||
| } | ||||
|  | ||||
| String _$customAppsHash() => r'450bedaf4220b8963cb44afeb14d4c0e80f01b11'; | ||||
|  | ||||
| /// See also [customApps]. | ||||
| @ProviderFor(customApps) | ||||
| const customAppsProvider = CustomAppsFamily(); | ||||
|   | ||||
| @@ -183,7 +183,7 @@ class ArticlesScreen extends ConsumerWidget { | ||||
|                       ), | ||||
|                     ), | ||||
|                   ); | ||||
|                 }).toList(), | ||||
|                 }), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|   | ||||
| @@ -6,7 +6,7 @@ part of 'articles.dart'; | ||||
| // RiverpodGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$subscribedFeedsHash() => r'cd2f5d7d4ea49ad00dc731f8fc2ed65450a3f0e4'; | ||||
| String _$subscribedFeedsHash() => r'5c0c8c30c5f543f6ea1d39786a6778f77ba5b3df'; | ||||
|  | ||||
| /// See also [subscribedFeeds]. | ||||
| @ProviderFor(subscribedFeeds) | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:island/screens/chat/chat.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:island/models/chat.dart'; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user