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

View file

@ -29,8 +29,8 @@ const ISyncedItemSchema = IsarGeneratedSchema(
type: IsarType.string,
),
IsarPropertySchema(
name: 'sortKey',
type: IsarType.long,
name: 'sortName',
type: IsarType.string,
),
IsarPropertySchema(
name: 'parentId',
@ -94,7 +94,14 @@ int serializeISyncedItem(IsarWriter writer, ISyncedItem object) {
}
}
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;
if (value == null) {
@ -185,15 +192,8 @@ ISyncedItem deserializeISyncedItem(IsarReader reader) {
_userId = IsarCore.readString(reader, 1);
final String _id;
_id = IsarCore.readString(reader, 2) ?? '';
final int? _sortKey;
{
final value = IsarCore.readLong(reader, 3);
if (value == -9223372036854775808) {
_sortKey = null;
} else {
_sortKey = value;
}
}
final String? _sortName;
_sortName = IsarCore.readString(reader, 3);
final String? _parentId;
_parentId = IsarCore.readString(reader, 4);
final String? _path;
@ -254,7 +254,7 @@ ISyncedItem deserializeISyncedItem(IsarReader reader) {
final object = ISyncedItem(
userId: _userId,
id: _id,
sortKey: _sortKey,
sortName: _sortName,
parentId: _parentId,
path: _path,
fileSize: _fileSize,
@ -277,14 +277,7 @@ dynamic deserializeISyncedItemProp(IsarReader reader, int property) {
case 2:
return IsarCore.readString(reader, 2) ?? '';
case 3:
{
final value = IsarCore.readLong(reader, 3);
if (value == -9223372036854775808) {
return null;
} else {
return value;
}
}
return IsarCore.readString(reader, 3);
case 4:
return IsarCore.readString(reader, 4);
case 5:
@ -351,7 +344,7 @@ sealed class _ISyncedItemUpdate {
bool call({
required String id,
String? userId,
int? sortKey,
String? sortName,
String? parentId,
String? path,
int? fileSize,
@ -372,7 +365,7 @@ class _ISyncedItemUpdateImpl implements _ISyncedItemUpdate {
bool call({
required String id,
Object? userId = ignore,
Object? sortKey = ignore,
Object? sortName = ignore,
Object? parentId = ignore,
Object? path = ignore,
Object? fileSize = ignore,
@ -386,7 +379,7 @@ class _ISyncedItemUpdateImpl implements _ISyncedItemUpdate {
id
], {
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 (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?,
@ -404,7 +397,7 @@ sealed class _ISyncedItemUpdateAll {
int call({
required List<String> id,
String? userId,
int? sortKey,
String? sortName,
String? parentId,
String? path,
int? fileSize,
@ -425,7 +418,7 @@ class _ISyncedItemUpdateAllImpl implements _ISyncedItemUpdateAll {
int call({
required List<String> id,
Object? userId = ignore,
Object? sortKey = ignore,
Object? sortName = ignore,
Object? parentId = ignore,
Object? path = ignore,
Object? fileSize = ignore,
@ -437,7 +430,7 @@ class _ISyncedItemUpdateAllImpl implements _ISyncedItemUpdateAll {
}) {
return collection.updateProperties(id, {
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 (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?,
@ -459,7 +452,7 @@ extension ISyncedItemUpdate on IsarCollection<String, ISyncedItem> {
sealed class _ISyncedItemQueryUpdate {
int call({
String? userId,
int? sortKey,
String? sortName,
String? parentId,
String? path,
int? fileSize,
@ -480,7 +473,7 @@ class _ISyncedItemQueryUpdateImpl implements _ISyncedItemQueryUpdate {
@override
int call({
Object? userId = ignore,
Object? sortKey = ignore,
Object? sortName = ignore,
Object? parentId = ignore,
Object? path = ignore,
Object? fileSize = ignore,
@ -492,7 +485,7 @@ class _ISyncedItemQueryUpdateImpl implements _ISyncedItemQueryUpdate {
}) {
return query.updateProperties(limit: limit, {
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 (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?,
@ -521,7 +514,7 @@ class _ISyncedItemQueryBuilderUpdateImpl implements _ISyncedItemQueryUpdate {
@override
int call({
Object? userId = ignore,
Object? sortKey = ignore,
Object? sortName = ignore,
Object? parentId = ignore,
Object? path = ignore,
Object? fileSize = ignore,
@ -535,7 +528,7 @@ class _ISyncedItemQueryBuilderUpdateImpl implements _ISyncedItemQueryUpdate {
try {
return q.updateProperties(limit: limit, {
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 (path != ignore) 5: path as String?,
if (fileSize != ignore) 6: fileSize as int?,
@ -928,97 +921,193 @@ extension ISyncedItemQueryFilter
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyIsNull() {
sortNameIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const IsNullCondition(property: 3));
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyIsNotNull() {
sortNameIsNotNull() {
return QueryBuilder.apply(not(), (query) {
return query.addFilterCondition(const IsNullCondition(property: 3));
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortKeyEqualTo(
int? value,
) {
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortNameEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EqualCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyGreaterThan(
int? value,
) {
sortNameGreaterThan(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyGreaterThanOrEqualTo(
int? value,
) {
sortNameGreaterThanOrEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterOrEqualCondition(
property: 3,
value: value,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortKeyLessThan(
int? value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortKeyLessThanOrEqualTo(
int? value,
) {
sortNameLessThan(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessOrEqualCondition(
LessCondition(
property: 3,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> sortKeyBetween(
int? lower,
int? upper,
) {
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
sortNameLessThanOrEqualTo(
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 query.addFilterCondition(
BetweenCondition(
property: 3,
lower: lower,
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 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 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 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 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 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 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 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 query.addProperty(3);
});

View file

@ -1,8 +1,14 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:background_downloader/background_downloader.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/models/item_base_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/providers/sync/sync_provider_helpers.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.g.dart';
@freezed
class SyncedItem with _$SyncedItem {
@ -32,7 +33,7 @@ class SyncedItem with _$SyncedItem {
required String userId,
String? path,
@Default(false) bool markedForDelete,
int? sortKey,
String? sortName,
int? fileSize,
String? videoFileName,
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) {
return SyncedItem(
id: isarSyncedItem.id,
parentId: isarSyncedItem.parentId,
userId: isarSyncedItem.userId ?? "",
sortKey: isarSyncedItem.sortKey,
sortName: isarSyncedItem.sortName,
path: joinAll([savePath, isarSyncedItem.path ?? ""]),
fileSize: isarSyncedItem.fileSize,
videoFileName: isarSyncedItem.videoFileName,

View file

@ -14,10 +14,6 @@ T _$identity<T>(T value) => value;
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');
SyncedItem _$SyncedItemFromJson(Map<String, dynamic> json) {
return _SyncItem.fromJson(json);
}
/// @nodoc
mixin _$SyncedItem {
String get id => throw _privateConstructorUsedError;
@ -25,7 +21,7 @@ mixin _$SyncedItem {
String get userId => throw _privateConstructorUsedError;
String? get path => throw _privateConstructorUsedError;
bool get markedForDelete => throw _privateConstructorUsedError;
int? get sortKey => throw _privateConstructorUsedError;
String? get sortName => throw _privateConstructorUsedError;
int? get fileSize => throw _privateConstructorUsedError;
String? get videoFileName => throw _privateConstructorUsedError;
IntroOutSkipModel? get introOutSkipModel =>
@ -37,7 +33,6 @@ mixin _$SyncedItem {
@UserDataJsonSerializer()
UserData? get userData => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$SyncedItemCopyWith<SyncedItem> get copyWith =>
throw _privateConstructorUsedError;
@ -55,7 +50,7 @@ abstract class $SyncedItemCopyWith<$Res> {
String userId,
String? path,
bool markedForDelete,
int? sortKey,
String? sortName,
int? fileSize,
String? videoFileName,
IntroOutSkipModel? introOutSkipModel,
@ -87,7 +82,7 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
Object? userId = null,
Object? path = freezed,
Object? markedForDelete = null,
Object? sortKey = freezed,
Object? sortName = freezed,
Object? fileSize = freezed,
Object? videoFileName = freezed,
Object? introOutSkipModel = freezed,
@ -118,10 +113,10 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
? _value.markedForDelete
: markedForDelete // ignore: cast_nullable_to_non_nullable
as bool,
sortKey: freezed == sortKey
? _value.sortKey
: sortKey // ignore: cast_nullable_to_non_nullable
as int?,
sortName: freezed == sortName
? _value.sortName
: sortName // ignore: cast_nullable_to_non_nullable
as String?,
fileSize: freezed == fileSize
? _value.fileSize
: fileSize // ignore: cast_nullable_to_non_nullable
@ -196,7 +191,7 @@ abstract class _$$SyncItemImplCopyWith<$Res>
String userId,
String? path,
bool markedForDelete,
int? sortKey,
String? sortName,
int? fileSize,
String? videoFileName,
IntroOutSkipModel? introOutSkipModel,
@ -228,7 +223,7 @@ class __$$SyncItemImplCopyWithImpl<$Res>
Object? userId = null,
Object? path = freezed,
Object? markedForDelete = null,
Object? sortKey = freezed,
Object? sortName = freezed,
Object? fileSize = freezed,
Object? videoFileName = freezed,
Object? introOutSkipModel = freezed,
@ -259,10 +254,10 @@ class __$$SyncItemImplCopyWithImpl<$Res>
? _value.markedForDelete
: markedForDelete // ignore: cast_nullable_to_non_nullable
as bool,
sortKey: freezed == sortKey
? _value.sortKey
: sortKey // ignore: cast_nullable_to_non_nullable
as int?,
sortName: freezed == sortName
? _value.sortName
: sortName // ignore: cast_nullable_to_non_nullable
as String?,
fileSize: freezed == fileSize
? _value.fileSize
: fileSize // ignore: cast_nullable_to_non_nullable
@ -300,7 +295,7 @@ class __$$SyncItemImplCopyWithImpl<$Res>
}
/// @nodoc
@JsonSerializable()
class _$SyncItemImpl extends _SyncItem {
_$SyncItemImpl(
{required this.id,
@ -308,7 +303,7 @@ class _$SyncItemImpl extends _SyncItem {
required this.userId,
this.path,
this.markedForDelete = false,
this.sortKey,
this.sortName,
this.fileSize,
this.videoFileName,
this.introOutSkipModel,
@ -321,9 +316,6 @@ class _$SyncItemImpl extends _SyncItem {
_subtitles = subtitles,
super._();
factory _$SyncItemImpl.fromJson(Map<String, dynamic> json) =>
_$$SyncItemImplFromJson(json);
@override
final String id;
@override
@ -336,7 +328,7 @@ class _$SyncItemImpl extends _SyncItem {
@JsonKey()
final bool markedForDelete;
@override
final int? sortKey;
final String? sortName;
@override
final int? fileSize;
@override
@ -371,7 +363,7 @@ class _$SyncItemImpl extends _SyncItem {
@override
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
@ -386,7 +378,8 @@ class _$SyncItemImpl extends _SyncItem {
(identical(other.path, path) || other.path == path) &&
(identical(other.markedForDelete, markedForDelete) ||
other.markedForDelete == markedForDelete) &&
(identical(other.sortKey, sortKey) || other.sortKey == sortKey) &&
(identical(other.sortName, sortName) ||
other.sortName == sortName) &&
(identical(other.fileSize, fileSize) ||
other.fileSize == fileSize) &&
(identical(other.videoFileName, videoFileName) ||
@ -404,7 +397,6 @@ class _$SyncItemImpl extends _SyncItem {
other.userData == userData));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
@ -413,7 +405,7 @@ class _$SyncItemImpl extends _SyncItem {
userId,
path,
markedForDelete,
sortKey,
sortName,
fileSize,
videoFileName,
introOutSkipModel,
@ -428,13 +420,6 @@ class _$SyncItemImpl extends _SyncItem {
@pragma('vm:prefer-inline')
_$$SyncItemImplCopyWith<_$SyncItemImpl> get copyWith =>
__$$SyncItemImplCopyWithImpl<_$SyncItemImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$SyncItemImplToJson(
this,
);
}
}
abstract class _SyncItem extends SyncedItem {
@ -444,7 +429,7 @@ abstract class _SyncItem extends SyncedItem {
required final String userId,
final String? path,
final bool markedForDelete,
final int? sortKey,
final String? sortName,
final int? fileSize,
final String? videoFileName,
final IntroOutSkipModel? introOutSkipModel,
@ -455,9 +440,6 @@ abstract class _SyncItem extends SyncedItem {
@UserDataJsonSerializer() final UserData? userData}) = _$SyncItemImpl;
_SyncItem._() : super._();
factory _SyncItem.fromJson(Map<String, dynamic> json) =
_$SyncItemImpl.fromJson;
@override
String get id;
@override
@ -469,7 +451,7 @@ abstract class _SyncItem extends SyncedItem {
@override
bool get markedForDelete;
@override
int? get sortKey;
String? get sortName;
@override
int? get fileSize;
@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: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';
@riverpod
@ -18,7 +18,7 @@ class SyncChildren extends _$SyncChildren {
while (toProcess.isNotEmpty) {
final currentLevel = toProcess.map(
(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 ?? "")) ??
<SyncedItem>[];
},

View file

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

View file

@ -3,22 +3,12 @@ import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:background_downloader/background_downloader.dart';
import 'package:collection/collection.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:http/http.dart' as http;
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/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/images_models.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/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/profiles/default_profile.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/screens/shared/fladder_snackbar.dart';
final syncProvider = StateNotifierProvider<SyncNotifier, SyncSettingsModel>((ref) => throw UnimplementedError());
@ -147,7 +148,7 @@ class SyncNotifier extends StateNotifier<SyncSettingsModel> {
while (toProcess.isNotEmpty) {
final currentLevel = toProcess.map(
(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 ?? "")) ??
<SyncedItem>[];
},
@ -159,7 +160,7 @@ class SyncNotifier extends StateNotifier<SyncSettingsModel> {
}
List<SyncedItem> getChildren(SyncedItem item) {
return (syncedItems?.where().parentIdEqualTo(item.id).sortBySortKey().findAll())
return (syncedItems?.where().parentIdEqualTo(item.id).sortBySortName().findAll())
?.map(
(e) => SyncedItem.fromIsar(e, syncPath ?? ""),
)
@ -493,7 +494,7 @@ extension SyncNotifierHelpers on SyncNotifier {
return syncItem.copyWith(
id: item.id,
parentId: parent?.id,
sortKey: (response.parentIndexNumber ?? 0) * (response.indexNumber ?? 0),
sortName: response.sortName,
path: directory.path,
fChapters: await saveChapterImages(origChapters, directory) ?? [],
fileSize: response.mediaSources?.firstOrNull?.size ?? 0,

View file

@ -1,4 +1,8 @@
import 'package:flutter/material.dart';
import 'package:ficonsax/ficonsax.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/book_model.dart';
import 'package:fladder/models/item_base_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/identifty_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/playlists/add_to_playlists.dart';
import 'package:fladder/screens/shared/fladder_snackbar.dart';
import 'package:fladder/screens/syncing/sync_button.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/widgets/pop_up/delete_file.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> {
Map<FladderItemType, List<ItemBaseModel>> get groupedItems {
@ -195,7 +197,7 @@ extension ItemBaseModelExtensions on ItemBaseModel {
},
label: Text(context.localized.refreshMetadata),
),
if (!exclude.contains(ItemActions.download) && downloadEnabled) ...{
if (!exclude.contains(ItemActions.download) && downloadEnabled)
if (syncedItem == null)
ItemActionButton(
icon: const Icon(IconsaxOutline.arrow_down_2),
@ -207,8 +209,7 @@ extension ItemBaseModelExtensions on ItemBaseModel {
icon: IgnorePointer(child: SyncButton(item: this, syncedItem: syncedItem)),
action: () => showSyncItemDetails(context, syncedItem, ref),
label: Text(context.localized.syncDetails),
)
},
),
if (canDelete == true)
ItemActionButton(
icon: Container(