[Bugfix] Sync items not sorted by sortName (#13)

Now sort the items by sortName

---------

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2024-10-13 19:53:45 +02:00 committed by GitHub
parent c53b9b2281
commit a932fa71ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 244 additions and 230 deletions

View file

@ -1,8 +1,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:fladder/models/syncing/sync_item.dart';
part 'i_synced_item.g.dart'; part 'i_synced_item.g.dart';
// extension IsarExtensions on String? { // extension IsarExtensions on String? {
@ -27,7 +28,7 @@ part 'i_synced_item.g.dart';
class ISyncedItem { class ISyncedItem {
String? userId; String? userId;
String id; String id;
int? sortKey; String? sortName;
String? parentId; String? parentId;
String? path; String? path;
int? fileSize; int? fileSize;
@ -41,7 +42,7 @@ class ISyncedItem {
ISyncedItem({ ISyncedItem({
this.userId, this.userId,
required this.id, required this.id,
this.sortKey, this.sortName,
this.parentId, this.parentId,
this.path, this.path,
this.fileSize, this.fileSize,
@ -61,7 +62,7 @@ class ISyncedItem {
userId: syncedItem.userId, userId: syncedItem.userId,
path: syncedItem.path?.replaceAll(path ?? "", '').substring(1), path: syncedItem.path?.replaceAll(path ?? "", '').substring(1),
fileSize: syncedItem.fileSize, fileSize: syncedItem.fileSize,
sortKey: syncedItem.sortKey, sortName: syncedItem.sortName,
videoFileName: syncedItem.videoFileName, videoFileName: syncedItem.videoFileName,
trickPlayModel: syncedItem.fTrickPlayModel != null ? jsonEncode(syncedItem.fTrickPlayModel?.toJson()) : null, trickPlayModel: syncedItem.fTrickPlayModel != null ? jsonEncode(syncedItem.fTrickPlayModel?.toJson()) : null,
introOutroSkipModel: introOutroSkipModel:

View file

@ -29,8 +29,8 @@ const ISyncedItemSchema = IsarGeneratedSchema(
type: IsarType.string, type: IsarType.string,
), ),
IsarPropertySchema( IsarPropertySchema(
name: 'sortKey', name: 'sortName',
type: IsarType.long, type: IsarType.string,
), ),
IsarPropertySchema( IsarPropertySchema(
name: 'parentId', name: 'parentId',
@ -94,7 +94,14 @@ int serializeISyncedItem(IsarWriter writer, ISyncedItem object) {
} }
} }
IsarCore.writeString(writer, 2, object.id); IsarCore.writeString(writer, 2, object.id);
IsarCore.writeLong(writer, 3, object.sortKey ?? -9223372036854775808); {
final value = object.sortName;
if (value == null) {
IsarCore.writeNull(writer, 3);
} else {
IsarCore.writeString(writer, 3, value);
}
}
{ {
final value = object.parentId; final value = object.parentId;
if (value == null) { if (value == null) {
@ -185,15 +192,8 @@ ISyncedItem deserializeISyncedItem(IsarReader reader) {
_userId = IsarCore.readString(reader, 1); _userId = IsarCore.readString(reader, 1);
final String _id; final String _id;
_id = IsarCore.readString(reader, 2) ?? ''; _id = IsarCore.readString(reader, 2) ?? '';
final int? _sortKey; final String? _sortName;
{ _sortName = IsarCore.readString(reader, 3);
final value = IsarCore.readLong(reader, 3);
if (value == -9223372036854775808) {
_sortKey = null;
} else {
_sortKey = value;
}
}
final String? _parentId; final String? _parentId;
_parentId = IsarCore.readString(reader, 4); _parentId = IsarCore.readString(reader, 4);
final String? _path; final String? _path;
@ -254,7 +254,7 @@ ISyncedItem deserializeISyncedItem(IsarReader reader) {
final object = ISyncedItem( final object = ISyncedItem(
userId: _userId, userId: _userId,
id: _id, id: _id,
sortKey: _sortKey, sortName: _sortName,
parentId: _parentId, parentId: _parentId,
path: _path, path: _path,
fileSize: _fileSize, fileSize: _fileSize,
@ -277,14 +277,7 @@ dynamic deserializeISyncedItemProp(IsarReader reader, int property) {
case 2: case 2:
return IsarCore.readString(reader, 2) ?? ''; return IsarCore.readString(reader, 2) ?? '';
case 3: case 3:
{ return IsarCore.readString(reader, 3);
final value = IsarCore.readLong(reader, 3);
if (value == -9223372036854775808) {
return null;
} else {
return value;
}
}
case 4: case 4:
return IsarCore.readString(reader, 4); return IsarCore.readString(reader, 4);
case 5: case 5:
@ -351,7 +344,7 @@ sealed class _ISyncedItemUpdate {
bool call({ bool call({
required String id, required String id,
String? userId, String? userId,
int? sortKey, String? sortName,
String? parentId, String? parentId,
String? path, String? path,
int? fileSize, int? fileSize,
@ -372,7 +365,7 @@ class _ISyncedItemUpdateImpl implements _ISyncedItemUpdate {
bool call({ bool call({
required String id, required String id,
Object? userId = ignore, Object? userId = ignore,
Object? sortKey = ignore, Object? sortName = ignore,
Object? parentId = ignore, Object? parentId = ignore,
Object? path = ignore, Object? path = ignore,
Object? fileSize = ignore, Object? fileSize = ignore,
@ -386,7 +379,7 @@ class _ISyncedItemUpdateImpl implements _ISyncedItemUpdate {
id id
], { ], {
if (userId != ignore) 1: userId as String?, if (userId != ignore) 1: userId as String?,
if (sortKey != ignore) 3: sortKey as int?, if (sortName != ignore) 3: sortName as String?,
if (parentId != ignore) 4: parentId as String?, if (parentId != ignore) 4: parentId as String?,
if (path != ignore) 5: path as String?, if (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?, if (fileSize != ignore) 6: fileSize as int?,
@ -404,7 +397,7 @@ sealed class _ISyncedItemUpdateAll {
int call({ int call({
required List<String> id, required List<String> id,
String? userId, String? userId,
int? sortKey, String? sortName,
String? parentId, String? parentId,
String? path, String? path,
int? fileSize, int? fileSize,
@ -425,7 +418,7 @@ class _ISyncedItemUpdateAllImpl implements _ISyncedItemUpdateAll {
int call({ int call({
required List<String> id, required List<String> id,
Object? userId = ignore, Object? userId = ignore,
Object? sortKey = ignore, Object? sortName = ignore,
Object? parentId = ignore, Object? parentId = ignore,
Object? path = ignore, Object? path = ignore,
Object? fileSize = ignore, Object? fileSize = ignore,
@ -437,7 +430,7 @@ class _ISyncedItemUpdateAllImpl implements _ISyncedItemUpdateAll {
}) { }) {
return collection.updateProperties(id, { return collection.updateProperties(id, {
if (userId != ignore) 1: userId as String?, if (userId != ignore) 1: userId as String?,
if (sortKey != ignore) 3: sortKey as int?, if (sortName != ignore) 3: sortName as String?,
if (parentId != ignore) 4: parentId as String?, if (parentId != ignore) 4: parentId as String?,
if (path != ignore) 5: path as String?, if (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?, if (fileSize != ignore) 6: fileSize as int?,
@ -459,7 +452,7 @@ extension ISyncedItemUpdate on IsarCollection<String, ISyncedItem> {
sealed class _ISyncedItemQueryUpdate { sealed class _ISyncedItemQueryUpdate {
int call({ int call({
String? userId, String? userId,
int? sortKey, String? sortName,
String? parentId, String? parentId,
String? path, String? path,
int? fileSize, int? fileSize,
@ -480,7 +473,7 @@ class _ISyncedItemQueryUpdateImpl implements _ISyncedItemQueryUpdate {
@override @override
int call({ int call({
Object? userId = ignore, Object? userId = ignore,
Object? sortKey = ignore, Object? sortName = ignore,
Object? parentId = ignore, Object? parentId = ignore,
Object? path = ignore, Object? path = ignore,
Object? fileSize = ignore, Object? fileSize = ignore,
@ -492,7 +485,7 @@ class _ISyncedItemQueryUpdateImpl implements _ISyncedItemQueryUpdate {
}) { }) {
return query.updateProperties(limit: limit, { return query.updateProperties(limit: limit, {
if (userId != ignore) 1: userId as String?, if (userId != ignore) 1: userId as String?,
if (sortKey != ignore) 3: sortKey as int?, if (sortName != ignore) 3: sortName as String?,
if (parentId != ignore) 4: parentId as String?, if (parentId != ignore) 4: parentId as String?,
if (path != ignore) 5: path as String?, if (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?, if (fileSize != ignore) 6: fileSize as int?,
@ -521,7 +514,7 @@ class _ISyncedItemQueryBuilderUpdateImpl implements _ISyncedItemQueryUpdate {
@override @override
int call({ int call({
Object? userId = ignore, Object? userId = ignore,
Object? sortKey = ignore, Object? sortName = ignore,
Object? parentId = ignore, Object? parentId = ignore,
Object? path = ignore, Object? path = ignore,
Object? fileSize = ignore, Object? fileSize = ignore,
@ -535,7 +528,7 @@ class _ISyncedItemQueryBuilderUpdateImpl implements _ISyncedItemQueryUpdate {
try { try {
return q.updateProperties(limit: limit, { return q.updateProperties(limit: limit, {
if (userId != ignore) 1: userId as String?, if (userId != ignore) 1: userId as String?,
if (sortKey != ignore) 3: sortKey as int?, if (sortName != ignore) 3: sortName as String?,
if (parentId != ignore) 4: parentId as String?, if (parentId != ignore) 4: parentId as String?,
if (path != ignore) 5: path as String?, if (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?, if (fileSize != ignore) 6: fileSize as int?,
@ -928,97 +921,193 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyIsNull() { sortNameIsNull() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const IsNullCondition(property: 3)); return query.addFilterCondition(const IsNullCondition(property: 3));
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyIsNotNull() { sortNameIsNotNull() {
return QueryBuilder.apply(not(), (query) { return QueryBuilder.apply(not(), (query) {
return query.addFilterCondition(const IsNullCondition(property: 3)); return query.addFilterCondition(const IsNullCondition(property: 3));
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortKeyEqualTo( QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortNameEqualTo(
int? value, String? value, {
) { bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
EqualCondition( EqualCondition(
property: 3, property: 3,
value: value, value: value,
caseSensitive: caseSensitive,
), ),
); );
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyGreaterThan( sortNameGreaterThan(
int? value, String? value, {
) { bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
GreaterCondition( GreaterCondition(
property: 3, property: 3,
value: value, value: value,
caseSensitive: caseSensitive,
), ),
); );
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyGreaterThanOrEqualTo( sortNameGreaterThanOrEqualTo(
int? value, String? value, {
) { bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
GreaterOrEqualCondition( GreaterOrEqualCondition(
property: 3, property: 3,
value: value, value: value,
), caseSensitive: caseSensitive,
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortKeyLessThan(
int? value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessCondition(
property: 3,
value: value,
), ),
); );
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyLessThanOrEqualTo( sortNameLessThan(
int? value, String? value, {
) { bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
LessOrEqualCondition( LessCondition(
property: 3, property: 3,
value: value, value: value,
caseSensitive: caseSensitive,
), ),
); );
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortKeyBetween( QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
int? lower, sortNameLessThanOrEqualTo(
int? upper, String? value, {
) { bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessOrEqualCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortNameBetween(
String? lower,
String? upper, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
BetweenCondition( BetweenCondition(
property: 3, property: 3,
lower: lower, lower: lower,
upper: upper, upper: upper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortNameStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
StartsWithCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortNameEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EndsWithCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortNameContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
ContainsCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortNameMatches(
String pattern,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
MatchesCondition(
property: 3,
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortNameIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const EqualCondition(
property: 3,
value: '',
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortNameIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const GreaterCondition(
property: 3,
value: '',
), ),
); );
}); });
@ -2937,15 +3026,24 @@ extension ISyncedItemQuerySortBy
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> sortBySortKey() { QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> sortBySortName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy(3); return query.addSortBy(
3,
caseSensitive: caseSensitive,
);
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> sortBySortKeyDesc() { QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> sortBySortNameDesc(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy(3, sort: Sort.desc); return query.addSortBy(
3,
sort: Sort.desc,
caseSensitive: caseSensitive,
);
}); });
} }
@ -3139,15 +3237,17 @@ extension ISyncedItemQuerySortThenBy
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> thenBySortKey() { QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> thenBySortName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy(3); return query.addSortBy(3, caseSensitive: caseSensitive);
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> thenBySortKeyDesc() { QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> thenBySortNameDesc(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy(3, sort: Sort.desc); return query.addSortBy(3, sort: Sort.desc, caseSensitive: caseSensitive);
}); });
} }
@ -3271,9 +3371,10 @@ extension ISyncedItemQueryWhereDistinct
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterDistinct> distinctBySortKey() { QueryBuilder<ISyncedItem, ISyncedItem, QAfterDistinct> distinctBySortName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(3); return query.addDistinctBy(3, caseSensitive: caseSensitive);
}); });
} }
@ -3359,7 +3460,7 @@ extension ISyncedItemQueryProperty1
}); });
} }
QueryBuilder<ISyncedItem, int?, QAfterProperty> sortKeyProperty() { QueryBuilder<ISyncedItem, String?, QAfterProperty> sortNameProperty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addProperty(3); return query.addProperty(3);
}); });
@ -3441,7 +3542,7 @@ extension ISyncedItemQueryProperty2<R>
}); });
} }
QueryBuilder<ISyncedItem, (R, int?), QAfterProperty> sortKeyProperty() { QueryBuilder<ISyncedItem, (R, String?), QAfterProperty> sortNameProperty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addProperty(3); return query.addProperty(3);
}); });
@ -3527,7 +3628,7 @@ extension ISyncedItemQueryProperty3<R1, R2>
}); });
} }
QueryBuilder<ISyncedItem, (R1, R2, int?), QOperations> sortKeyProperty() { QueryBuilder<ISyncedItem, (R1, R2, String?), QOperations> sortNameProperty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addProperty(3); return query.addProperty(3);
}); });

View file

@ -1,8 +1,14 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart';
import 'package:background_downloader/background_downloader.dart'; import 'package:background_downloader/background_downloader.dart';
import 'package:ficonsax/ficonsax.dart'; import 'package:ficonsax/ficonsax.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:path/path.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
@ -14,13 +20,8 @@ import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/models/syncing/i_synced_item.dart'; import 'package:fladder/models/syncing/i_synced_item.dart';
import 'package:fladder/providers/sync/sync_provider_helpers.dart'; import 'package:fladder/providers/sync/sync_provider_helpers.dart';
import 'package:fladder/providers/sync_provider.dart'; import 'package:fladder/providers/sync_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:path/path.dart';
part 'sync_item.freezed.dart'; part 'sync_item.freezed.dart';
part 'sync_item.g.dart';
@freezed @freezed
class SyncedItem with _$SyncedItem { class SyncedItem with _$SyncedItem {
@ -32,7 +33,7 @@ class SyncedItem with _$SyncedItem {
required String userId, required String userId,
String? path, String? path,
@Default(false) bool markedForDelete, @Default(false) bool markedForDelete,
int? sortKey, String? sortName,
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
IntroOutSkipModel? introOutSkipModel, IntroOutSkipModel? introOutSkipModel,
@ -119,14 +120,12 @@ class SyncedItem with _$SyncedItem {
); );
} }
factory SyncedItem.fromJson(Map<String, dynamic> json) => _$SyncedItemFromJson(json);
factory SyncedItem.fromIsar(ISyncedItem isarSyncedItem, String savePath) { factory SyncedItem.fromIsar(ISyncedItem isarSyncedItem, String savePath) {
return SyncedItem( return SyncedItem(
id: isarSyncedItem.id, id: isarSyncedItem.id,
parentId: isarSyncedItem.parentId, parentId: isarSyncedItem.parentId,
userId: isarSyncedItem.userId ?? "", userId: isarSyncedItem.userId ?? "",
sortKey: isarSyncedItem.sortKey, sortName: isarSyncedItem.sortName,
path: joinAll([savePath, isarSyncedItem.path ?? ""]), path: joinAll([savePath, isarSyncedItem.path ?? ""]),
fileSize: isarSyncedItem.fileSize, fileSize: isarSyncedItem.fileSize,
videoFileName: isarSyncedItem.videoFileName, videoFileName: isarSyncedItem.videoFileName,

View file

@ -14,10 +14,6 @@ T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError( final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
SyncedItem _$SyncedItemFromJson(Map<String, dynamic> json) {
return _SyncItem.fromJson(json);
}
/// @nodoc /// @nodoc
mixin _$SyncedItem { mixin _$SyncedItem {
String get id => throw _privateConstructorUsedError; String get id => throw _privateConstructorUsedError;
@ -25,7 +21,7 @@ mixin _$SyncedItem {
String get userId => throw _privateConstructorUsedError; String get userId => throw _privateConstructorUsedError;
String? get path => throw _privateConstructorUsedError; String? get path => throw _privateConstructorUsedError;
bool get markedForDelete => throw _privateConstructorUsedError; bool get markedForDelete => throw _privateConstructorUsedError;
int? get sortKey => throw _privateConstructorUsedError; String? get sortName => throw _privateConstructorUsedError;
int? get fileSize => throw _privateConstructorUsedError; int? get fileSize => throw _privateConstructorUsedError;
String? get videoFileName => throw _privateConstructorUsedError; String? get videoFileName => throw _privateConstructorUsedError;
IntroOutSkipModel? get introOutSkipModel => IntroOutSkipModel? get introOutSkipModel =>
@ -37,7 +33,6 @@ mixin _$SyncedItem {
@UserDataJsonSerializer() @UserDataJsonSerializer()
UserData? get userData => throw _privateConstructorUsedError; UserData? get userData => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$SyncedItemCopyWith<SyncedItem> get copyWith => $SyncedItemCopyWith<SyncedItem> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -55,7 +50,7 @@ abstract class $SyncedItemCopyWith<$Res> {
String userId, String userId,
String? path, String? path,
bool markedForDelete, bool markedForDelete,
int? sortKey, String? sortName,
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
IntroOutSkipModel? introOutSkipModel, IntroOutSkipModel? introOutSkipModel,
@ -87,7 +82,7 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
Object? userId = null, Object? userId = null,
Object? path = freezed, Object? path = freezed,
Object? markedForDelete = null, Object? markedForDelete = null,
Object? sortKey = freezed, Object? sortName = freezed,
Object? fileSize = freezed, Object? fileSize = freezed,
Object? videoFileName = freezed, Object? videoFileName = freezed,
Object? introOutSkipModel = freezed, Object? introOutSkipModel = freezed,
@ -118,10 +113,10 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
? _value.markedForDelete ? _value.markedForDelete
: markedForDelete // ignore: cast_nullable_to_non_nullable : markedForDelete // ignore: cast_nullable_to_non_nullable
as bool, as bool,
sortKey: freezed == sortKey sortName: freezed == sortName
? _value.sortKey ? _value.sortName
: sortKey // ignore: cast_nullable_to_non_nullable : sortName // ignore: cast_nullable_to_non_nullable
as int?, as String?,
fileSize: freezed == fileSize fileSize: freezed == fileSize
? _value.fileSize ? _value.fileSize
: fileSize // ignore: cast_nullable_to_non_nullable : fileSize // ignore: cast_nullable_to_non_nullable
@ -196,7 +191,7 @@ abstract class _$$SyncItemImplCopyWith<$Res>
String userId, String userId,
String? path, String? path,
bool markedForDelete, bool markedForDelete,
int? sortKey, String? sortName,
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
IntroOutSkipModel? introOutSkipModel, IntroOutSkipModel? introOutSkipModel,
@ -228,7 +223,7 @@ class __$$SyncItemImplCopyWithImpl<$Res>
Object? userId = null, Object? userId = null,
Object? path = freezed, Object? path = freezed,
Object? markedForDelete = null, Object? markedForDelete = null,
Object? sortKey = freezed, Object? sortName = freezed,
Object? fileSize = freezed, Object? fileSize = freezed,
Object? videoFileName = freezed, Object? videoFileName = freezed,
Object? introOutSkipModel = freezed, Object? introOutSkipModel = freezed,
@ -259,10 +254,10 @@ class __$$SyncItemImplCopyWithImpl<$Res>
? _value.markedForDelete ? _value.markedForDelete
: markedForDelete // ignore: cast_nullable_to_non_nullable : markedForDelete // ignore: cast_nullable_to_non_nullable
as bool, as bool,
sortKey: freezed == sortKey sortName: freezed == sortName
? _value.sortKey ? _value.sortName
: sortKey // ignore: cast_nullable_to_non_nullable : sortName // ignore: cast_nullable_to_non_nullable
as int?, as String?,
fileSize: freezed == fileSize fileSize: freezed == fileSize
? _value.fileSize ? _value.fileSize
: fileSize // ignore: cast_nullable_to_non_nullable : fileSize // ignore: cast_nullable_to_non_nullable
@ -300,7 +295,7 @@ class __$$SyncItemImplCopyWithImpl<$Res>
} }
/// @nodoc /// @nodoc
@JsonSerializable()
class _$SyncItemImpl extends _SyncItem { class _$SyncItemImpl extends _SyncItem {
_$SyncItemImpl( _$SyncItemImpl(
{required this.id, {required this.id,
@ -308,7 +303,7 @@ class _$SyncItemImpl extends _SyncItem {
required this.userId, required this.userId,
this.path, this.path,
this.markedForDelete = false, this.markedForDelete = false,
this.sortKey, this.sortName,
this.fileSize, this.fileSize,
this.videoFileName, this.videoFileName,
this.introOutSkipModel, this.introOutSkipModel,
@ -321,9 +316,6 @@ class _$SyncItemImpl extends _SyncItem {
_subtitles = subtitles, _subtitles = subtitles,
super._(); super._();
factory _$SyncItemImpl.fromJson(Map<String, dynamic> json) =>
_$$SyncItemImplFromJson(json);
@override @override
final String id; final String id;
@override @override
@ -336,7 +328,7 @@ class _$SyncItemImpl extends _SyncItem {
@JsonKey() @JsonKey()
final bool markedForDelete; final bool markedForDelete;
@override @override
final int? sortKey; final String? sortName;
@override @override
final int? fileSize; final int? fileSize;
@override @override
@ -371,7 +363,7 @@ class _$SyncItemImpl extends _SyncItem {
@override @override
String toString() { String toString() {
return 'SyncedItem(id: $id, parentId: $parentId, userId: $userId, path: $path, markedForDelete: $markedForDelete, sortKey: $sortKey, fileSize: $fileSize, videoFileName: $videoFileName, introOutSkipModel: $introOutSkipModel, fTrickPlayModel: $fTrickPlayModel, fImages: $fImages, fChapters: $fChapters, subtitles: $subtitles, userData: $userData)'; return 'SyncedItem(id: $id, parentId: $parentId, userId: $userId, path: $path, markedForDelete: $markedForDelete, sortName: $sortName, fileSize: $fileSize, videoFileName: $videoFileName, introOutSkipModel: $introOutSkipModel, fTrickPlayModel: $fTrickPlayModel, fImages: $fImages, fChapters: $fChapters, subtitles: $subtitles, userData: $userData)';
} }
@override @override
@ -386,7 +378,8 @@ class _$SyncItemImpl extends _SyncItem {
(identical(other.path, path) || other.path == path) && (identical(other.path, path) || other.path == path) &&
(identical(other.markedForDelete, markedForDelete) || (identical(other.markedForDelete, markedForDelete) ||
other.markedForDelete == markedForDelete) && other.markedForDelete == markedForDelete) &&
(identical(other.sortKey, sortKey) || other.sortKey == sortKey) && (identical(other.sortName, sortName) ||
other.sortName == sortName) &&
(identical(other.fileSize, fileSize) || (identical(other.fileSize, fileSize) ||
other.fileSize == fileSize) && other.fileSize == fileSize) &&
(identical(other.videoFileName, videoFileName) || (identical(other.videoFileName, videoFileName) ||
@ -404,7 +397,6 @@ class _$SyncItemImpl extends _SyncItem {
other.userData == userData)); other.userData == userData));
} }
@JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash( int get hashCode => Object.hash(
runtimeType, runtimeType,
@ -413,7 +405,7 @@ class _$SyncItemImpl extends _SyncItem {
userId, userId,
path, path,
markedForDelete, markedForDelete,
sortKey, sortName,
fileSize, fileSize,
videoFileName, videoFileName,
introOutSkipModel, introOutSkipModel,
@ -428,13 +420,6 @@ class _$SyncItemImpl extends _SyncItem {
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
_$$SyncItemImplCopyWith<_$SyncItemImpl> get copyWith => _$$SyncItemImplCopyWith<_$SyncItemImpl> get copyWith =>
__$$SyncItemImplCopyWithImpl<_$SyncItemImpl>(this, _$identity); __$$SyncItemImplCopyWithImpl<_$SyncItemImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$SyncItemImplToJson(
this,
);
}
} }
abstract class _SyncItem extends SyncedItem { abstract class _SyncItem extends SyncedItem {
@ -444,7 +429,7 @@ abstract class _SyncItem extends SyncedItem {
required final String userId, required final String userId,
final String? path, final String? path,
final bool markedForDelete, final bool markedForDelete,
final int? sortKey, final String? sortName,
final int? fileSize, final int? fileSize,
final String? videoFileName, final String? videoFileName,
final IntroOutSkipModel? introOutSkipModel, final IntroOutSkipModel? introOutSkipModel,
@ -455,9 +440,6 @@ abstract class _SyncItem extends SyncedItem {
@UserDataJsonSerializer() final UserData? userData}) = _$SyncItemImpl; @UserDataJsonSerializer() final UserData? userData}) = _$SyncItemImpl;
_SyncItem._() : super._(); _SyncItem._() : super._();
factory _SyncItem.fromJson(Map<String, dynamic> json) =
_$SyncItemImpl.fromJson;
@override @override
String get id; String get id;
@override @override
@ -469,7 +451,7 @@ abstract class _SyncItem extends SyncedItem {
@override @override
bool get markedForDelete; bool get markedForDelete;
@override @override
int? get sortKey; String? get sortName;
@override @override
int? get fileSize; int? get fileSize;
@override @override

View file

@ -1,71 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'sync_item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$SyncItemImpl _$$SyncItemImplFromJson(Map<String, dynamic> json) =>
_$SyncItemImpl(
id: json['id'] as String,
parentId: json['parentId'] as String?,
userId: json['userId'] as String,
path: json['path'] as String?,
markedForDelete: json['markedForDelete'] as bool? ?? false,
sortKey: (json['sortKey'] as num?)?.toInt(),
fileSize: (json['fileSize'] as num?)?.toInt(),
videoFileName: json['videoFileName'] as String?,
introOutSkipModel: json['introOutSkipModel'] == null
? null
: IntroOutSkipModel.fromJson(
json['introOutSkipModel'] as Map<String, dynamic>),
fTrickPlayModel: json['fTrickPlayModel'] == null
? null
: TrickPlayModel.fromJson(
json['fTrickPlayModel'] as Map<String, dynamic>),
fImages: json['fImages'] == null
? null
: ImagesData.fromJson(json['fImages'] as String),
fChapters: (json['fChapters'] as List<dynamic>?)
?.map((e) => Chapter.fromJson(e as String))
.toList() ??
const [],
subtitles: (json['subtitles'] as List<dynamic>?)
?.map((e) => SubStreamModel.fromJson(e as String))
.toList() ??
const [],
userData: _$JsonConverterFromJson<String, UserData>(
json['userData'], const UserDataJsonSerializer().fromJson),
);
Map<String, dynamic> _$$SyncItemImplToJson(_$SyncItemImpl instance) =>
<String, dynamic>{
'id': instance.id,
'parentId': instance.parentId,
'userId': instance.userId,
'path': instance.path,
'markedForDelete': instance.markedForDelete,
'sortKey': instance.sortKey,
'fileSize': instance.fileSize,
'videoFileName': instance.videoFileName,
'introOutSkipModel': instance.introOutSkipModel,
'fTrickPlayModel': instance.fTrickPlayModel,
'fImages': instance.fImages,
'fChapters': instance.fChapters,
'subtitles': instance.subtitles,
'userData': _$JsonConverterToJson<String, UserData>(
instance.userData, const UserDataJsonSerializer().toJson),
};
Value? _$JsonConverterFromJson<Json, Value>(
Object? json,
Value? Function(Json json) fromJson,
) =>
json == null ? null : fromJson(json as Json);
Json? _$JsonConverterToJson<Json, Value>(
Value? value,
Json? Function(Value value) toJson,
) =>
value == null ? null : toJson(value);

View file

@ -1,11 +1,11 @@
import 'package:fladder/models/syncing/i_synced_item.dart';
import 'package:fladder/providers/sync_provider.dart';
import 'package:fladder/models/syncing/download_stream.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:fladder/models/syncing/download_stream.dart';
import 'package:fladder/models/syncing/i_synced_item.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/providers/sync_provider.dart';
part 'sync_provider_helpers.g.dart'; part 'sync_provider_helpers.g.dart';
@riverpod @riverpod
@ -18,7 +18,7 @@ class SyncChildren extends _$SyncChildren {
while (toProcess.isNotEmpty) { while (toProcess.isNotEmpty) {
final currentLevel = toProcess.map( final currentLevel = toProcess.map(
(parent) { (parent) {
final children = syncedItemIsar?.iSyncedItems.where().parentIdEqualTo(parent.id).sortBySortKey().findAll(); final children = syncedItemIsar?.iSyncedItems.where().parentIdEqualTo(parent.id).sortBySortName().findAll();
return children?.map((e) => SyncedItem.fromIsar(e, ref.read(syncProvider.notifier).syncPath ?? "")) ?? return children?.map((e) => SyncedItem.fromIsar(e, ref.read(syncProvider.notifier).syncPath ?? "")) ??
<SyncedItem>[]; <SyncedItem>[];
}, },

View file

@ -6,7 +6,7 @@ part of 'sync_provider_helpers.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$syncChildrenHash() => r'798a9998103adae18a238a69219559f3ccbf3def'; String _$syncChildrenHash() => r'f6fdb1aa36d6655976baa5fbe0d8a6b812d7e95b';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View file

@ -3,22 +3,12 @@ import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:background_downloader/background_downloader.dart'; import 'package:background_downloader/background_downloader.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/movie_model.dart';
import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/models/syncing/download_stream.dart';
import 'package:fladder/models/syncing/i_synced_item.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/models/syncing/sync_settings_model.dart';
import 'package:fladder/providers/service_provider.dart';
import 'package:fladder/providers/settings/client_settings_provider.dart';
import 'package:fladder/providers/sync/background_download_provider.dart';
import 'package:fladder/screens/shared/fladder_snackbar.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
@ -26,14 +16,25 @@ import 'package:path/path.dart' as path;
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/episode_model.dart'; import 'package:fladder/models/items/episode_model.dart';
import 'package:fladder/models/items/images_models.dart'; import 'package:fladder/models/items/images_models.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/items/movie_model.dart';
import 'package:fladder/models/items/series_model.dart'; import 'package:fladder/models/items/series_model.dart';
import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/models/syncing/download_stream.dart';
import 'package:fladder/models/syncing/i_synced_item.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/models/syncing/sync_settings_model.dart';
import 'package:fladder/models/video_stream_model.dart'; import 'package:fladder/models/video_stream_model.dart';
import 'package:fladder/profiles/default_profile.dart'; import 'package:fladder/profiles/default_profile.dart';
import 'package:fladder/providers/api_provider.dart'; import 'package:fladder/providers/api_provider.dart';
import 'package:fladder/providers/service_provider.dart';
import 'package:fladder/providers/settings/client_settings_provider.dart';
import 'package:fladder/providers/sync/background_download_provider.dart';
import 'package:fladder/providers/user_provider.dart'; import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/screens/shared/fladder_snackbar.dart';
final syncProvider = StateNotifierProvider<SyncNotifier, SyncSettingsModel>((ref) => throw UnimplementedError()); final syncProvider = StateNotifierProvider<SyncNotifier, SyncSettingsModel>((ref) => throw UnimplementedError());
@ -147,7 +148,7 @@ class SyncNotifier extends StateNotifier<SyncSettingsModel> {
while (toProcess.isNotEmpty) { while (toProcess.isNotEmpty) {
final currentLevel = toProcess.map( final currentLevel = toProcess.map(
(parent) { (parent) {
final children = syncedItems?.where().parentIdEqualTo(parent.id).sortBySortKey().findAll(); final children = syncedItems?.where().parentIdEqualTo(parent.id).sortBySortName().findAll();
return children?.map((e) => SyncedItem.fromIsar(e, ref.read(syncProvider.notifier).syncPath ?? "")) ?? return children?.map((e) => SyncedItem.fromIsar(e, ref.read(syncProvider.notifier).syncPath ?? "")) ??
<SyncedItem>[]; <SyncedItem>[];
}, },
@ -159,7 +160,7 @@ class SyncNotifier extends StateNotifier<SyncSettingsModel> {
} }
List<SyncedItem> getChildren(SyncedItem item) { List<SyncedItem> getChildren(SyncedItem item) {
return (syncedItems?.where().parentIdEqualTo(item.id).sortBySortKey().findAll()) return (syncedItems?.where().parentIdEqualTo(item.id).sortBySortName().findAll())
?.map( ?.map(
(e) => SyncedItem.fromIsar(e, syncPath ?? ""), (e) => SyncedItem.fromIsar(e, syncPath ?? ""),
) )
@ -493,7 +494,7 @@ extension SyncNotifierHelpers on SyncNotifier {
return syncItem.copyWith( return syncItem.copyWith(
id: item.id, id: item.id,
parentId: parent?.id, parentId: parent?.id,
sortKey: (response.parentIndexNumber ?? 0) * (response.indexNumber ?? 0), sortName: response.sortName,
path: directory.path, path: directory.path,
fChapters: await saveChapterImages(origChapters, directory) ?? [], fChapters: await saveChapterImages(origChapters, directory) ?? [],
fileSize: response.mediaSources?.firstOrNull?.size ?? 0, fileSize: response.mediaSources?.firstOrNull?.size ?? 0,

View file

@ -1,4 +1,8 @@
import 'package:flutter/material.dart';
import 'package:ficonsax/ficonsax.dart'; import 'package:ficonsax/ficonsax.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/book_model.dart'; import 'package:fladder/models/book_model.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/episode_model.dart'; import 'package:fladder/models/items/episode_model.dart';
@ -10,8 +14,8 @@ import 'package:fladder/screens/collections/add_to_collection.dart';
import 'package:fladder/screens/metadata/edit_item.dart'; import 'package:fladder/screens/metadata/edit_item.dart';
import 'package:fladder/screens/metadata/identifty_screen.dart'; import 'package:fladder/screens/metadata/identifty_screen.dart';
import 'package:fladder/screens/metadata/info_screen.dart'; import 'package:fladder/screens/metadata/info_screen.dart';
import 'package:fladder/screens/playlists/add_to_playlists.dart';
import 'package:fladder/screens/metadata/refresh_metadata.dart'; import 'package:fladder/screens/metadata/refresh_metadata.dart';
import 'package:fladder/screens/playlists/add_to_playlists.dart';
import 'package:fladder/screens/shared/fladder_snackbar.dart'; import 'package:fladder/screens/shared/fladder_snackbar.dart';
import 'package:fladder/screens/syncing/sync_button.dart'; import 'package:fladder/screens/syncing/sync_button.dart';
import 'package:fladder/screens/syncing/sync_item_details.dart'; import 'package:fladder/screens/syncing/sync_item_details.dart';
@ -20,8 +24,6 @@ import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/util/refresh_state.dart'; import 'package:fladder/util/refresh_state.dart';
import 'package:fladder/widgets/pop_up/delete_file.dart'; import 'package:fladder/widgets/pop_up/delete_file.dart';
import 'package:fladder/widgets/shared/item_actions.dart'; import 'package:fladder/widgets/shared/item_actions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
extension ItemBaseModelsBooleans on List<ItemBaseModel> { extension ItemBaseModelsBooleans on List<ItemBaseModel> {
Map<FladderItemType, List<ItemBaseModel>> get groupedItems { Map<FladderItemType, List<ItemBaseModel>> get groupedItems {
@ -195,7 +197,7 @@ extension ItemBaseModelExtensions on ItemBaseModel {
}, },
label: Text(context.localized.refreshMetadata), label: Text(context.localized.refreshMetadata),
), ),
if (!exclude.contains(ItemActions.download) && downloadEnabled) ...{ if (!exclude.contains(ItemActions.download) && downloadEnabled)
if (syncedItem == null) if (syncedItem == null)
ItemActionButton( ItemActionButton(
icon: const Icon(IconsaxOutline.arrow_down_2), icon: const Icon(IconsaxOutline.arrow_down_2),
@ -207,8 +209,7 @@ extension ItemBaseModelExtensions on ItemBaseModel {
icon: IgnorePointer(child: SyncButton(item: this, syncedItem: syncedItem)), icon: IgnorePointer(child: SyncButton(item: this, syncedItem: syncedItem)),
action: () => showSyncItemDetails(context, syncedItem, ref), action: () => showSyncItemDetails(context, syncedItem, ref),
label: Text(context.localized.syncDetails), label: Text(context.localized.syncDetails),
) ),
},
if (canDelete == true) if (canDelete == true)
ItemActionButton( ItemActionButton(
icon: Container( icon: Container(