✨ File rename, sensitive
This commit is contained in:
@@ -737,5 +737,21 @@
|
|||||||
"repliesLoadMore": "Load more replies",
|
"repliesLoadMore": "Load more replies",
|
||||||
"attachmentsRecentUploads": "Recent Uploads",
|
"attachmentsRecentUploads": "Recent Uploads",
|
||||||
"attachmentsManualInput": "Manual Input",
|
"attachmentsManualInput": "Manual Input",
|
||||||
"crop": "Crop"
|
"crop": "Crop",
|
||||||
|
"rename": "Rename",
|
||||||
|
"markAsSensitive": "Mark as Sensitive",
|
||||||
|
"fileName": "File name",
|
||||||
|
"sensitiveCategories.language": "Language",
|
||||||
|
"sensitiveCategories.sexualContent": "Sexual Content",
|
||||||
|
"sensitiveCategories.violence": "Violence",
|
||||||
|
"sensitiveCategories.profanity": "Profanity",
|
||||||
|
"sensitiveCategories.hateSpeech": "Hate Speech",
|
||||||
|
"sensitiveCategories.racism": "Racism",
|
||||||
|
"sensitiveCategories.adultContent": "Adult Content",
|
||||||
|
"sensitiveCategories.drugAbuse": "Drug Abuse",
|
||||||
|
"sensitiveCategories.alcoholAbuse": "Alcohol Abuse",
|
||||||
|
"sensitiveCategories.gambling": "Gambling",
|
||||||
|
"sensitiveCategories.selfHarm": "Self-harm",
|
||||||
|
"sensitiveCategories.childAbuse": "Child Abuse",
|
||||||
|
"sensitiveCategories.other": "Other"
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@ sealed class SnCloudFile with _$SnCloudFile {
|
|||||||
required String? description,
|
required String? description,
|
||||||
required Map<String, dynamic>? fileMeta,
|
required Map<String, dynamic>? fileMeta,
|
||||||
required Map<String, dynamic>? userMeta,
|
required Map<String, dynamic>? userMeta,
|
||||||
|
@Default([]) List<int> sensitiveMarks,
|
||||||
required String? mimeType,
|
required String? mimeType,
|
||||||
required String? hash,
|
required String? hash,
|
||||||
required int size,
|
required int size,
|
||||||
|
@@ -278,7 +278,7 @@ as bool,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnCloudFile {
|
mixin _$SnCloudFile {
|
||||||
|
|
||||||
String get id; String get name; String? get description; Map<String, dynamic>? get fileMeta; Map<String, dynamic>? get userMeta; String? get mimeType; String? get hash; int get size; DateTime? get uploadedAt; String? get uploadedTo; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get name; String? get description; Map<String, dynamic>? get fileMeta; Map<String, dynamic>? get userMeta; List<int> get sensitiveMarks; String? get mimeType; String? get hash; int get size; DateTime? get uploadedAt; String? get uploadedTo; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnCloudFile
|
/// Create a copy of SnCloudFile
|
||||||
/// 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)
|
||||||
@@ -291,16 +291,16 @@ $SnCloudFileCopyWith<SnCloudFile> get copyWith => _$SnCloudFileCopyWithImpl<SnCl
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&const DeepCollectionEquality().equals(other.sensitiveMarks, sensitiveMarks)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(fileMeta),const DeepCollectionEquality().hash(userMeta),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(fileMeta),const DeepCollectionEquality().hash(userMeta),const DeepCollectionEquality().hash(sensitiveMarks),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, sensitiveMarks: $sensitiveMarks, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ abstract mixin class $SnCloudFileCopyWith<$Res> {
|
|||||||
factory $SnCloudFileCopyWith(SnCloudFile value, $Res Function(SnCloudFile) _then) = _$SnCloudFileCopyWithImpl;
|
factory $SnCloudFileCopyWith(SnCloudFile value, $Res Function(SnCloudFile) _then) = _$SnCloudFileCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -328,14 +328,15 @@ class _$SnCloudFileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnCloudFile
|
/// Create a copy of SnCloudFile
|
||||||
/// 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? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? sensitiveMarks = null,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
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,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,fileMeta: freezed == fileMeta ? _self.fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable
|
as String?,fileMeta: freezed == fileMeta ? _self.fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self.userMeta : userMeta // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self.userMeta : userMeta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,sensitiveMarks: null == sensitiveMarks ? _self.sensitiveMarks : sensitiveMarks // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<int>,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable
|
as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
||||||
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -425,10 +426,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnCloudFile() when $default != null:
|
case _SnCloudFile() when $default != null:
|
||||||
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -446,10 +447,10 @@ return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userM
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnCloudFile():
|
case _SnCloudFile():
|
||||||
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -463,10 +464,10 @@ return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userM
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnCloudFile() when $default != null:
|
case _SnCloudFile() when $default != null:
|
||||||
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -478,7 +479,7 @@ return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userM
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnCloudFile implements SnCloudFile {
|
class _SnCloudFile implements SnCloudFile {
|
||||||
const _SnCloudFile({required this.id, required this.name, required this.description, required final Map<String, dynamic>? fileMeta, required final Map<String, dynamic>? userMeta, required this.mimeType, required this.hash, required this.size, required this.uploadedAt, required this.uploadedTo, required this.createdAt, required this.updatedAt, required this.deletedAt}): _fileMeta = fileMeta,_userMeta = userMeta;
|
const _SnCloudFile({required this.id, required this.name, required this.description, required final Map<String, dynamic>? fileMeta, required final Map<String, dynamic>? userMeta, final List<int> sensitiveMarks = const [], required this.mimeType, required this.hash, required this.size, required this.uploadedAt, required this.uploadedTo, required this.createdAt, required this.updatedAt, required this.deletedAt}): _fileMeta = fileMeta,_userMeta = userMeta,_sensitiveMarks = sensitiveMarks;
|
||||||
factory _SnCloudFile.fromJson(Map<String, dynamic> json) => _$SnCloudFileFromJson(json);
|
factory _SnCloudFile.fromJson(Map<String, dynamic> json) => _$SnCloudFileFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -502,6 +503,13 @@ class _SnCloudFile implements SnCloudFile {
|
|||||||
return EqualUnmodifiableMapView(value);
|
return EqualUnmodifiableMapView(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<int> _sensitiveMarks;
|
||||||
|
@override@JsonKey() List<int> get sensitiveMarks {
|
||||||
|
if (_sensitiveMarks is EqualUnmodifiableListView) return _sensitiveMarks;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_sensitiveMarks);
|
||||||
|
}
|
||||||
|
|
||||||
@override final String? mimeType;
|
@override final String? mimeType;
|
||||||
@override final String? hash;
|
@override final String? hash;
|
||||||
@override final int size;
|
@override final int size;
|
||||||
@@ -524,16 +532,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._fileMeta, _fileMeta)&&const DeepCollectionEquality().equals(other._userMeta, _userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._fileMeta, _fileMeta)&&const DeepCollectionEquality().equals(other._userMeta, _userMeta)&&const DeepCollectionEquality().equals(other._sensitiveMarks, _sensitiveMarks)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(_fileMeta),const DeepCollectionEquality().hash(_userMeta),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(_fileMeta),const DeepCollectionEquality().hash(_userMeta),const DeepCollectionEquality().hash(_sensitiveMarks),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, sensitiveMarks: $sensitiveMarks, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -544,7 +552,7 @@ abstract mixin class _$SnCloudFileCopyWith<$Res> implements $SnCloudFileCopyWith
|
|||||||
factory _$SnCloudFileCopyWith(_SnCloudFile value, $Res Function(_SnCloudFile) _then) = __$SnCloudFileCopyWithImpl;
|
factory _$SnCloudFileCopyWith(_SnCloudFile value, $Res Function(_SnCloudFile) _then) = __$SnCloudFileCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -561,14 +569,15 @@ class __$SnCloudFileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnCloudFile
|
/// Create a copy of SnCloudFile
|
||||||
/// 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? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? sensitiveMarks = null,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnCloudFile(
|
return _then(_SnCloudFile(
|
||||||
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,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,fileMeta: freezed == fileMeta ? _self._fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable
|
as String?,fileMeta: freezed == fileMeta ? _self._fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self._userMeta : userMeta // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self._userMeta : userMeta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,sensitiveMarks: null == sensitiveMarks ? _self._sensitiveMarks : sensitiveMarks // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<int>,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable
|
as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
||||||
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
@@ -33,6 +33,11 @@ _SnCloudFile _$SnCloudFileFromJson(Map<String, dynamic> json) => _SnCloudFile(
|
|||||||
description: json['description'] as String?,
|
description: json['description'] as String?,
|
||||||
fileMeta: json['file_meta'] as Map<String, dynamic>?,
|
fileMeta: json['file_meta'] as Map<String, dynamic>?,
|
||||||
userMeta: json['user_meta'] as Map<String, dynamic>?,
|
userMeta: json['user_meta'] as Map<String, dynamic>?,
|
||||||
|
sensitiveMarks:
|
||||||
|
(json['sensitive_marks'] as List<dynamic>?)
|
||||||
|
?.map((e) => (e as num).toInt())
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
mimeType: json['mime_type'] as String?,
|
mimeType: json['mime_type'] as String?,
|
||||||
hash: json['hash'] as String?,
|
hash: json['hash'] as String?,
|
||||||
size: (json['size'] as num).toInt(),
|
size: (json['size'] as num).toInt(),
|
||||||
@@ -56,6 +61,7 @@ Map<String, dynamic> _$SnCloudFileToJson(_SnCloudFile instance) =>
|
|||||||
'description': instance.description,
|
'description': instance.description,
|
||||||
'file_meta': instance.fileMeta,
|
'file_meta': instance.fileMeta,
|
||||||
'user_meta': instance.userMeta,
|
'user_meta': instance.userMeta,
|
||||||
|
'sensitive_marks': instance.sensitiveMarks,
|
||||||
'mime_type': instance.mimeType,
|
'mime_type': instance.mimeType,
|
||||||
'hash': instance.hash,
|
'hash': instance.hash,
|
||||||
'size': instance.size,
|
'size': instance.size,
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cross_file/cross_file.dart';
|
import 'package:cross_file/cross_file.dart';
|
||||||
@@ -5,14 +6,81 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/services/file.dart';
|
import 'package:island/services/file.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:super_context_menu/super_context_menu.dart';
|
import 'package:super_context_menu/super_context_menu.dart';
|
||||||
|
|
||||||
class AttachmentPreview extends StatelessWidget {
|
import 'sensitive.dart';
|
||||||
|
|
||||||
|
class SensitiveMarksSelector extends StatefulWidget {
|
||||||
|
final List<int> initial;
|
||||||
|
final ValueChanged<List<int>>? onChanged;
|
||||||
|
|
||||||
|
const SensitiveMarksSelector({
|
||||||
|
super.key,
|
||||||
|
required this.initial,
|
||||||
|
this.onChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SensitiveMarksSelector> createState() => SensitiveMarksSelectorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SensitiveMarksSelectorState extends State<SensitiveMarksSelector> {
|
||||||
|
late List<int> _selected;
|
||||||
|
|
||||||
|
List<int> get current => _selected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selected = [...widget.initial];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggle(int value) {
|
||||||
|
setState(() {
|
||||||
|
if (_selected.contains(value)) {
|
||||||
|
_selected.remove(value);
|
||||||
|
} else {
|
||||||
|
_selected.add(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
widget.onChanged?.call([..._selected]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// Build a list of all categories in fixed order as int list indices
|
||||||
|
final categories = kSensitiveCategoriesOrdered;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
for (var i = 0; i < categories.length; i++)
|
||||||
|
FilterChip(
|
||||||
|
label: Text(categories[i].i18nKey.tr()),
|
||||||
|
avatar: Text(categories[i].symbol),
|
||||||
|
selected: _selected.contains(i),
|
||||||
|
onSelected: (_) => _toggle(i),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AttachmentPreview extends HookConsumerWidget {
|
||||||
final UniversalFile item;
|
final UniversalFile item;
|
||||||
final double? progress;
|
final double? progress;
|
||||||
final Function(int)? onMove;
|
final Function(int)? onMove;
|
||||||
@@ -20,6 +88,7 @@ class AttachmentPreview extends StatelessWidget {
|
|||||||
final Function? onInsert;
|
final Function? onInsert;
|
||||||
final Function(UniversalFile)? onUpdate;
|
final Function(UniversalFile)? onUpdate;
|
||||||
final Function? onRequestUpload;
|
final Function? onRequestUpload;
|
||||||
|
|
||||||
const AttachmentPreview({
|
const AttachmentPreview({
|
||||||
super.key,
|
super.key,
|
||||||
required this.item,
|
required this.item,
|
||||||
@@ -31,8 +100,166 @@ class AttachmentPreview extends StatelessWidget {
|
|||||||
this.onInsert,
|
this.onInsert,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// GlobalKey for selector
|
||||||
|
static final GlobalKey<SensitiveMarksSelectorState> _sensitiveSelectorKey =
|
||||||
|
GlobalKey<SensitiveMarksSelectorState>();
|
||||||
|
|
||||||
|
Future<void> _showRenameDialog(BuildContext context, WidgetRef ref) async {
|
||||||
|
final nameController = TextEditingController(text: item.data.name);
|
||||||
|
String? errorMessage;
|
||||||
|
|
||||||
|
await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder:
|
||||||
|
(context) => SheetScaffold(
|
||||||
|
heightFactor: 0.6,
|
||||||
|
titleText: 'rename'.tr(),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
vertical: 24,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
controller: nameController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'fileName'.tr(),
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
errorText: errorMessage,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text('cancel'.tr()),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final newName = nameController.text.trim();
|
||||||
|
if (newName.isEmpty) {
|
||||||
|
errorMessage = 'fieldCannotBeEmpty'.tr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
showLoadingModal(context);
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
await apiClient.patch(
|
||||||
|
'/drive/files/${item.data.id}/name',
|
||||||
|
data: jsonEncode(newName),
|
||||||
|
);
|
||||||
|
final newData = item.data;
|
||||||
|
newData.name = newName;
|
||||||
|
final updatedFile = item.copyWith(data: newData);
|
||||||
|
onUpdate?.call(item.copyWith(data: updatedFile));
|
||||||
|
if (context.mounted) Navigator.pop(context);
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('rename'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 16, vertical: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _showSensitiveDialog(BuildContext context, WidgetRef ref) async {
|
||||||
|
await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder:
|
||||||
|
(context) => SheetScaffold(
|
||||||
|
heightFactor: 0.6,
|
||||||
|
titleText: 'markAsSensitive'.tr(),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
vertical: 24,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Sensitive categories checklist
|
||||||
|
SensitiveMarksSelector(
|
||||||
|
key: _sensitiveSelectorKey,
|
||||||
|
initial:
|
||||||
|
(item.data.sensitiveMarks ?? [])
|
||||||
|
.map((e) => e as int)
|
||||||
|
.cast<int>()
|
||||||
|
.toList(),
|
||||||
|
onChanged: (marks) {
|
||||||
|
// Update local data immediately (optimistic)
|
||||||
|
final newData = item.data;
|
||||||
|
newData.sensitiveMarks = marks;
|
||||||
|
final updatedFile = item.copyWith(data: newData);
|
||||||
|
onUpdate?.call(item.copyWith(data: updatedFile));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text('cancel'.tr()),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
showLoadingModal(context);
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
// Use the current selections from stateful selector via GlobalKey
|
||||||
|
final selectorState =
|
||||||
|
_sensitiveSelectorKey.currentState;
|
||||||
|
final marks = selectorState?.current ?? <int>[];
|
||||||
|
await apiClient.put(
|
||||||
|
'/drive/files/${item.data.id}/marks',
|
||||||
|
data: jsonEncode({'sensitive_marks': marks}),
|
||||||
|
);
|
||||||
|
final newData = item.data as SnCloudFile;
|
||||||
|
final updatedFile = item.copyWith(
|
||||||
|
data: newData.copyWith(sensitiveMarks: marks),
|
||||||
|
);
|
||||||
|
onUpdate?.call(updatedFile);
|
||||||
|
if (context.mounted) Navigator.pop(context);
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('confirm'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 16, vertical: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
var ratio =
|
var ratio =
|
||||||
item.isOnCloud
|
item.isOnCloud
|
||||||
? (item.data.fileMeta?['ratio'] is num
|
? (item.data.fileMeta?['ratio'] is num
|
||||||
@@ -281,6 +508,22 @@ class AttachmentPreview extends StatelessWidget {
|
|||||||
onUpdate?.call(item.copyWith(data: result));
|
onUpdate?.call(item.copyWith(data: result));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (item.isOnCloud)
|
||||||
|
MenuAction(
|
||||||
|
title: 'rename'.tr(),
|
||||||
|
image: MenuImage.icon(Symbols.edit),
|
||||||
|
callback: () async {
|
||||||
|
await _showRenameDialog(context, ref);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (item.isOnCloud)
|
||||||
|
MenuAction(
|
||||||
|
title: 'markAsSensitive'.tr(),
|
||||||
|
image: MenuImage.icon(Symbols.no_adult_content),
|
||||||
|
callback: () async {
|
||||||
|
await _showSensitiveDialog(context, ref);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: contentWidget,
|
child: contentWidget,
|
||||||
|
71
lib/widgets/content/sensitive.dart
Normal file
71
lib/widgets/content/sensitive.dart
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) Solsynth
|
||||||
|
// Sensitive content categories for content warnings, in fixed order.
|
||||||
|
|
||||||
|
enum SensitiveCategory {
|
||||||
|
language,
|
||||||
|
sexualContent,
|
||||||
|
violence,
|
||||||
|
profanity,
|
||||||
|
hateSpeech,
|
||||||
|
racism,
|
||||||
|
adultContent,
|
||||||
|
drugAbuse,
|
||||||
|
alcoholAbuse,
|
||||||
|
gambling,
|
||||||
|
selfHarm,
|
||||||
|
childAbuse,
|
||||||
|
other,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SensitiveCategoryI18n on SensitiveCategory {
|
||||||
|
/// i18n key to look up localized label
|
||||||
|
String get i18nKey => switch (this) {
|
||||||
|
SensitiveCategory.language => 'sensitiveCategories.language',
|
||||||
|
SensitiveCategory.sexualContent => 'sensitiveCategories.sexualContent',
|
||||||
|
SensitiveCategory.violence => 'sensitiveCategories.violence',
|
||||||
|
SensitiveCategory.profanity => 'sensitiveCategories.profanity',
|
||||||
|
SensitiveCategory.hateSpeech => 'sensitiveCategories.hateSpeech',
|
||||||
|
SensitiveCategory.racism => 'sensitiveCategories.racism',
|
||||||
|
SensitiveCategory.adultContent => 'sensitiveCategories.adultContent',
|
||||||
|
SensitiveCategory.drugAbuse => 'sensitiveCategories.drugAbuse',
|
||||||
|
SensitiveCategory.alcoholAbuse => 'sensitiveCategories.alcoholAbuse',
|
||||||
|
SensitiveCategory.gambling => 'sensitiveCategories.gambling',
|
||||||
|
SensitiveCategory.selfHarm => 'sensitiveCategories.selfHarm',
|
||||||
|
SensitiveCategory.childAbuse => 'sensitiveCategories.childAbuse',
|
||||||
|
SensitiveCategory.other => 'sensitiveCategories.other',
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Optional symbol you can use alongside the label in UI
|
||||||
|
String get symbol => switch (this) {
|
||||||
|
SensitiveCategory.language => '🌐',
|
||||||
|
SensitiveCategory.sexualContent => '🔞',
|
||||||
|
SensitiveCategory.violence => '⚠️',
|
||||||
|
SensitiveCategory.profanity => '🗯️',
|
||||||
|
SensitiveCategory.hateSpeech => '🚫',
|
||||||
|
SensitiveCategory.racism => '✋',
|
||||||
|
SensitiveCategory.adultContent => '🍑',
|
||||||
|
SensitiveCategory.drugAbuse => '💊',
|
||||||
|
SensitiveCategory.alcoholAbuse => '🍺',
|
||||||
|
SensitiveCategory.gambling => '🎲',
|
||||||
|
SensitiveCategory.selfHarm => '🆘',
|
||||||
|
SensitiveCategory.childAbuse => '🛑',
|
||||||
|
SensitiveCategory.other => '❗',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ordered list for UI consumption, matching enum declaration order.
|
||||||
|
const List<SensitiveCategory> kSensitiveCategoriesOrdered = [
|
||||||
|
SensitiveCategory.language,
|
||||||
|
SensitiveCategory.sexualContent,
|
||||||
|
SensitiveCategory.violence,
|
||||||
|
SensitiveCategory.profanity,
|
||||||
|
SensitiveCategory.hateSpeech,
|
||||||
|
SensitiveCategory.racism,
|
||||||
|
SensitiveCategory.adultContent,
|
||||||
|
SensitiveCategory.drugAbuse,
|
||||||
|
SensitiveCategory.alcoholAbuse,
|
||||||
|
SensitiveCategory.gambling,
|
||||||
|
SensitiveCategory.selfHarm,
|
||||||
|
SensitiveCategory.childAbuse,
|
||||||
|
SensitiveCategory.other,
|
||||||
|
];
|
Reference in New Issue
Block a user