From 7dfe411053436022623104a4de20b4664d8a2c8b Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 23 Aug 2025 02:19:07 +0800 Subject: [PATCH] :sparkles: Add more developer pages (wip) --- lib/models/bot.dart | 69 ++ lib/models/bot.freezed.dart | 1252 ++++++++++++++++++++++++ lib/models/bot.g.dart | 123 +++ lib/route.dart | 75 ++ lib/screens/developers/apps.dart | 6 +- lib/screens/developers/apps.g.dart | 2 +- lib/screens/developers/bots.dart | 160 +++ lib/screens/developers/bots.g.dart | 156 +++ lib/screens/developers/edit_app.dart | 11 +- lib/screens/developers/edit_app.g.dart | 2 +- lib/screens/developers/edit_bot.dart | 263 +++++ lib/screens/developers/edit_bot.g.dart | 144 +++ lib/screens/developers/hub.dart | 18 + lib/screens/developers/hub.g.dart | 4 +- 14 files changed, 2270 insertions(+), 15 deletions(-) create mode 100644 lib/models/bot.dart create mode 100644 lib/models/bot.freezed.dart create mode 100644 lib/models/bot.g.dart create mode 100644 lib/screens/developers/bots.dart create mode 100644 lib/screens/developers/bots.g.dart create mode 100644 lib/screens/developers/edit_bot.dart create mode 100644 lib/screens/developers/edit_bot.g.dart diff --git a/lib/models/bot.dart b/lib/models/bot.dart new file mode 100644 index 00000000..e834f978 --- /dev/null +++ b/lib/models/bot.dart @@ -0,0 +1,69 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:island/models/file.dart'; +import 'package:island/models/account.dart'; + +part 'bot.freezed.dart'; +part 'bot.g.dart'; + +@freezed +sealed class Bot with _$Bot { + const factory Bot({ + @Default('') String id, + @Default('') String name, + @Default('') String slug, + String? description, + @Default(0) int status, + SnCloudFile? picture, + SnCloudFile? background, + SnVerificationMark? verification, + BotConfig? config, + BotLinks? links, + @Default('') String publisherId, + @Default('') String appId, + DateTime? createdAt, + DateTime? updatedAt, + }) = _Bot; + + factory Bot.fromJson(Map json) => _$BotFromJson(json); +} + +@freezed +sealed class BotConfig with _$BotConfig { + const factory BotConfig({ + @Default(false) bool isPublic, + @Default(false) bool isInteractive, + @Default([]) List allowedRealms, + @Default([]) List allowedChatTypes, + @Default({}) Map metadata, + }) = _BotConfig; + + factory BotConfig.fromJson(Map json) => + _$BotConfigFromJson(json); +} + +@freezed +sealed class BotLinks with _$BotLinks { + const factory BotLinks({ + String? website, + String? documentation, + String? privacyPolicy, + String? termsOfService, + }) = _BotLinks; + + factory BotLinks.fromJson(Map json) => + _$BotLinksFromJson(json); +} + +@freezed +sealed class BotSecret with _$BotSecret { + const factory BotSecret({ + @Default('') String id, + @Default('') String secret, + String? description, + DateTime? expiredAt, + @Default('') String botId, + }) = _BotSecret; + + factory BotSecret.fromJson(Map json) => + _$BotSecretFromJson(json); +} diff --git a/lib/models/bot.freezed.dart b/lib/models/bot.freezed.dart new file mode 100644 index 00000000..278e79a6 --- /dev/null +++ b/lib/models/bot.freezed.dart @@ -0,0 +1,1252 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'bot.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$Bot { + + String get id; String get name; String get slug; String? get description; int get status; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; BotConfig? get config; BotLinks? get links; String get publisherId; String get appId; DateTime? get createdAt; DateTime? get updatedAt; +/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$BotCopyWith get copyWith => _$BotCopyWithImpl(this as Bot, _$identity); + + /// Serializes this Bot to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Bot&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.description, description) || other.description == description)&&(identical(other.status, status) || other.status == status)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.config, config) || other.config == config)&&(identical(other.links, links) || other.links == links)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.appId, appId) || other.appId == appId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,name,slug,description,status,picture,background,verification,config,links,publisherId,appId,createdAt,updatedAt); + +@override +String toString() { + return 'Bot(id: $id, name: $name, slug: $slug, description: $description, status: $status, picture: $picture, background: $background, verification: $verification, config: $config, links: $links, publisherId: $publisherId, appId: $appId, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $BotCopyWith<$Res> { + factory $BotCopyWith(Bot value, $Res Function(Bot) _then) = _$BotCopyWithImpl; +@useResult +$Res call({ + String id, String name, String slug, String? description, int status, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, BotConfig? config, BotLinks? links, String publisherId, String appId, DateTime? createdAt, DateTime? updatedAt +}); + + +$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;$BotConfigCopyWith<$Res>? get config;$BotLinksCopyWith<$Res>? get links; + +} +/// @nodoc +class _$BotCopyWithImpl<$Res> + implements $BotCopyWith<$Res> { + _$BotCopyWithImpl(this._self, this._then); + + final Bot _self; + final $Res Function(Bot) _then; + +/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? slug = null,Object? description = freezed,Object? status = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? config = freezed,Object? links = freezed,Object? publisherId = null,Object? appId = null,Object? createdAt = freezed,Object? updatedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as int,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable +as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable +as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable +as SnVerificationMark?,config: freezed == config ? _self.config : config // ignore: cast_nullable_to_non_nullable +as BotConfig?,links: freezed == links ? _self.links : links // ignore: cast_nullable_to_non_nullable +as BotLinks?,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable +as String,appId: null == appId ? _self.appId : appId // ignore: cast_nullable_to_non_nullable +as String,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, + )); +} +/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnCloudFileCopyWith<$Res>? get picture { + if (_self.picture == null) { + return null; + } + + return $SnCloudFileCopyWith<$Res>(_self.picture!, (value) { + return _then(_self.copyWith(picture: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnCloudFileCopyWith<$Res>? get background { + if (_self.background == null) { + return null; + } + + return $SnCloudFileCopyWith<$Res>(_self.background!, (value) { + return _then(_self.copyWith(background: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnVerificationMarkCopyWith<$Res>? get verification { + if (_self.verification == null) { + return null; + } + + return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) { + return _then(_self.copyWith(verification: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$BotConfigCopyWith<$Res>? get config { + if (_self.config == null) { + return null; + } + + return $BotConfigCopyWith<$Res>(_self.config!, (value) { + return _then(_self.copyWith(config: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$BotLinksCopyWith<$Res>? get links { + if (_self.links == null) { + return null; + } + + return $BotLinksCopyWith<$Res>(_self.links!, (value) { + return _then(_self.copyWith(links: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [Bot]. +extension BotPatterns on Bot { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _Bot value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _Bot() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _Bot value) $default,){ +final _that = this; +switch (_that) { +case _Bot(): +return $default(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _Bot value)? $default,){ +final _that = this; +switch (_that) { +case _Bot() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String slug, String? description, int status, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, BotConfig? config, BotLinks? links, String publisherId, String appId, DateTime? createdAt, DateTime? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _Bot() when $default != null: +return $default(_that.id,_that.name,_that.slug,_that.description,_that.status,_that.picture,_that.background,_that.verification,_that.config,_that.links,_that.publisherId,_that.appId,_that.createdAt,_that.updatedAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String name, String slug, String? description, int status, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, BotConfig? config, BotLinks? links, String publisherId, String appId, DateTime? createdAt, DateTime? updatedAt) $default,) {final _that = this; +switch (_that) { +case _Bot(): +return $default(_that.id,_that.name,_that.slug,_that.description,_that.status,_that.picture,_that.background,_that.verification,_that.config,_that.links,_that.publisherId,_that.appId,_that.createdAt,_that.updatedAt);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String slug, String? description, int status, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, BotConfig? config, BotLinks? links, String publisherId, String appId, DateTime? createdAt, DateTime? updatedAt)? $default,) {final _that = this; +switch (_that) { +case _Bot() when $default != null: +return $default(_that.id,_that.name,_that.slug,_that.description,_that.status,_that.picture,_that.background,_that.verification,_that.config,_that.links,_that.publisherId,_that.appId,_that.createdAt,_that.updatedAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _Bot implements Bot { + const _Bot({this.id = '', this.name = '', this.slug = '', this.description, this.status = 0, this.picture, this.background, this.verification, this.config, this.links, this.publisherId = '', this.appId = '', this.createdAt, this.updatedAt}); + factory _Bot.fromJson(Map json) => _$BotFromJson(json); + +@override@JsonKey() final String id; +@override@JsonKey() final String name; +@override@JsonKey() final String slug; +@override final String? description; +@override@JsonKey() final int status; +@override final SnCloudFile? picture; +@override final SnCloudFile? background; +@override final SnVerificationMark? verification; +@override final BotConfig? config; +@override final BotLinks? links; +@override@JsonKey() final String publisherId; +@override@JsonKey() final String appId; +@override final DateTime? createdAt; +@override final DateTime? updatedAt; + +/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$BotCopyWith<_Bot> get copyWith => __$BotCopyWithImpl<_Bot>(this, _$identity); + +@override +Map toJson() { + return _$BotToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Bot&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.description, description) || other.description == description)&&(identical(other.status, status) || other.status == status)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.config, config) || other.config == config)&&(identical(other.links, links) || other.links == links)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.appId, appId) || other.appId == appId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,name,slug,description,status,picture,background,verification,config,links,publisherId,appId,createdAt,updatedAt); + +@override +String toString() { + return 'Bot(id: $id, name: $name, slug: $slug, description: $description, status: $status, picture: $picture, background: $background, verification: $verification, config: $config, links: $links, publisherId: $publisherId, appId: $appId, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$BotCopyWith<$Res> implements $BotCopyWith<$Res> { + factory _$BotCopyWith(_Bot value, $Res Function(_Bot) _then) = __$BotCopyWithImpl; +@override @useResult +$Res call({ + String id, String name, String slug, String? description, int status, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, BotConfig? config, BotLinks? links, String publisherId, String appId, DateTime? createdAt, DateTime? updatedAt +}); + + +@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;@override $BotConfigCopyWith<$Res>? get config;@override $BotLinksCopyWith<$Res>? get links; + +} +/// @nodoc +class __$BotCopyWithImpl<$Res> + implements _$BotCopyWith<$Res> { + __$BotCopyWithImpl(this._self, this._then); + + final _Bot _self; + final $Res Function(_Bot) _then; + +/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? slug = null,Object? description = freezed,Object? status = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? config = freezed,Object? links = freezed,Object? publisherId = null,Object? appId = null,Object? createdAt = freezed,Object? updatedAt = freezed,}) { + return _then(_Bot( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as int,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable +as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable +as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable +as SnVerificationMark?,config: freezed == config ? _self.config : config // ignore: cast_nullable_to_non_nullable +as BotConfig?,links: freezed == links ? _self.links : links // ignore: cast_nullable_to_non_nullable +as BotLinks?,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable +as String,appId: null == appId ? _self.appId : appId // ignore: cast_nullable_to_non_nullable +as String,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, + )); +} + +/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnCloudFileCopyWith<$Res>? get picture { + if (_self.picture == null) { + return null; + } + + return $SnCloudFileCopyWith<$Res>(_self.picture!, (value) { + return _then(_self.copyWith(picture: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnCloudFileCopyWith<$Res>? get background { + if (_self.background == null) { + return null; + } + + return $SnCloudFileCopyWith<$Res>(_self.background!, (value) { + return _then(_self.copyWith(background: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnVerificationMarkCopyWith<$Res>? get verification { + if (_self.verification == null) { + return null; + } + + return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) { + return _then(_self.copyWith(verification: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$BotConfigCopyWith<$Res>? get config { + if (_self.config == null) { + return null; + } + + return $BotConfigCopyWith<$Res>(_self.config!, (value) { + return _then(_self.copyWith(config: value)); + }); +}/// Create a copy of Bot +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$BotLinksCopyWith<$Res>? get links { + if (_self.links == null) { + return null; + } + + return $BotLinksCopyWith<$Res>(_self.links!, (value) { + return _then(_self.copyWith(links: value)); + }); +} +} + + +/// @nodoc +mixin _$BotConfig { + + bool get isPublic; bool get isInteractive; List get allowedRealms; List get allowedChatTypes; Map get metadata; +/// Create a copy of BotConfig +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$BotConfigCopyWith get copyWith => _$BotConfigCopyWithImpl(this as BotConfig, _$identity); + + /// Serializes this BotConfig to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is BotConfig&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.isInteractive, isInteractive) || other.isInteractive == isInteractive)&&const DeepCollectionEquality().equals(other.allowedRealms, allowedRealms)&&const DeepCollectionEquality().equals(other.allowedChatTypes, allowedChatTypes)&&const DeepCollectionEquality().equals(other.metadata, metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,isPublic,isInteractive,const DeepCollectionEquality().hash(allowedRealms),const DeepCollectionEquality().hash(allowedChatTypes),const DeepCollectionEquality().hash(metadata)); + +@override +String toString() { + return 'BotConfig(isPublic: $isPublic, isInteractive: $isInteractive, allowedRealms: $allowedRealms, allowedChatTypes: $allowedChatTypes, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $BotConfigCopyWith<$Res> { + factory $BotConfigCopyWith(BotConfig value, $Res Function(BotConfig) _then) = _$BotConfigCopyWithImpl; +@useResult +$Res call({ + bool isPublic, bool isInteractive, List allowedRealms, List allowedChatTypes, Map metadata +}); + + + + +} +/// @nodoc +class _$BotConfigCopyWithImpl<$Res> + implements $BotConfigCopyWith<$Res> { + _$BotConfigCopyWithImpl(this._self, this._then); + + final BotConfig _self; + final $Res Function(BotConfig) _then; + +/// Create a copy of BotConfig +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? isPublic = null,Object? isInteractive = null,Object? allowedRealms = null,Object? allowedChatTypes = null,Object? metadata = null,}) { + return _then(_self.copyWith( +isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable +as bool,isInteractive: null == isInteractive ? _self.isInteractive : isInteractive // ignore: cast_nullable_to_non_nullable +as bool,allowedRealms: null == allowedRealms ? _self.allowedRealms : allowedRealms // ignore: cast_nullable_to_non_nullable +as List,allowedChatTypes: null == allowedChatTypes ? _self.allowedChatTypes : allowedChatTypes // ignore: cast_nullable_to_non_nullable +as List,metadata: null == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map, + )); +} + +} + + +/// Adds pattern-matching-related methods to [BotConfig]. +extension BotConfigPatterns on BotConfig { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _BotConfig value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _BotConfig() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _BotConfig value) $default,){ +final _that = this; +switch (_that) { +case _BotConfig(): +return $default(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _BotConfig value)? $default,){ +final _that = this; +switch (_that) { +case _BotConfig() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( bool isPublic, bool isInteractive, List allowedRealms, List allowedChatTypes, Map metadata)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _BotConfig() when $default != null: +return $default(_that.isPublic,_that.isInteractive,_that.allowedRealms,_that.allowedChatTypes,_that.metadata);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( bool isPublic, bool isInteractive, List allowedRealms, List allowedChatTypes, Map metadata) $default,) {final _that = this; +switch (_that) { +case _BotConfig(): +return $default(_that.isPublic,_that.isInteractive,_that.allowedRealms,_that.allowedChatTypes,_that.metadata);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool isPublic, bool isInteractive, List allowedRealms, List allowedChatTypes, Map metadata)? $default,) {final _that = this; +switch (_that) { +case _BotConfig() when $default != null: +return $default(_that.isPublic,_that.isInteractive,_that.allowedRealms,_that.allowedChatTypes,_that.metadata);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _BotConfig implements BotConfig { + const _BotConfig({this.isPublic = false, this.isInteractive = false, final List allowedRealms = const [], final List allowedChatTypes = const [], final Map metadata = const {}}): _allowedRealms = allowedRealms,_allowedChatTypes = allowedChatTypes,_metadata = metadata; + factory _BotConfig.fromJson(Map json) => _$BotConfigFromJson(json); + +@override@JsonKey() final bool isPublic; +@override@JsonKey() final bool isInteractive; + final List _allowedRealms; +@override@JsonKey() List get allowedRealms { + if (_allowedRealms is EqualUnmodifiableListView) return _allowedRealms; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_allowedRealms); +} + + final List _allowedChatTypes; +@override@JsonKey() List get allowedChatTypes { + if (_allowedChatTypes is EqualUnmodifiableListView) return _allowedChatTypes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_allowedChatTypes); +} + + final Map _metadata; +@override@JsonKey() Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); +} + + +/// Create a copy of BotConfig +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$BotConfigCopyWith<_BotConfig> get copyWith => __$BotConfigCopyWithImpl<_BotConfig>(this, _$identity); + +@override +Map toJson() { + return _$BotConfigToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _BotConfig&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.isInteractive, isInteractive) || other.isInteractive == isInteractive)&&const DeepCollectionEquality().equals(other._allowedRealms, _allowedRealms)&&const DeepCollectionEquality().equals(other._allowedChatTypes, _allowedChatTypes)&&const DeepCollectionEquality().equals(other._metadata, _metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,isPublic,isInteractive,const DeepCollectionEquality().hash(_allowedRealms),const DeepCollectionEquality().hash(_allowedChatTypes),const DeepCollectionEquality().hash(_metadata)); + +@override +String toString() { + return 'BotConfig(isPublic: $isPublic, isInteractive: $isInteractive, allowedRealms: $allowedRealms, allowedChatTypes: $allowedChatTypes, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class _$BotConfigCopyWith<$Res> implements $BotConfigCopyWith<$Res> { + factory _$BotConfigCopyWith(_BotConfig value, $Res Function(_BotConfig) _then) = __$BotConfigCopyWithImpl; +@override @useResult +$Res call({ + bool isPublic, bool isInteractive, List allowedRealms, List allowedChatTypes, Map metadata +}); + + + + +} +/// @nodoc +class __$BotConfigCopyWithImpl<$Res> + implements _$BotConfigCopyWith<$Res> { + __$BotConfigCopyWithImpl(this._self, this._then); + + final _BotConfig _self; + final $Res Function(_BotConfig) _then; + +/// Create a copy of BotConfig +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? isPublic = null,Object? isInteractive = null,Object? allowedRealms = null,Object? allowedChatTypes = null,Object? metadata = null,}) { + return _then(_BotConfig( +isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable +as bool,isInteractive: null == isInteractive ? _self.isInteractive : isInteractive // ignore: cast_nullable_to_non_nullable +as bool,allowedRealms: null == allowedRealms ? _self._allowedRealms : allowedRealms // ignore: cast_nullable_to_non_nullable +as List,allowedChatTypes: null == allowedChatTypes ? _self._allowedChatTypes : allowedChatTypes // ignore: cast_nullable_to_non_nullable +as List,metadata: null == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map, + )); +} + + +} + + +/// @nodoc +mixin _$BotLinks { + + String? get website; String? get documentation; String? get privacyPolicy; String? get termsOfService; +/// Create a copy of BotLinks +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$BotLinksCopyWith get copyWith => _$BotLinksCopyWithImpl(this as BotLinks, _$identity); + + /// Serializes this BotLinks to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is BotLinks&&(identical(other.website, website) || other.website == website)&&(identical(other.documentation, documentation) || other.documentation == documentation)&&(identical(other.privacyPolicy, privacyPolicy) || other.privacyPolicy == privacyPolicy)&&(identical(other.termsOfService, termsOfService) || other.termsOfService == termsOfService)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,website,documentation,privacyPolicy,termsOfService); + +@override +String toString() { + return 'BotLinks(website: $website, documentation: $documentation, privacyPolicy: $privacyPolicy, termsOfService: $termsOfService)'; +} + + +} + +/// @nodoc +abstract mixin class $BotLinksCopyWith<$Res> { + factory $BotLinksCopyWith(BotLinks value, $Res Function(BotLinks) _then) = _$BotLinksCopyWithImpl; +@useResult +$Res call({ + String? website, String? documentation, String? privacyPolicy, String? termsOfService +}); + + + + +} +/// @nodoc +class _$BotLinksCopyWithImpl<$Res> + implements $BotLinksCopyWith<$Res> { + _$BotLinksCopyWithImpl(this._self, this._then); + + final BotLinks _self; + final $Res Function(BotLinks) _then; + +/// Create a copy of BotLinks +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? website = freezed,Object? documentation = freezed,Object? privacyPolicy = freezed,Object? termsOfService = freezed,}) { + return _then(_self.copyWith( +website: freezed == website ? _self.website : website // ignore: cast_nullable_to_non_nullable +as String?,documentation: freezed == documentation ? _self.documentation : documentation // ignore: cast_nullable_to_non_nullable +as String?,privacyPolicy: freezed == privacyPolicy ? _self.privacyPolicy : privacyPolicy // ignore: cast_nullable_to_non_nullable +as String?,termsOfService: freezed == termsOfService ? _self.termsOfService : termsOfService // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [BotLinks]. +extension BotLinksPatterns on BotLinks { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _BotLinks value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _BotLinks() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _BotLinks value) $default,){ +final _that = this; +switch (_that) { +case _BotLinks(): +return $default(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _BotLinks value)? $default,){ +final _that = this; +switch (_that) { +case _BotLinks() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String? website, String? documentation, String? privacyPolicy, String? termsOfService)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _BotLinks() when $default != null: +return $default(_that.website,_that.documentation,_that.privacyPolicy,_that.termsOfService);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String? website, String? documentation, String? privacyPolicy, String? termsOfService) $default,) {final _that = this; +switch (_that) { +case _BotLinks(): +return $default(_that.website,_that.documentation,_that.privacyPolicy,_that.termsOfService);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String? website, String? documentation, String? privacyPolicy, String? termsOfService)? $default,) {final _that = this; +switch (_that) { +case _BotLinks() when $default != null: +return $default(_that.website,_that.documentation,_that.privacyPolicy,_that.termsOfService);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _BotLinks implements BotLinks { + const _BotLinks({this.website, this.documentation, this.privacyPolicy, this.termsOfService}); + factory _BotLinks.fromJson(Map json) => _$BotLinksFromJson(json); + +@override final String? website; +@override final String? documentation; +@override final String? privacyPolicy; +@override final String? termsOfService; + +/// Create a copy of BotLinks +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$BotLinksCopyWith<_BotLinks> get copyWith => __$BotLinksCopyWithImpl<_BotLinks>(this, _$identity); + +@override +Map toJson() { + return _$BotLinksToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _BotLinks&&(identical(other.website, website) || other.website == website)&&(identical(other.documentation, documentation) || other.documentation == documentation)&&(identical(other.privacyPolicy, privacyPolicy) || other.privacyPolicy == privacyPolicy)&&(identical(other.termsOfService, termsOfService) || other.termsOfService == termsOfService)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,website,documentation,privacyPolicy,termsOfService); + +@override +String toString() { + return 'BotLinks(website: $website, documentation: $documentation, privacyPolicy: $privacyPolicy, termsOfService: $termsOfService)'; +} + + +} + +/// @nodoc +abstract mixin class _$BotLinksCopyWith<$Res> implements $BotLinksCopyWith<$Res> { + factory _$BotLinksCopyWith(_BotLinks value, $Res Function(_BotLinks) _then) = __$BotLinksCopyWithImpl; +@override @useResult +$Res call({ + String? website, String? documentation, String? privacyPolicy, String? termsOfService +}); + + + + +} +/// @nodoc +class __$BotLinksCopyWithImpl<$Res> + implements _$BotLinksCopyWith<$Res> { + __$BotLinksCopyWithImpl(this._self, this._then); + + final _BotLinks _self; + final $Res Function(_BotLinks) _then; + +/// Create a copy of BotLinks +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? website = freezed,Object? documentation = freezed,Object? privacyPolicy = freezed,Object? termsOfService = freezed,}) { + return _then(_BotLinks( +website: freezed == website ? _self.website : website // ignore: cast_nullable_to_non_nullable +as String?,documentation: freezed == documentation ? _self.documentation : documentation // ignore: cast_nullable_to_non_nullable +as String?,privacyPolicy: freezed == privacyPolicy ? _self.privacyPolicy : privacyPolicy // ignore: cast_nullable_to_non_nullable +as String?,termsOfService: freezed == termsOfService ? _self.termsOfService : termsOfService // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + + +/// @nodoc +mixin _$BotSecret { + + String get id; String get secret; String? get description; DateTime? get expiredAt; String get botId; +/// Create a copy of BotSecret +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$BotSecretCopyWith get copyWith => _$BotSecretCopyWithImpl(this as BotSecret, _$identity); + + /// Serializes this BotSecret to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is BotSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.botId, botId) || other.botId == botId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,secret,description,expiredAt,botId); + +@override +String toString() { + return 'BotSecret(id: $id, secret: $secret, description: $description, expiredAt: $expiredAt, botId: $botId)'; +} + + +} + +/// @nodoc +abstract mixin class $BotSecretCopyWith<$Res> { + factory $BotSecretCopyWith(BotSecret value, $Res Function(BotSecret) _then) = _$BotSecretCopyWithImpl; +@useResult +$Res call({ + String id, String secret, String? description, DateTime? expiredAt, String botId +}); + + + + +} +/// @nodoc +class _$BotSecretCopyWithImpl<$Res> + implements $BotSecretCopyWith<$Res> { + _$BotSecretCopyWithImpl(this._self, this._then); + + final BotSecret _self; + final $Res Function(BotSecret) _then; + +/// Create a copy of BotSecret +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? secret = null,Object? description = freezed,Object? expiredAt = freezed,Object? botId = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,secret: null == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable +as DateTime?,botId: null == botId ? _self.botId : botId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [BotSecret]. +extension BotSecretPatterns on BotSecret { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _BotSecret value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _BotSecret() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _BotSecret value) $default,){ +final _that = this; +switch (_that) { +case _BotSecret(): +return $default(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _BotSecret value)? $default,){ +final _that = this; +switch (_that) { +case _BotSecret() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String secret, String? description, DateTime? expiredAt, String botId)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _BotSecret() when $default != null: +return $default(_that.id,_that.secret,_that.description,_that.expiredAt,_that.botId);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String secret, String? description, DateTime? expiredAt, String botId) $default,) {final _that = this; +switch (_that) { +case _BotSecret(): +return $default(_that.id,_that.secret,_that.description,_that.expiredAt,_that.botId);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String secret, String? description, DateTime? expiredAt, String botId)? $default,) {final _that = this; +switch (_that) { +case _BotSecret() when $default != null: +return $default(_that.id,_that.secret,_that.description,_that.expiredAt,_that.botId);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _BotSecret implements BotSecret { + const _BotSecret({this.id = '', this.secret = '', this.description, this.expiredAt, this.botId = ''}); + factory _BotSecret.fromJson(Map json) => _$BotSecretFromJson(json); + +@override@JsonKey() final String id; +@override@JsonKey() final String secret; +@override final String? description; +@override final DateTime? expiredAt; +@override@JsonKey() final String botId; + +/// Create a copy of BotSecret +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$BotSecretCopyWith<_BotSecret> get copyWith => __$BotSecretCopyWithImpl<_BotSecret>(this, _$identity); + +@override +Map toJson() { + return _$BotSecretToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _BotSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.botId, botId) || other.botId == botId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,secret,description,expiredAt,botId); + +@override +String toString() { + return 'BotSecret(id: $id, secret: $secret, description: $description, expiredAt: $expiredAt, botId: $botId)'; +} + + +} + +/// @nodoc +abstract mixin class _$BotSecretCopyWith<$Res> implements $BotSecretCopyWith<$Res> { + factory _$BotSecretCopyWith(_BotSecret value, $Res Function(_BotSecret) _then) = __$BotSecretCopyWithImpl; +@override @useResult +$Res call({ + String id, String secret, String? description, DateTime? expiredAt, String botId +}); + + + + +} +/// @nodoc +class __$BotSecretCopyWithImpl<$Res> + implements _$BotSecretCopyWith<$Res> { + __$BotSecretCopyWithImpl(this._self, this._then); + + final _BotSecret _self; + final $Res Function(_BotSecret) _then; + +/// Create a copy of BotSecret +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? secret = null,Object? description = freezed,Object? expiredAt = freezed,Object? botId = null,}) { + return _then(_BotSecret( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,secret: null == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable +as DateTime?,botId: null == botId ? _self.botId : botId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/lib/models/bot.g.dart b/lib/models/bot.g.dart new file mode 100644 index 00000000..c8cf1aa8 --- /dev/null +++ b/lib/models/bot.g.dart @@ -0,0 +1,123 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'bot.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_Bot _$BotFromJson(Map json) => _Bot( + id: json['id'] as String? ?? '', + name: json['name'] as String? ?? '', + slug: json['slug'] as String? ?? '', + description: json['description'] as String?, + status: (json['status'] as num?)?.toInt() ?? 0, + picture: + json['picture'] == null + ? null + : SnCloudFile.fromJson(json['picture'] as Map), + background: + json['background'] == null + ? null + : SnCloudFile.fromJson(json['background'] as Map), + verification: + json['verification'] == null + ? null + : SnVerificationMark.fromJson( + json['verification'] as Map, + ), + config: + json['config'] == null + ? null + : BotConfig.fromJson(json['config'] as Map), + links: + json['links'] == null + ? null + : BotLinks.fromJson(json['links'] as Map), + publisherId: json['publisher_id'] as String? ?? '', + appId: json['app_id'] as String? ?? '', + createdAt: + json['created_at'] == null + ? null + : DateTime.parse(json['created_at'] as String), + updatedAt: + json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String), +); + +Map _$BotToJson(_Bot instance) => { + 'id': instance.id, + 'name': instance.name, + 'slug': instance.slug, + 'description': instance.description, + 'status': instance.status, + 'picture': instance.picture?.toJson(), + 'background': instance.background?.toJson(), + 'verification': instance.verification?.toJson(), + 'config': instance.config?.toJson(), + 'links': instance.links?.toJson(), + 'publisher_id': instance.publisherId, + 'app_id': instance.appId, + 'created_at': instance.createdAt?.toIso8601String(), + 'updated_at': instance.updatedAt?.toIso8601String(), +}; + +_BotConfig _$BotConfigFromJson(Map json) => _BotConfig( + isPublic: json['is_public'] as bool? ?? false, + isInteractive: json['is_interactive'] as bool? ?? false, + allowedRealms: + (json['allowed_realms'] as List?) + ?.map((e) => e as String) + .toList() ?? + const [], + allowedChatTypes: + (json['allowed_chat_types'] as List?) + ?.map((e) => e as String) + .toList() ?? + const [], + metadata: json['metadata'] as Map? ?? const {}, +); + +Map _$BotConfigToJson(_BotConfig instance) => + { + 'is_public': instance.isPublic, + 'is_interactive': instance.isInteractive, + 'allowed_realms': instance.allowedRealms, + 'allowed_chat_types': instance.allowedChatTypes, + 'metadata': instance.metadata, + }; + +_BotLinks _$BotLinksFromJson(Map json) => _BotLinks( + website: json['website'] as String?, + documentation: json['documentation'] as String?, + privacyPolicy: json['privacy_policy'] as String?, + termsOfService: json['terms_of_service'] as String?, +); + +Map _$BotLinksToJson(_BotLinks instance) => { + 'website': instance.website, + 'documentation': instance.documentation, + 'privacy_policy': instance.privacyPolicy, + 'terms_of_service': instance.termsOfService, +}; + +_BotSecret _$BotSecretFromJson(Map json) => _BotSecret( + id: json['id'] as String? ?? '', + secret: json['secret'] as String? ?? '', + description: json['description'] as String?, + expiredAt: + json['expired_at'] == null + ? null + : DateTime.parse(json['expired_at'] as String), + botId: json['bot_id'] as String? ?? '', +); + +Map _$BotSecretToJson(_BotSecret instance) => + { + 'id': instance.id, + 'secret': instance.secret, + 'description': instance.description, + 'expired_at': instance.expiredAt?.toIso8601String(), + 'bot_id': instance.botId, + }; diff --git a/lib/route.dart b/lib/route.dart index 9dbe54bd..b60c4ba9 100644 --- a/lib/route.dart +++ b/lib/route.dart @@ -8,7 +8,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/screens/about.dart'; import 'package:island/screens/account/credits.dart'; import 'package:island/screens/developers/apps.dart'; +import 'package:island/screens/developers/bots.dart'; import 'package:island/screens/developers/edit_app.dart'; +import 'package:island/screens/developers/edit_bot.dart'; import 'package:island/screens/developers/new_app.dart'; import 'package:island/screens/developers/hub.dart'; import 'package:island/screens/discovery/articles.dart'; @@ -315,6 +317,79 @@ final routerProvider = Provider((ref) { id: state.pathParameters['id']!, ), ), + // Bot routes + GoRoute( + name: 'developerBots', + path: '/developers/:name/bots', + builder: + (context, state) => BotsScreen( + publisherName: state.pathParameters['name']!, + ), + ), + GoRoute( + name: 'developerBotsApp', + path: '/developers/:name/apps/:appId/bots', + builder: + (context, state) => BotsScreen( + publisherName: state.pathParameters['name']!, + appId: state.pathParameters['appId']!, + ), + ), + GoRoute( + name: 'developerBotNew', + path: '/developers/:name/bots/new', + builder: + (context, state) => EditBotScreen( + publisherName: state.pathParameters['name']!, + ), + ), + GoRoute( + name: 'developerBotNewApp', + path: '/developers/:name/apps/:appId/bots/new', + builder: + (context, state) => EditBotScreen( + publisherName: state.pathParameters['name']!, + appId: state.pathParameters['appId']!, + ), + ), + GoRoute( + name: 'developerBotEdit', + path: '/developers/:name/bots/:id', + builder: + (context, state) => EditBotScreen( + publisherName: state.pathParameters['name']!, + id: state.pathParameters['id']!, + ), + ), + GoRoute( + name: 'developerBotEditApp', + path: '/developers/:name/apps/:appId/bots/:id', + builder: + (context, state) => EditBotScreen( + publisherName: state.pathParameters['name']!, + id: state.pathParameters['id']!, + appId: state.pathParameters['appId']!, + ), + ), + GoRoute( + name: 'developerBotDetail', + path: '/developers/:name/bots/:id/detail', + builder: + (context, state) => EditBotScreen( + publisherName: state.pathParameters['name']!, + id: state.pathParameters['id']!, + ), + ), + GoRoute( + name: 'developerBotDetailApp', + path: '/developers/:name/apps/:appId/bots/:id/detail', + builder: + (context, state) => EditBotScreen( + publisherName: state.pathParameters['name']!, + id: state.pathParameters['id']!, + appId: state.pathParameters['appId']!, + ), + ), ], ), diff --git a/lib/screens/developers/apps.dart b/lib/screens/developers/apps.dart index 08f2e4e7..5cc07638 100644 --- a/lib/screens/developers/apps.dart +++ b/lib/screens/developers/apps.dart @@ -18,7 +18,7 @@ part 'apps.g.dart'; @riverpod Future> customApps(Ref ref, String publisherName) async { final client = ref.watch(apiClientProvider); - final resp = await client.get('/develop/developers/$publisherName/apps'); + final resp = await client.get('/develop/$publisherName'); return resp.data.map((e) => CustomApp.fromJson(e)).cast().toList(); } @@ -138,9 +138,7 @@ class CustomAppsScreen extends HookConsumerWidget { ).then((confirm) { if (confirm) { final client = ref.read(apiClientProvider); - client.delete( - '/develop/developers/$publisherName/apps/${app.id}', - ); + client.delete('/develop/apps/${app.id}'); ref.invalidate( customAppsProvider(publisherName), ); diff --git a/lib/screens/developers/apps.g.dart b/lib/screens/developers/apps.g.dart index f91f0f2c..850759be 100644 --- a/lib/screens/developers/apps.g.dart +++ b/lib/screens/developers/apps.g.dart @@ -6,7 +6,7 @@ part of 'apps.dart'; // RiverpodGenerator // ************************************************************************** -String _$customAppsHash() => r'c6ac78060eb51a2b208a749a81ecbe0a9c608ce1'; +String _$customAppsHash() => r'bcceb50ddbc9ca01f6555faf9b4f9ed21a7b5057'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/screens/developers/bots.dart b/lib/screens/developers/bots.dart new file mode 100644 index 00000000..bc6a66d1 --- /dev/null +++ b/lib/screens/developers/bots.dart @@ -0,0 +1,160 @@ +import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:go_router/go_router.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/models/bot.dart'; +import 'package:island/pods/network.dart'; +import 'package:island/widgets/alert.dart'; +import 'package:island/widgets/app_scaffold.dart'; +import 'package:island/widgets/content/cloud_files.dart'; +import 'package:island/widgets/response.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'bots.g.dart'; + +@riverpod +Future> bots(Ref ref, String publisherName, {String? appId}) async { + final client = ref.watch(apiClientProvider); + final queryParams = { + 'publisher': publisherName, + if (appId != null) 'app_id': appId, + }; + final resp = await client.get('/develop/bots', queryParameters: queryParams); + return resp.data.map((e) => Bot.fromJson(e)).cast().toList(); +} + +class BotsScreen extends HookConsumerWidget { + final String publisherName; + final String? appId; + const BotsScreen({super.key, required this.publisherName, this.appId}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final botsList = ref.watch(botsProvider(publisherName, appId: appId)); + + return AppScaffold( + appBar: AppBar( + title: Text('bots').tr(), + actions: [ + IconButton( + icon: const Icon(Symbols.add), + onPressed: () { + context.pushNamed( + 'developerBotNew', + pathParameters: { + 'name': publisherName, + if (appId != null) 'appId': appId!, + }, + ); + }, + ), + ], + ), + body: botsList.when( + data: (data) { + if (data.isEmpty) { + return Center(child: Text('noBots').tr()); + } + return RefreshIndicator( + onRefresh: + () => ref.refresh( + botsProvider(publisherName, appId: appId).future, + ), + child: ListView.builder( + padding: const EdgeInsets.only(top: 4), + itemCount: data.length, + itemBuilder: (context, index) { + final bot = data[index]; + return Card( + margin: const EdgeInsets.all(8.0), + child: ListTile( + leading: CircleAvatar( + child: + bot.picture != null + ? CloudFileWidget(item: bot.picture!) + : const Icon(Symbols.smart_toy), + ), + title: Text(bot.name), + subtitle: Text(bot.description ?? ''), + trailing: PopupMenuButton( + itemBuilder: + (context) => [ + PopupMenuItem( + value: 'edit', + child: Row( + children: [ + const Icon(Symbols.edit), + const SizedBox(width: 12), + Text('edit').tr(), + ], + ), + ), + PopupMenuItem( + value: 'delete', + child: Row( + children: [ + const Icon(Symbols.delete, color: Colors.red), + const SizedBox(width: 12), + Text( + 'delete', + style: TextStyle(color: Colors.red), + ).tr(), + ], + ), + ), + ], + onSelected: (value) { + if (value == 'edit') { + context.pushNamed( + 'developerBotEdit', + pathParameters: { + 'name': publisherName, + 'id': bot.id, + if (appId != null) 'appId': appId!, + }, + ); + } else if (value == 'delete') { + showConfirmAlert( + 'deleteBotHint'.tr(), + 'deleteBot'.tr(), + ).then((confirm) { + if (confirm) { + final client = ref.read(apiClientProvider); + client.delete('/develop/bots/${bot.id}'); + ref.invalidate( + botsProvider(publisherName, appId: appId), + ); + } + }); + } + }, + ), + onTap: () { + context.pushNamed( + 'developerBotDetail', + pathParameters: { + 'name': publisherName, + 'id': bot.id, + if (appId != null) 'appId': appId!, + }, + ); + }, + ), + ); + }, + ), + ); + }, + loading: () => const Center(child: CircularProgressIndicator()), + error: + (err, stack) => ResponseErrorWidget( + error: err, + onRetry: + () => + ref.invalidate(botsProvider(publisherName, appId: appId)), + ), + ), + ); + } +} diff --git a/lib/screens/developers/bots.g.dart b/lib/screens/developers/bots.g.dart new file mode 100644 index 00000000..4f9f72f6 --- /dev/null +++ b/lib/screens/developers/bots.g.dart @@ -0,0 +1,156 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'bots.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$botsHash() => r'04bff237afa91032310eaa8acd792c5a98da0d75'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [bots]. +@ProviderFor(bots) +const botsProvider = BotsFamily(); + +/// See also [bots]. +class BotsFamily extends Family>> { + /// See also [bots]. + const BotsFamily(); + + /// See also [bots]. + BotsProvider call(String publisherName, {String? appId}) { + return BotsProvider(publisherName, appId: appId); + } + + @override + BotsProvider getProviderOverride(covariant BotsProvider provider) { + return call(provider.publisherName, appId: provider.appId); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'botsProvider'; +} + +/// See also [bots]. +class BotsProvider extends AutoDisposeFutureProvider> { + /// See also [bots]. + BotsProvider(String publisherName, {String? appId}) + : this._internal( + (ref) => bots(ref as BotsRef, publisherName, appId: appId), + from: botsProvider, + name: r'botsProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$botsHash, + dependencies: BotsFamily._dependencies, + allTransitiveDependencies: BotsFamily._allTransitiveDependencies, + publisherName: publisherName, + appId: appId, + ); + + BotsProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.publisherName, + required this.appId, + }) : super.internal(); + + final String publisherName; + final String? appId; + + @override + Override overrideWith(FutureOr> Function(BotsRef provider) create) { + return ProviderOverride( + origin: this, + override: BotsProvider._internal( + (ref) => create(ref as BotsRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + publisherName: publisherName, + appId: appId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _BotsProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is BotsProvider && + other.publisherName == publisherName && + other.appId == appId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, publisherName.hashCode); + hash = _SystemHash.combine(hash, appId.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin BotsRef on AutoDisposeFutureProviderRef> { + /// The parameter `publisherName` of this provider. + String get publisherName; + + /// The parameter `appId` of this provider. + String? get appId; +} + +class _BotsProviderElement extends AutoDisposeFutureProviderElement> + with BotsRef { + _BotsProviderElement(super.provider); + + @override + String get publisherName => (origin as BotsProvider).publisherName; + @override + String? get appId => (origin as BotsProvider).appId; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/screens/developers/edit_app.dart b/lib/screens/developers/edit_app.dart index f0a329f4..613de185 100644 --- a/lib/screens/developers/edit_app.dart +++ b/lib/screens/developers/edit_app.dart @@ -24,7 +24,7 @@ part 'edit_app.g.dart'; @riverpod Future customApp(Ref ref, String publisherName, String id) async { final client = ref.watch(apiClientProvider); - final resp = await client.get('/develop/developers/$publisherName/apps/$id'); + final resp = await client.get('/develop/apps/$id'); return CustomApp.fromJson(resp.data); } @@ -283,14 +283,11 @@ class EditAppScreen extends HookConsumerWidget { }; if (isNew) { await client.post( - '/develop/developers/$publisherName/apps', - data: data, + '/develop/apps', + data: {...data, 'publisher_id': publisherName}, ); } else { - await client.patch( - '/develop/developers/$publisherName/apps/$id', - data: data, - ); + await client.patch('/develop/apps/$id', data: data); } ref.invalidate(customAppsProvider(publisherName)); if (context.mounted) { diff --git a/lib/screens/developers/edit_app.g.dart b/lib/screens/developers/edit_app.g.dart index 99a76d2b..56345991 100644 --- a/lib/screens/developers/edit_app.g.dart +++ b/lib/screens/developers/edit_app.g.dart @@ -6,7 +6,7 @@ part of 'edit_app.dart'; // RiverpodGenerator // ************************************************************************** -String _$customAppHash() => r'42ad937b8439c793e3c5c35568bb5fa4da017df3'; +String _$customAppHash() => r'e2b022c9103cf459f7d81018e34d8f7a31b5c864'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/screens/developers/edit_bot.dart b/lib/screens/developers/edit_bot.dart new file mode 100644 index 00000000..bc692983 --- /dev/null +++ b/lib/screens/developers/edit_bot.dart @@ -0,0 +1,263 @@ +import 'package:croppy/croppy.dart' hide cropImage; +import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:island/models/bot.dart'; +import 'package:island/models/file.dart'; +import 'package:island/pods/config.dart'; +import 'package:island/pods/network.dart'; +import 'package:island/services/file.dart'; +import 'package:island/widgets/alert.dart'; +import 'package:island/widgets/app_scaffold.dart'; +import 'package:island/widgets/content/cloud_files.dart'; +import 'package:island/widgets/response.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:styled_widget/styled_widget.dart'; + +part 'edit_bot.g.dart'; + +@riverpod +Future bot(Ref ref, String id) async { + final client = ref.watch(apiClientProvider); + final resp = await client.get('/develop/bots/$id'); + return Bot.fromJson(resp.data); +} + +class EditBotScreen extends HookConsumerWidget { + final String publisherName; + final String? id; + final String? appId; + const EditBotScreen({ + super.key, + required this.publisherName, + this.id, + this.appId, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isNew = id == null; + final botData = isNew ? null : ref.watch(botProvider(id!)); + + final formKey = useMemoized(() => GlobalKey()); + final submitting = useState(false); + + final nameController = useTextEditingController(); + final slugController = useTextEditingController(); + final descriptionController = useTextEditingController(); + final picture = useState(null); + final websiteController = useTextEditingController(); + final documentationController = useTextEditingController(); + + final isPublic = useState(false); + final isInteractive = useState(false); + + useEffect(() { + if (botData?.value != null) { + nameController.text = botData!.value!.name; + slugController.text = botData.value!.slug; + descriptionController.text = botData.value!.description ?? ''; + picture.value = botData.value!.picture; + websiteController.text = botData.value!.links?.website ?? ''; + documentationController.text = + botData.value!.links?.documentation ?? ''; + isPublic.value = botData.value!.config?.isPublic ?? false; + isInteractive.value = botData.value!.config?.isInteractive ?? false; + } + return null; + }, [botData]); + + void setPicture() async { + showLoadingModal(context); + var result = await ref + .read(imagePickerProvider) + .pickImage(source: ImageSource.gallery); + if (result == null) { + if (context.mounted) hideLoadingModal(context); + return; + } + if (!context.mounted) return; + hideLoadingModal(context); + + result = await cropImage( + context, + image: result, + allowedAspectRatios: [const CropAspectRatio(height: 1, width: 1)], + ); + if (result == null) { + if (context.mounted) hideLoadingModal(context); + return; + } + if (!context.mounted) return; + showLoadingModal(context); + + submitting.value = true; + try { + final baseUrl = ref.watch(serverUrlProvider); + final token = await getToken(ref.watch(tokenProvider)); + if (token == null) throw ArgumentError('Token is null'); + final cloudFile = + await putMediaToCloud( + fileData: UniversalFile( + data: result, + type: UniversalFileType.image, + ), + atk: token, + baseUrl: baseUrl, + filename: result.name, + mimetype: result.mimeType ?? 'image/jpeg', + ).future; + if (cloudFile == null) { + throw ArgumentError('Failed to upload the file...'); + } + picture.value = cloudFile; + } catch (err) { + showErrorAlert(err); + } finally { + if (context.mounted) hideLoadingModal(context); + submitting.value = false; + } + } + + void performAction() async { + final client = ref.read(apiClientProvider); + final data = { + 'name': nameController.text, + 'slug': slugController.text, + 'description': descriptionController.text, + 'picture_id': picture.value?.id, + 'config': { + 'is_public': isPublic.value, + 'is_interactive': isInteractive.value, + }, + 'links': { + 'website': + websiteController.text.isNotEmpty ? websiteController.text : null, + 'documentation': + documentationController.text.isNotEmpty + ? documentationController.text + : null, + }, + 'publisher_id': publisherName, + if (appId != null) 'app_id': appId, + }; + + if (isNew) { + await client.post('/develop/bots', data: data); + } else { + await client.patch('/develop/bots/$id', data: data); + } + + if (context.mounted) { + Navigator.pop(context); + } + } + + return AppScaffold( + appBar: AppBar(title: Text(isNew ? 'createBot'.tr() : 'editBot'.tr())), + body: + botData == null && !isNew + ? const Center(child: CircularProgressIndicator()) + : botData?.hasError == true && !isNew + ? ResponseErrorWidget( + error: botData!.error, + onRetry: () => ref.invalidate(botProvider(id!)), + ) + : SingleChildScrollView( + child: Column( + children: [ + AspectRatio( + aspectRatio: 1, + child: GestureDetector( + onTap: setPicture, + child: Container( + color: + Theme.of( + context, + ).colorScheme.surfaceContainerHigh, + child: + picture.value != null + ? CloudFileWidget( + item: picture.value!, + fit: BoxFit.cover, + ) + : const Icon(Symbols.smart_toy, size: 48), + ), + ), + ).padding(bottom: 32), + Form( + key: formKey, + child: Column( + children: [ + TextFormField( + controller: nameController, + decoration: InputDecoration(labelText: 'name'.tr()), + ), + const SizedBox(height: 16), + TextFormField( + controller: slugController, + decoration: InputDecoration( + labelText: 'slug'.tr(), + helperText: 'slugHint'.tr(), + ), + ), + const SizedBox(height: 16), + TextFormField( + controller: descriptionController, + decoration: InputDecoration( + labelText: 'description'.tr(), + alignLabelWithHint: true, + ), + maxLines: 3, + ), + const SizedBox(height: 16), + TextFormField( + controller: websiteController, + decoration: InputDecoration( + labelText: 'websiteUrl'.tr(), + hintText: 'https://example.com', + ), + keyboardType: TextInputType.url, + ), + const SizedBox(height: 16), + TextFormField( + controller: documentationController, + decoration: InputDecoration( + labelText: 'documentationUrl'.tr(), + hintText: 'https://example.com/docs', + ), + keyboardType: TextInputType.url, + ), + const SizedBox(height: 16), + SwitchListTile( + title: Text('isPublic').tr(), + value: isPublic.value, + onChanged: (value) => isPublic.value = value, + ), + SwitchListTile( + title: Text('isInteractive').tr(), + value: isInteractive.value, + onChanged: (value) => isInteractive.value = value, + ), + const SizedBox(height: 16), + Align( + alignment: Alignment.centerRight, + child: TextButton.icon( + onPressed: + submitting.value ? null : performAction, + label: Text('saveChanges'.tr()), + icon: const Icon(Symbols.save), + ), + ), + ], + ).padding(all: 24), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/developers/edit_bot.g.dart b/lib/screens/developers/edit_bot.g.dart new file mode 100644 index 00000000..4f265b5c --- /dev/null +++ b/lib/screens/developers/edit_bot.g.dart @@ -0,0 +1,144 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'edit_bot.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$botHash() => r'267c75029a194fe180aeaebf12cbb0c1da9b8529'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [bot]. +@ProviderFor(bot) +const botProvider = BotFamily(); + +/// See also [bot]. +class BotFamily extends Family> { + /// See also [bot]. + const BotFamily(); + + /// See also [bot]. + BotProvider call(String id) { + return BotProvider(id); + } + + @override + BotProvider getProviderOverride(covariant BotProvider provider) { + return call(provider.id); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'botProvider'; +} + +/// See also [bot]. +class BotProvider extends AutoDisposeFutureProvider { + /// See also [bot]. + BotProvider(String id) + : this._internal( + (ref) => bot(ref as BotRef, id), + from: botProvider, + name: r'botProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$botHash, + dependencies: BotFamily._dependencies, + allTransitiveDependencies: BotFamily._allTransitiveDependencies, + id: id, + ); + + BotProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.id, + }) : super.internal(); + + final String id; + + @override + Override overrideWith(FutureOr Function(BotRef provider) create) { + return ProviderOverride( + origin: this, + override: BotProvider._internal( + (ref) => create(ref as BotRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + id: id, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _BotProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is BotProvider && other.id == id; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, id.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin BotRef on AutoDisposeFutureProviderRef { + /// The parameter `id` of this provider. + String get id; +} + +class _BotProviderElement extends AutoDisposeFutureProviderElement + with BotRef { + _BotProviderElement(super.provider); + + @override + String get id => (origin as BotProvider).id; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/screens/developers/hub.dart b/lib/screens/developers/hub.dart index 581fe126..8d535151 100644 --- a/lib/screens/developers/hub.dart +++ b/lib/screens/developers/hub.dart @@ -251,6 +251,24 @@ class DeveloperHubScreen extends HookConsumerWidget { ); }, ), + ListTile( + minTileHeight: 48, + title: Text('bots').tr(), + trailing: Icon(Symbols.chevron_right), + leading: const Icon(Symbols.smart_toy), + contentPadding: EdgeInsets.symmetric( + horizontal: 24, + ), + onTap: () { + context.pushNamed( + 'developerBots', + pathParameters: { + 'name': + currentDeveloper.value!.publisher!.name, + }, + ); + }, + ), ], ), ), diff --git a/lib/screens/developers/hub.g.dart b/lib/screens/developers/hub.g.dart index d287526a..791e3c64 100644 --- a/lib/screens/developers/hub.g.dart +++ b/lib/screens/developers/hub.g.dart @@ -6,7 +6,7 @@ part of 'hub.dart'; // RiverpodGenerator // ************************************************************************** -String _$developerStatsHash() => r'45546f29ec7cd1a9c3a4e0f4e39275e78bf34755'; +String _$developerStatsHash() => r'4ca5c3f7abf4158cb32116e806f18faa888020d5'; /// Copied from Dart SDK class _SystemHash { @@ -149,7 +149,7 @@ class _DeveloperStatsProviderElement String? get uname => (origin as DeveloperStatsProvider).uname; } -String _$developersHash() => r'252341098617ac398ce133994453f318dd3edbd2'; +String _$developersHash() => r'1793a1897ad105cb424525b357fd33ed15215f26'; /// See also [developers]. @ProviderFor(developers)