Compare commits
	
		
			8 Commits
		
	
	
		
			6c7d42c31a
			...
			3.0.0+110
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 007acedf29 | |||
| 8e903ec6c1 | |||
| b55e56c3c4 | |||
| 6f9de431b1 | |||
| a8efd26262 | |||
| e367fc3f5c | |||
| 8a1af120ea | |||
| f03f0181f8 | 
| @@ -675,5 +675,8 @@ | ||||
|   "publisherFeatureDevelop": "Developer Program", | ||||
|   "publisherFeatureDevelopDescription": "Unlock development abilities for your publisher, including custom apps, API keys, and more.", | ||||
|   "publisherFeatureDevelopHint": "Currently, this feature is under active development, you need send a request to unlock this feature.", | ||||
|   "learnMore": "Learn More" | ||||
|   "learnMore": "Learn More", | ||||
|   "discoverWebArticles": "Articles from external sites", | ||||
|   "webArticlesStand": "Article Stand", | ||||
|   "about": "About" | ||||
| } | ||||
|   | ||||
| @@ -40,31 +40,31 @@ PODS: | ||||
|   - file_picker (0.0.1): | ||||
|     - DKImagePickerController/PhotoGallery | ||||
|     - Flutter | ||||
|   - Firebase/CoreOnly (11.13.0): | ||||
|     - FirebaseCore (~> 11.13.0) | ||||
|   - Firebase/Messaging (11.13.0): | ||||
|   - Firebase/CoreOnly (11.15.0): | ||||
|     - FirebaseCore (~> 11.15.0) | ||||
|   - Firebase/Messaging (11.15.0): | ||||
|     - Firebase/CoreOnly | ||||
|     - FirebaseMessaging (~> 11.13.0) | ||||
|   - firebase_core (3.14.0): | ||||
|     - Firebase/CoreOnly (= 11.13.0) | ||||
|     - FirebaseMessaging (~> 11.15.0) | ||||
|   - firebase_core (3.15.0): | ||||
|     - Firebase/CoreOnly (= 11.15.0) | ||||
|     - Flutter | ||||
|   - firebase_messaging (15.2.7): | ||||
|     - Firebase/Messaging (= 11.13.0) | ||||
|   - firebase_messaging (15.2.8): | ||||
|     - Firebase/Messaging (= 11.15.0) | ||||
|     - firebase_core | ||||
|     - Flutter | ||||
|   - FirebaseCore (11.13.0): | ||||
|     - FirebaseCoreInternal (~> 11.13.0) | ||||
|   - FirebaseCore (11.15.0): | ||||
|     - FirebaseCoreInternal (~> 11.15.0) | ||||
|     - GoogleUtilities/Environment (~> 8.1) | ||||
|     - GoogleUtilities/Logger (~> 8.1) | ||||
|   - FirebaseCoreInternal (11.13.0): | ||||
|   - FirebaseCoreInternal (11.15.0): | ||||
|     - "GoogleUtilities/NSData+zlib (~> 8.1)" | ||||
|   - FirebaseInstallations (11.13.0): | ||||
|     - FirebaseCore (~> 11.13.0) | ||||
|   - FirebaseInstallations (11.15.0): | ||||
|     - FirebaseCore (~> 11.15.0) | ||||
|     - GoogleUtilities/Environment (~> 8.1) | ||||
|     - GoogleUtilities/UserDefaults (~> 8.1) | ||||
|     - PromisesObjC (~> 2.4) | ||||
|   - FirebaseMessaging (11.13.0): | ||||
|     - FirebaseCore (~> 11.13.0) | ||||
|   - FirebaseMessaging (11.15.0): | ||||
|     - FirebaseCore (~> 11.15.0) | ||||
|     - FirebaseInstallations (~> 11.0) | ||||
|     - GoogleDataTransport (~> 10.0) | ||||
|     - GoogleUtilities/AppDelegateSwizzler (~> 8.1) | ||||
| @@ -80,6 +80,8 @@ PODS: | ||||
|   - flutter_inappwebview_ios/Core (0.0.1): | ||||
|     - Flutter | ||||
|     - OrderedSet (~> 6.0.3) | ||||
|   - flutter_keyboard_visibility (0.0.1): | ||||
|     - Flutter | ||||
|   - flutter_native_splash (2.4.3): | ||||
|     - Flutter | ||||
|   - flutter_platform_alert (0.0.1): | ||||
| @@ -128,8 +130,8 @@ PODS: | ||||
|     - Flutter | ||||
|   - irondash_engine_context (0.0.1): | ||||
|     - Flutter | ||||
|   - Kingfisher (8.3.2) | ||||
|   - livekit_client (2.4.8): | ||||
|   - Kingfisher (8.3.3) | ||||
|   - livekit_client (2.4.9): | ||||
|     - Flutter | ||||
|     - flutter_webrtc | ||||
|     - WebRTC-SDK (= 125.6422.07) | ||||
| @@ -155,6 +157,8 @@ PODS: | ||||
|   - path_provider_foundation (0.0.1): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - pointer_interceptor_ios (0.0.1): | ||||
|     - Flutter | ||||
|   - PromisesObjC (2.4.0) | ||||
|   - receive_sharing_intent (1.8.1): | ||||
|     - Flutter | ||||
| @@ -217,6 +221,7 @@ DEPENDENCIES: | ||||
|   - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) | ||||
|   - Flutter (from `Flutter`) | ||||
|   - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) | ||||
|   - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) | ||||
|   - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) | ||||
|   - flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`) | ||||
|   - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) | ||||
| @@ -235,6 +240,7 @@ DEPENDENCIES: | ||||
|   - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) | ||||
|   - pasteboard (from `.symlinks/plugins/pasteboard/ios`) | ||||
|   - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) | ||||
|   - pointer_interceptor_ios (from `.symlinks/plugins/pointer_interceptor_ios/ios`) | ||||
|   - receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`) | ||||
|   - record_ios (from `.symlinks/plugins/record_ios/ios`) | ||||
|   - share_plus (from `.symlinks/plugins/share_plus/ios`) | ||||
| @@ -286,6 +292,8 @@ EXTERNAL SOURCES: | ||||
|     :path: Flutter | ||||
|   flutter_inappwebview_ios: | ||||
|     :path: ".symlinks/plugins/flutter_inappwebview_ios/ios" | ||||
|   flutter_keyboard_visibility: | ||||
|     :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" | ||||
|   flutter_native_splash: | ||||
|     :path: ".symlinks/plugins/flutter_native_splash/ios" | ||||
|   flutter_platform_alert: | ||||
| @@ -320,6 +328,8 @@ EXTERNAL SOURCES: | ||||
|     :path: ".symlinks/plugins/pasteboard/ios" | ||||
|   path_provider_foundation: | ||||
|     :path: ".symlinks/plugins/path_provider_foundation/darwin" | ||||
|   pointer_interceptor_ios: | ||||
|     :path: ".symlinks/plugins/pointer_interceptor_ios/ios" | ||||
|   receive_sharing_intent: | ||||
|     :path: ".symlinks/plugins/receive_sharing_intent/ios" | ||||
|   record_ios: | ||||
| @@ -351,15 +361,16 @@ SPEC CHECKSUMS: | ||||
|   DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c | ||||
|   DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 | ||||
|   file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be | ||||
|   Firebase: 3435bc66b4d494c2f22c79fd3aae4c1db6662327 | ||||
|   firebase_core: 700bac7ed92bb754fd70fbf01d72b36ecdd6d450 | ||||
|   firebase_messaging: 860c017fcfbb5e27c163062d1d3135388f3ef954 | ||||
|   FirebaseCore: c692c7f1c75305ab6aff2b367f25e11d73aa8bd0 | ||||
|   FirebaseCoreInternal: 29d7b3af4aaf0b8f3ed20b568c13df399b06f68c | ||||
|   FirebaseInstallations: 0ee9074f2c1e86561ace168ee1470dc67aabaf02 | ||||
|   FirebaseMessaging: 195bbdb73e6ca1dbc76cd46e73f3552c084ef6e4 | ||||
|   Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e | ||||
|   firebase_core: c727a02c560a53f1f1e56e18f16515eb5753c492 | ||||
|   firebase_messaging: 4158969b04b667f5435731ec9d6e453bb58b0c4c | ||||
|   FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e | ||||
|   FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 | ||||
|   FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 | ||||
|   FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 | ||||
|   Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 | ||||
|   flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 | ||||
|   flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619 | ||||
|   flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf | ||||
|   flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3 | ||||
|   flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 | ||||
| @@ -371,8 +382,8 @@ SPEC CHECKSUMS: | ||||
|   GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 | ||||
|   image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a | ||||
|   irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486 | ||||
|   Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5 | ||||
|   livekit_client: 9e901890552514206e5ff828903ed271531da264 | ||||
|   Kingfisher: ff82cb91d9266ddb56cbb2f72d32c26f00d3e5be | ||||
|   livekit_client: 3f79d79233a5bd13d5b541732624ef959d7c538e | ||||
|   local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 | ||||
|   media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 | ||||
|   media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474 | ||||
| @@ -382,6 +393,7 @@ SPEC CHECKSUMS: | ||||
|   package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 | ||||
|   pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c | ||||
|   path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 | ||||
|   pointer_interceptor_ios: ec847ef8b0915778bed2b2cef636f4d177fa8eed | ||||
|   PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 | ||||
|   receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00 | ||||
|   record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b | ||||
|   | ||||
							
								
								
									
										34
									
								
								lib/models/auto_completion.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/models/auto_completion.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | ||||
|  | ||||
| part 'auto_completion.freezed.dart'; | ||||
| part 'auto_completion.g.dart'; | ||||
|  | ||||
| @freezed | ||||
| sealed class AutoCompletionResponse with _$AutoCompletionResponse { | ||||
|   const factory AutoCompletionResponse.account({ | ||||
|     required String type, | ||||
|     required List<AutoCompletionItem> items, | ||||
|   }) = AutoCompletionAccountResponse; | ||||
|  | ||||
|   const factory AutoCompletionResponse.sticker({ | ||||
|     required String type, | ||||
|     required List<AutoCompletionItem> items, | ||||
|   }) = AutoCompletionStickerResponse; | ||||
|  | ||||
|   factory AutoCompletionResponse.fromJson(Map<String, dynamic> json) => | ||||
|       _$AutoCompletionResponseFromJson(json); | ||||
| } | ||||
|  | ||||
| @freezed | ||||
| sealed class AutoCompletionItem with _$AutoCompletionItem { | ||||
|   const factory AutoCompletionItem({ | ||||
|     required String id, | ||||
|     required String displayName, | ||||
|     required String? secondaryText, | ||||
|     required String type, | ||||
|     required dynamic data, | ||||
|   }) = _AutoCompletionItem; | ||||
|  | ||||
|   factory AutoCompletionItem.fromJson(Map<String, dynamic> json) => | ||||
|       _$AutoCompletionItemFromJson(json); | ||||
| } | ||||
							
								
								
									
										410
									
								
								lib/models/auto_completion.freezed.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								lib/models/auto_completion.freezed.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,410 @@ | ||||
| // dart format width=80 | ||||
| // 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 'auto_completion.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // FreezedGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| // dart format off | ||||
| T _$identity<T>(T value) => value; | ||||
| AutoCompletionResponse _$AutoCompletionResponseFromJson( | ||||
|   Map<String, dynamic> json | ||||
| ) { | ||||
|         switch (json['runtimeType']) { | ||||
|                   case 'account': | ||||
|           return AutoCompletionAccountResponse.fromJson( | ||||
|             json | ||||
|           ); | ||||
|                 case 'sticker': | ||||
|           return AutoCompletionStickerResponse.fromJson( | ||||
|             json | ||||
|           ); | ||||
|          | ||||
|           default: | ||||
|             throw CheckedFromJsonException( | ||||
|   json, | ||||
|   'runtimeType', | ||||
|   'AutoCompletionResponse', | ||||
|   'Invalid union type "${json['runtimeType']}"!' | ||||
| ); | ||||
|         } | ||||
|        | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$AutoCompletionResponse { | ||||
|  | ||||
|  String get type; List<AutoCompletionItem> get items; | ||||
| /// Create a copy of AutoCompletionResponse | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $AutoCompletionResponseCopyWith<AutoCompletionResponse> get copyWith => _$AutoCompletionResponseCopyWithImpl<AutoCompletionResponse>(this as AutoCompletionResponse, _$identity); | ||||
|  | ||||
|   /// Serializes this AutoCompletionResponse to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is AutoCompletionResponse&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.items, items)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,type,const DeepCollectionEquality().hash(items)); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'AutoCompletionResponse(type: $type, items: $items)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $AutoCompletionResponseCopyWith<$Res>  { | ||||
|   factory $AutoCompletionResponseCopyWith(AutoCompletionResponse value, $Res Function(AutoCompletionResponse) _then) = _$AutoCompletionResponseCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  String type, List<AutoCompletionItem> items | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$AutoCompletionResponseCopyWithImpl<$Res> | ||||
|     implements $AutoCompletionResponseCopyWith<$Res> { | ||||
|   _$AutoCompletionResponseCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final AutoCompletionResponse _self; | ||||
|   final $Res Function(AutoCompletionResponse) _then; | ||||
|  | ||||
| /// Create a copy of AutoCompletionResponse | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? items = null,}) { | ||||
|   return _then(_self.copyWith( | ||||
| type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as String,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable | ||||
| as List<AutoCompletionItem>, | ||||
|   )); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class AutoCompletionAccountResponse implements AutoCompletionResponse { | ||||
|   const AutoCompletionAccountResponse({required this.type, required final  List<AutoCompletionItem> items, final  String? $type}): _items = items,$type = $type ?? 'account'; | ||||
|   factory AutoCompletionAccountResponse.fromJson(Map<String, dynamic> json) => _$AutoCompletionAccountResponseFromJson(json); | ||||
|  | ||||
| @override final  String type; | ||||
|  final  List<AutoCompletionItem> _items; | ||||
| @override List<AutoCompletionItem> get items { | ||||
|   if (_items is EqualUnmodifiableListView) return _items; | ||||
|   // ignore: implicit_dynamic_type | ||||
|   return EqualUnmodifiableListView(_items); | ||||
| } | ||||
|  | ||||
|  | ||||
| @JsonKey(name: 'runtimeType') | ||||
| final String $type; | ||||
|  | ||||
|  | ||||
| /// Create a copy of AutoCompletionResponse | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $AutoCompletionAccountResponseCopyWith<AutoCompletionAccountResponse> get copyWith => _$AutoCompletionAccountResponseCopyWithImpl<AutoCompletionAccountResponse>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$AutoCompletionAccountResponseToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is AutoCompletionAccountResponse&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._items, _items)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,type,const DeepCollectionEquality().hash(_items)); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'AutoCompletionResponse.account(type: $type, items: $items)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $AutoCompletionAccountResponseCopyWith<$Res> implements $AutoCompletionResponseCopyWith<$Res> { | ||||
|   factory $AutoCompletionAccountResponseCopyWith(AutoCompletionAccountResponse value, $Res Function(AutoCompletionAccountResponse) _then) = _$AutoCompletionAccountResponseCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String type, List<AutoCompletionItem> items | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$AutoCompletionAccountResponseCopyWithImpl<$Res> | ||||
|     implements $AutoCompletionAccountResponseCopyWith<$Res> { | ||||
|   _$AutoCompletionAccountResponseCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final AutoCompletionAccountResponse _self; | ||||
|   final $Res Function(AutoCompletionAccountResponse) _then; | ||||
|  | ||||
| /// Create a copy of AutoCompletionResponse | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? items = null,}) { | ||||
|   return _then(AutoCompletionAccountResponse( | ||||
| type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as String,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable | ||||
| as List<AutoCompletionItem>, | ||||
|   )); | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class AutoCompletionStickerResponse implements AutoCompletionResponse { | ||||
|   const AutoCompletionStickerResponse({required this.type, required final  List<AutoCompletionItem> items, final  String? $type}): _items = items,$type = $type ?? 'sticker'; | ||||
|   factory AutoCompletionStickerResponse.fromJson(Map<String, dynamic> json) => _$AutoCompletionStickerResponseFromJson(json); | ||||
|  | ||||
| @override final  String type; | ||||
|  final  List<AutoCompletionItem> _items; | ||||
| @override List<AutoCompletionItem> get items { | ||||
|   if (_items is EqualUnmodifiableListView) return _items; | ||||
|   // ignore: implicit_dynamic_type | ||||
|   return EqualUnmodifiableListView(_items); | ||||
| } | ||||
|  | ||||
|  | ||||
| @JsonKey(name: 'runtimeType') | ||||
| final String $type; | ||||
|  | ||||
|  | ||||
| /// Create a copy of AutoCompletionResponse | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $AutoCompletionStickerResponseCopyWith<AutoCompletionStickerResponse> get copyWith => _$AutoCompletionStickerResponseCopyWithImpl<AutoCompletionStickerResponse>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$AutoCompletionStickerResponseToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is AutoCompletionStickerResponse&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._items, _items)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,type,const DeepCollectionEquality().hash(_items)); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'AutoCompletionResponse.sticker(type: $type, items: $items)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $AutoCompletionStickerResponseCopyWith<$Res> implements $AutoCompletionResponseCopyWith<$Res> { | ||||
|   factory $AutoCompletionStickerResponseCopyWith(AutoCompletionStickerResponse value, $Res Function(AutoCompletionStickerResponse) _then) = _$AutoCompletionStickerResponseCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String type, List<AutoCompletionItem> items | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$AutoCompletionStickerResponseCopyWithImpl<$Res> | ||||
|     implements $AutoCompletionStickerResponseCopyWith<$Res> { | ||||
|   _$AutoCompletionStickerResponseCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final AutoCompletionStickerResponse _self; | ||||
|   final $Res Function(AutoCompletionStickerResponse) _then; | ||||
|  | ||||
| /// Create a copy of AutoCompletionResponse | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? items = null,}) { | ||||
|   return _then(AutoCompletionStickerResponse( | ||||
| type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as String,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable | ||||
| as List<AutoCompletionItem>, | ||||
|   )); | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$AutoCompletionItem { | ||||
|  | ||||
|  String get id; String get displayName; String? get secondaryText; String get type; dynamic get data; | ||||
| /// Create a copy of AutoCompletionItem | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $AutoCompletionItemCopyWith<AutoCompletionItem> get copyWith => _$AutoCompletionItemCopyWithImpl<AutoCompletionItem>(this as AutoCompletionItem, _$identity); | ||||
|  | ||||
|   /// Serializes this AutoCompletionItem to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is AutoCompletionItem&&(identical(other.id, id) || other.id == id)&&(identical(other.displayName, displayName) || other.displayName == displayName)&&(identical(other.secondaryText, secondaryText) || other.secondaryText == secondaryText)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.data, data)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,displayName,secondaryText,type,const DeepCollectionEquality().hash(data)); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'AutoCompletionItem(id: $id, displayName: $displayName, secondaryText: $secondaryText, type: $type, data: $data)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $AutoCompletionItemCopyWith<$Res>  { | ||||
|   factory $AutoCompletionItemCopyWith(AutoCompletionItem value, $Res Function(AutoCompletionItem) _then) = _$AutoCompletionItemCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  String id, String displayName, String? secondaryText, String type, dynamic data | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$AutoCompletionItemCopyWithImpl<$Res> | ||||
|     implements $AutoCompletionItemCopyWith<$Res> { | ||||
|   _$AutoCompletionItemCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final AutoCompletionItem _self; | ||||
|   final $Res Function(AutoCompletionItem) _then; | ||||
|  | ||||
| /// Create a copy of AutoCompletionItem | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? displayName = null,Object? secondaryText = freezed,Object? type = null,Object? data = freezed,}) { | ||||
|   return _then(_self.copyWith( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,displayName: null == displayName ? _self.displayName : displayName // ignore: cast_nullable_to_non_nullable | ||||
| as String,secondaryText: freezed == secondaryText ? _self.secondaryText : secondaryText // ignore: cast_nullable_to_non_nullable | ||||
| as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable | ||||
| as dynamic, | ||||
|   )); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class _AutoCompletionItem implements AutoCompletionItem { | ||||
|   const _AutoCompletionItem({required this.id, required this.displayName, required this.secondaryText, required this.type, required this.data}); | ||||
|   factory _AutoCompletionItem.fromJson(Map<String, dynamic> json) => _$AutoCompletionItemFromJson(json); | ||||
|  | ||||
| @override final  String id; | ||||
| @override final  String displayName; | ||||
| @override final  String? secondaryText; | ||||
| @override final  String type; | ||||
| @override final  dynamic data; | ||||
|  | ||||
| /// Create a copy of AutoCompletionItem | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| _$AutoCompletionItemCopyWith<_AutoCompletionItem> get copyWith => __$AutoCompletionItemCopyWithImpl<_AutoCompletionItem>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$AutoCompletionItemToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _AutoCompletionItem&&(identical(other.id, id) || other.id == id)&&(identical(other.displayName, displayName) || other.displayName == displayName)&&(identical(other.secondaryText, secondaryText) || other.secondaryText == secondaryText)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.data, data)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,displayName,secondaryText,type,const DeepCollectionEquality().hash(data)); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'AutoCompletionItem(id: $id, displayName: $displayName, secondaryText: $secondaryText, type: $type, data: $data)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class _$AutoCompletionItemCopyWith<$Res> implements $AutoCompletionItemCopyWith<$Res> { | ||||
|   factory _$AutoCompletionItemCopyWith(_AutoCompletionItem value, $Res Function(_AutoCompletionItem) _then) = __$AutoCompletionItemCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String id, String displayName, String? secondaryText, String type, dynamic data | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class __$AutoCompletionItemCopyWithImpl<$Res> | ||||
|     implements _$AutoCompletionItemCopyWith<$Res> { | ||||
|   __$AutoCompletionItemCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final _AutoCompletionItem _self; | ||||
|   final $Res Function(_AutoCompletionItem) _then; | ||||
|  | ||||
| /// Create a copy of AutoCompletionItem | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? displayName = null,Object? secondaryText = freezed,Object? type = null,Object? data = freezed,}) { | ||||
|   return _then(_AutoCompletionItem( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,displayName: null == displayName ? _self.displayName : displayName // ignore: cast_nullable_to_non_nullable | ||||
| as String,secondaryText: freezed == secondaryText ? _self.secondaryText : secondaryText // ignore: cast_nullable_to_non_nullable | ||||
| as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable | ||||
| as dynamic, | ||||
|   )); | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| // dart format on | ||||
							
								
								
									
										63
									
								
								lib/models/auto_completion.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								lib/models/auto_completion.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'auto_completion.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // JsonSerializableGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| AutoCompletionAccountResponse _$AutoCompletionAccountResponseFromJson( | ||||
|   Map<String, dynamic> json, | ||||
| ) => AutoCompletionAccountResponse( | ||||
|   type: json['type'] as String, | ||||
|   items: | ||||
|       (json['items'] as List<dynamic>) | ||||
|           .map((e) => AutoCompletionItem.fromJson(e as Map<String, dynamic>)) | ||||
|           .toList(), | ||||
|   $type: json['runtimeType'] as String?, | ||||
| ); | ||||
|  | ||||
| Map<String, dynamic> _$AutoCompletionAccountResponseToJson( | ||||
|   AutoCompletionAccountResponse instance, | ||||
| ) => <String, dynamic>{ | ||||
|   'type': instance.type, | ||||
|   'items': instance.items.map((e) => e.toJson()).toList(), | ||||
|   'runtimeType': instance.$type, | ||||
| }; | ||||
|  | ||||
| AutoCompletionStickerResponse _$AutoCompletionStickerResponseFromJson( | ||||
|   Map<String, dynamic> json, | ||||
| ) => AutoCompletionStickerResponse( | ||||
|   type: json['type'] as String, | ||||
|   items: | ||||
|       (json['items'] as List<dynamic>) | ||||
|           .map((e) => AutoCompletionItem.fromJson(e as Map<String, dynamic>)) | ||||
|           .toList(), | ||||
|   $type: json['runtimeType'] as String?, | ||||
| ); | ||||
|  | ||||
| Map<String, dynamic> _$AutoCompletionStickerResponseToJson( | ||||
|   AutoCompletionStickerResponse instance, | ||||
| ) => <String, dynamic>{ | ||||
|   'type': instance.type, | ||||
|   'items': instance.items.map((e) => e.toJson()).toList(), | ||||
|   'runtimeType': instance.$type, | ||||
| }; | ||||
|  | ||||
| _AutoCompletionItem _$AutoCompletionItemFromJson(Map<String, dynamic> json) => | ||||
|     _AutoCompletionItem( | ||||
|       id: json['id'] as String, | ||||
|       displayName: json['display_name'] as String, | ||||
|       secondaryText: json['secondary_text'] as String?, | ||||
|       type: json['type'] as String, | ||||
|       data: json['data'], | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$AutoCompletionItemToJson(_AutoCompletionItem instance) => | ||||
|     <String, dynamic>{ | ||||
|       'id': instance.id, | ||||
|       'display_name': instance.displayName, | ||||
|       'secondary_text': instance.secondaryText, | ||||
|       'type': instance.type, | ||||
|       'data': instance.data, | ||||
|     }; | ||||
| @@ -7,57 +7,58 @@ part 'webfeed.freezed.dart'; | ||||
| part 'webfeed.g.dart'; | ||||
|  | ||||
| @freezed | ||||
| sealed class WebFeedConfig with _$WebFeedConfig { | ||||
|   const factory WebFeedConfig({@Default(false) bool scrapPage}) = | ||||
|       _WebFeedConfig; | ||||
| sealed class SnWebFeedConfig with _$SnWebFeedConfig { | ||||
|   const factory SnWebFeedConfig({@Default(false) bool scrapPage}) = | ||||
|       _SnWebFeedConfig; | ||||
|  | ||||
|   factory WebFeedConfig.fromJson(Map<String, dynamic> json) => | ||||
|       _$WebFeedConfigFromJson(json); | ||||
|   factory SnWebFeedConfig.fromJson(Map<String, dynamic> json) => | ||||
|       _$SnWebFeedConfigFromJson(json); | ||||
| } | ||||
|  | ||||
| @freezed | ||||
| sealed class WebFeed with _$WebFeed { | ||||
|   const factory WebFeed({ | ||||
| sealed class SnWebFeed with _$SnWebFeed { | ||||
|   const factory SnWebFeed({ | ||||
|     required String id, | ||||
|     required String url, | ||||
|     required String title, | ||||
|     String? description, | ||||
|     SnScrappedLink? preview, | ||||
|     @Default(WebFeedConfig()) WebFeedConfig config, | ||||
|     @Default(SnWebFeedConfig()) SnWebFeedConfig config, | ||||
|     required String publisherId, | ||||
|     @Default([]) List<WebArticle> articles, | ||||
|     @Default([]) List<SnWebArticle> articles, | ||||
|     required DateTime createdAt, | ||||
|     required DateTime updatedAt, | ||||
|     DateTime? deletedAt, | ||||
|   }) = _WebFeed; | ||||
|   }) = _SnWebFeed; | ||||
|  | ||||
|   factory WebFeed.fromJson(Map<String, dynamic> json) => | ||||
|       _$WebFeedFromJson(json); | ||||
|   factory SnWebFeed.fromJson(Map<String, dynamic> json) => | ||||
|       _$SnWebFeedFromJson(json); | ||||
|  | ||||
|   factory WebFeed.fromJsonString(String jsonString) => | ||||
|       WebFeed.fromJson(jsonDecode(jsonString) as Map<String, dynamic>); | ||||
|   factory SnWebFeed.fromJsonString(String jsonString) => | ||||
|       SnWebFeed.fromJson(jsonDecode(jsonString) as Map<String, dynamic>); | ||||
| } | ||||
|  | ||||
| @freezed | ||||
| sealed class WebArticle with _$WebArticle { | ||||
|   const factory WebArticle({ | ||||
| sealed class SnWebArticle with _$SnWebArticle { | ||||
|   const factory SnWebArticle({ | ||||
|     required String id, | ||||
|     required String title, | ||||
|     required String url, | ||||
|     String? author, | ||||
|     Map<String, dynamic>? meta, | ||||
|     SnScrappedLink? preview, | ||||
|     SnWebFeed? feed, | ||||
|     String? content, | ||||
|     DateTime? publishedAt, | ||||
|     required String feedId, | ||||
|     required DateTime createdAt, | ||||
|     required DateTime updatedAt, | ||||
|     DateTime? deletedAt, | ||||
|   }) = _WebArticle; | ||||
|   }) = _SnWebArticle; | ||||
|  | ||||
|   factory WebArticle.fromJson(Map<String, dynamic> json) => | ||||
|       _$WebArticleFromJson(json); | ||||
|   factory SnWebArticle.fromJson(Map<String, dynamic> json) => | ||||
|       _$SnWebArticleFromJson(json); | ||||
|  | ||||
|   factory WebArticle.fromJsonString(String jsonString) => | ||||
|       WebArticle.fromJson(jsonDecode(jsonString) as Map<String, dynamic>); | ||||
|   factory SnWebArticle.fromJsonString(String jsonString) => | ||||
|       SnWebArticle.fromJson(jsonDecode(jsonString) as Map<String, dynamic>); | ||||
| } | ||||
|   | ||||
| @@ -14,22 +14,22 @@ part of 'webfeed.dart'; | ||||
| T _$identity<T>(T value) => value; | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$WebFeedConfig { | ||||
| mixin _$SnWebFeedConfig { | ||||
|  | ||||
|  bool get scrapPage; | ||||
| /// Create a copy of WebFeedConfig | ||||
| /// Create a copy of SnWebFeedConfig | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $WebFeedConfigCopyWith<WebFeedConfig> get copyWith => _$WebFeedConfigCopyWithImpl<WebFeedConfig>(this as WebFeedConfig, _$identity); | ||||
| $SnWebFeedConfigCopyWith<SnWebFeedConfig> get copyWith => _$SnWebFeedConfigCopyWithImpl<SnWebFeedConfig>(this as SnWebFeedConfig, _$identity); | ||||
|  | ||||
|   /// Serializes this WebFeedConfig to a JSON map. | ||||
|   /// Serializes this SnWebFeedConfig to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is WebFeedConfig&&(identical(other.scrapPage, scrapPage) || other.scrapPage == scrapPage)); | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWebFeedConfig&&(identical(other.scrapPage, scrapPage) || other.scrapPage == scrapPage)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @@ -38,15 +38,15 @@ int get hashCode => Object.hash(runtimeType,scrapPage); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'WebFeedConfig(scrapPage: $scrapPage)'; | ||||
|   return 'SnWebFeedConfig(scrapPage: $scrapPage)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $WebFeedConfigCopyWith<$Res>  { | ||||
|   factory $WebFeedConfigCopyWith(WebFeedConfig value, $Res Function(WebFeedConfig) _then) = _$WebFeedConfigCopyWithImpl; | ||||
| abstract mixin class $SnWebFeedConfigCopyWith<$Res>  { | ||||
|   factory $SnWebFeedConfigCopyWith(SnWebFeedConfig value, $Res Function(SnWebFeedConfig) _then) = _$SnWebFeedConfigCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  bool scrapPage | ||||
| @@ -57,14 +57,14 @@ $Res call({ | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$WebFeedConfigCopyWithImpl<$Res> | ||||
|     implements $WebFeedConfigCopyWith<$Res> { | ||||
|   _$WebFeedConfigCopyWithImpl(this._self, this._then); | ||||
| class _$SnWebFeedConfigCopyWithImpl<$Res> | ||||
|     implements $SnWebFeedConfigCopyWith<$Res> { | ||||
|   _$SnWebFeedConfigCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final WebFeedConfig _self; | ||||
|   final $Res Function(WebFeedConfig) _then; | ||||
|   final SnWebFeedConfig _self; | ||||
|   final $Res Function(SnWebFeedConfig) _then; | ||||
|  | ||||
| /// Create a copy of WebFeedConfig | ||||
| /// Create a copy of SnWebFeedConfig | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? scrapPage = null,}) { | ||||
|   return _then(_self.copyWith( | ||||
| @@ -79,26 +79,26 @@ as bool, | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class _WebFeedConfig implements WebFeedConfig { | ||||
|   const _WebFeedConfig({this.scrapPage = false}); | ||||
|   factory _WebFeedConfig.fromJson(Map<String, dynamic> json) => _$WebFeedConfigFromJson(json); | ||||
| class _SnWebFeedConfig implements SnWebFeedConfig { | ||||
|   const _SnWebFeedConfig({this.scrapPage = false}); | ||||
|   factory _SnWebFeedConfig.fromJson(Map<String, dynamic> json) => _$SnWebFeedConfigFromJson(json); | ||||
|  | ||||
| @override@JsonKey() final  bool scrapPage; | ||||
|  | ||||
| /// Create a copy of WebFeedConfig | ||||
| /// Create a copy of SnWebFeedConfig | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| _$WebFeedConfigCopyWith<_WebFeedConfig> get copyWith => __$WebFeedConfigCopyWithImpl<_WebFeedConfig>(this, _$identity); | ||||
| _$SnWebFeedConfigCopyWith<_SnWebFeedConfig> get copyWith => __$SnWebFeedConfigCopyWithImpl<_SnWebFeedConfig>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$WebFeedConfigToJson(this, ); | ||||
|   return _$SnWebFeedConfigToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _WebFeedConfig&&(identical(other.scrapPage, scrapPage) || other.scrapPage == scrapPage)); | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnWebFeedConfig&&(identical(other.scrapPage, scrapPage) || other.scrapPage == scrapPage)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @@ -107,15 +107,15 @@ int get hashCode => Object.hash(runtimeType,scrapPage); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'WebFeedConfig(scrapPage: $scrapPage)'; | ||||
|   return 'SnWebFeedConfig(scrapPage: $scrapPage)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class _$WebFeedConfigCopyWith<$Res> implements $WebFeedConfigCopyWith<$Res> { | ||||
|   factory _$WebFeedConfigCopyWith(_WebFeedConfig value, $Res Function(_WebFeedConfig) _then) = __$WebFeedConfigCopyWithImpl; | ||||
| abstract mixin class _$SnWebFeedConfigCopyWith<$Res> implements $SnWebFeedConfigCopyWith<$Res> { | ||||
|   factory _$SnWebFeedConfigCopyWith(_SnWebFeedConfig value, $Res Function(_SnWebFeedConfig) _then) = __$SnWebFeedConfigCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  bool scrapPage | ||||
| @@ -126,17 +126,17 @@ $Res call({ | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class __$WebFeedConfigCopyWithImpl<$Res> | ||||
|     implements _$WebFeedConfigCopyWith<$Res> { | ||||
|   __$WebFeedConfigCopyWithImpl(this._self, this._then); | ||||
| class __$SnWebFeedConfigCopyWithImpl<$Res> | ||||
|     implements _$SnWebFeedConfigCopyWith<$Res> { | ||||
|   __$SnWebFeedConfigCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final _WebFeedConfig _self; | ||||
|   final $Res Function(_WebFeedConfig) _then; | ||||
|   final _SnWebFeedConfig _self; | ||||
|   final $Res Function(_SnWebFeedConfig) _then; | ||||
|  | ||||
| /// Create a copy of WebFeedConfig | ||||
| /// Create a copy of SnWebFeedConfig | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? scrapPage = null,}) { | ||||
|   return _then(_WebFeedConfig( | ||||
|   return _then(_SnWebFeedConfig( | ||||
| scrapPage: null == scrapPage ? _self.scrapPage : scrapPage // ignore: cast_nullable_to_non_nullable | ||||
| as bool, | ||||
|   )); | ||||
| @@ -147,22 +147,22 @@ as bool, | ||||
|  | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$WebFeed { | ||||
| mixin _$SnWebFeed { | ||||
|  | ||||
|  String get id; String get url; String get title; String? get description; SnScrappedLink? get preview; WebFeedConfig get config; String get publisherId; List<WebArticle> get articles; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; | ||||
| /// Create a copy of WebFeed | ||||
|  String get id; String get url; String get title; String? get description; SnScrappedLink? get preview; SnWebFeedConfig get config; String get publisherId; List<SnWebArticle> get articles; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; | ||||
| /// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $WebFeedCopyWith<WebFeed> get copyWith => _$WebFeedCopyWithImpl<WebFeed>(this as WebFeed, _$identity); | ||||
| $SnWebFeedCopyWith<SnWebFeed> get copyWith => _$SnWebFeedCopyWithImpl<SnWebFeed>(this as SnWebFeed, _$identity); | ||||
|  | ||||
|   /// Serializes this WebFeed to a JSON map. | ||||
|   /// Serializes this SnWebFeed to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is WebFeed&&(identical(other.id, id) || other.id == id)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.config, config) || other.config == config)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&const DeepCollectionEquality().equals(other.articles, articles)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWebFeed&&(identical(other.id, id) || other.id == id)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.config, config) || other.config == config)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&const DeepCollectionEquality().equals(other.articles, articles)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @@ -171,33 +171,33 @@ int get hashCode => Object.hash(runtimeType,id,url,title,description,preview,con | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'WebFeed(id: $id, url: $url, title: $title, description: $description, preview: $preview, config: $config, publisherId: $publisherId, articles: $articles, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
|   return 'SnWebFeed(id: $id, url: $url, title: $title, description: $description, preview: $preview, config: $config, publisherId: $publisherId, articles: $articles, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $WebFeedCopyWith<$Res>  { | ||||
|   factory $WebFeedCopyWith(WebFeed value, $Res Function(WebFeed) _then) = _$WebFeedCopyWithImpl; | ||||
| abstract mixin class $SnWebFeedCopyWith<$Res>  { | ||||
|   factory $SnWebFeedCopyWith(SnWebFeed value, $Res Function(SnWebFeed) _then) = _$SnWebFeedCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  String id, String url, String title, String? description, SnScrappedLink? preview, WebFeedConfig config, String publisherId, List<WebArticle> articles, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
|  String id, String url, String title, String? description, SnScrappedLink? preview, SnWebFeedConfig config, String publisherId, List<SnWebArticle> articles, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
| }); | ||||
|  | ||||
|  | ||||
| $SnScrappedLinkCopyWith<$Res>? get preview;$WebFeedConfigCopyWith<$Res> get config; | ||||
| $SnScrappedLinkCopyWith<$Res>? get preview;$SnWebFeedConfigCopyWith<$Res> get config; | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$WebFeedCopyWithImpl<$Res> | ||||
|     implements $WebFeedCopyWith<$Res> { | ||||
|   _$WebFeedCopyWithImpl(this._self, this._then); | ||||
| class _$SnWebFeedCopyWithImpl<$Res> | ||||
|     implements $SnWebFeedCopyWith<$Res> { | ||||
|   _$SnWebFeedCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final WebFeed _self; | ||||
|   final $Res Function(WebFeed) _then; | ||||
|   final SnWebFeed _self; | ||||
|   final $Res Function(SnWebFeed) _then; | ||||
|  | ||||
| /// Create a copy of WebFeed | ||||
| /// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? url = null,Object? title = null,Object? description = freezed,Object? preview = freezed,Object? config = null,Object? publisherId = null,Object? articles = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_self.copyWith( | ||||
| @@ -207,15 +207,15 @@ as String,title: null == title ? _self.title : title // ignore: cast_nullable_to | ||||
| as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable | ||||
| as String?,preview: freezed == preview ? _self.preview : preview // ignore: cast_nullable_to_non_nullable | ||||
| as SnScrappedLink?,config: null == config ? _self.config : config // ignore: cast_nullable_to_non_nullable | ||||
| as WebFeedConfig,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable | ||||
| as SnWebFeedConfig,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable | ||||
| as String,articles: null == articles ? _self.articles : articles // ignore: cast_nullable_to_non_nullable | ||||
| as List<WebArticle>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as List<SnWebArticle>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?, | ||||
|   )); | ||||
| } | ||||
| /// Create a copy of WebFeed | ||||
| /// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| @@ -227,13 +227,13 @@ $SnScrappedLinkCopyWith<$Res>? get preview { | ||||
|   return $SnScrappedLinkCopyWith<$Res>(_self.preview!, (value) { | ||||
|     return _then(_self.copyWith(preview: value)); | ||||
|   }); | ||||
| }/// Create a copy of WebFeed | ||||
| }/// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| $WebFeedConfigCopyWith<$Res> get config { | ||||
| $SnWebFeedConfigCopyWith<$Res> get config { | ||||
|    | ||||
|   return $WebFeedConfigCopyWith<$Res>(_self.config, (value) { | ||||
|   return $SnWebFeedConfigCopyWith<$Res>(_self.config, (value) { | ||||
|     return _then(_self.copyWith(config: value)); | ||||
|   }); | ||||
| } | ||||
| @@ -243,19 +243,19 @@ $WebFeedConfigCopyWith<$Res> get config { | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class _WebFeed implements WebFeed { | ||||
|   const _WebFeed({required this.id, required this.url, required this.title, this.description, this.preview, this.config = const WebFeedConfig(), required this.publisherId, final  List<WebArticle> articles = const [], required this.createdAt, required this.updatedAt, this.deletedAt}): _articles = articles; | ||||
|   factory _WebFeed.fromJson(Map<String, dynamic> json) => _$WebFeedFromJson(json); | ||||
| class _SnWebFeed implements SnWebFeed { | ||||
|   const _SnWebFeed({required this.id, required this.url, required this.title, this.description, this.preview, this.config = const SnWebFeedConfig(), required this.publisherId, final  List<SnWebArticle> articles = const [], required this.createdAt, required this.updatedAt, this.deletedAt}): _articles = articles; | ||||
|   factory _SnWebFeed.fromJson(Map<String, dynamic> json) => _$SnWebFeedFromJson(json); | ||||
|  | ||||
| @override final  String id; | ||||
| @override final  String url; | ||||
| @override final  String title; | ||||
| @override final  String? description; | ||||
| @override final  SnScrappedLink? preview; | ||||
| @override@JsonKey() final  WebFeedConfig config; | ||||
| @override@JsonKey() final  SnWebFeedConfig config; | ||||
| @override final  String publisherId; | ||||
|  final  List<WebArticle> _articles; | ||||
| @override@JsonKey() List<WebArticle> get articles { | ||||
|  final  List<SnWebArticle> _articles; | ||||
| @override@JsonKey() List<SnWebArticle> get articles { | ||||
|   if (_articles is EqualUnmodifiableListView) return _articles; | ||||
|   // ignore: implicit_dynamic_type | ||||
|   return EqualUnmodifiableListView(_articles); | ||||
| @@ -265,20 +265,20 @@ class _WebFeed implements WebFeed { | ||||
| @override final  DateTime updatedAt; | ||||
| @override final  DateTime? deletedAt; | ||||
|  | ||||
| /// Create a copy of WebFeed | ||||
| /// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| _$WebFeedCopyWith<_WebFeed> get copyWith => __$WebFeedCopyWithImpl<_WebFeed>(this, _$identity); | ||||
| _$SnWebFeedCopyWith<_SnWebFeed> get copyWith => __$SnWebFeedCopyWithImpl<_SnWebFeed>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$WebFeedToJson(this, ); | ||||
|   return _$SnWebFeedToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _WebFeed&&(identical(other.id, id) || other.id == id)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.config, config) || other.config == config)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&const DeepCollectionEquality().equals(other._articles, _articles)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnWebFeed&&(identical(other.id, id) || other.id == id)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.config, config) || other.config == config)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&const DeepCollectionEquality().equals(other._articles, _articles)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @@ -287,52 +287,52 @@ int get hashCode => Object.hash(runtimeType,id,url,title,description,preview,con | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'WebFeed(id: $id, url: $url, title: $title, description: $description, preview: $preview, config: $config, publisherId: $publisherId, articles: $articles, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
|   return 'SnWebFeed(id: $id, url: $url, title: $title, description: $description, preview: $preview, config: $config, publisherId: $publisherId, articles: $articles, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class _$WebFeedCopyWith<$Res> implements $WebFeedCopyWith<$Res> { | ||||
|   factory _$WebFeedCopyWith(_WebFeed value, $Res Function(_WebFeed) _then) = __$WebFeedCopyWithImpl; | ||||
| abstract mixin class _$SnWebFeedCopyWith<$Res> implements $SnWebFeedCopyWith<$Res> { | ||||
|   factory _$SnWebFeedCopyWith(_SnWebFeed value, $Res Function(_SnWebFeed) _then) = __$SnWebFeedCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String id, String url, String title, String? description, SnScrappedLink? preview, WebFeedConfig config, String publisherId, List<WebArticle> articles, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
|  String id, String url, String title, String? description, SnScrappedLink? preview, SnWebFeedConfig config, String publisherId, List<SnWebArticle> articles, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
| }); | ||||
|  | ||||
|  | ||||
| @override $SnScrappedLinkCopyWith<$Res>? get preview;@override $WebFeedConfigCopyWith<$Res> get config; | ||||
| @override $SnScrappedLinkCopyWith<$Res>? get preview;@override $SnWebFeedConfigCopyWith<$Res> get config; | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class __$WebFeedCopyWithImpl<$Res> | ||||
|     implements _$WebFeedCopyWith<$Res> { | ||||
|   __$WebFeedCopyWithImpl(this._self, this._then); | ||||
| class __$SnWebFeedCopyWithImpl<$Res> | ||||
|     implements _$SnWebFeedCopyWith<$Res> { | ||||
|   __$SnWebFeedCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final _WebFeed _self; | ||||
|   final $Res Function(_WebFeed) _then; | ||||
|   final _SnWebFeed _self; | ||||
|   final $Res Function(_SnWebFeed) _then; | ||||
|  | ||||
| /// Create a copy of WebFeed | ||||
| /// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? url = null,Object? title = null,Object? description = freezed,Object? preview = freezed,Object? config = null,Object? publisherId = null,Object? articles = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_WebFeed( | ||||
|   return _then(_SnWebFeed( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable | ||||
| as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable | ||||
| as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable | ||||
| as String?,preview: freezed == preview ? _self.preview : preview // ignore: cast_nullable_to_non_nullable | ||||
| as SnScrappedLink?,config: null == config ? _self.config : config // ignore: cast_nullable_to_non_nullable | ||||
| as WebFeedConfig,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable | ||||
| as SnWebFeedConfig,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable | ||||
| as String,articles: null == articles ? _self._articles : articles // ignore: cast_nullable_to_non_nullable | ||||
| as List<WebArticle>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as List<SnWebArticle>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?, | ||||
|   )); | ||||
| } | ||||
|  | ||||
| /// Create a copy of WebFeed | ||||
| /// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| @@ -344,13 +344,13 @@ $SnScrappedLinkCopyWith<$Res>? get preview { | ||||
|   return $SnScrappedLinkCopyWith<$Res>(_self.preview!, (value) { | ||||
|     return _then(_self.copyWith(preview: value)); | ||||
|   }); | ||||
| }/// Create a copy of WebFeed | ||||
| }/// Create a copy of SnWebFeed | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| $WebFeedConfigCopyWith<$Res> get config { | ||||
| $SnWebFeedConfigCopyWith<$Res> get config { | ||||
|    | ||||
|   return $WebFeedConfigCopyWith<$Res>(_self.config, (value) { | ||||
|   return $SnWebFeedConfigCopyWith<$Res>(_self.config, (value) { | ||||
|     return _then(_self.copyWith(config: value)); | ||||
|   }); | ||||
| } | ||||
| @@ -358,59 +358,59 @@ $WebFeedConfigCopyWith<$Res> get config { | ||||
|  | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$WebArticle { | ||||
| mixin _$SnWebArticle { | ||||
|  | ||||
|  String get id; String get title; String get url; String? get author; Map<String, dynamic>? get meta; SnScrappedLink? get preview; String? get content; DateTime? get publishedAt; String get feedId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; | ||||
| /// Create a copy of WebArticle | ||||
|  String get id; String get title; String get url; String? get author; Map<String, dynamic>? get meta; SnScrappedLink? get preview; SnWebFeed? get feed; String? get content; DateTime? get publishedAt; String get feedId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; | ||||
| /// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $WebArticleCopyWith<WebArticle> get copyWith => _$WebArticleCopyWithImpl<WebArticle>(this as WebArticle, _$identity); | ||||
| $SnWebArticleCopyWith<SnWebArticle> get copyWith => _$SnWebArticleCopyWithImpl<SnWebArticle>(this as SnWebArticle, _$identity); | ||||
|  | ||||
|   /// Serializes this WebArticle to a JSON map. | ||||
|   /// Serializes this SnWebArticle to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is WebArticle&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.url, url) || other.url == url)&&(identical(other.author, author) || other.author == author)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.content, content) || other.content == content)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.feedId, feedId) || other.feedId == feedId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWebArticle&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.url, url) || other.url == url)&&(identical(other.author, author) || other.author == author)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.feed, feed) || other.feed == feed)&&(identical(other.content, content) || other.content == content)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.feedId, feedId) || other.feedId == feedId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,title,url,author,const DeepCollectionEquality().hash(meta),preview,content,publishedAt,feedId,createdAt,updatedAt,deletedAt); | ||||
| int get hashCode => Object.hash(runtimeType,id,title,url,author,const DeepCollectionEquality().hash(meta),preview,feed,content,publishedAt,feedId,createdAt,updatedAt,deletedAt); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'WebArticle(id: $id, title: $title, url: $url, author: $author, meta: $meta, preview: $preview, content: $content, publishedAt: $publishedAt, feedId: $feedId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
|   return 'SnWebArticle(id: $id, title: $title, url: $url, author: $author, meta: $meta, preview: $preview, feed: $feed, content: $content, publishedAt: $publishedAt, feedId: $feedId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $WebArticleCopyWith<$Res>  { | ||||
|   factory $WebArticleCopyWith(WebArticle value, $Res Function(WebArticle) _then) = _$WebArticleCopyWithImpl; | ||||
| abstract mixin class $SnWebArticleCopyWith<$Res>  { | ||||
|   factory $SnWebArticleCopyWith(SnWebArticle value, $Res Function(SnWebArticle) _then) = _$SnWebArticleCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  String id, String title, String url, String? author, Map<String, dynamic>? meta, SnScrappedLink? preview, String? content, DateTime? publishedAt, String feedId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
|  String id, String title, String url, String? author, Map<String, dynamic>? meta, SnScrappedLink? preview, SnWebFeed? feed, String? content, DateTime? publishedAt, String feedId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
| }); | ||||
|  | ||||
|  | ||||
| $SnScrappedLinkCopyWith<$Res>? get preview; | ||||
| $SnScrappedLinkCopyWith<$Res>? get preview;$SnWebFeedCopyWith<$Res>? get feed; | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$WebArticleCopyWithImpl<$Res> | ||||
|     implements $WebArticleCopyWith<$Res> { | ||||
|   _$WebArticleCopyWithImpl(this._self, this._then); | ||||
| class _$SnWebArticleCopyWithImpl<$Res> | ||||
|     implements $SnWebArticleCopyWith<$Res> { | ||||
|   _$SnWebArticleCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final WebArticle _self; | ||||
|   final $Res Function(WebArticle) _then; | ||||
|   final SnWebArticle _self; | ||||
|   final $Res Function(SnWebArticle) _then; | ||||
|  | ||||
| /// Create a copy of WebArticle | ||||
| /// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = null,Object? url = null,Object? author = freezed,Object? meta = freezed,Object? preview = freezed,Object? content = freezed,Object? publishedAt = freezed,Object? feedId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = null,Object? url = null,Object? author = freezed,Object? meta = freezed,Object? preview = freezed,Object? feed = freezed,Object? content = freezed,Object? publishedAt = freezed,Object? feedId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_self.copyWith( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable | ||||
| @@ -418,7 +418,8 @@ as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nul | ||||
| as String,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable | ||||
| as String?,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable | ||||
| as Map<String, dynamic>?,preview: freezed == preview ? _self.preview : preview // ignore: cast_nullable_to_non_nullable | ||||
| as SnScrappedLink?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable | ||||
| as SnScrappedLink?,feed: freezed == feed ? _self.feed : feed // ignore: cast_nullable_to_non_nullable | ||||
| as SnWebFeed?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable | ||||
| as String?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?,feedId: null == feedId ? _self.feedId : feedId // ignore: cast_nullable_to_non_nullable | ||||
| as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| @@ -427,7 +428,7 @@ as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ign | ||||
| as DateTime?, | ||||
|   )); | ||||
| } | ||||
| /// Create a copy of WebArticle | ||||
| /// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| @@ -439,6 +440,18 @@ $SnScrappedLinkCopyWith<$Res>? get preview { | ||||
|   return $SnScrappedLinkCopyWith<$Res>(_self.preview!, (value) { | ||||
|     return _then(_self.copyWith(preview: value)); | ||||
|   }); | ||||
| }/// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| $SnWebFeedCopyWith<$Res>? get feed { | ||||
|     if (_self.feed == null) { | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   return $SnWebFeedCopyWith<$Res>(_self.feed!, (value) { | ||||
|     return _then(_self.copyWith(feed: value)); | ||||
|   }); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -446,9 +459,9 @@ $SnScrappedLinkCopyWith<$Res>? get preview { | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class _WebArticle implements WebArticle { | ||||
|   const _WebArticle({required this.id, required this.title, required this.url, this.author, final  Map<String, dynamic>? meta, this.preview, this.content, this.publishedAt, required this.feedId, required this.createdAt, required this.updatedAt, this.deletedAt}): _meta = meta; | ||||
|   factory _WebArticle.fromJson(Map<String, dynamic> json) => _$WebArticleFromJson(json); | ||||
| class _SnWebArticle implements SnWebArticle { | ||||
|   const _SnWebArticle({required this.id, required this.title, required this.url, this.author, final  Map<String, dynamic>? meta, this.preview, this.feed, this.content, this.publishedAt, required this.feedId, required this.createdAt, required this.updatedAt, this.deletedAt}): _meta = meta; | ||||
|   factory _SnWebArticle.fromJson(Map<String, dynamic> json) => _$SnWebArticleFromJson(json); | ||||
|  | ||||
| @override final  String id; | ||||
| @override final  String title; | ||||
| @@ -464,6 +477,7 @@ class _WebArticle implements WebArticle { | ||||
| } | ||||
|  | ||||
| @override final  SnScrappedLink? preview; | ||||
| @override final  SnWebFeed? feed; | ||||
| @override final  String? content; | ||||
| @override final  DateTime? publishedAt; | ||||
| @override final  String feedId; | ||||
| @@ -471,65 +485,66 @@ class _WebArticle implements WebArticle { | ||||
| @override final  DateTime updatedAt; | ||||
| @override final  DateTime? deletedAt; | ||||
|  | ||||
| /// Create a copy of WebArticle | ||||
| /// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| _$WebArticleCopyWith<_WebArticle> get copyWith => __$WebArticleCopyWithImpl<_WebArticle>(this, _$identity); | ||||
| _$SnWebArticleCopyWith<_SnWebArticle> get copyWith => __$SnWebArticleCopyWithImpl<_SnWebArticle>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$WebArticleToJson(this, ); | ||||
|   return _$SnWebArticleToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _WebArticle&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.url, url) || other.url == url)&&(identical(other.author, author) || other.author == author)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.content, content) || other.content == content)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.feedId, feedId) || other.feedId == feedId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnWebArticle&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.url, url) || other.url == url)&&(identical(other.author, author) || other.author == author)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.preview, preview) || other.preview == preview)&&(identical(other.feed, feed) || other.feed == feed)&&(identical(other.content, content) || other.content == content)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.feedId, feedId) || other.feedId == feedId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,title,url,author,const DeepCollectionEquality().hash(_meta),preview,content,publishedAt,feedId,createdAt,updatedAt,deletedAt); | ||||
| int get hashCode => Object.hash(runtimeType,id,title,url,author,const DeepCollectionEquality().hash(_meta),preview,feed,content,publishedAt,feedId,createdAt,updatedAt,deletedAt); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'WebArticle(id: $id, title: $title, url: $url, author: $author, meta: $meta, preview: $preview, content: $content, publishedAt: $publishedAt, feedId: $feedId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
|   return 'SnWebArticle(id: $id, title: $title, url: $url, author: $author, meta: $meta, preview: $preview, feed: $feed, content: $content, publishedAt: $publishedAt, feedId: $feedId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class _$WebArticleCopyWith<$Res> implements $WebArticleCopyWith<$Res> { | ||||
|   factory _$WebArticleCopyWith(_WebArticle value, $Res Function(_WebArticle) _then) = __$WebArticleCopyWithImpl; | ||||
| abstract mixin class _$SnWebArticleCopyWith<$Res> implements $SnWebArticleCopyWith<$Res> { | ||||
|   factory _$SnWebArticleCopyWith(_SnWebArticle value, $Res Function(_SnWebArticle) _then) = __$SnWebArticleCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String id, String title, String url, String? author, Map<String, dynamic>? meta, SnScrappedLink? preview, String? content, DateTime? publishedAt, String feedId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
|  String id, String title, String url, String? author, Map<String, dynamic>? meta, SnScrappedLink? preview, SnWebFeed? feed, String? content, DateTime? publishedAt, String feedId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
| }); | ||||
|  | ||||
|  | ||||
| @override $SnScrappedLinkCopyWith<$Res>? get preview; | ||||
| @override $SnScrappedLinkCopyWith<$Res>? get preview;@override $SnWebFeedCopyWith<$Res>? get feed; | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class __$WebArticleCopyWithImpl<$Res> | ||||
|     implements _$WebArticleCopyWith<$Res> { | ||||
|   __$WebArticleCopyWithImpl(this._self, this._then); | ||||
| class __$SnWebArticleCopyWithImpl<$Res> | ||||
|     implements _$SnWebArticleCopyWith<$Res> { | ||||
|   __$SnWebArticleCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final _WebArticle _self; | ||||
|   final $Res Function(_WebArticle) _then; | ||||
|   final _SnWebArticle _self; | ||||
|   final $Res Function(_SnWebArticle) _then; | ||||
|  | ||||
| /// Create a copy of WebArticle | ||||
| /// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = null,Object? url = null,Object? author = freezed,Object? meta = freezed,Object? preview = freezed,Object? content = freezed,Object? publishedAt = freezed,Object? feedId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_WebArticle( | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = null,Object? url = null,Object? author = freezed,Object? meta = freezed,Object? preview = freezed,Object? feed = freezed,Object? content = freezed,Object? publishedAt = freezed,Object? feedId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_SnWebArticle( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable | ||||
| as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable | ||||
| as String,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable | ||||
| as String?,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable | ||||
| as Map<String, dynamic>?,preview: freezed == preview ? _self.preview : preview // ignore: cast_nullable_to_non_nullable | ||||
| as SnScrappedLink?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable | ||||
| as SnScrappedLink?,feed: freezed == feed ? _self.feed : feed // ignore: cast_nullable_to_non_nullable | ||||
| as SnWebFeed?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable | ||||
| as String?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?,feedId: null == feedId ? _self.feedId : feedId // ignore: cast_nullable_to_non_nullable | ||||
| as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| @@ -539,7 +554,7 @@ as DateTime?, | ||||
|   )); | ||||
| } | ||||
|  | ||||
| /// Create a copy of WebArticle | ||||
| /// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| @@ -551,6 +566,18 @@ $SnScrappedLinkCopyWith<$Res>? get preview { | ||||
|   return $SnScrappedLinkCopyWith<$Res>(_self.preview!, (value) { | ||||
|     return _then(_self.copyWith(preview: value)); | ||||
|   }); | ||||
| }/// Create a copy of SnWebArticle | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override | ||||
| @pragma('vm:prefer-inline') | ||||
| $SnWebFeedCopyWith<$Res>? get feed { | ||||
|     if (_self.feed == null) { | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   return $SnWebFeedCopyWith<$Res>(_self.feed!, (value) { | ||||
|     return _then(_self.copyWith(feed: value)); | ||||
|   }); | ||||
| } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -6,13 +6,13 @@ part of 'webfeed.dart'; | ||||
| // JsonSerializableGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| _WebFeedConfig _$WebFeedConfigFromJson(Map<String, dynamic> json) => | ||||
|     _WebFeedConfig(scrapPage: json['scrap_page'] as bool? ?? false); | ||||
| _SnWebFeedConfig _$SnWebFeedConfigFromJson(Map<String, dynamic> json) => | ||||
|     _SnWebFeedConfig(scrapPage: json['scrap_page'] as bool? ?? false); | ||||
|  | ||||
| Map<String, dynamic> _$WebFeedConfigToJson(_WebFeedConfig instance) => | ||||
| Map<String, dynamic> _$SnWebFeedConfigToJson(_SnWebFeedConfig instance) => | ||||
|     <String, dynamic>{'scrap_page': instance.scrapPage}; | ||||
|  | ||||
| _WebFeed _$WebFeedFromJson(Map<String, dynamic> json) => _WebFeed( | ||||
| _SnWebFeed _$SnWebFeedFromJson(Map<String, dynamic> json) => _SnWebFeed( | ||||
|   id: json['id'] as String, | ||||
|   url: json['url'] as String, | ||||
|   title: json['title'] as String, | ||||
| @@ -23,12 +23,12 @@ _WebFeed _$WebFeedFromJson(Map<String, dynamic> json) => _WebFeed( | ||||
|           : SnScrappedLink.fromJson(json['preview'] as Map<String, dynamic>), | ||||
|   config: | ||||
|       json['config'] == null | ||||
|           ? const WebFeedConfig() | ||||
|           : WebFeedConfig.fromJson(json['config'] as Map<String, dynamic>), | ||||
|           ? const SnWebFeedConfig() | ||||
|           : SnWebFeedConfig.fromJson(json['config'] as Map<String, dynamic>), | ||||
|   publisherId: json['publisher_id'] as String, | ||||
|   articles: | ||||
|       (json['articles'] as List<dynamic>?) | ||||
|           ?.map((e) => WebArticle.fromJson(e as Map<String, dynamic>)) | ||||
|           ?.map((e) => SnWebArticle.fromJson(e as Map<String, dynamic>)) | ||||
|           .toList() ?? | ||||
|       const [], | ||||
|   createdAt: DateTime.parse(json['created_at'] as String), | ||||
| @@ -39,7 +39,8 @@ _WebFeed _$WebFeedFromJson(Map<String, dynamic> json) => _WebFeed( | ||||
|           : DateTime.parse(json['deleted_at'] as String), | ||||
| ); | ||||
|  | ||||
| Map<String, dynamic> _$WebFeedToJson(_WebFeed instance) => <String, dynamic>{ | ||||
| Map<String, dynamic> _$SnWebFeedToJson(_SnWebFeed instance) => | ||||
|     <String, dynamic>{ | ||||
|       'id': instance.id, | ||||
|       'url': instance.url, | ||||
|       'title': instance.title, | ||||
| @@ -53,7 +54,8 @@ Map<String, dynamic> _$WebFeedToJson(_WebFeed instance) => <String, dynamic>{ | ||||
|       'deleted_at': instance.deletedAt?.toIso8601String(), | ||||
|     }; | ||||
|  | ||||
| _WebArticle _$WebArticleFromJson(Map<String, dynamic> json) => _WebArticle( | ||||
| _SnWebArticle _$SnWebArticleFromJson(Map<String, dynamic> json) => | ||||
|     _SnWebArticle( | ||||
|       id: json['id'] as String, | ||||
|       title: json['title'] as String, | ||||
|       url: json['url'] as String, | ||||
| @@ -62,7 +64,13 @@ _WebArticle _$WebArticleFromJson(Map<String, dynamic> json) => _WebArticle( | ||||
|       preview: | ||||
|           json['preview'] == null | ||||
|               ? null | ||||
|           : SnScrappedLink.fromJson(json['preview'] as Map<String, dynamic>), | ||||
|               : SnScrappedLink.fromJson( | ||||
|                 json['preview'] as Map<String, dynamic>, | ||||
|               ), | ||||
|       feed: | ||||
|           json['feed'] == null | ||||
|               ? null | ||||
|               : SnWebFeed.fromJson(json['feed'] as Map<String, dynamic>), | ||||
|       content: json['content'] as String?, | ||||
|       publishedAt: | ||||
|           json['published_at'] == null | ||||
| @@ -77,7 +85,7 @@ _WebArticle _$WebArticleFromJson(Map<String, dynamic> json) => _WebArticle( | ||||
|               : DateTime.parse(json['deleted_at'] as String), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$WebArticleToJson(_WebArticle instance) => | ||||
| Map<String, dynamic> _$SnWebArticleToJson(_SnWebArticle instance) => | ||||
|     <String, dynamic>{ | ||||
|       'id': instance.id, | ||||
|       'title': instance.title, | ||||
| @@ -85,6 +93,7 @@ Map<String, dynamic> _$WebArticleToJson(_WebArticle instance) => | ||||
|       'author': instance.author, | ||||
|       'meta': instance.meta, | ||||
|       'preview': instance.preview?.toJson(), | ||||
|       'feed': instance.feed?.toJson(), | ||||
|       'content': instance.content, | ||||
|       'published_at': instance.publishedAt?.toIso8601String(), | ||||
|       'feed_id': instance.feedId, | ||||
|   | ||||
							
								
								
									
										31
									
								
								lib/pods/article_detail.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/pods/article_detail.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
|  | ||||
| /// Provider that fetches a single article by its ID | ||||
| final articleDetailProvider = FutureProvider.autoDispose.family<SnWebArticle, String>( | ||||
|   (ref, articleId) async { | ||||
|     final dio = ref.watch(apiClientProvider); | ||||
|      | ||||
|     try { | ||||
|       final response = await dio.get<Map<String, dynamic>>( | ||||
|         '/feeds/articles/$articleId', | ||||
|       ); | ||||
|        | ||||
|       if (response.statusCode == 200 && response.data != null) { | ||||
|         return SnWebArticle.fromJson(response.data!); | ||||
|       } else { | ||||
|         throw Exception('Failed to load article'); | ||||
|       } | ||||
|     } on DioException catch (e) { | ||||
|       if (e.response?.statusCode == 404) { | ||||
|         throw Exception('Article not found'); | ||||
|       } else { | ||||
|         throw Exception('Failed to load article: ${e.message}'); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       throw Exception('Failed to load article: $e'); | ||||
|     } | ||||
|   }, | ||||
| ); | ||||
							
								
								
									
										1
									
								
								lib/pods/article_list.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								lib/pods/article_list.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
|  | ||||
| @@ -1,28 +1,31 @@ | ||||
| import 'dart:async'; | ||||
|  | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
|  | ||||
| final webFeedListProvider = FutureProvider.family<List<WebFeed>, String>(( | ||||
| final webFeedListProvider = FutureProvider.family<List<SnWebFeed>, String>(( | ||||
|   ref, | ||||
|   pubName, | ||||
| ) async { | ||||
|   final client = ref.watch(apiClientProvider); | ||||
|   final response = await client.get('/publishers/$pubName/feeds'); | ||||
|   return (response.data as List).map((json) => WebFeed.fromJson(json)).toList(); | ||||
|   return (response.data as List) | ||||
|       .map((json) => SnWebFeed.fromJson(json)) | ||||
|       .toList(); | ||||
| }); | ||||
|  | ||||
| class WebFeedNotifier | ||||
|     extends | ||||
|         AutoDisposeFamilyAsyncNotifier< | ||||
|           WebFeed, | ||||
|           SnWebFeed, | ||||
|           ({String pubName, String? feedId}) | ||||
|         > { | ||||
|   @override | ||||
|   FutureOr<WebFeed> build(({String pubName, String? feedId}) arg) async { | ||||
|   FutureOr<SnWebFeed> build(({String pubName, String? feedId}) arg) async { | ||||
|     if (arg.feedId == null || arg.feedId!.isEmpty) { | ||||
|       return WebFeed( | ||||
|       return SnWebFeed( | ||||
|         id: '', | ||||
|         url: '', | ||||
|         title: '', | ||||
| @@ -38,13 +41,13 @@ class WebFeedNotifier | ||||
|       final response = await client.get( | ||||
|         '/publishers/${arg.pubName}/feeds/${arg.feedId}', | ||||
|       ); | ||||
|       return WebFeed.fromJson(response.data); | ||||
|       return SnWebFeed.fromJson(response.data); | ||||
|     } catch (e) { | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<void> saveFeed(WebFeed feed) async { | ||||
|   Future<void> saveFeed(SnWebFeed feed) async { | ||||
|     state = const AsyncValue.loading(); | ||||
|     try { | ||||
|       final client = ref.read(apiClientProvider); | ||||
| @@ -55,7 +58,7 @@ class WebFeedNotifier | ||||
|               ? await client.post(url, data: feed.toJson()) | ||||
|               : await client.patch('$url/${feed.id}', data: feed.toJson()); | ||||
|  | ||||
|       state = AsyncValue.data(WebFeed.fromJson(response.data)); | ||||
|       state = AsyncValue.data(SnWebFeed.fromJson(response.data)); | ||||
|     } catch (error, stackTrace) { | ||||
|       state = AsyncValue.error(error, stackTrace); | ||||
|       rethrow; | ||||
| @@ -71,7 +74,7 @@ class WebFeedNotifier | ||||
|       final client = ref.read(apiClientProvider); | ||||
|       await client.delete('/publishers/${arg.pubName}/feeds/$feedId'); | ||||
|       state = AsyncValue.data( | ||||
|         WebFeed( | ||||
|         SnWebFeed( | ||||
|           id: '', | ||||
|           url: '', | ||||
|           title: '', | ||||
| @@ -94,13 +97,19 @@ class WebFeedNotifier | ||||
|     state = const AsyncValue.loading(); | ||||
|     try { | ||||
|       final client = ref.read(apiClientProvider); | ||||
|       await client.post('/publishers/${arg.pubName}/feeds/$feedId/scrap'); | ||||
|       await client.post( | ||||
|         '/publishers/${arg.pubName}/feeds/$feedId/scrap', | ||||
|         options: Options( | ||||
|           sendTimeout: const Duration(seconds: 60), | ||||
|           receiveTimeout: const Duration(seconds: 180), | ||||
|         ), | ||||
|       ); | ||||
|  | ||||
|       // Reload the feed | ||||
|       final response = await client.get( | ||||
|         '/publishers/${arg.pubName}/feeds/$feedId', | ||||
|       ); | ||||
|       state = AsyncValue.data(WebFeed.fromJson(response.data)); | ||||
|       state = AsyncValue.data(SnWebFeed.fromJson(response.data)); | ||||
|     } catch (error, stackTrace) { | ||||
|       state = AsyncValue.error(error, stackTrace); | ||||
|       rethrow; | ||||
| @@ -109,6 +118,6 @@ class WebFeedNotifier | ||||
| } | ||||
|  | ||||
| final webFeedNotifierProvider = AsyncNotifierProvider.autoDispose | ||||
|     .family<WebFeedNotifier, WebFeed, ({String pubName, String? feedId})>( | ||||
|     .family<WebFeedNotifier, SnWebFeed, ({String pubName, String? feedId})>( | ||||
|       WebFeedNotifier.new, | ||||
|     ); | ||||
|   | ||||
| @@ -1,14 +1,17 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/screens/about.dart'; | ||||
| import 'package:island/screens/developers/apps.dart'; | ||||
| import 'package:island/screens/developers/edit_app.dart'; | ||||
| import 'package:island/screens/developers/new_app.dart'; | ||||
| import 'package:island/screens/developers/hub.dart'; | ||||
| import 'package:island/screens/discovery/articles.dart'; | ||||
| import 'package:island/screens/posts/post_search.dart'; | ||||
| import 'package:island/widgets/app_wrapper.dart'; | ||||
| import 'package:island/screens/tabs.dart'; | ||||
|  | ||||
| import 'package:island/screens/explore.dart'; | ||||
| import 'package:island/screens/article_detail_screen.dart'; | ||||
| import 'package:island/screens/account.dart'; | ||||
| import 'package:island/screens/notification.dart'; | ||||
| import 'package:island/screens/wallet.dart'; | ||||
| @@ -219,6 +222,19 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|             ], | ||||
|           ), | ||||
|  | ||||
|           // Web articles | ||||
|           GoRoute( | ||||
|             path: '/feeds/articles', | ||||
|             builder: (context, state) => const ArticlesScreen(), | ||||
|           ), | ||||
|           GoRoute( | ||||
|             path: '/feeds/articles/:id', | ||||
|             builder: (context, state) { | ||||
|               final id = state.pathParameters['id']!; | ||||
|               return ArticleDetailScreen(articleId: id); | ||||
|             }, | ||||
|           ), | ||||
|  | ||||
|           // Auth routes | ||||
|           GoRoute( | ||||
|             path: '/auth/login', | ||||
| @@ -234,6 +250,10 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|             path: '/settings', | ||||
|             builder: (context, state) => const SettingsScreen(), | ||||
|           ), | ||||
|           GoRoute( | ||||
|             path: '/about', | ||||
|             builder: (context, state) => const AboutScreen(), | ||||
|           ), | ||||
|  | ||||
|           // Main tabs with TabsScreen shell | ||||
|           ShellRoute( | ||||
| @@ -251,6 +271,10 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|                     path: '/', | ||||
|                     builder: (context, state) => const ExploreScreen(), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     path: '/posts/search', | ||||
|                     builder: (context, state) => const PostSearchScreen(), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     path: '/posts/:id', | ||||
|                     builder: (context, state) { | ||||
|   | ||||
							
								
								
									
										300
									
								
								lib/screens/about.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								lib/screens/about.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:package_info_plus/package_info_plus.dart'; | ||||
| import 'package:url_launcher/url_launcher.dart'; | ||||
|  | ||||
| class AboutScreen extends StatefulWidget { | ||||
|   const AboutScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<AboutScreen> createState() => _AboutScreenState(); | ||||
| } | ||||
|  | ||||
| class _AboutScreenState extends State<AboutScreen> { | ||||
|   PackageInfo _packageInfo = PackageInfo( | ||||
|     appName: 'Island', | ||||
|     packageName: 'com.example.island', | ||||
|     version: '1.0.0', | ||||
|     buildNumber: '1', | ||||
|   ); | ||||
|   bool _isLoading = true; | ||||
|   String? _errorMessage; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     _initPackageInfo(); | ||||
|   } | ||||
|  | ||||
|   Future<void> _initPackageInfo() async { | ||||
|     try { | ||||
|       final info = await PackageInfo.fromPlatform(); | ||||
|       if (mounted) { | ||||
|         setState(() { | ||||
|           _packageInfo = info; | ||||
|           _isLoading = false; | ||||
|         }); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       if (mounted) { | ||||
|         setState(() { | ||||
|           _errorMessage = 'Failed to load package info: $e'; | ||||
|           _isLoading = false; | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<void> _launchURL(String url) async { | ||||
|     final uri = Uri.parse(url); | ||||
|     if (await canLaunchUrl(uri)) { | ||||
|       await launchUrl(uri); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final theme = Theme.of(context); | ||||
|  | ||||
|     return Scaffold( | ||||
|       appBar: AppBar(title: const Text('About'), elevation: 0), | ||||
|       body: | ||||
|           _isLoading | ||||
|               ? const Center(child: CircularProgressIndicator()) | ||||
|               : _errorMessage != null | ||||
|               ? Center(child: Text(_errorMessage!)) | ||||
|               : SingleChildScrollView( | ||||
|                 child: Column( | ||||
|                   crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                   children: [ | ||||
|                     const SizedBox(height: 24), | ||||
|                     // App Icon and Name | ||||
|                     CircleAvatar( | ||||
|                       radius: 50, | ||||
|                       backgroundColor: theme.colorScheme.primary.withOpacity( | ||||
|                         0.1, | ||||
|                       ), | ||||
|                       child: Image.asset( | ||||
|                         'assets/icons/icon.png', | ||||
|                         width: 56, | ||||
|                         height: 56, | ||||
|                       ), | ||||
|                     ), | ||||
|                     const SizedBox(height: 16), | ||||
|                     Text( | ||||
|                       _packageInfo.appName, | ||||
|                       style: theme.textTheme.headlineSmall?.copyWith( | ||||
|                         fontWeight: FontWeight.bold, | ||||
|                       ), | ||||
|                     ), | ||||
|                     Text( | ||||
|                       'Version ${_packageInfo.version} (${_packageInfo.buildNumber})', | ||||
|                       style: theme.textTheme.bodyMedium?.copyWith( | ||||
|                         color: theme.textTheme.bodySmall?.color, | ||||
|                       ), | ||||
|                     ), | ||||
|                     const SizedBox(height: 32), | ||||
|  | ||||
|                     // App Info Card | ||||
|                     _buildSection( | ||||
|                       context, | ||||
|                       title: 'App Information', | ||||
|                       children: [ | ||||
|                         _buildInfoItem( | ||||
|                           context, | ||||
|                           icon: Icons.info_outline, | ||||
|                           label: 'Package Name', | ||||
|                           value: _packageInfo.packageName, | ||||
|                         ), | ||||
|                         _buildInfoItem( | ||||
|                           context, | ||||
|                           icon: Icons.update, | ||||
|                           label: 'Version', | ||||
|                           value: _packageInfo.version, | ||||
|                         ), | ||||
|                         _buildInfoItem( | ||||
|                           context, | ||||
|                           icon: Icons.build, | ||||
|                           label: 'Build Number', | ||||
|                           value: _packageInfo.buildNumber, | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|  | ||||
|                     const SizedBox(height: 16), | ||||
|  | ||||
|                     // Links Card | ||||
|                     _buildSection( | ||||
|                       context, | ||||
|                       title: 'Links', | ||||
|                       children: [ | ||||
|                         _buildListTile( | ||||
|                           context, | ||||
|                           icon: Icons.privacy_tip_outlined, | ||||
|                           title: 'Privacy Policy', | ||||
|                           onTap: | ||||
|                               () => _launchURL( | ||||
|                                 'https://solsynth.dev/terms/privacy-policy', | ||||
|                               ), | ||||
|                         ), | ||||
|                         _buildListTile( | ||||
|                           context, | ||||
|                           icon: Icons.description_outlined, | ||||
|                           title: 'Terms of Service', | ||||
|                           onTap: | ||||
|                               () => _launchURL( | ||||
|                                 'https://example.com/terms/basic-law', | ||||
|                               ), | ||||
|                         ), | ||||
|                         _buildListTile( | ||||
|                           context, | ||||
|                           icon: Icons.code, | ||||
|                           title: 'Open Source Licenses', | ||||
|                           onTap: () { | ||||
|                             showLicensePage( | ||||
|                               context: context, | ||||
|                               applicationName: _packageInfo.appName, | ||||
|                               applicationVersion: | ||||
|                                   'Version ${_packageInfo.version}', | ||||
|                             ); | ||||
|                           }, | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|  | ||||
|                     const SizedBox(height: 16), | ||||
|  | ||||
|                     // Developer Info | ||||
|                     _buildSection( | ||||
|                       context, | ||||
|                       title: 'Developer', | ||||
|                       children: [ | ||||
|                         _buildListTile( | ||||
|                           context, | ||||
|                           icon: Icons.email_outlined, | ||||
|                           title: 'Contact Us', | ||||
|                           subtitle: 'lily@solsynth.dev', | ||||
|                           onTap: () => _launchURL('mailto:lily@solsynth.dev'), | ||||
|                         ), | ||||
|                         _buildListTile( | ||||
|                           context, | ||||
|                           icon: Icons.copyright, | ||||
|                           title: 'License', | ||||
|                           subtitle: | ||||
|                               'Copyright reserved © ${DateTime.now().year} Solsynth\nGNU Affero General Public License v3.0', | ||||
|                           onTap: | ||||
|                               () => _launchURL( | ||||
|                                 'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt', | ||||
|                               ), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|  | ||||
|                     const SizedBox(height: 32), | ||||
|  | ||||
|                     // Copyright | ||||
|                     Padding( | ||||
|                       padding: const EdgeInsets.all(16.0), | ||||
|                       child: Text( | ||||
|                         '© ${DateTime.now().year} ${_packageInfo.appName}. All rights reserved.', | ||||
|                         style: theme.textTheme.bodySmall, | ||||
|                         textAlign: TextAlign.center, | ||||
|                       ), | ||||
|                     ), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildSection( | ||||
|     BuildContext context, { | ||||
|     required String title, | ||||
|     required List<Widget> children, | ||||
|   }) { | ||||
|     return Card( | ||||
|       margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), | ||||
|       child: Column( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.fromLTRB(16, 16, 16, 8), | ||||
|             child: Text( | ||||
|               title, | ||||
|               style: Theme.of( | ||||
|                 context, | ||||
|               ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold), | ||||
|             ), | ||||
|           ), | ||||
|           const Divider(height: 1), | ||||
|           ...children, | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildInfoItem( | ||||
|     BuildContext context, { | ||||
|     required IconData icon, | ||||
|     required String label, | ||||
|     required String value, | ||||
|   }) { | ||||
|     return Padding( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), | ||||
|       child: Row( | ||||
|         children: [ | ||||
|           Icon(icon, size: 20, color: Theme.of(context).hintColor), | ||||
|           const SizedBox(width: 16), | ||||
|           Expanded( | ||||
|             child: Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 Text(label, style: Theme.of(context).textTheme.bodySmall), | ||||
|                 const SizedBox(height: 2), | ||||
|                 SelectableText( | ||||
|                   value, | ||||
|                   style: Theme.of(context).textTheme.bodyMedium, | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|           if (value.startsWith('http') || value.contains('@')) | ||||
|             IconButton( | ||||
|               icon: const Icon(Icons.copy, size: 16), | ||||
|               onPressed: () { | ||||
|                 Clipboard.setData(ClipboardData(text: value)); | ||||
|                 ScaffoldMessenger.of(context).showSnackBar( | ||||
|                   const SnackBar(content: Text('Copied to clipboard')), | ||||
|                 ); | ||||
|               }, | ||||
|               padding: EdgeInsets.zero, | ||||
|               constraints: const BoxConstraints(), | ||||
|               tooltip: 'Copy to clipboard', | ||||
|             ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildListTile( | ||||
|     BuildContext context, { | ||||
|     required IconData icon, | ||||
|     required String title, | ||||
|     String? subtitle, | ||||
|     required VoidCallback onTap, | ||||
|   }) { | ||||
|     return Column( | ||||
|       children: [ | ||||
|         ListTile( | ||||
|           leading: Icon(icon), | ||||
|           title: Text(title), | ||||
|           subtitle: subtitle != null ? Text(subtitle) : null, | ||||
|           trailing: const Icon(Icons.chevron_right), | ||||
|           onTap: onTap, | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 16), | ||||
|           minLeadingWidth: 24, | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -281,6 +281,16 @@ class AccountScreen extends HookConsumerWidget { | ||||
|                 }, | ||||
|               ), | ||||
|             const Divider(height: 1).padding(vertical: 8), | ||||
|             ListTile( | ||||
|               minTileHeight: 48, | ||||
|               leading: const Icon(Symbols.info), | ||||
|               trailing: const Icon(Symbols.chevron_right), | ||||
|               contentPadding: EdgeInsets.symmetric(horizontal: 24), | ||||
|               title: Text('about').tr(), | ||||
|               onTap: () { | ||||
|                 context.push('/about'); | ||||
|               }, | ||||
|             ), | ||||
|             ListTile( | ||||
|               minTileHeight: 48, | ||||
|               leading: const Icon(Symbols.logout), | ||||
|   | ||||
							
								
								
									
										105
									
								
								lib/screens/article_detail_screen.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								lib/screens/article_detail_screen.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/widgets/content/markdown.dart'; | ||||
| import 'package:url_launcher/url_launcher_string.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/article_detail.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/loading_indicator.dart'; | ||||
| import 'package:html2md/html2md.dart' as html2md; | ||||
|  | ||||
| class ArticleDetailScreen extends ConsumerWidget { | ||||
|   final String articleId; | ||||
|  | ||||
|   const ArticleDetailScreen({super.key, required this.articleId}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final articleAsync = ref.watch(articleDetailProvider(articleId)); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       body: articleAsync.when( | ||||
|         data: | ||||
|             (article) => AppScaffold( | ||||
|               appBar: AppBar( | ||||
|                 leading: const BackButton(), | ||||
|                 title: Text(article.title), | ||||
|               ), | ||||
|               body: _ArticleDetailContent(article: article), | ||||
|             ), | ||||
|         loading: () => const Center(child: LoadingIndicator()), | ||||
|         error: | ||||
|             (error, stackTrace) => | ||||
|                 Center(child: Text('Failed to load article: $error')), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _ArticleDetailContent extends HookConsumerWidget { | ||||
|   final SnWebArticle article; | ||||
|  | ||||
|   const _ArticleDetailContent({required this.article}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final markdownContent = useMemoized( | ||||
|       () => html2md.convert(article.content ?? ''), | ||||
|       [article], | ||||
|     ); | ||||
|  | ||||
|     return SingleChildScrollView( | ||||
|       child: Column( | ||||
|         crossAxisAlignment: CrossAxisAlignment.stretch, | ||||
|         children: [ | ||||
|           if (article.preview?.imageUrl != null) | ||||
|             Image.network( | ||||
|               article.preview!.imageUrl!, | ||||
|               width: double.infinity, | ||||
|               height: 200, | ||||
|               fit: BoxFit.cover, | ||||
|             ), | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.all(16.0), | ||||
|             child: Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 Text( | ||||
|                   article.title, | ||||
|                   style: Theme.of(context).textTheme.headlineSmall, | ||||
|                 ), | ||||
|                 const SizedBox(height: 8), | ||||
|                 if (article.feed?.title != null) | ||||
|                   Text( | ||||
|                     article.feed!.title, | ||||
|                     style: Theme.of(context).textTheme.bodyMedium?.copyWith( | ||||
|                       color: Theme.of(context).colorScheme.onSurfaceVariant, | ||||
|                     ), | ||||
|                   ), | ||||
|                 const Divider(height: 32), | ||||
|                 if (article.content != null) | ||||
|                   ...MarkdownTextContent.buildGenerator( | ||||
|                     isDark: Theme.of(context).brightness == Brightness.dark, | ||||
|                   ).buildWidgets(markdownContent) | ||||
|                 else if (article.preview?.description != null) | ||||
|                   Text(article.preview!.description!), | ||||
|                 const Gap(24), | ||||
|                 FilledButton( | ||||
|                   onPressed: | ||||
|                       () => launchUrlString( | ||||
|                         article.url, | ||||
|                         mode: LaunchMode.externalApplication, | ||||
|                       ), | ||||
|                   child: const Text('Read Full Article'), | ||||
|                 ), | ||||
|                 Gap(MediaQuery.of(context).padding.bottom), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -40,12 +40,12 @@ class WebFeedEditScreen extends HookConsumerWidget { | ||||
|       isLoading.value = true; | ||||
|  | ||||
|       try { | ||||
|         final feed = WebFeed( | ||||
|         final feed = SnWebFeed( | ||||
|           id: feedId ?? '', | ||||
|           title: titleController.text, | ||||
|           url: urlController.text, | ||||
|           description: descriptionController.text, | ||||
|           config: WebFeedConfig(scrapPage: isScrapEnabled.value), | ||||
|           config: SnWebFeedConfig(scrapPage: isScrapEnabled.value), | ||||
|           publisherId: pubName, | ||||
|           createdAt: DateTime.now(), | ||||
|           updatedAt: DateTime.now(), | ||||
|   | ||||
							
								
								
									
										142
									
								
								lib/screens/discovery/articles.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								lib/screens/discovery/articles.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/web_article_card.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; | ||||
|  | ||||
| part 'articles.g.dart'; | ||||
|  | ||||
| @riverpod | ||||
| class ArticlesListNotifier extends _$ArticlesListNotifier | ||||
|     with CursorPagingNotifierMixin<SnWebArticle> { | ||||
|   static const int _pageSize = 20; | ||||
|  | ||||
|   Map<String, dynamic> _params = {}; | ||||
|  | ||||
|   @override | ||||
|   Future<CursorPagingData<SnWebArticle>> build({ | ||||
|     String? feedId, | ||||
|     String? publisherId, | ||||
|   }) async { | ||||
|     _params = { | ||||
|       if (feedId != null) 'feedId': feedId, | ||||
|       if (publisherId != null) 'publisherId': publisherId, | ||||
|     }; | ||||
|     return fetch(cursor: null); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Future<CursorPagingData<SnWebArticle>> fetch({ | ||||
|     required String? cursor, | ||||
|   }) async { | ||||
|     final client = ref.read(apiClientProvider); | ||||
|     final offset = cursor == null ? 0 : int.parse(cursor); | ||||
|  | ||||
|     final queryParams = {'limit': _pageSize, 'offset': offset, ..._params}; | ||||
|  | ||||
|     try { | ||||
|       final response = await client.get( | ||||
|         '/feeds/articles', | ||||
|         queryParameters: queryParams, | ||||
|       ); | ||||
|  | ||||
|       final List<dynamic> data = response.data; | ||||
|       final articles = | ||||
|           data | ||||
|               .map( | ||||
|                 (json) => SnWebArticle.fromJson(json as Map<String, dynamic>), | ||||
|               ) | ||||
|               .toList(); | ||||
|  | ||||
|       final total = int.tryParse(response.headers.value('X-Total') ?? '0') ?? 0; | ||||
|       final hasMore = offset + articles.length < total; | ||||
|       final nextCursor = hasMore ? (offset + articles.length).toString() : null; | ||||
|  | ||||
|       return CursorPagingData( | ||||
|         items: articles, | ||||
|         hasMore: hasMore, | ||||
|         nextCursor: nextCursor, | ||||
|       ); | ||||
|     } catch (e) { | ||||
|       debugPrint('Error fetching articles: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| class SliverArticlesList extends ConsumerWidget { | ||||
|   final String? feedId; | ||||
|   final String? publisherId; | ||||
|   final Color? backgroundColor; | ||||
|   final EdgeInsets? padding; | ||||
|   final Function? onRefresh; | ||||
|  | ||||
|   const SliverArticlesList({ | ||||
|     super.key, | ||||
|     this.feedId, | ||||
|     this.publisherId, | ||||
|     this.backgroundColor, | ||||
|     this.padding, | ||||
|     this.onRefresh, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     return PagingHelperSliverView( | ||||
|       provider: articlesListNotifierProvider( | ||||
|         feedId: feedId, | ||||
|         publisherId: publisherId, | ||||
|       ), | ||||
|       futureRefreshable: | ||||
|           articlesListNotifierProvider( | ||||
|             feedId: feedId, | ||||
|             publisherId: publisherId, | ||||
|           ).future, | ||||
|       notifierRefreshable: | ||||
|           articlesListNotifierProvider( | ||||
|             feedId: feedId, | ||||
|             publisherId: publisherId, | ||||
|           ).notifier, | ||||
|       contentBuilder: | ||||
|           (data, widgetCount, endItemView) => SliverList.builder( | ||||
|             itemCount: widgetCount, | ||||
|             itemBuilder: (context, index) { | ||||
|               if (index == widgetCount - 1) { | ||||
|                 return endItemView; | ||||
|               } | ||||
|  | ||||
|               final article = data.items[index]; | ||||
|               return WebArticleCard(article: article, showDetails: true); | ||||
|             }, | ||||
|           ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class ArticlesScreen extends ConsumerWidget { | ||||
|   final String? feedId; | ||||
|   final String? publisherId; | ||||
|   final String? title; | ||||
|  | ||||
|   const ArticlesScreen({super.key, this.feedId, this.publisherId, this.title}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     return Scaffold( | ||||
|       appBar: AppBar(title: Text(title ?? 'Articles')), | ||||
|       body: CustomScrollView( | ||||
|         slivers: [ | ||||
|           SliverPadding( | ||||
|             padding: const EdgeInsets.only(top: 8, left: 8, right: 8), | ||||
|             sliver: SliverArticlesList( | ||||
|               feedId: feedId, | ||||
|               publisherId: publisherId, | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										206
									
								
								lib/screens/discovery/articles.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								lib/screens/discovery/articles.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'articles.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // RiverpodGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$articlesListNotifierHash() => | ||||
|     r'924f2344c3bbf0ff7b92fe69e88d3b64a534b538'; | ||||
|  | ||||
| /// 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)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| abstract class _$ArticlesListNotifier | ||||
|     extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnWebArticle>> { | ||||
|   late final String? feedId; | ||||
|   late final String? publisherId; | ||||
|  | ||||
|   FutureOr<CursorPagingData<SnWebArticle>> build({ | ||||
|     String? feedId, | ||||
|     String? publisherId, | ||||
|   }); | ||||
| } | ||||
|  | ||||
| /// See also [ArticlesListNotifier]. | ||||
| @ProviderFor(ArticlesListNotifier) | ||||
| const articlesListNotifierProvider = ArticlesListNotifierFamily(); | ||||
|  | ||||
| /// See also [ArticlesListNotifier]. | ||||
| class ArticlesListNotifierFamily | ||||
|     extends Family<AsyncValue<CursorPagingData<SnWebArticle>>> { | ||||
|   /// See also [ArticlesListNotifier]. | ||||
|   const ArticlesListNotifierFamily(); | ||||
|  | ||||
|   /// See also [ArticlesListNotifier]. | ||||
|   ArticlesListNotifierProvider call({String? feedId, String? publisherId}) { | ||||
|     return ArticlesListNotifierProvider( | ||||
|       feedId: feedId, | ||||
|       publisherId: publisherId, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   ArticlesListNotifierProvider getProviderOverride( | ||||
|     covariant ArticlesListNotifierProvider provider, | ||||
|   ) { | ||||
|     return call(feedId: provider.feedId, publisherId: provider.publisherId); | ||||
|   } | ||||
|  | ||||
|   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'articlesListNotifierProvider'; | ||||
| } | ||||
|  | ||||
| /// See also [ArticlesListNotifier]. | ||||
| class ArticlesListNotifierProvider | ||||
|     extends | ||||
|         AutoDisposeAsyncNotifierProviderImpl< | ||||
|           ArticlesListNotifier, | ||||
|           CursorPagingData<SnWebArticle> | ||||
|         > { | ||||
|   /// See also [ArticlesListNotifier]. | ||||
|   ArticlesListNotifierProvider({String? feedId, String? publisherId}) | ||||
|     : this._internal( | ||||
|         () => | ||||
|             ArticlesListNotifier() | ||||
|               ..feedId = feedId | ||||
|               ..publisherId = publisherId, | ||||
|         from: articlesListNotifierProvider, | ||||
|         name: r'articlesListNotifierProvider', | ||||
|         debugGetCreateSourceHash: | ||||
|             const bool.fromEnvironment('dart.vm.product') | ||||
|                 ? null | ||||
|                 : _$articlesListNotifierHash, | ||||
|         dependencies: ArticlesListNotifierFamily._dependencies, | ||||
|         allTransitiveDependencies: | ||||
|             ArticlesListNotifierFamily._allTransitiveDependencies, | ||||
|         feedId: feedId, | ||||
|         publisherId: publisherId, | ||||
|       ); | ||||
|  | ||||
|   ArticlesListNotifierProvider._internal( | ||||
|     super._createNotifier, { | ||||
|     required super.name, | ||||
|     required super.dependencies, | ||||
|     required super.allTransitiveDependencies, | ||||
|     required super.debugGetCreateSourceHash, | ||||
|     required super.from, | ||||
|     required this.feedId, | ||||
|     required this.publisherId, | ||||
|   }) : super.internal(); | ||||
|  | ||||
|   final String? feedId; | ||||
|   final String? publisherId; | ||||
|  | ||||
|   @override | ||||
|   FutureOr<CursorPagingData<SnWebArticle>> runNotifierBuild( | ||||
|     covariant ArticlesListNotifier notifier, | ||||
|   ) { | ||||
|     return notifier.build(feedId: feedId, publisherId: publisherId); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Override overrideWith(ArticlesListNotifier Function() create) { | ||||
|     return ProviderOverride( | ||||
|       origin: this, | ||||
|       override: ArticlesListNotifierProvider._internal( | ||||
|         () => | ||||
|             create() | ||||
|               ..feedId = feedId | ||||
|               ..publisherId = publisherId, | ||||
|         from: from, | ||||
|         name: null, | ||||
|         dependencies: null, | ||||
|         allTransitiveDependencies: null, | ||||
|         debugGetCreateSourceHash: null, | ||||
|         feedId: feedId, | ||||
|         publisherId: publisherId, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   AutoDisposeAsyncNotifierProviderElement< | ||||
|     ArticlesListNotifier, | ||||
|     CursorPagingData<SnWebArticle> | ||||
|   > | ||||
|   createElement() { | ||||
|     return _ArticlesListNotifierProviderElement(this); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return other is ArticlesListNotifierProvider && | ||||
|         other.feedId == feedId && | ||||
|         other.publisherId == publisherId; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   int get hashCode { | ||||
|     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||
|     hash = _SystemHash.combine(hash, feedId.hashCode); | ||||
|     hash = _SystemHash.combine(hash, publisherId.hashCode); | ||||
|  | ||||
|     return _SystemHash.finish(hash); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||
| // ignore: unused_element | ||||
| mixin ArticlesListNotifierRef | ||||
|     on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnWebArticle>> { | ||||
|   /// The parameter `feedId` of this provider. | ||||
|   String? get feedId; | ||||
|  | ||||
|   /// The parameter `publisherId` of this provider. | ||||
|   String? get publisherId; | ||||
| } | ||||
|  | ||||
| class _ArticlesListNotifierProviderElement | ||||
|     extends | ||||
|         AutoDisposeAsyncNotifierProviderElement< | ||||
|           ArticlesListNotifier, | ||||
|           CursorPagingData<SnWebArticle> | ||||
|         > | ||||
|     with ArticlesListNotifierRef { | ||||
|   _ArticlesListNotifierProviderElement(super.provider); | ||||
|  | ||||
|   @override | ||||
|   String? get feedId => (origin as ArticlesListNotifierProvider).feedId; | ||||
|   @override | ||||
|   String? get publisherId => | ||||
|       (origin as ArticlesListNotifierProvider).publisherId; | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| @@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/activity.dart'; | ||||
| import 'package:island/models/publisher.dart'; | ||||
| import 'package:island/models/realm.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/userinfo.dart'; | ||||
| import 'package:island/services/responsive.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| @@ -21,6 +22,7 @@ import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/realm/realm_card.dart'; | ||||
| import 'package:island/widgets/publisher/publisher_card.dart'; | ||||
| import 'package:island/widgets/web_article_card.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| part 'explore.g.dart'; | ||||
| @@ -91,32 +93,39 @@ class ExploreScreen extends HookConsumerWidget { | ||||
|       extendBody: false, // Prevent conflicts with tabs navigation | ||||
|       appBar: AppBar( | ||||
|         toolbarHeight: 0, | ||||
|         bottom: TabBar( | ||||
|         bottom: PreferredSize( | ||||
|           preferredSize: const Size.fromHeight(48), | ||||
|           child: Row( | ||||
|             children: [ | ||||
|               Expanded( | ||||
|                 child: TabBar( | ||||
|                   controller: tabController, | ||||
|                   tabAlignment: TabAlignment.start, | ||||
|                   isScrollable: true, | ||||
|                   tabs: [ | ||||
|                     Tab( | ||||
|               child: Text( | ||||
|                 'explore'.tr(), | ||||
|                 textAlign: TextAlign.center, | ||||
|                 style: TextStyle( | ||||
|                       icon: Tooltip( | ||||
|                         message: 'explore'.tr(), | ||||
|                         child: Icon( | ||||
|                           Symbols.explore, | ||||
|                           color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                     Tab( | ||||
|               child: Text( | ||||
|                 'exploreFilterSubscriptions'.tr(), | ||||
|                 textAlign: TextAlign.center, | ||||
|                 style: TextStyle( | ||||
|                       icon: Tooltip( | ||||
|                         message: 'exploreFilterSubscriptions'.tr(), | ||||
|                         child: Icon( | ||||
|                           Symbols.subscriptions, | ||||
|                           color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                     Tab( | ||||
|               child: Text( | ||||
|                 'exploreFilterFriends'.tr(), | ||||
|                 textAlign: TextAlign.center, | ||||
|                 style: TextStyle( | ||||
|                       icon: Tooltip( | ||||
|                         message: 'exploreFilterFriends'.tr(), | ||||
|                         child: Icon( | ||||
|                           Symbols.people, | ||||
|                           color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                         ), | ||||
|                       ), | ||||
| @@ -124,6 +133,31 @@ class ExploreScreen extends HookConsumerWidget { | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|               Spacer(), | ||||
|               IconButton( | ||||
|                 onPressed: () { | ||||
|                   context.push('/feeds/articles'); | ||||
|                 }, | ||||
|                 icon: Icon( | ||||
|                   Symbols.auto_stories, | ||||
|                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                 ), | ||||
|                 tooltip: 'webArticlesStand'.tr(), | ||||
|               ), | ||||
|               IconButton( | ||||
|                 onPressed: () { | ||||
|                   context.push('/posts/search'); | ||||
|                 }, | ||||
|                 icon: Icon( | ||||
|                   Symbols.search, | ||||
|                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                 ), | ||||
|                 tooltip: 'search'.tr(), | ||||
|               ), | ||||
|             ], | ||||
|           ).padding(horizontal: 8), | ||||
|         ), | ||||
|       ), | ||||
|       floatingActionButton: FloatingActionButton( | ||||
|         heroTag: Key("explore-page-fab"), | ||||
|         onPressed: () { | ||||
| @@ -196,6 +230,7 @@ class _DiscoveryActivityItem extends StatelessWidget { | ||||
|               (switch (type) { | ||||
|                 'realm' => 'discoverRealms', | ||||
|                 'publisher' => 'discoverPublishers', | ||||
|                 'article' => 'discoverWebArticles', | ||||
|                 _ => 'unknown', | ||||
|               }).tr(), | ||||
|               style: Theme.of(context).textTheme.titleMedium, | ||||
| @@ -221,6 +256,11 @@ class _DiscoveryActivityItem extends StatelessWidget { | ||||
|                     publisher: SnPublisher.fromJson(item['data']), | ||||
|                     maxWidth: 280, | ||||
|                   ); | ||||
|                 case 'article': | ||||
|                   return WebArticleCard( | ||||
|                     article: SnWebArticle.fromJson(item['data']), | ||||
|                     maxWidth: 280, | ||||
|                   ); | ||||
|                 default: | ||||
|                   return Placeholder(); | ||||
|               } | ||||
| @@ -342,7 +382,7 @@ class ActivityListNotifier extends _$ActivityListNotifier | ||||
|       if (cursor != null) 'cursor': cursor, | ||||
|       'take': take, | ||||
|       if (filter != null) 'filter': filter, | ||||
|       if (kDebugMode) 'debugInclude': 'realms,publishers', | ||||
|       if (kDebugMode) 'debugInclude': 'realms,publishers,articles', | ||||
|     }; | ||||
|  | ||||
|     final response = await client.get( | ||||
|   | ||||
| @@ -7,7 +7,7 @@ part of 'explore.dart'; | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$activityListNotifierHash() => | ||||
|     r'57e9dcec944a9f88f8508b69fc91342592f5b349'; | ||||
|     r'98b62fb9b958023d2c9e320af7ec1f1244836f49'; | ||||
|  | ||||
| /// Copied from Dart SDK | ||||
| class _SystemHash { | ||||
|   | ||||
							
								
								
									
										165
									
								
								lib/screens/posts/post_search.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								lib/screens/posts/post_search.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| import 'dart:async'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/post.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/post/post_item.dart'; | ||||
| import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; | ||||
|  | ||||
| final postSearchNotifierProvider = StateNotifierProvider.autoDispose< | ||||
|   PostSearchNotifier, | ||||
|   AsyncValue<CursorPagingData<SnPost>> | ||||
| >((ref) => PostSearchNotifier(ref)); | ||||
|  | ||||
| class PostSearchNotifier | ||||
|     extends StateNotifier<AsyncValue<CursorPagingData<SnPost>>> { | ||||
|   final AutoDisposeRef ref; | ||||
|   static const int _pageSize = 20; | ||||
|   String _currentQuery = ''; | ||||
|   bool _isLoading = false; | ||||
|  | ||||
|   PostSearchNotifier(this.ref) : super(const AsyncValue.loading()) { | ||||
|     state = const AsyncValue.data( | ||||
|       CursorPagingData(items: [], hasMore: false, nextCursor: null), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Future<void> search(String query) async { | ||||
|     if (_isLoading) return; | ||||
|  | ||||
|     _currentQuery = query.trim(); | ||||
|     if (_currentQuery.isEmpty) { | ||||
|       state = AsyncValue.data( | ||||
|         CursorPagingData(items: [], hasMore: false, nextCursor: null), | ||||
|       ); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     await fetch(cursor: null); | ||||
|   } | ||||
|  | ||||
|   Future<void> fetch({String? cursor}) async { | ||||
|     if (_isLoading) return; | ||||
|  | ||||
|     _isLoading = true; | ||||
|     state = const AsyncValue.loading(); | ||||
|  | ||||
|     try { | ||||
|       final client = ref.read(apiClientProvider); | ||||
|       final offset = cursor == null ? 0 : int.parse(cursor); | ||||
|  | ||||
|       final response = await client.get( | ||||
|         '/posts/search', | ||||
|         queryParameters: { | ||||
|           'query': _currentQuery, | ||||
|           'offset': offset, | ||||
|           'take': _pageSize, | ||||
|           'useVector': true, | ||||
|         }, | ||||
|       ); | ||||
|  | ||||
|       final data = response.data as List; | ||||
|       final posts = data.map((json) => SnPost.fromJson(json)).toList(); | ||||
|       final hasMore = posts.length == _pageSize; | ||||
|       final nextCursor = hasMore ? (offset + posts.length).toString() : null; | ||||
|  | ||||
|       state = AsyncValue.data( | ||||
|         CursorPagingData( | ||||
|           items: posts, | ||||
|           hasMore: hasMore, | ||||
|           nextCursor: nextCursor, | ||||
|         ), | ||||
|       ); | ||||
|     } catch (e, stack) { | ||||
|       state = AsyncValue.error(e, stack); | ||||
|     } finally { | ||||
|       _isLoading = false; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| class PostSearchScreen extends ConsumerStatefulWidget { | ||||
|   const PostSearchScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   ConsumerState<PostSearchScreen> createState() => _PostSearchScreenState(); | ||||
| } | ||||
|  | ||||
| class _PostSearchScreenState extends ConsumerState<PostSearchScreen> { | ||||
|   final _searchController = TextEditingController(); | ||||
|   final _debounce = Duration(milliseconds: 500); | ||||
|   Timer? _debounceTimer; | ||||
|  | ||||
|   @override | ||||
|   void dispose() { | ||||
|     _searchController.dispose(); | ||||
|     _debounceTimer?.cancel(); | ||||
|     super.dispose(); | ||||
|   } | ||||
|  | ||||
|   void _onSearchChanged(String query) { | ||||
|     if (_debounceTimer?.isActive ?? false) _debounceTimer!.cancel(); | ||||
|  | ||||
|     _debounceTimer = Timer(_debounce, () { | ||||
|       ref.read(postSearchNotifierProvider.notifier).search(query); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       appBar: AppBar( | ||||
|         title: TextField( | ||||
|           controller: _searchController, | ||||
|           decoration: InputDecoration( | ||||
|             hintText: 'Search posts...', | ||||
|             border: InputBorder.none, | ||||
|             hintStyle: TextStyle( | ||||
|               color: Theme.of(context).appBarTheme.foregroundColor, | ||||
|             ), | ||||
|           ), | ||||
|           style: TextStyle( | ||||
|             color: Theme.of(context).appBarTheme.foregroundColor, | ||||
|           ), | ||||
|           onChanged: _onSearchChanged, | ||||
|           onSubmitted: (value) { | ||||
|             ref.read(postSearchNotifierProvider.notifier).search(value); | ||||
|           }, | ||||
|           autofocus: true, | ||||
|         ), | ||||
|       ), | ||||
|       body: Consumer( | ||||
|         builder: (context, ref, child) { | ||||
|           final searchState = ref.watch(postSearchNotifierProvider); | ||||
|  | ||||
|           return searchState.when( | ||||
|             data: (data) { | ||||
|               if (data.items.isEmpty && _searchController.text.isNotEmpty) { | ||||
|                 return const Center(child: Text('No results found')); | ||||
|               } | ||||
|  | ||||
|               return ListView.builder( | ||||
|                 itemCount: data.items.length + (data.hasMore ? 1 : 0), | ||||
|                 itemBuilder: (context, index) { | ||||
|                   if (index >= data.items.length) { | ||||
|                     ref | ||||
|                         .read(postSearchNotifierProvider.notifier) | ||||
|                         .fetch(cursor: data.nextCursor); | ||||
|                     return const Center(child: CircularProgressIndicator()); | ||||
|                   } | ||||
|  | ||||
|                   final post = data.items[index]; | ||||
|                   return Column( | ||||
|                     children: [PostItem(item: post), const Divider(height: 1)], | ||||
|                   ); | ||||
|                 }, | ||||
|               ); | ||||
|             }, | ||||
|             loading: () => const Center(child: CircularProgressIndicator()), | ||||
|             error: (error, stack) => Center(child: Text('Error: $error')), | ||||
|           ); | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								lib/widgets/article/article_list.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								lib/widgets/article/article_list.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
|  | ||||
| @@ -1,4 +1,3 @@ | ||||
| import 'dart:convert'; | ||||
| import 'dart:math' as math; | ||||
| import 'dart:ui'; | ||||
|  | ||||
| @@ -212,28 +211,117 @@ class CloudFileZoomIn extends HookConsumerWidget { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     Widget buildInfoRow(IconData icon, String label, String value) { | ||||
|       return Padding( | ||||
|         padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24), | ||||
|         child: Row( | ||||
|           children: [ | ||||
|             Icon( | ||||
|               icon, | ||||
|               size: 20, | ||||
|               color: Theme.of(context).colorScheme.onSurface, | ||||
|             ), | ||||
|             const SizedBox(width: 12), | ||||
|             Text( | ||||
|               label, | ||||
|               style: Theme.of(context).textTheme.bodyMedium?.copyWith( | ||||
|                 color: Theme.of(context).textTheme.bodySmall?.color, | ||||
|               ), | ||||
|             ), | ||||
|             const Spacer(), | ||||
|             Flexible( | ||||
|               child: Text( | ||||
|                 value, | ||||
|                 style: Theme.of( | ||||
|                   context, | ||||
|                 ).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500), | ||||
|                 textAlign: TextAlign.end, | ||||
|                 overflow: TextOverflow.ellipsis, | ||||
|               ), | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     String _formatFileSize(int bytes) { | ||||
|       if (bytes <= 0) return '0 B'; | ||||
|       if (bytes < 1024) return '$bytes B'; | ||||
|       if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB'; | ||||
|       if (bytes < 1024 * 1024 * 1024) { | ||||
|         return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB'; | ||||
|       } | ||||
|       return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB'; | ||||
|     } | ||||
|  | ||||
|     void showInfoSheet() { | ||||
|       final exifData = item.fileMeta?['exif'] ?? {}; | ||||
|       final theme = Theme.of(context); | ||||
|       final exifData = item.fileMeta?['exif'] as Map<String, dynamic>? ?? {}; | ||||
|  | ||||
|       showModalBottomSheet( | ||||
|         useRootNavigator: true, | ||||
|         context: context, | ||||
|         isScrollControlled: true, | ||||
|         builder: | ||||
|             (context) => SheetScaffold( | ||||
|               titleText: 'File Info', | ||||
|               titleText: 'File Information', | ||||
|               child: SingleChildScrollView( | ||||
|                 child: Column( | ||||
|                   crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                   children: [ | ||||
|                     Text('Name: ${item.name}'), | ||||
|                     Text('Size: ${item.size} bytes'), | ||||
|                     Text('Type: ${item.mimeType ?? 'Unknown'}'), | ||||
|                     buildInfoRow(Icons.description, 'Name', item.name), | ||||
|                     const Divider(height: 1), | ||||
|                     buildInfoRow( | ||||
|                       Icons.storage, | ||||
|                       'Size', | ||||
|                       _formatFileSize(item.size), | ||||
|                     ), | ||||
|                     const Divider(height: 1), | ||||
|                     buildInfoRow( | ||||
|                       Icons.category, | ||||
|                       'Type', | ||||
|                       item.mimeType?.toUpperCase() ?? 'UNKNOWN', | ||||
|                     ), | ||||
|                     if (exifData.isNotEmpty) ...[ | ||||
|                       const Gap(16), | ||||
|                       Text('EXIF Data:'), | ||||
|                       const Gap(8), | ||||
|                       for (var entry in exifData.entries) | ||||
|                         Text('${entry.key}: ${entry.value}'), | ||||
|                       const SizedBox(height: 16), | ||||
|                       Text( | ||||
|                         'EXIF Data', | ||||
|                         style: theme.textTheme.titleMedium?.copyWith( | ||||
|                           fontWeight: FontWeight.bold, | ||||
|                         ), | ||||
|                       ).padding(horizontal: 24), | ||||
|                       const SizedBox(height: 8), | ||||
|                       Column( | ||||
|                         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                         children: [ | ||||
|                           ...exifData.entries.map( | ||||
|                             (entry) => Padding( | ||||
|                               padding: const EdgeInsets.symmetric(vertical: 4), | ||||
|                               child: Row( | ||||
|                                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                                 children: [ | ||||
|                                   Text( | ||||
|                                     '• ${entry.key.contains('-') ? entry.key.split('-').last : entry.key}: ', | ||||
|                                     style: theme.textTheme.bodyMedium?.copyWith( | ||||
|                                       fontWeight: FontWeight.w500, | ||||
|                                     ), | ||||
|                                   ), | ||||
|                                   Expanded( | ||||
|                                     child: Text( | ||||
|                                       '${entry.value}'.isNotEmpty | ||||
|                                           ? '${entry.value}' | ||||
|                                           : 'N/A', | ||||
|                                       style: theme.textTheme.bodyMedium, | ||||
|                                     ), | ||||
|                                   ), | ||||
|                                 ], | ||||
|                               ), | ||||
|                             ), | ||||
|                           ), | ||||
|                         ], | ||||
|                       ).padding(horizontal: 24), | ||||
|                     ], | ||||
|                     const SizedBox(height: 16), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|   | ||||
| @@ -74,9 +74,7 @@ class MarkdownTextContent extends HookConsumerWidget { | ||||
|               final url = Uri.tryParse(href); | ||||
|               if (url != null) { | ||||
|                 if (url.scheme == 'solian') { | ||||
|                   context.push( | ||||
|                     ['', url.host, ...url.pathSegments].join('/'), | ||||
|                   ); | ||||
|                   context.push(['', url.host, ...url.pathSegments].join('/')); | ||||
|                   return; | ||||
|                 } | ||||
|                 final whitelistDomains = ['solian.app', 'solsynth.dev']; | ||||
| @@ -143,7 +141,18 @@ class MarkdownTextContent extends HookConsumerWidget { | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|       generator: MarkdownGenerator( | ||||
|       generator: MarkdownTextContent.buildGenerator( | ||||
|         isDark: isDark, | ||||
|         linesMargin: linesMargin, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   static MarkdownGenerator buildGenerator({ | ||||
|     bool isDark = false, | ||||
|     EdgeInsets? linesMargin, | ||||
|   }) { | ||||
|     return MarkdownGenerator( | ||||
|       generators: [latexGenerator], | ||||
|       inlineSyntaxList: [ | ||||
|         _UserNameCardInlineSyntax(), | ||||
| @@ -151,7 +160,6 @@ class MarkdownTextContent extends HookConsumerWidget { | ||||
|         LatexSyntax(isDark), | ||||
|       ], | ||||
|       linesMargin: linesMargin ?? EdgeInsets.symmetric(vertical: 4), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										33
									
								
								lib/widgets/loading_indicator.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								lib/widgets/loading_indicator.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| /// A simple loading indicator widget that can be used throughout the app | ||||
| class LoadingIndicator extends StatelessWidget { | ||||
|   /// The size of the loading indicator | ||||
|   final double size; | ||||
|  | ||||
|   /// The color of the loading indicator | ||||
|   final Color? color; | ||||
|  | ||||
|   /// Creates a loading indicator | ||||
|   const LoadingIndicator({ | ||||
|     super.key, | ||||
|     this.size = 24.0, | ||||
|     this.color, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return SizedBox( | ||||
|       width: size, | ||||
|       height: size, | ||||
|       child: CircularProgressIndicator( | ||||
|         strokeWidth: 2.0, | ||||
|         valueColor: color != null | ||||
|             ? AlwaysStoppedAnimation<Color>( | ||||
|                 color!, | ||||
|               ) | ||||
|             : null, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										139
									
								
								lib/widgets/web_article_card.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								lib/widgets/web_article_card.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| import 'package:cached_network_image/cached_network_image.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/services/time.dart'; | ||||
|  | ||||
| class WebArticleCard extends StatelessWidget { | ||||
|   final SnWebArticle article; | ||||
|   final double? maxWidth; | ||||
|   final bool showDetails; | ||||
|  | ||||
|   const WebArticleCard({ | ||||
|     super.key, | ||||
|     required this.article, | ||||
|     this.maxWidth, | ||||
|     this.showDetails = false, | ||||
|   }); | ||||
|  | ||||
|   void _onTap(BuildContext context) { | ||||
|     context.push('/feeds/articles/${article.id}'); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final theme = Theme.of(context); | ||||
|     final colorScheme = theme.colorScheme; | ||||
|  | ||||
|     return ConstrainedBox( | ||||
|       constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity), | ||||
|       child: Card( | ||||
|         clipBehavior: Clip.antiAlias, | ||||
|         child: InkWell( | ||||
|           onTap: () => _onTap(context), | ||||
|           child: AspectRatio( | ||||
|             aspectRatio: 16 / 9, | ||||
|             child: Stack( | ||||
|               fit: StackFit.expand, | ||||
|               children: [ | ||||
|                 // Image or fallback | ||||
|                 article.preview?.imageUrl != null | ||||
|                     ? CachedNetworkImage( | ||||
|                       imageUrl: article.preview!.imageUrl!, | ||||
|                       fit: BoxFit.cover, | ||||
|                       width: double.infinity, | ||||
|                       height: double.infinity, | ||||
|                     ) | ||||
|                     : ColoredBox( | ||||
|                       color: colorScheme.secondaryContainer, | ||||
|                       child: const Center( | ||||
|                         child: Icon( | ||||
|                           Icons.article_outlined, | ||||
|                           size: 48, | ||||
|                           color: Colors.white, | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                 // Gradient overlay | ||||
|                 Container( | ||||
|                   decoration: BoxDecoration( | ||||
|                     gradient: LinearGradient( | ||||
|                       begin: Alignment.topCenter, | ||||
|                       end: Alignment.bottomCenter, | ||||
|                       colors: [ | ||||
|                         Colors.transparent, | ||||
|                         Colors.black.withOpacity(0.7), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|                 // Title | ||||
|                 Align( | ||||
|                   alignment: Alignment.bottomLeft, | ||||
|                   child: Container( | ||||
|                     padding: const EdgeInsets.only( | ||||
|                       left: 12, | ||||
|                       right: 12, | ||||
|                       bottom: 8, | ||||
|                     ), | ||||
|                     child: Column( | ||||
|                       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                       mainAxisAlignment: MainAxisAlignment.end, | ||||
|                       mainAxisSize: MainAxisSize.min, | ||||
|                       children: [ | ||||
|                         if (showDetails) | ||||
|                           const SizedBox(height: 8) | ||||
|                         else | ||||
|                           Spacer(), | ||||
|                         Text( | ||||
|                           article.title, | ||||
|                           style: theme.textTheme.titleSmall?.copyWith( | ||||
|                             color: Colors.white, | ||||
|                             fontWeight: FontWeight.bold, | ||||
|                             height: 1.3, | ||||
|                           ), | ||||
|                           maxLines: showDetails ? 3 : 2, | ||||
|                           overflow: TextOverflow.ellipsis, | ||||
|                         ), | ||||
|                         if (showDetails && | ||||
|                             article.author?.isNotEmpty == true) ...[ | ||||
|                           const SizedBox(height: 4), | ||||
|                           Text( | ||||
|                             article.author!, | ||||
|                             style: TextStyle( | ||||
|                               fontSize: 10, | ||||
|                               color: Colors.white.withOpacity(0.9), | ||||
|                               fontWeight: FontWeight.w500, | ||||
|                             ), | ||||
|                           ), | ||||
|                         ], | ||||
|                         if (showDetails) const Spacer(), | ||||
|                         if (showDetails && article.publishedAt != null) ...[ | ||||
|                           Text( | ||||
|                             '${article.publishedAt!.formatSystem()} · ${article.publishedAt!.formatRelative(context)}', | ||||
|                             style: const TextStyle( | ||||
|                               fontSize: 9, | ||||
|                               color: Colors.white70, | ||||
|                             ), | ||||
|                           ), | ||||
|                           const SizedBox(height: 2), | ||||
|                         ], | ||||
|                         Text( | ||||
|                           article.feed?.title ?? 'Unknown Source', | ||||
|                           style: const TextStyle( | ||||
|                             fontSize: 9, | ||||
|                             color: Colors.white70, | ||||
|                           ), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -11,32 +11,32 @@ PODS: | ||||
|     - FlutterMacOS | ||||
|   - file_selector_macos (0.0.1): | ||||
|     - FlutterMacOS | ||||
|   - Firebase/CoreOnly (11.13.0): | ||||
|     - FirebaseCore (~> 11.13.0) | ||||
|   - Firebase/Messaging (11.13.0): | ||||
|   - Firebase/CoreOnly (11.15.0): | ||||
|     - FirebaseCore (~> 11.15.0) | ||||
|   - Firebase/Messaging (11.15.0): | ||||
|     - Firebase/CoreOnly | ||||
|     - FirebaseMessaging (~> 11.13.0) | ||||
|   - firebase_core (3.14.0): | ||||
|     - Firebase/CoreOnly (~> 11.13.0) | ||||
|     - FirebaseMessaging (~> 11.15.0) | ||||
|   - firebase_core (3.15.0): | ||||
|     - Firebase/CoreOnly (~> 11.15.0) | ||||
|     - FlutterMacOS | ||||
|   - firebase_messaging (15.2.7): | ||||
|     - Firebase/CoreOnly (~> 11.13.0) | ||||
|     - Firebase/Messaging (~> 11.13.0) | ||||
|   - firebase_messaging (15.2.8): | ||||
|     - Firebase/CoreOnly (~> 11.15.0) | ||||
|     - Firebase/Messaging (~> 11.15.0) | ||||
|     - firebase_core | ||||
|     - FlutterMacOS | ||||
|   - FirebaseCore (11.13.0): | ||||
|     - FirebaseCoreInternal (~> 11.13.0) | ||||
|   - FirebaseCore (11.15.0): | ||||
|     - FirebaseCoreInternal (~> 11.15.0) | ||||
|     - GoogleUtilities/Environment (~> 8.1) | ||||
|     - GoogleUtilities/Logger (~> 8.1) | ||||
|   - FirebaseCoreInternal (11.13.0): | ||||
|   - FirebaseCoreInternal (11.15.0): | ||||
|     - "GoogleUtilities/NSData+zlib (~> 8.1)" | ||||
|   - FirebaseInstallations (11.13.0): | ||||
|     - FirebaseCore (~> 11.13.0) | ||||
|   - FirebaseInstallations (11.15.0): | ||||
|     - FirebaseCore (~> 11.15.0) | ||||
|     - GoogleUtilities/Environment (~> 8.1) | ||||
|     - GoogleUtilities/UserDefaults (~> 8.1) | ||||
|     - PromisesObjC (~> 2.4) | ||||
|   - FirebaseMessaging (11.13.0): | ||||
|     - FirebaseCore (~> 11.13.0) | ||||
|   - FirebaseMessaging (11.15.0): | ||||
|     - FirebaseCore (~> 11.15.0) | ||||
|     - FirebaseInstallations (~> 11.0) | ||||
|     - GoogleDataTransport (~> 10.0) | ||||
|     - GoogleUtilities/AppDelegateSwizzler (~> 8.1) | ||||
| @@ -92,7 +92,7 @@ PODS: | ||||
|     - GoogleUtilities/Privacy | ||||
|   - irondash_engine_context (0.0.1): | ||||
|     - FlutterMacOS | ||||
|   - livekit_client (2.4.8): | ||||
|   - livekit_client (2.4.9): | ||||
|     - flutter_webrtc | ||||
|     - FlutterMacOS | ||||
|     - WebRTC-SDK (= 125.6422.07) | ||||
| @@ -291,13 +291,13 @@ SPEC CHECKSUMS: | ||||
|   device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76 | ||||
|   file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a | ||||
|   file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31 | ||||
|   Firebase: 3435bc66b4d494c2f22c79fd3aae4c1db6662327 | ||||
|   firebase_core: 1095fcf33161d99bc34aa10f7c0d89414a208d15 | ||||
|   firebase_messaging: 6417056ffb85141607618ddfef9fec9f3caab3ea | ||||
|   FirebaseCore: c692c7f1c75305ab6aff2b367f25e11d73aa8bd0 | ||||
|   FirebaseCoreInternal: 29d7b3af4aaf0b8f3ed20b568c13df399b06f68c | ||||
|   FirebaseInstallations: 0ee9074f2c1e86561ace168ee1470dc67aabaf02 | ||||
|   FirebaseMessaging: 195bbdb73e6ca1dbc76cd46e73f3552c084ef6e4 | ||||
|   Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e | ||||
|   firebase_core: 177f51be1650b15d2d5b9f1abf48792619288070 | ||||
|   firebase_messaging: 8748a5d4bb435993cffa7f5501292f3e914a23d7 | ||||
|   FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e | ||||
|   FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 | ||||
|   FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 | ||||
|   FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 | ||||
|   flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d | ||||
|   flutter_platform_alert: 8fa7a7c21f95b26d08b4a3891936ca27e375f284 | ||||
|   flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54 | ||||
| @@ -309,7 +309,7 @@ SPEC CHECKSUMS: | ||||
|   GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 | ||||
|   GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 | ||||
|   irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba | ||||
|   livekit_client: 6a35243df3da61750c98e266e02dedcf5d25c888 | ||||
|   livekit_client: c9d9f41996f5cf22b9ba0e8483e6af4ca5094059 | ||||
|   local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 | ||||
|   media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65 | ||||
|   media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758 | ||||
|   | ||||
							
								
								
									
										140
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -13,10 +13,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: _flutterfire_internals | ||||
|       sha256: dda4fd7909a732a014239009aa52537b136f8ce568de23c212587097887e2307 | ||||
|       sha256: "50e24b769bd1e725732f0aff18b806b8731c1fbcf4e8018ab98e7c4805a2a52f" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.3.56" | ||||
|     version: "1.3.57" | ||||
|   analyzer: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -629,50 +629,50 @@ packages: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: firebase_core | ||||
|       sha256: "420d9111dcf095341f1ea8fdce926eef750cf7b9745d21f38000de780c94f608" | ||||
|       sha256: "5bba5924139e91d26446fd2601c18a6aa62c1161c768a989bb5e245dcdc20644" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.14.0" | ||||
|     version: "3.15.0" | ||||
|   firebase_core_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_core_platform_interface | ||||
|       sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf | ||||
|       sha256: "5d2ab45779d91af2aa0252dec9fe4ee1caa015d83377de255454dcaa1526a0e0" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "5.4.0" | ||||
|     version: "5.4.1" | ||||
|   firebase_core_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_core_web | ||||
|       sha256: ddd72baa6f727e5b23f32d9af23d7d453d67946f380bd9c21daf474ee0f7326e | ||||
|       sha256: eb3afccfc452b2b2075acbe0c4b27de62dd596802b4e5e19869c1e926cbb20b3 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.23.0" | ||||
|     version: "2.24.0" | ||||
|   firebase_messaging: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: firebase_messaging | ||||
|       sha256: "758461f67b96aa5ad27625aaae39882fd6d1961b1c7e005301f9a74b6336100b" | ||||
|       sha256: c6711cf2f455532b84a94022c7aaf85088849763af2f01b775ca79d82d10a01a | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "15.2.7" | ||||
|     version: "15.2.8" | ||||
|   firebase_messaging_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_messaging_platform_interface | ||||
|       sha256: "614db1b0df0f53e541e41cc182b6d7ede5763c400f6ba232a5f8d0e1b5e5de32" | ||||
|       sha256: "1c9dacccb1aee1bf17ba519dda5563a16fdd2ec1e79b5f2e421cb4bf75a166f7" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.6.7" | ||||
|     version: "4.6.8" | ||||
|   firebase_messaging_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_messaging_web | ||||
|       sha256: b5fbbcdd3e0e7f3fde72b0c119410f22737638fed5fc428b54bba06bc1455d81 | ||||
|       sha256: "54317c26fa92f0d90a2017977ac791cb0504eca29fcf397f06adf727d4a7a2d5" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.10.7" | ||||
|     version: "3.10.8" | ||||
|   fixnum: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -798,6 +798,54 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.6.0" | ||||
|   flutter_keyboard_visibility: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_keyboard_visibility | ||||
|       sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "6.0.0" | ||||
|   flutter_keyboard_visibility_linux: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_keyboard_visibility_linux | ||||
|       sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.0.0" | ||||
|   flutter_keyboard_visibility_macos: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_keyboard_visibility_macos | ||||
|       sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.0.0" | ||||
|   flutter_keyboard_visibility_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_keyboard_visibility_platform_interface | ||||
|       sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.0.0" | ||||
|   flutter_keyboard_visibility_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_keyboard_visibility_web | ||||
|       sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.0.0" | ||||
|   flutter_keyboard_visibility_windows: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_keyboard_visibility_windows | ||||
|       sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.0.0" | ||||
|   flutter_launcher_icons: | ||||
|     dependency: "direct dev" | ||||
|     description: | ||||
| @@ -960,6 +1008,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.1.1" | ||||
|   flutter_typeahead: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: flutter_typeahead | ||||
|       sha256: d64712c65db240b1057559b952398ebb6e498077baeebf9b0731dade62438a6d | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "5.2.0" | ||||
|   flutter_udid: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -977,10 +1033,10 @@ packages: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: flutter_webrtc | ||||
|       sha256: dd47ca103b5b6217771e6277882674276d9621bbf9eb23da3c03898b507844e3 | ||||
|       sha256: "792aa1e5838a719f29ae52c0773dbb5dd781fc33b1bf87c321b274e55ab51ad1" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.14.1" | ||||
|     version: "0.14.2" | ||||
|   font_awesome_flutter: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1093,6 +1149,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.15.6" | ||||
|   html2md: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: html2md | ||||
|       sha256: "465cf8ffa1b510fe0e97941579bf5b22e2d575f2cecb500a9c0254efe33a8036" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.3.2" | ||||
|   http: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1297,10 +1361,10 @@ packages: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: livekit_client | ||||
|       sha256: c270720a49b935591960c6f3296fd8f00c09b45a70cd64aef78cd0a8f8257913 | ||||
|       sha256: "5d182f40cc9aafce60a9acf936bad8bc69010b5cbf0a949f6f27dc4390f2fcce" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.8" | ||||
|     version: "2.4.9" | ||||
|   local_auth: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -1677,6 +1741,38 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.1.8" | ||||
|   pointer_interceptor: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: pointer_interceptor | ||||
|       sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.10.1+2" | ||||
|   pointer_interceptor_ios: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: pointer_interceptor_ios | ||||
|       sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.10.1" | ||||
|   pointer_interceptor_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: pointer_interceptor_platform_interface | ||||
|       sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.10.0+1" | ||||
|   pointer_interceptor_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: pointer_interceptor_web | ||||
|       sha256: "460b600e71de6fcea2b3d5f662c92293c049c4319e27f0829310e5a953b3ee2a" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.10.3" | ||||
|   pool: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1689,10 +1785,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: posix | ||||
|       sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62 | ||||
|       sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "6.0.2" | ||||
|     version: "6.0.3" | ||||
|   protobuf: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1809,10 +1905,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: record_web | ||||
|       sha256: "024c81eb7f51468b1833a3eca8b461c7ca25c04899dba37abe580bb57afd32e4" | ||||
|       sha256: a12856d0b3dd03d336b4b10d7520a8b3e21649a06a8f95815318feaa8f07adbb | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.1.8" | ||||
|     version: "1.1.9" | ||||
|   record_windows: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev | ||||
| # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||||
| # In Windows, build-name is used as the major, minor, and patch parts | ||||
| # of the product and file versions while build-number is used as the build suffix. | ||||
| version: 3.0.0+109 | ||||
| version: 3.0.0+110 | ||||
|  | ||||
| environment: | ||||
|   sdk: ^3.7.2 | ||||
| @@ -37,7 +37,7 @@ dependencies: | ||||
|   flutter_hooks: ^0.21.2 | ||||
|   hooks_riverpod: ^2.6.1 | ||||
|   bitsdojo_window: ^0.1.6 | ||||
|   go_router: ^15.2.4 | ||||
|   go_router: ^15.1.3 | ||||
|   styled_widget: ^0.4.1 | ||||
|   shared_preferences: ^2.5.3 | ||||
|   flutter_riverpod: ^2.6.1 | ||||
| @@ -127,6 +127,8 @@ dependencies: | ||||
|       url: https://github.com/lionelmennig/textfield_tags.git | ||||
|       ref: fixes/allow-controller-re-registration | ||||
|   mime: ^2.0.0 | ||||
|   html2md: ^1.3.2 | ||||
|   flutter_typeahead: ^5.2.0 | ||||
|  | ||||
| dev_dependencies: | ||||
|   flutter_test: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user