Bot basis

This commit is contained in:
2025-08-23 17:07:42 +08:00
parent 4beda9200e
commit 178c12b893
14 changed files with 323 additions and 346 deletions

View File

@@ -651,6 +651,10 @@
"editProject": "Edit Project", "editProject": "Edit Project",
"projectDetails": "Project Details", "projectDetails": "Project Details",
"createBot": "Create Bot", "createBot": "Create Bot",
"bots": "Bots",
"noBots": "No bots yet.",
"deleteBotHint": "Are you sure you want to delete this bot? This action cannot be undone.",
"deleteBot": "Delete Bot",
"customApps": "Custom Apps", "customApps": "Custom Apps",
"noCustomApps": "No custom apps yet.", "noCustomApps": "No custom apps yet.",
"createCustomApp": "Create Custom App", "createCustomApp": "Create Custom App",
@@ -885,5 +889,6 @@
"socialCreditsLevelGood": "Good", "socialCreditsLevelGood": "Good",
"socialCreditsLevelExcellent": "Excellent", "socialCreditsLevelExcellent": "Excellent",
"orderByPopularity": "Sort by popularity", "orderByPopularity": "Sort by popularity",
"orderByReleaseDate": "Sort by release date" "orderByReleaseDate": "Sort by release date",
"editBot": "Edit Bot"
} }

View File

@@ -1,5 +1,4 @@
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/file.dart';
import 'package:island/models/account.dart'; import 'package:island/models/account.dart';
part 'bot.freezed.dart'; part 'bot.freezed.dart';
@@ -8,20 +7,13 @@ part 'bot.g.dart';
@freezed @freezed
sealed class Bot with _$Bot { sealed class Bot with _$Bot {
const factory Bot({ const factory Bot({
@Default('') String id, required String id,
@Default('') String name, required String slug,
@Default('') String slug, required bool isActive,
String? description, required String projectId,
@Default(0) int status, required DateTime createdAt,
SnCloudFile? picture, required DateTime updatedAt,
SnCloudFile? background, required SnAccount account,
SnVerificationMark? verification,
BotConfig? config,
BotLinks? links,
@Default('') String publisherId,
@Default('') String appId,
DateTime? createdAt,
DateTime? updatedAt,
}) = _Bot; }) = _Bot;
factory Bot.fromJson(Map<String, dynamic> json) => _$BotFromJson(json); factory Bot.fromJson(Map<String, dynamic> json) => _$BotFromJson(json);

View File

@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$Bot { 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; String get id; String get slug; bool get isActive; String get projectId; DateTime get createdAt; DateTime get updatedAt; SnAccount get account;
/// Create a copy of Bot /// Create a copy of Bot
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $BotCopyWith<Bot> get copyWith => _$BotCopyWithImpl<Bot>(this as Bot, _$identity
@override @override
bool operator ==(Object other) { 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)); return identical(this, other) || (other.runtimeType == runtimeType&&other is Bot&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.isActive, isActive) || other.isActive == isActive)&&(identical(other.projectId, projectId) || other.projectId == projectId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.account, account) || other.account == account));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,id,name,slug,description,status,picture,background,verification,config,links,publisherId,appId,createdAt,updatedAt); int get hashCode => Object.hash(runtimeType,id,slug,isActive,projectId,createdAt,updatedAt,account);
@override @override
String toString() { 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)'; return 'Bot(id: $id, slug: $slug, isActive: $isActive, projectId: $projectId, createdAt: $createdAt, updatedAt: $updatedAt, account: $account)';
} }
@@ -48,11 +48,11 @@ abstract mixin class $BotCopyWith<$Res> {
factory $BotCopyWith(Bot value, $Res Function(Bot) _then) = _$BotCopyWithImpl; factory $BotCopyWith(Bot value, $Res Function(Bot) _then) = _$BotCopyWithImpl;
@useResult @useResult
$Res call({ $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 String id, String slug, bool isActive, String projectId, DateTime createdAt, DateTime updatedAt, SnAccount account
}); });
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;$BotConfigCopyWith<$Res>? get config;$BotLinksCopyWith<$Res>? get links; $SnAccountCopyWith<$Res> get account;
} }
/// @nodoc /// @nodoc
@@ -65,84 +65,26 @@ class _$BotCopyWithImpl<$Res>
/// Create a copy of Bot /// Create a copy of Bot
/// with the given fields replaced by the non-null parameter values. /// 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,}) { @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? isActive = null,Object? projectId = null,Object? createdAt = null,Object? updatedAt = null,Object? account = null,}) {
return _then(_self.copyWith( return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable 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,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,isActive: null == isActive ? _self.isActive : isActive // ignore: cast_nullable_to_non_nullable
as String?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable as bool,projectId: null == projectId ? _self.projectId : projectId // ignore: cast_nullable_to_non_nullable
as int,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable as DateTime,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
as SnVerificationMark?,config: freezed == config ? _self.config : config // ignore: cast_nullable_to_non_nullable as SnAccount,
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 /// Create a copy of Bot
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$SnCloudFileCopyWith<$Res>? get picture { $SnAccountCopyWith<$Res> get account {
if (_self.picture == null) {
return null;
}
return $SnCloudFileCopyWith<$Res>(_self.picture!, (value) { return $SnAccountCopyWith<$Res>(_self.account, (value) {
return _then(_self.copyWith(picture: value)); return _then(_self.copyWith(account: 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));
}); });
} }
} }
@@ -223,10 +165,10 @@ return $default(_that);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(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; @optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, bool isActive, String projectId, DateTime createdAt, DateTime updatedAt, SnAccount account)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) { switch (_that) {
case _Bot() when $default != null: 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 $default(_that.id,_that.slug,_that.isActive,_that.projectId,_that.createdAt,_that.updatedAt,_that.account);case _:
return orElse(); return orElse();
} }
@@ -244,10 +186,10 @@ return $default(_that.id,_that.name,_that.slug,_that.description,_that.status,_t
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult when<TResult extends Object?>(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; @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, bool isActive, String projectId, DateTime createdAt, DateTime updatedAt, SnAccount account) $default,) {final _that = this;
switch (_that) { switch (_that) {
case _Bot(): 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);} return $default(_that.id,_that.slug,_that.isActive,_that.projectId,_that.createdAt,_that.updatedAt,_that.account);}
} }
/// A variant of `when` that fallback to returning `null` /// A variant of `when` that fallback to returning `null`
/// ///
@@ -261,10 +203,10 @@ return $default(_that.id,_that.name,_that.slug,_that.description,_that.status,_t
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(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; @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, bool isActive, String projectId, DateTime createdAt, DateTime updatedAt, SnAccount account)? $default,) {final _that = this;
switch (_that) { switch (_that) {
case _Bot() when $default != null: 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 $default(_that.id,_that.slug,_that.isActive,_that.projectId,_that.createdAt,_that.updatedAt,_that.account);case _:
return null; return null;
} }
@@ -276,23 +218,16 @@ return $default(_that.id,_that.name,_that.slug,_that.description,_that.status,_t
@JsonSerializable() @JsonSerializable()
class _Bot implements Bot { 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}); const _Bot({required this.id, required this.slug, required this.isActive, required this.projectId, required this.createdAt, required this.updatedAt, required this.account});
factory _Bot.fromJson(Map<String, dynamic> json) => _$BotFromJson(json); factory _Bot.fromJson(Map<String, dynamic> json) => _$BotFromJson(json);
@override@JsonKey() final String id; @override final String id;
@override@JsonKey() final String name; @override final String slug;
@override@JsonKey() final String slug; @override final bool isActive;
@override final String? description; @override final String projectId;
@override@JsonKey() final int status; @override final DateTime createdAt;
@override final SnCloudFile? picture; @override final DateTime updatedAt;
@override final SnCloudFile? background; @override final SnAccount account;
@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 /// Create a copy of Bot
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -307,16 +242,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { 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)); return identical(this, other) || (other.runtimeType == runtimeType&&other is _Bot&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.isActive, isActive) || other.isActive == isActive)&&(identical(other.projectId, projectId) || other.projectId == projectId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.account, account) || other.account == account));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,id,name,slug,description,status,picture,background,verification,config,links,publisherId,appId,createdAt,updatedAt); int get hashCode => Object.hash(runtimeType,id,slug,isActive,projectId,createdAt,updatedAt,account);
@override @override
String toString() { 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)'; return 'Bot(id: $id, slug: $slug, isActive: $isActive, projectId: $projectId, createdAt: $createdAt, updatedAt: $updatedAt, account: $account)';
} }
@@ -327,11 +262,11 @@ abstract mixin class _$BotCopyWith<$Res> implements $BotCopyWith<$Res> {
factory _$BotCopyWith(_Bot value, $Res Function(_Bot) _then) = __$BotCopyWithImpl; factory _$BotCopyWith(_Bot value, $Res Function(_Bot) _then) = __$BotCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $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 String id, String slug, bool isActive, String projectId, DateTime createdAt, DateTime updatedAt, SnAccount account
}); });
@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; @override $SnAccountCopyWith<$Res> get account;
} }
/// @nodoc /// @nodoc
@@ -344,23 +279,16 @@ class __$BotCopyWithImpl<$Res>
/// Create a copy of Bot /// Create a copy of Bot
/// with the given fields replaced by the non-null parameter values. /// 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,}) { @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? isActive = null,Object? projectId = null,Object? createdAt = null,Object? updatedAt = null,Object? account = null,}) {
return _then(_Bot( return _then(_Bot(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable 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,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,isActive: null == isActive ? _self.isActive : isActive // ignore: cast_nullable_to_non_nullable
as String?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable as bool,projectId: null == projectId ? _self.projectId : projectId // ignore: cast_nullable_to_non_nullable
as int,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable as DateTime,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
as SnVerificationMark?,config: freezed == config ? _self.config : config // ignore: cast_nullable_to_non_nullable as SnAccount,
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?,
)); ));
} }
@@ -368,61 +296,10 @@ as DateTime?,
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$SnCloudFileCopyWith<$Res>? get picture { $SnAccountCopyWith<$Res> get account {
if (_self.picture == null) {
return null;
}
return $SnCloudFileCopyWith<$Res>(_self.picture!, (value) { return $SnAccountCopyWith<$Res>(_self.account, (value) {
return _then(_self.copyWith(picture: value)); return _then(_self.copyWith(account: 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));
}); });
} }
} }

View File

@@ -7,60 +7,23 @@ part of 'bot.dart';
// ************************************************************************** // **************************************************************************
_Bot _$BotFromJson(Map<String, dynamic> json) => _Bot( _Bot _$BotFromJson(Map<String, dynamic> json) => _Bot(
id: json['id'] as String? ?? '', id: json['id'] as String,
name: json['name'] as String? ?? '', slug: json['slug'] as String,
slug: json['slug'] as String? ?? '', isActive: json['is_active'] as bool,
description: json['description'] as String?, projectId: json['project_id'] as String,
status: (json['status'] as num?)?.toInt() ?? 0, createdAt: DateTime.parse(json['created_at'] as String),
picture: updatedAt: DateTime.parse(json['updated_at'] as String),
json['picture'] == null account: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
? null
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
background:
json['background'] == null
? null
: SnCloudFile.fromJson(json['background'] as Map<String, dynamic>),
verification:
json['verification'] == null
? null
: SnVerificationMark.fromJson(
json['verification'] as Map<String, dynamic>,
),
config:
json['config'] == null
? null
: BotConfig.fromJson(json['config'] as Map<String, dynamic>),
links:
json['links'] == null
? null
: BotLinks.fromJson(json['links'] as Map<String, dynamic>),
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<String, dynamic> _$BotToJson(_Bot instance) => <String, dynamic>{ Map<String, dynamic> _$BotToJson(_Bot instance) => <String, dynamic>{
'id': instance.id, 'id': instance.id,
'name': instance.name,
'slug': instance.slug, 'slug': instance.slug,
'description': instance.description, 'is_active': instance.isActive,
'status': instance.status, 'project_id': instance.projectId,
'picture': instance.picture?.toJson(), 'created_at': instance.createdAt.toIso8601String(),
'background': instance.background?.toJson(), 'updated_at': instance.updatedAt.toIso8601String(),
'verification': instance.verification?.toJson(), 'account': instance.account.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<String, dynamic> json) => _BotConfig( _BotConfig _$BotConfigFromJson(Map<String, dynamic> json) => _BotConfig(

View File

@@ -366,17 +366,6 @@ final routerProvider = Provider<GoRouter>((ref) {
id: state.pathParameters['id']!, id: state.pathParameters['id']!,
), ),
), ),
GoRoute(
name: 'developerBotDetail',
path: 'bots/:id/detail',
builder:
(context, state) => EditBotScreen(
// Assuming EditBotScreen can also serve as a detail view
publisherName: state.pathParameters['name']!,
projectId: state.pathParameters['projectId']!,
id: state.pathParameters['id']!,
),
),
], ],
), ),
], ],

View File

@@ -6,7 +6,7 @@ part of 'apps.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$customAppsHash() => r'c36e5ee59f16a29220dc0e9fba65e579d341a28f'; String _$customAppsHash() => r'450bedaf4220b8963cb44afeb14d4c0e80f01b11';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View File

@@ -71,14 +71,19 @@ class BotsScreen extends HookConsumerWidget {
return Card( return Card(
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
child: ListTile( child: ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
leading: CircleAvatar( leading: CircleAvatar(
child: child:
bot.picture != null bot.account.profile.picture != null
? CloudFileWidget(item: bot.picture!) ? ProfilePictureWidget(
file: bot.account.profile.picture!,
)
: const Icon(Symbols.smart_toy), : const Icon(Symbols.smart_toy),
), ),
title: Text(bot.name), title: Text(bot.account.nick),
subtitle: Text(bot.description ?? ''), subtitle: Text(bot.account.name),
trailing: PopupMenuButton( trailing: PopupMenuButton(
itemBuilder: itemBuilder:
(context) => [ (context) => [
@@ -135,13 +140,9 @@ class BotsScreen extends HookConsumerWidget {
}, },
), ),
onTap: () { onTap: () {
context.pushNamed( context.goNamed(
'developerBotDetail', 'accountProfile',
pathParameters: { pathParameters: {'name': bot.account.name},
'name': publisherName,
'projectId': projectId,
'id': bot.id,
},
); );
}, },
), ),

View File

@@ -6,7 +6,7 @@ part of 'bots.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$botsHash() => r'a54c8b4df23f94754398706779044903fcca6eea'; String _$botsHash() => r'15cefd5781350eb68208a342e85fcb0b9e0e3269';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View File

@@ -6,7 +6,7 @@ part of 'edit_app.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$customAppHash() => r'17b3d1385e59bc5ee7f13fb0f11c56cf8a9ba41f'; String _$customAppHash() => r'8e1b38f3dc9b04fad362ee1141fcbfc53f008c09';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View File

@@ -55,31 +55,44 @@ class EditBotScreen extends HookConsumerWidget {
final submitting = useState(false); final submitting = useState(false);
final nameController = useTextEditingController(); final nameController = useTextEditingController();
final nickController = useTextEditingController();
final slugController = useTextEditingController(); final slugController = useTextEditingController();
final descriptionController = useTextEditingController();
final picture = useState<SnCloudFile?>(null); final picture = useState<SnCloudFile?>(null);
final websiteController = useTextEditingController();
final documentationController = useTextEditingController();
final isPublic = useState(false); final firstNameController = useTextEditingController();
final isInteractive = useState(false); final middleNameController = useTextEditingController();
final lastNameController = useTextEditingController();
final genderController = useTextEditingController();
final pronounsController = useTextEditingController();
final locationController = useTextEditingController();
final timeZoneController = useTextEditingController();
final bioController = useTextEditingController();
final birthday = useState<DateTime?>(null);
final background = useState<SnCloudFile?>(null);
useEffect(() { useEffect(() {
if (botData?.value != null) { if (botData?.value != null) {
nameController.text = botData!.value!.name; nameController.text = botData!.value!.account.name;
nickController.text = botData.value!.account.nick;
slugController.text = botData.value!.slug; slugController.text = botData.value!.slug;
descriptionController.text = botData.value!.description ?? ''; picture.value = botData.value!.account.profile.picture;
picture.value = botData.value!.picture; background.value = botData.value!.account.profile.background;
websiteController.text = botData.value!.links?.website ?? '';
documentationController.text = // Populate from botData.value.account.profile
botData.value!.links?.documentation ?? ''; firstNameController.text = botData.value!.account.profile.firstName;
isPublic.value = botData.value!.config?.isPublic ?? false; middleNameController.text = botData.value!.account.profile.middleName;
isInteractive.value = botData.value!.config?.isInteractive ?? false; lastNameController.text = botData.value!.account.profile.lastName;
genderController.text = botData.value!.account.profile.gender;
pronounsController.text = botData.value!.account.profile.pronouns;
locationController.text = botData.value!.account.profile.location;
timeZoneController.text = botData.value!.account.profile.timeZone;
bioController.text = botData.value!.account.profile.bio;
birthday.value = botData.value!.account.profile.birthday?.toLocal();
} }
return null; return null;
}, [botData]); }, [botData]);
void setPicture() async { void setPicture(String position) async {
showLoadingModal(context); showLoadingModal(context);
var result = await ref var result = await ref
.read(imagePickerProvider) .read(imagePickerProvider)
@@ -94,7 +107,12 @@ class EditBotScreen extends HookConsumerWidget {
result = await cropImage( result = await cropImage(
context, context,
image: result, image: result,
allowedAspectRatios: [const CropAspectRatio(height: 1, width: 1)], allowedAspectRatios: [
if (position == 'background')
const CropAspectRatio(height: 7, width: 16)
else
const CropAspectRatio(height: 1, width: 1),
],
); );
if (result == null) { if (result == null) {
if (context.mounted) hideLoadingModal(context); if (context.mounted) hideLoadingModal(context);
@@ -122,7 +140,12 @@ class EditBotScreen extends HookConsumerWidget {
if (cloudFile == null) { if (cloudFile == null) {
throw ArgumentError('Failed to upload the file...'); throw ArgumentError('Failed to upload the file...');
} }
picture.value = cloudFile; switch (position) {
case 'picture':
picture.value = cloudFile;
case 'background':
background.value = cloudFile;
}
} catch (err) { } catch (err) {
showErrorAlert(err); showErrorAlert(err);
} finally { } finally {
@@ -135,37 +158,42 @@ class EditBotScreen extends HookConsumerWidget {
final client = ref.read(apiClientProvider); final client = ref.read(apiClientProvider);
final data = { final data = {
'name': nameController.text, 'name': nameController.text,
'nick': nickController.text,
'slug': slugController.text, 'slug': slugController.text,
'description': descriptionController.text,
'picture_id': picture.value?.id, 'picture_id': picture.value?.id,
'config': { 'background_id': background.value?.id,
'is_public': isPublic.value, 'first_name': firstNameController.text,
'is_interactive': isInteractive.value, 'middle_name': middleNameController.text,
}, 'last_name': lastNameController.text,
'links': { 'gender': genderController.text,
'website': 'pronouns': pronounsController.text,
websiteController.text.isNotEmpty ? websiteController.text : null, 'location': locationController.text,
'documentation': 'time_zone': timeZoneController.text,
documentationController.text.isNotEmpty 'bio': bioController.text,
? documentationController.text 'birthday': birthday.value?.toUtc().toIso8601String(),
: null,
},
}; };
if (isNew) { try {
await client.post( showLoadingModal(context);
'/develop/developers/$publisherName/projects/$projectId/bots', if (isNew) {
data: data, await client.post(
); '/develop/developers/$publisherName/projects/$projectId/bots',
} else { data: data,
await client.patch( );
'/develop/developers/$publisherName/projects/$projectId/bots/$id', } else {
data: data, await client.patch(
); '/develop/developers/$publisherName/projects/$projectId/bots/$id',
} data: data,
);
}
if (context.mounted) { if (context.mounted) {
context.pop(); context.pop();
}
} catch (err) {
showErrorAlert(err);
} finally {
if (context.mounted) hideLoadingModal(context);
} }
} }
@@ -186,22 +214,44 @@ class EditBotScreen extends HookConsumerWidget {
child: Column( child: Column(
children: [ children: [
AspectRatio( AspectRatio(
aspectRatio: 1, aspectRatio: 16 / 7,
child: GestureDetector( child: Stack(
onTap: setPicture, clipBehavior: Clip.none,
child: Container( fit: StackFit.expand,
color: children: [
Theme.of( GestureDetector(
context, child: Container(
).colorScheme.surfaceContainerHigh, color:
child: Theme.of(
picture.value != null context,
? CloudFileWidget( ).colorScheme.surfaceContainerHigh,
item: picture.value!, child:
fit: BoxFit.cover, background.value != null
) ? CloudFileWidget(
: const Icon(Symbols.smart_toy, size: 48), item: background.value!,
), fit: BoxFit.cover,
)
: const SizedBox.shrink(),
),
onTap: () {
setPicture('background');
},
),
Positioned(
left: 20,
bottom: -32,
child: GestureDetector(
child: ProfilePictureWidget(
fileId: picture.value?.id,
radius: 40,
fallbackIcon: Symbols.smart_toy,
),
onTap: () {
setPicture('picture');
},
),
),
],
), ),
).padding(bottom: 32), ).padding(bottom: 32),
Form( Form(
@@ -213,6 +263,14 @@ class EditBotScreen extends HookConsumerWidget {
decoration: InputDecoration(labelText: 'name'.tr()), decoration: InputDecoration(labelText: 'name'.tr()),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField(
controller: nickController,
decoration: InputDecoration(
labelText: 'nickname'.tr(),
alignLabelWithHint: true,
),
),
const SizedBox(height: 16),
TextFormField( TextFormField(
controller: slugController, controller: slugController,
decoration: InputDecoration( decoration: InputDecoration(
@@ -222,41 +280,129 @@ class EditBotScreen extends HookConsumerWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( TextFormField(
controller: descriptionController, controller: bioController,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'description'.tr(), labelText: 'bio'.tr(),
alignLabelWithHint: true, alignLabelWithHint: true,
), ),
maxLines: 3, maxLines: 3,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( Row(
controller: websiteController, spacing: 16,
decoration: InputDecoration( children: [
labelText: 'websiteUrl'.tr(), Expanded(
hintText: 'https://example.com', child: TextFormField(
), controller: firstNameController,
keyboardType: TextInputType.url, decoration: InputDecoration(
labelText: 'firstName'.tr(),
),
),
),
Expanded(
child: TextFormField(
controller: middleNameController,
decoration: InputDecoration(
labelText: 'middleName'.tr(),
),
),
),
Expanded(
child: TextFormField(
controller: lastNameController,
decoration: InputDecoration(
labelText: 'lastName'.tr(),
),
),
),
],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( Row(
controller: documentationController, spacing: 16,
decoration: InputDecoration( children: [
labelText: 'documentationUrl'.tr(), Expanded(
hintText: 'https://example.com/docs', child: TextFormField(
), controller: genderController,
keyboardType: TextInputType.url, decoration: InputDecoration(
labelText: 'gender'.tr(),
),
),
),
Expanded(
child: TextFormField(
controller: pronounsController,
decoration: InputDecoration(
labelText: 'pronouns'.tr(),
),
),
),
],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
SwitchListTile( Row(
title: Text('isPublic').tr(), spacing: 16,
value: isPublic.value, children: [
onChanged: (value) => isPublic.value = value, Expanded(
child: TextFormField(
controller: locationController,
decoration: InputDecoration(
labelText: 'location'.tr(),
),
),
),
Expanded(
child: TextFormField(
controller: timeZoneController,
decoration: InputDecoration(
labelText: 'timeZone'.tr(),
),
),
),
],
), ),
SwitchListTile( const SizedBox(height: 16),
title: Text('isInteractive').tr(), GestureDetector(
value: isInteractive.value, onTap: () async {
onChanged: (value) => isInteractive.value = value, final date = await showDatePicker(
context: context,
initialDate: birthday.value ?? DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime.now(),
);
if (date != null) {
birthday.value = date;
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).dividerColor,
width: 1,
),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'birthday'.tr(),
style: TextStyle(
color: Theme.of(context).hintColor,
),
),
Text(
birthday.value != null
? DateFormat.yMMMd().format(
birthday.value!,
)
: 'Select a date'.tr(),
),
],
),
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Align( Align(
@@ -264,7 +410,7 @@ class EditBotScreen extends HookConsumerWidget {
child: TextButton.icon( child: TextButton.icon(
onPressed: onPressed:
submitting.value ? null : performAction, submitting.value ? null : performAction,
label: Text('saveChanges'.tr()), label: Text('saveChanges').tr(),
icon: const Icon(Symbols.save), icon: const Icon(Symbols.save),
), ),
), ),

View File

@@ -6,7 +6,7 @@ part of 'edit_bot.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$botHash() => r'a3e412ed575c513434bc718b7920db1d017111f4'; String _$botHash() => r'7bec47bb2a4061a5babc6d6d19c3d4c320c91188';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View File

@@ -6,7 +6,7 @@ part of 'edit_project.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$devProjectHash() => r'fc68254c6e598e3fa05c86c36f1469c0b689bc43'; String _$devProjectHash() => r'd92be3f5cdc510c2a377615ed5c70622a6842bf2';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View File

@@ -61,6 +61,10 @@ class DevProjectsScreen extends HookConsumerWidget {
return Card( return Card(
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
child: ListTile( child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
contentPadding: EdgeInsets.only(left: 20, right: 12),
title: Text(project.name), title: Text(project.name),
subtitle: Text(project.description ?? ''), subtitle: Text(project.description ?? ''),
trailing: PopupMenuButton( trailing: PopupMenuButton(

View File

@@ -6,7 +6,7 @@ part of 'projects.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$devProjectsHash() => r'4c86ea5c3c02185514dbfa32804f1529f68d56c7'; String _$devProjectsHash() => r'87fdcab47cd7d79ab019a5625617abeb1ffa1f39';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {