diff --git a/app/lib/app.dart b/app/lib/app.dart index 6e36cc5..6593a72 100644 --- a/app/lib/app.dart +++ b/app/lib/app.dart @@ -4,7 +4,8 @@ // MultiRepositoryProvider // ├─ ApiClient // ├─ AuthRepository -// ├─ JournalRepository (RemoteJournalRepository) +// ├─ JournalRepository (IsarJournalRepository — 离线优先) +// ├─ RemoteJournalRepository (供 SyncEngine 使用) // └─ ClassRepository // └─ BlocProvider // └─ MaterialApp.router @@ -18,8 +19,10 @@ import 'core/routing/app_router.dart'; import 'data/remote/api_client.dart'; import 'data/repositories/auth_repository.dart'; import 'data/repositories/journal_repository.dart'; +import 'data/repositories/isar_journal_repository.dart'; import 'data/repositories/remote_journal_repository.dart'; import 'data/repositories/class_repository.dart'; +import 'data/services/sync_engine.dart'; import 'features/auth/bloc/auth_bloc.dart'; import 'features/profile/bloc/settings_bloc.dart'; @@ -32,7 +35,10 @@ class NuanjiApp extends StatelessWidget { // 创建全局依赖(App 生命周期内单例) final apiClient = ApiClient(); final authRepository = AuthRepository(apiClient: apiClient); - final journalRepository = RemoteJournalRepository(api: apiClient); + // 离线优先:Isar 为主要本地仓库,Remote 供 SyncEngine 推送 + final journalRepository = IsarJournalRepository(); + final remoteJournalRepository = RemoteJournalRepository(api: apiClient); + final syncEngine = SyncEngine(apiClient: apiClient); final classRepository = ClassRepository(api: apiClient); final settingsBloc = SettingsBloc(); final authBloc = AuthBloc(authRepository: authRepository); @@ -40,6 +46,9 @@ class NuanjiApp extends StatelessWidget { // 启动时检查认证状态 authBloc.add(const AppStarted()); + // 异步恢复 SyncEngine 持久化队列(fire-and-forget,不阻塞 UI) + syncEngine.restorePendingQueue(); + // 认证成功后注入 JWT token 到 ApiClient authBloc.stream.listen((state) { if (state is Authenticated) { @@ -55,6 +64,8 @@ class NuanjiApp extends StatelessWidget { RepositoryProvider.value(value: apiClient), RepositoryProvider.value(value: authRepository), RepositoryProvider.value(value: journalRepository), + RepositoryProvider.value(value: remoteJournalRepository), + RepositoryProvider.value(value: syncEngine), RepositoryProvider.value(value: classRepository), RepositoryProvider.value(value: settingsBloc), ], diff --git a/app/lib/data/local/collections/journal_element_collection.dart b/app/lib/data/local/collections/journal_element_collection.dart new file mode 100644 index 0000000..141cb95 --- /dev/null +++ b/app/lib/data/local/collections/journal_element_collection.dart @@ -0,0 +1,63 @@ +// 日记元素 Isar Collection — 本地持久化存储 +// +// 与纯 Dart 模型 JournalElement 分离,通过转换函数桥接。 +// journalId 索引支持按日记查询所有元素。 + +import 'package:isar/isar.dart'; + +part 'journal_element_collection.g.dart'; + +@collection +class JournalElementCollection { + /// Isar 自增主键 + Id isarId = Isar.autoIncrement; + + /// 业务 UUID(索引) + @Index() + String id = ''; + + /// 所属日记 ID(索引,用于外键查询) + @Index() + String journalId = ''; + + /// 元素类型(enum → string: text/image/sticker/handwriting_ref/tape) + String elementType = 'text'; + + /// X 坐标 + double positionX = 0; + + /// Y 坐标 + double positionY = 0; + + /// 宽度 + double width = 100; + + /// 高度 + double height = 100; + + /// 旋转角度 + double rotation = 0; + + /// 层级 + int zIndex = 0; + + /// 结构化内容(JSON String) + /// text: {'text':'...','fontSize':16.0} + /// image: {'filePath':'...'} + /// sticker: {'stickerPackId':'...','stickerId':'...'} + /// handwriting_ref: {'strokesJson':'...','strokeCount':42} + /// tape: {'tapeStyle':'washi_dots'} + String contentJson = '{}'; + + /// 版本号(乐观锁) + int version = 1; + + /// 创建时间(epoch milliseconds) + int createdAtEpoch = 0; + + /// 更新时间(epoch milliseconds) + int updatedAtEpoch = 0; + + /// 软删除标记 + bool isDeleted = false; +} diff --git a/app/lib/data/local/collections/journal_element_collection.g.dart b/app/lib/data/local/collections/journal_element_collection.g.dart new file mode 100644 index 0000000..292a173 --- /dev/null +++ b/app/lib/data/local/collections/journal_element_collection.g.dart @@ -0,0 +1,2218 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'journal_element_collection.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetJournalElementCollectionCollection on Isar { + IsarCollection get journalElementCollections => + this.collection(); +} + +const JournalElementCollectionSchema = CollectionSchema( + name: r'JournalElementCollection', + id: -3625932583395690305, + properties: { + r'contentJson': PropertySchema( + id: 0, + name: r'contentJson', + type: IsarType.string, + ), + r'createdAtEpoch': PropertySchema( + id: 1, + name: r'createdAtEpoch', + type: IsarType.long, + ), + r'elementType': PropertySchema( + id: 2, + name: r'elementType', + type: IsarType.string, + ), + r'height': PropertySchema( + id: 3, + name: r'height', + type: IsarType.double, + ), + r'id': PropertySchema( + id: 4, + name: r'id', + type: IsarType.string, + ), + r'isDeleted': PropertySchema( + id: 5, + name: r'isDeleted', + type: IsarType.bool, + ), + r'journalId': PropertySchema( + id: 6, + name: r'journalId', + type: IsarType.string, + ), + r'positionX': PropertySchema( + id: 7, + name: r'positionX', + type: IsarType.double, + ), + r'positionY': PropertySchema( + id: 8, + name: r'positionY', + type: IsarType.double, + ), + r'rotation': PropertySchema( + id: 9, + name: r'rotation', + type: IsarType.double, + ), + r'updatedAtEpoch': PropertySchema( + id: 10, + name: r'updatedAtEpoch', + type: IsarType.long, + ), + r'version': PropertySchema( + id: 11, + name: r'version', + type: IsarType.long, + ), + r'width': PropertySchema( + id: 12, + name: r'width', + type: IsarType.double, + ), + r'zIndex': PropertySchema( + id: 13, + name: r'zIndex', + type: IsarType.long, + ) + }, + estimateSize: _journalElementCollectionEstimateSize, + serialize: _journalElementCollectionSerialize, + deserialize: _journalElementCollectionDeserialize, + deserializeProp: _journalElementCollectionDeserializeProp, + idName: r'isarId', + indexes: { + r'id': IndexSchema( + id: -3268401673993471357, + name: r'id', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'id', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ), + r'journalId': IndexSchema( + id: 1745640946427815323, + name: r'journalId', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'journalId', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _journalElementCollectionGetId, + getLinks: _journalElementCollectionGetLinks, + attach: _journalElementCollectionAttach, + version: '3.1.0+1', +); + +int _journalElementCollectionEstimateSize( + JournalElementCollection object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + bytesCount += 3 + object.contentJson.length * 3; + bytesCount += 3 + object.elementType.length * 3; + bytesCount += 3 + object.id.length * 3; + bytesCount += 3 + object.journalId.length * 3; + return bytesCount; +} + +void _journalElementCollectionSerialize( + JournalElementCollection object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeString(offsets[0], object.contentJson); + writer.writeLong(offsets[1], object.createdAtEpoch); + writer.writeString(offsets[2], object.elementType); + writer.writeDouble(offsets[3], object.height); + writer.writeString(offsets[4], object.id); + writer.writeBool(offsets[5], object.isDeleted); + writer.writeString(offsets[6], object.journalId); + writer.writeDouble(offsets[7], object.positionX); + writer.writeDouble(offsets[8], object.positionY); + writer.writeDouble(offsets[9], object.rotation); + writer.writeLong(offsets[10], object.updatedAtEpoch); + writer.writeLong(offsets[11], object.version); + writer.writeDouble(offsets[12], object.width); + writer.writeLong(offsets[13], object.zIndex); +} + +JournalElementCollection _journalElementCollectionDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = JournalElementCollection(); + object.contentJson = reader.readString(offsets[0]); + object.createdAtEpoch = reader.readLong(offsets[1]); + object.elementType = reader.readString(offsets[2]); + object.height = reader.readDouble(offsets[3]); + object.id = reader.readString(offsets[4]); + object.isDeleted = reader.readBool(offsets[5]); + object.isarId = id; + object.journalId = reader.readString(offsets[6]); + object.positionX = reader.readDouble(offsets[7]); + object.positionY = reader.readDouble(offsets[8]); + object.rotation = reader.readDouble(offsets[9]); + object.updatedAtEpoch = reader.readLong(offsets[10]); + object.version = reader.readLong(offsets[11]); + object.width = reader.readDouble(offsets[12]); + object.zIndex = reader.readLong(offsets[13]); + return object; +} + +P _journalElementCollectionDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readString(offset)) as P; + case 1: + return (reader.readLong(offset)) as P; + case 2: + return (reader.readString(offset)) as P; + case 3: + return (reader.readDouble(offset)) as P; + case 4: + return (reader.readString(offset)) as P; + case 5: + return (reader.readBool(offset)) as P; + case 6: + return (reader.readString(offset)) as P; + case 7: + return (reader.readDouble(offset)) as P; + case 8: + return (reader.readDouble(offset)) as P; + case 9: + return (reader.readDouble(offset)) as P; + case 10: + return (reader.readLong(offset)) as P; + case 11: + return (reader.readLong(offset)) as P; + case 12: + return (reader.readDouble(offset)) as P; + case 13: + return (reader.readLong(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _journalElementCollectionGetId(JournalElementCollection object) { + return object.isarId; +} + +List> _journalElementCollectionGetLinks( + JournalElementCollection object) { + return []; +} + +void _journalElementCollectionAttach( + IsarCollection col, Id id, JournalElementCollection object) { + object.isarId = id; +} + +extension JournalElementCollectionQueryWhereSort on QueryBuilder< + JournalElementCollection, JournalElementCollection, QWhere> { + QueryBuilder + anyIsarId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension JournalElementCollectionQueryWhere on QueryBuilder< + JournalElementCollection, JournalElementCollection, QWhereClause> { + QueryBuilder isarIdEqualTo(Id isarId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: isarId, + upper: isarId, + )); + }); + } + + QueryBuilder isarIdNotEqualTo(Id isarId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: false), + ); + } + }); + } + + QueryBuilder isarIdGreaterThan(Id isarId, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: include), + ); + }); + } + + QueryBuilder isarIdLessThan(Id isarId, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: include), + ); + }); + } + + QueryBuilder isarIdBetween( + Id lowerIsarId, + Id upperIsarId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerIsarId, + includeLower: includeLower, + upper: upperIsarId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder idEqualTo(String id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'id', + value: [id], + )); + }); + } + + QueryBuilder idNotEqualTo(String id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [], + upper: [id], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [id], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [id], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [], + upper: [id], + includeUpper: false, + )); + } + }); + } + + QueryBuilder journalIdEqualTo(String journalId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'journalId', + value: [journalId], + )); + }); + } + + QueryBuilder journalIdNotEqualTo(String journalId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'journalId', + lower: [], + upper: [journalId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'journalId', + lower: [journalId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'journalId', + lower: [journalId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'journalId', + lower: [], + upper: [journalId], + includeUpper: false, + )); + } + }); + } +} + +extension JournalElementCollectionQueryFilter on QueryBuilder< + JournalElementCollection, JournalElementCollection, QFilterCondition> { + QueryBuilder contentJsonEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'contentJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder contentJsonGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'contentJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder contentJsonLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'contentJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder contentJsonBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'contentJson', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder contentJsonStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'contentJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder contentJsonEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'contentJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + contentJsonContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'contentJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + contentJsonMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'contentJson', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder contentJsonIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'contentJson', + value: '', + )); + }); + } + + QueryBuilder contentJsonIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'contentJson', + value: '', + )); + }); + } + + QueryBuilder createdAtEpochEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'createdAtEpoch', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder elementTypeEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'elementType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder elementTypeGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'elementType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder elementTypeLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'elementType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder elementTypeBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'elementType', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder elementTypeStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'elementType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder elementTypeEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'elementType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + elementTypeContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'elementType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + elementTypeMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'elementType', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder elementTypeIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'elementType', + value: '', + )); + }); + } + + QueryBuilder elementTypeIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'elementType', + value: '', + )); + }); + } + + QueryBuilder heightEqualTo( + double value, { + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'height', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder heightGreaterThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'height', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder heightLessThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'height', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder heightBetween( + double lower, + double upper, { + bool includeLower = true, + bool includeUpper = true, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'height', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + epsilon: epsilon, + )); + }); + } + + QueryBuilder idEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + idContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + idMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'id', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: '', + )); + }); + } + + QueryBuilder idIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'id', + value: '', + )); + }); + } + + QueryBuilder isDeletedEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isDeleted', + value: value, + )); + }); + } + + QueryBuilder isarIdEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'isarId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder journalIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'journalId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder journalIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'journalId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder journalIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'journalId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder journalIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'journalId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder journalIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'journalId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder journalIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'journalId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + journalIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'journalId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + journalIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'journalId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder journalIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'journalId', + value: '', + )); + }); + } + + QueryBuilder journalIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'journalId', + value: '', + )); + }); + } + + QueryBuilder positionXEqualTo( + double value, { + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'positionX', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionXGreaterThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'positionX', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionXLessThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'positionX', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionXBetween( + double lower, + double upper, { + bool includeLower = true, + bool includeUpper = true, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'positionX', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionYEqualTo( + double value, { + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'positionY', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionYGreaterThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'positionY', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionYLessThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'positionY', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder positionYBetween( + double lower, + double upper, { + bool includeLower = true, + bool includeUpper = true, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'positionY', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + epsilon: epsilon, + )); + }); + } + + QueryBuilder rotationEqualTo( + double value, { + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'rotation', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder rotationGreaterThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'rotation', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder rotationLessThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'rotation', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder rotationBetween( + double lower, + double upper, { + bool includeLower = true, + bool includeUpper = true, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'rotation', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + epsilon: epsilon, + )); + }); + } + + QueryBuilder updatedAtEpochEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'updatedAtEpoch', + value: value, + )); + }); + } + + QueryBuilder updatedAtEpochGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'updatedAtEpoch', + value: value, + )); + }); + } + + QueryBuilder updatedAtEpochLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'updatedAtEpoch', + value: value, + )); + }); + } + + QueryBuilder updatedAtEpochBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'updatedAtEpoch', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder versionEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'version', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder widthEqualTo( + double value, { + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'width', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder widthGreaterThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'width', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder widthLessThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'width', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder widthBetween( + double lower, + double upper, { + bool includeLower = true, + bool includeUpper = true, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'width', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + epsilon: epsilon, + )); + }); + } + + QueryBuilder zIndexEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'zIndex', + value: value, + )); + }); + } + + QueryBuilder zIndexGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'zIndex', + value: value, + )); + }); + } + + QueryBuilder zIndexLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'zIndex', + value: value, + )); + }); + } + + QueryBuilder zIndexBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'zIndex', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } +} + +extension JournalElementCollectionQueryObject on QueryBuilder< + JournalElementCollection, JournalElementCollection, QFilterCondition> {} + +extension JournalElementCollectionQueryLinks on QueryBuilder< + JournalElementCollection, JournalElementCollection, QFilterCondition> {} + +extension JournalElementCollectionQuerySortBy on QueryBuilder< + JournalElementCollection, JournalElementCollection, QSortBy> { + QueryBuilder + sortByContentJson() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'contentJson', Sort.asc); + }); + } + + QueryBuilder + sortByContentJsonDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'contentJson', Sort.desc); + }); + } + + QueryBuilder + sortByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.asc); + }); + } + + QueryBuilder + sortByCreatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.desc); + }); + } + + QueryBuilder + sortByElementType() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'elementType', Sort.asc); + }); + } + + QueryBuilder + sortByElementTypeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'elementType', Sort.desc); + }); + } + + QueryBuilder + sortByHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'height', Sort.asc); + }); + } + + QueryBuilder + sortByHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'height', Sort.desc); + }); + } + + QueryBuilder + sortById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + sortByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + sortByIsDeleted() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.asc); + }); + } + + QueryBuilder + sortByIsDeletedDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.desc); + }); + } + + QueryBuilder + sortByJournalId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'journalId', Sort.asc); + }); + } + + QueryBuilder + sortByJournalIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'journalId', Sort.desc); + }); + } + + QueryBuilder + sortByPositionX() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionX', Sort.asc); + }); + } + + QueryBuilder + sortByPositionXDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionX', Sort.desc); + }); + } + + QueryBuilder + sortByPositionY() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionY', Sort.asc); + }); + } + + QueryBuilder + sortByPositionYDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionY', Sort.desc); + }); + } + + QueryBuilder + sortByRotation() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'rotation', Sort.asc); + }); + } + + QueryBuilder + sortByRotationDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'rotation', Sort.desc); + }); + } + + QueryBuilder + sortByUpdatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.asc); + }); + } + + QueryBuilder + sortByUpdatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.desc); + }); + } + + QueryBuilder + sortByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.asc); + }); + } + + QueryBuilder + sortByVersionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.desc); + }); + } + + QueryBuilder + sortByWidth() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'width', Sort.asc); + }); + } + + QueryBuilder + sortByWidthDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'width', Sort.desc); + }); + } + + QueryBuilder + sortByZIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zIndex', Sort.asc); + }); + } + + QueryBuilder + sortByZIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zIndex', Sort.desc); + }); + } +} + +extension JournalElementCollectionQuerySortThenBy on QueryBuilder< + JournalElementCollection, JournalElementCollection, QSortThenBy> { + QueryBuilder + thenByContentJson() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'contentJson', Sort.asc); + }); + } + + QueryBuilder + thenByContentJsonDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'contentJson', Sort.desc); + }); + } + + QueryBuilder + thenByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.asc); + }); + } + + QueryBuilder + thenByCreatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.desc); + }); + } + + QueryBuilder + thenByElementType() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'elementType', Sort.asc); + }); + } + + QueryBuilder + thenByElementTypeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'elementType', Sort.desc); + }); + } + + QueryBuilder + thenByHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'height', Sort.asc); + }); + } + + QueryBuilder + thenByHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'height', Sort.desc); + }); + } + + QueryBuilder + thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByIsDeleted() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.asc); + }); + } + + QueryBuilder + thenByIsDeletedDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.desc); + }); + } + + QueryBuilder + thenByIsarId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isarId', Sort.asc); + }); + } + + QueryBuilder + thenByIsarIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isarId', Sort.desc); + }); + } + + QueryBuilder + thenByJournalId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'journalId', Sort.asc); + }); + } + + QueryBuilder + thenByJournalIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'journalId', Sort.desc); + }); + } + + QueryBuilder + thenByPositionX() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionX', Sort.asc); + }); + } + + QueryBuilder + thenByPositionXDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionX', Sort.desc); + }); + } + + QueryBuilder + thenByPositionY() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionY', Sort.asc); + }); + } + + QueryBuilder + thenByPositionYDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'positionY', Sort.desc); + }); + } + + QueryBuilder + thenByRotation() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'rotation', Sort.asc); + }); + } + + QueryBuilder + thenByRotationDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'rotation', Sort.desc); + }); + } + + QueryBuilder + thenByUpdatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.asc); + }); + } + + QueryBuilder + thenByUpdatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.desc); + }); + } + + QueryBuilder + thenByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.asc); + }); + } + + QueryBuilder + thenByVersionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.desc); + }); + } + + QueryBuilder + thenByWidth() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'width', Sort.asc); + }); + } + + QueryBuilder + thenByWidthDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'width', Sort.desc); + }); + } + + QueryBuilder + thenByZIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zIndex', Sort.asc); + }); + } + + QueryBuilder + thenByZIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zIndex', Sort.desc); + }); + } +} + +extension JournalElementCollectionQueryWhereDistinct on QueryBuilder< + JournalElementCollection, JournalElementCollection, QDistinct> { + QueryBuilder + distinctByContentJson({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'contentJson', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'createdAtEpoch'); + }); + } + + QueryBuilder + distinctByElementType({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'elementType', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByHeight() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'height'); + }); + } + + QueryBuilder + distinctById({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'id', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByIsDeleted() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isDeleted'); + }); + } + + QueryBuilder + distinctByJournalId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'journalId', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByPositionX() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'positionX'); + }); + } + + QueryBuilder + distinctByPositionY() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'positionY'); + }); + } + + QueryBuilder + distinctByRotation() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'rotation'); + }); + } + + QueryBuilder + distinctByUpdatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'updatedAtEpoch'); + }); + } + + QueryBuilder + distinctByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'version'); + }); + } + + QueryBuilder + distinctByWidth() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'width'); + }); + } + + QueryBuilder + distinctByZIndex() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'zIndex'); + }); + } +} + +extension JournalElementCollectionQueryProperty on QueryBuilder< + JournalElementCollection, JournalElementCollection, QQueryProperty> { + QueryBuilder + isarIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isarId'); + }); + } + + QueryBuilder + contentJsonProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'contentJson'); + }); + } + + QueryBuilder + createdAtEpochProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'createdAtEpoch'); + }); + } + + QueryBuilder + elementTypeProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'elementType'); + }); + } + + QueryBuilder + heightProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'height'); + }); + } + + QueryBuilder + idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + isDeletedProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isDeleted'); + }); + } + + QueryBuilder + journalIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'journalId'); + }); + } + + QueryBuilder + positionXProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'positionX'); + }); + } + + QueryBuilder + positionYProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'positionY'); + }); + } + + QueryBuilder + rotationProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'rotation'); + }); + } + + QueryBuilder + updatedAtEpochProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'updatedAtEpoch'); + }); + } + + QueryBuilder + versionProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'version'); + }); + } + + QueryBuilder + widthProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'width'); + }); + } + + QueryBuilder + zIndexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'zIndex'); + }); + } +} diff --git a/app/lib/data/local/collections/journal_entry_collection.dart b/app/lib/data/local/collections/journal_entry_collection.dart new file mode 100644 index 0000000..e278e47 --- /dev/null +++ b/app/lib/data/local/collections/journal_entry_collection.dart @@ -0,0 +1,60 @@ +// 日记条目 Isar Collection — 本地持久化存储 +// +// 与纯 Dart 模型 JournalEntry 分离,通过转换函数桥接。 +// 业务 ID (String UUID) 作为索引字段,Isar 主键用 autoIncrement。 + +import 'package:isar/isar.dart'; + +part 'journal_entry_collection.g.dart'; + +@collection +class JournalEntryCollection { + /// Isar 自增主键 + Id isarId = Isar.autoIncrement; + + /// 业务 UUID(索引,用于查找) + @Index() + String id = ''; + + /// 作者 ID + String authorId = ''; + + /// 班级 ID(可选) + String? classId; + + /// 日记标题 + String title = ''; + + /// 日记日期(epoch milliseconds) + int dateEpoch = 0; + + /// 心情(enum → string) + String mood = 'calm'; + + /// 天气(enum → string) + String weather = 'sunny'; + + /// 标签列表(JSON String) + String tagsJson = '[]'; + + /// 是否私密 + bool isPrivate = true; + + /// 是否分享到班级 + bool sharedToClass = false; + + /// 关联主题 ID(可选) + String? assignedTopicId; + + /// 版本号(乐观锁) + int version = 1; + + /// 创建时间(epoch milliseconds) + int createdAtEpoch = 0; + + /// 更新时间(epoch milliseconds) + int updatedAtEpoch = 0; + + /// 软删除标记 + bool isDeleted = false; +} diff --git a/app/lib/data/local/collections/journal_entry_collection.g.dart b/app/lib/data/local/collections/journal_entry_collection.g.dart new file mode 100644 index 0000000..98fab31 --- /dev/null +++ b/app/lib/data/local/collections/journal_entry_collection.g.dart @@ -0,0 +1,2502 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'journal_entry_collection.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetJournalEntryCollectionCollection on Isar { + IsarCollection get journalEntryCollections => + this.collection(); +} + +const JournalEntryCollectionSchema = CollectionSchema( + name: r'JournalEntryCollection', + id: -6325316395299921961, + properties: { + r'assignedTopicId': PropertySchema( + id: 0, + name: r'assignedTopicId', + type: IsarType.string, + ), + r'authorId': PropertySchema( + id: 1, + name: r'authorId', + type: IsarType.string, + ), + r'classId': PropertySchema( + id: 2, + name: r'classId', + type: IsarType.string, + ), + r'createdAtEpoch': PropertySchema( + id: 3, + name: r'createdAtEpoch', + type: IsarType.long, + ), + r'dateEpoch': PropertySchema( + id: 4, + name: r'dateEpoch', + type: IsarType.long, + ), + r'id': PropertySchema( + id: 5, + name: r'id', + type: IsarType.string, + ), + r'isDeleted': PropertySchema( + id: 6, + name: r'isDeleted', + type: IsarType.bool, + ), + r'isPrivate': PropertySchema( + id: 7, + name: r'isPrivate', + type: IsarType.bool, + ), + r'mood': PropertySchema( + id: 8, + name: r'mood', + type: IsarType.string, + ), + r'sharedToClass': PropertySchema( + id: 9, + name: r'sharedToClass', + type: IsarType.bool, + ), + r'tagsJson': PropertySchema( + id: 10, + name: r'tagsJson', + type: IsarType.string, + ), + r'title': PropertySchema( + id: 11, + name: r'title', + type: IsarType.string, + ), + r'updatedAtEpoch': PropertySchema( + id: 12, + name: r'updatedAtEpoch', + type: IsarType.long, + ), + r'version': PropertySchema( + id: 13, + name: r'version', + type: IsarType.long, + ), + r'weather': PropertySchema( + id: 14, + name: r'weather', + type: IsarType.string, + ) + }, + estimateSize: _journalEntryCollectionEstimateSize, + serialize: _journalEntryCollectionSerialize, + deserialize: _journalEntryCollectionDeserialize, + deserializeProp: _journalEntryCollectionDeserializeProp, + idName: r'isarId', + indexes: { + r'id': IndexSchema( + id: -3268401673993471357, + name: r'id', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'id', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _journalEntryCollectionGetId, + getLinks: _journalEntryCollectionGetLinks, + attach: _journalEntryCollectionAttach, + version: '3.1.0+1', +); + +int _journalEntryCollectionEstimateSize( + JournalEntryCollection object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.assignedTopicId; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.authorId.length * 3; + { + final value = object.classId; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.id.length * 3; + bytesCount += 3 + object.mood.length * 3; + bytesCount += 3 + object.tagsJson.length * 3; + bytesCount += 3 + object.title.length * 3; + bytesCount += 3 + object.weather.length * 3; + return bytesCount; +} + +void _journalEntryCollectionSerialize( + JournalEntryCollection object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeString(offsets[0], object.assignedTopicId); + writer.writeString(offsets[1], object.authorId); + writer.writeString(offsets[2], object.classId); + writer.writeLong(offsets[3], object.createdAtEpoch); + writer.writeLong(offsets[4], object.dateEpoch); + writer.writeString(offsets[5], object.id); + writer.writeBool(offsets[6], object.isDeleted); + writer.writeBool(offsets[7], object.isPrivate); + writer.writeString(offsets[8], object.mood); + writer.writeBool(offsets[9], object.sharedToClass); + writer.writeString(offsets[10], object.tagsJson); + writer.writeString(offsets[11], object.title); + writer.writeLong(offsets[12], object.updatedAtEpoch); + writer.writeLong(offsets[13], object.version); + writer.writeString(offsets[14], object.weather); +} + +JournalEntryCollection _journalEntryCollectionDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = JournalEntryCollection(); + object.assignedTopicId = reader.readStringOrNull(offsets[0]); + object.authorId = reader.readString(offsets[1]); + object.classId = reader.readStringOrNull(offsets[2]); + object.createdAtEpoch = reader.readLong(offsets[3]); + object.dateEpoch = reader.readLong(offsets[4]); + object.id = reader.readString(offsets[5]); + object.isDeleted = reader.readBool(offsets[6]); + object.isPrivate = reader.readBool(offsets[7]); + object.isarId = id; + object.mood = reader.readString(offsets[8]); + object.sharedToClass = reader.readBool(offsets[9]); + object.tagsJson = reader.readString(offsets[10]); + object.title = reader.readString(offsets[11]); + object.updatedAtEpoch = reader.readLong(offsets[12]); + object.version = reader.readLong(offsets[13]); + object.weather = reader.readString(offsets[14]); + return object; +} + +P _journalEntryCollectionDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readStringOrNull(offset)) as P; + case 1: + return (reader.readString(offset)) as P; + case 2: + return (reader.readStringOrNull(offset)) as P; + case 3: + return (reader.readLong(offset)) as P; + case 4: + return (reader.readLong(offset)) as P; + case 5: + return (reader.readString(offset)) as P; + case 6: + return (reader.readBool(offset)) as P; + case 7: + return (reader.readBool(offset)) as P; + case 8: + return (reader.readString(offset)) as P; + case 9: + return (reader.readBool(offset)) as P; + case 10: + return (reader.readString(offset)) as P; + case 11: + return (reader.readString(offset)) as P; + case 12: + return (reader.readLong(offset)) as P; + case 13: + return (reader.readLong(offset)) as P; + case 14: + return (reader.readString(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _journalEntryCollectionGetId(JournalEntryCollection object) { + return object.isarId; +} + +List> _journalEntryCollectionGetLinks( + JournalEntryCollection object) { + return []; +} + +void _journalEntryCollectionAttach( + IsarCollection col, Id id, JournalEntryCollection object) { + object.isarId = id; +} + +extension JournalEntryCollectionQueryWhereSort + on QueryBuilder { + QueryBuilder + anyIsarId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension JournalEntryCollectionQueryWhere on QueryBuilder< + JournalEntryCollection, JournalEntryCollection, QWhereClause> { + QueryBuilder isarIdEqualTo(Id isarId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: isarId, + upper: isarId, + )); + }); + } + + QueryBuilder isarIdNotEqualTo(Id isarId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: false), + ); + } + }); + } + + QueryBuilder isarIdGreaterThan(Id isarId, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: include), + ); + }); + } + + QueryBuilder isarIdLessThan(Id isarId, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: include), + ); + }); + } + + QueryBuilder isarIdBetween( + Id lowerIsarId, + Id upperIsarId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerIsarId, + includeLower: includeLower, + upper: upperIsarId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder idEqualTo(String id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'id', + value: [id], + )); + }); + } + + QueryBuilder idNotEqualTo(String id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [], + upper: [id], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [id], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [id], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [], + upper: [id], + includeUpper: false, + )); + } + }); + } +} + +extension JournalEntryCollectionQueryFilter on QueryBuilder< + JournalEntryCollection, JournalEntryCollection, QFilterCondition> { + QueryBuilder assignedTopicIdIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'assignedTopicId', + )); + }); + } + + QueryBuilder assignedTopicIdIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'assignedTopicId', + )); + }); + } + + QueryBuilder assignedTopicIdEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'assignedTopicId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder assignedTopicIdGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'assignedTopicId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder assignedTopicIdLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'assignedTopicId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder assignedTopicIdBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'assignedTopicId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder assignedTopicIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'assignedTopicId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder assignedTopicIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'assignedTopicId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + assignedTopicIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'assignedTopicId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + assignedTopicIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'assignedTopicId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder assignedTopicIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'assignedTopicId', + value: '', + )); + }); + } + + QueryBuilder assignedTopicIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'assignedTopicId', + value: '', + )); + }); + } + + QueryBuilder authorIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'authorId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder authorIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'authorId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder authorIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'authorId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder authorIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'authorId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder authorIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'authorId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder authorIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'authorId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + authorIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'authorId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + authorIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'authorId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder authorIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'authorId', + value: '', + )); + }); + } + + QueryBuilder authorIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'authorId', + value: '', + )); + }); + } + + QueryBuilder classIdIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'classId', + )); + }); + } + + QueryBuilder classIdIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'classId', + )); + }); + } + + QueryBuilder classIdEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'classId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder classIdGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'classId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder classIdLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'classId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder classIdBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'classId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder classIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'classId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder classIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'classId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + classIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'classId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + classIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'classId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder classIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'classId', + value: '', + )); + }); + } + + QueryBuilder classIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'classId', + value: '', + )); + }); + } + + QueryBuilder createdAtEpochEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'createdAtEpoch', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder dateEpochEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'dateEpoch', + value: value, + )); + }); + } + + QueryBuilder dateEpochGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'dateEpoch', + value: value, + )); + }); + } + + QueryBuilder dateEpochLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'dateEpoch', + value: value, + )); + }); + } + + QueryBuilder dateEpochBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'dateEpoch', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder idEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + idContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + idMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'id', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: '', + )); + }); + } + + QueryBuilder idIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'id', + value: '', + )); + }); + } + + QueryBuilder isDeletedEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isDeleted', + value: value, + )); + }); + } + + QueryBuilder isPrivateEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isPrivate', + value: value, + )); + }); + } + + QueryBuilder isarIdEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'isarId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder moodEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'mood', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder moodGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'mood', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder moodLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'mood', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder moodBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'mood', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder moodStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'mood', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder moodEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'mood', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + moodContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'mood', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + moodMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'mood', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder moodIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'mood', + value: '', + )); + }); + } + + QueryBuilder moodIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'mood', + value: '', + )); + }); + } + + QueryBuilder sharedToClassEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'sharedToClass', + value: value, + )); + }); + } + + QueryBuilder tagsJsonEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'tagsJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder tagsJsonGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'tagsJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder tagsJsonLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'tagsJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder tagsJsonBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'tagsJson', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder tagsJsonStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'tagsJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder tagsJsonEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'tagsJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tagsJsonContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'tagsJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tagsJsonMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'tagsJson', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder tagsJsonIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'tagsJson', + value: '', + )); + }); + } + + QueryBuilder tagsJsonIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'tagsJson', + value: '', + )); + }); + } + + QueryBuilder titleEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'title', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder titleGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'title', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder titleLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'title', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder titleBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'title', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder titleStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'title', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder titleEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'title', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + titleContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'title', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + titleMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'title', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder titleIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'title', + value: '', + )); + }); + } + + QueryBuilder titleIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'title', + value: '', + )); + }); + } + + QueryBuilder updatedAtEpochEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'updatedAtEpoch', + value: value, + )); + }); + } + + QueryBuilder updatedAtEpochGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'updatedAtEpoch', + value: value, + )); + }); + } + + QueryBuilder updatedAtEpochLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'updatedAtEpoch', + value: value, + )); + }); + } + + QueryBuilder updatedAtEpochBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'updatedAtEpoch', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder versionEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'version', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder weatherEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'weather', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder weatherGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'weather', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder weatherLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'weather', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder weatherBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'weather', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder weatherStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'weather', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder weatherEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'weather', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + weatherContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'weather', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + weatherMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'weather', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder weatherIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'weather', + value: '', + )); + }); + } + + QueryBuilder weatherIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'weather', + value: '', + )); + }); + } +} + +extension JournalEntryCollectionQueryObject on QueryBuilder< + JournalEntryCollection, JournalEntryCollection, QFilterCondition> {} + +extension JournalEntryCollectionQueryLinks on QueryBuilder< + JournalEntryCollection, JournalEntryCollection, QFilterCondition> {} + +extension JournalEntryCollectionQuerySortBy + on QueryBuilder { + QueryBuilder + sortByAssignedTopicId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'assignedTopicId', Sort.asc); + }); + } + + QueryBuilder + sortByAssignedTopicIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'assignedTopicId', Sort.desc); + }); + } + + QueryBuilder + sortByAuthorId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'authorId', Sort.asc); + }); + } + + QueryBuilder + sortByAuthorIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'authorId', Sort.desc); + }); + } + + QueryBuilder + sortByClassId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'classId', Sort.asc); + }); + } + + QueryBuilder + sortByClassIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'classId', Sort.desc); + }); + } + + QueryBuilder + sortByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.asc); + }); + } + + QueryBuilder + sortByCreatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.desc); + }); + } + + QueryBuilder + sortByDateEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dateEpoch', Sort.asc); + }); + } + + QueryBuilder + sortByDateEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dateEpoch', Sort.desc); + }); + } + + QueryBuilder + sortById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + sortByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + sortByIsDeleted() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.asc); + }); + } + + QueryBuilder + sortByIsDeletedDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.desc); + }); + } + + QueryBuilder + sortByIsPrivate() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isPrivate', Sort.asc); + }); + } + + QueryBuilder + sortByIsPrivateDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isPrivate', Sort.desc); + }); + } + + QueryBuilder + sortByMood() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'mood', Sort.asc); + }); + } + + QueryBuilder + sortByMoodDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'mood', Sort.desc); + }); + } + + QueryBuilder + sortBySharedToClass() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedToClass', Sort.asc); + }); + } + + QueryBuilder + sortBySharedToClassDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedToClass', Sort.desc); + }); + } + + QueryBuilder + sortByTagsJson() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tagsJson', Sort.asc); + }); + } + + QueryBuilder + sortByTagsJsonDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tagsJson', Sort.desc); + }); + } + + QueryBuilder + sortByTitle() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'title', Sort.asc); + }); + } + + QueryBuilder + sortByTitleDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'title', Sort.desc); + }); + } + + QueryBuilder + sortByUpdatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.asc); + }); + } + + QueryBuilder + sortByUpdatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.desc); + }); + } + + QueryBuilder + sortByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.asc); + }); + } + + QueryBuilder + sortByVersionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.desc); + }); + } + + QueryBuilder + sortByWeather() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'weather', Sort.asc); + }); + } + + QueryBuilder + sortByWeatherDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'weather', Sort.desc); + }); + } +} + +extension JournalEntryCollectionQuerySortThenBy on QueryBuilder< + JournalEntryCollection, JournalEntryCollection, QSortThenBy> { + QueryBuilder + thenByAssignedTopicId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'assignedTopicId', Sort.asc); + }); + } + + QueryBuilder + thenByAssignedTopicIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'assignedTopicId', Sort.desc); + }); + } + + QueryBuilder + thenByAuthorId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'authorId', Sort.asc); + }); + } + + QueryBuilder + thenByAuthorIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'authorId', Sort.desc); + }); + } + + QueryBuilder + thenByClassId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'classId', Sort.asc); + }); + } + + QueryBuilder + thenByClassIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'classId', Sort.desc); + }); + } + + QueryBuilder + thenByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.asc); + }); + } + + QueryBuilder + thenByCreatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.desc); + }); + } + + QueryBuilder + thenByDateEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dateEpoch', Sort.asc); + }); + } + + QueryBuilder + thenByDateEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dateEpoch', Sort.desc); + }); + } + + QueryBuilder + thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByIsDeleted() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.asc); + }); + } + + QueryBuilder + thenByIsDeletedDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isDeleted', Sort.desc); + }); + } + + QueryBuilder + thenByIsPrivate() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isPrivate', Sort.asc); + }); + } + + QueryBuilder + thenByIsPrivateDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isPrivate', Sort.desc); + }); + } + + QueryBuilder + thenByIsarId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isarId', Sort.asc); + }); + } + + QueryBuilder + thenByIsarIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isarId', Sort.desc); + }); + } + + QueryBuilder + thenByMood() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'mood', Sort.asc); + }); + } + + QueryBuilder + thenByMoodDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'mood', Sort.desc); + }); + } + + QueryBuilder + thenBySharedToClass() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedToClass', Sort.asc); + }); + } + + QueryBuilder + thenBySharedToClassDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedToClass', Sort.desc); + }); + } + + QueryBuilder + thenByTagsJson() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tagsJson', Sort.asc); + }); + } + + QueryBuilder + thenByTagsJsonDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tagsJson', Sort.desc); + }); + } + + QueryBuilder + thenByTitle() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'title', Sort.asc); + }); + } + + QueryBuilder + thenByTitleDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'title', Sort.desc); + }); + } + + QueryBuilder + thenByUpdatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.asc); + }); + } + + QueryBuilder + thenByUpdatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'updatedAtEpoch', Sort.desc); + }); + } + + QueryBuilder + thenByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.asc); + }); + } + + QueryBuilder + thenByVersionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.desc); + }); + } + + QueryBuilder + thenByWeather() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'weather', Sort.asc); + }); + } + + QueryBuilder + thenByWeatherDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'weather', Sort.desc); + }); + } +} + +extension JournalEntryCollectionQueryWhereDistinct + on QueryBuilder { + QueryBuilder + distinctByAssignedTopicId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'assignedTopicId', + caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByAuthorId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'authorId', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByClassId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'classId', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'createdAtEpoch'); + }); + } + + QueryBuilder + distinctByDateEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'dateEpoch'); + }); + } + + QueryBuilder + distinctById({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'id', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByIsDeleted() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isDeleted'); + }); + } + + QueryBuilder + distinctByIsPrivate() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isPrivate'); + }); + } + + QueryBuilder + distinctByMood({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'mood', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctBySharedToClass() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'sharedToClass'); + }); + } + + QueryBuilder + distinctByTagsJson({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'tagsJson', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByTitle({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'title', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByUpdatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'updatedAtEpoch'); + }); + } + + QueryBuilder + distinctByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'version'); + }); + } + + QueryBuilder + distinctByWeather({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'weather', caseSensitive: caseSensitive); + }); + } +} + +extension JournalEntryCollectionQueryProperty on QueryBuilder< + JournalEntryCollection, JournalEntryCollection, QQueryProperty> { + QueryBuilder isarIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isarId'); + }); + } + + QueryBuilder + assignedTopicIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'assignedTopicId'); + }); + } + + QueryBuilder + authorIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'authorId'); + }); + } + + QueryBuilder + classIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'classId'); + }); + } + + QueryBuilder + createdAtEpochProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'createdAtEpoch'); + }); + } + + QueryBuilder + dateEpochProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'dateEpoch'); + }); + } + + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + isDeletedProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isDeleted'); + }); + } + + QueryBuilder + isPrivateProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isPrivate'); + }); + } + + QueryBuilder + moodProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'mood'); + }); + } + + QueryBuilder + sharedToClassProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'sharedToClass'); + }); + } + + QueryBuilder + tagsJsonProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'tagsJson'); + }); + } + + QueryBuilder + titleProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'title'); + }); + } + + QueryBuilder + updatedAtEpochProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'updatedAtEpoch'); + }); + } + + QueryBuilder + versionProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'version'); + }); + } + + QueryBuilder + weatherProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'weather'); + }); + } +} diff --git a/app/lib/data/local/collections/pending_operation_collection.dart b/app/lib/data/local/collections/pending_operation_collection.dart new file mode 100644 index 0000000..8b5c477 --- /dev/null +++ b/app/lib/data/local/collections/pending_operation_collection.dart @@ -0,0 +1,36 @@ +// 待同步操作 Isar Collection — SyncEngine 队列持久化 +// +// 应用退出时将内存队列写入 Isar,下次启动时恢复。 +// 保证离线操作不会因进程终止而丢失。 + +import 'package:isar/isar.dart'; + +part 'pending_operation_collection.g.dart'; + +@collection +class PendingOperationCollection { + /// Isar 自增主键 + Id isarId = Isar.autoIncrement; + + /// 业务 UUID(索引) + @Index() + String id = ''; + + /// 操作类型:create / update / delete + String operationType = 'create'; + + /// API 端点(如 '/diary/journals') + String endpoint = ''; + + /// 请求负载(JSON String) + String dataJson = '{}'; + + /// 资源版本号(乐观锁) + int version = 1; + + /// 创建时间(epoch milliseconds) + int createdAtEpoch = 0; + + /// 重试次数(最大 5 次) + int retryCount = 0; +} diff --git a/app/lib/data/local/collections/pending_operation_collection.g.dart b/app/lib/data/local/collections/pending_operation_collection.g.dart new file mode 100644 index 0000000..81ff327 --- /dev/null +++ b/app/lib/data/local/collections/pending_operation_collection.g.dart @@ -0,0 +1,1408 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'pending_operation_collection.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetPendingOperationCollectionCollection on Isar { + IsarCollection get pendingOperationCollections => + this.collection(); +} + +const PendingOperationCollectionSchema = CollectionSchema( + name: r'PendingOperationCollection', + id: -6885010264946527864, + properties: { + r'createdAtEpoch': PropertySchema( + id: 0, + name: r'createdAtEpoch', + type: IsarType.long, + ), + r'dataJson': PropertySchema( + id: 1, + name: r'dataJson', + type: IsarType.string, + ), + r'endpoint': PropertySchema( + id: 2, + name: r'endpoint', + type: IsarType.string, + ), + r'id': PropertySchema( + id: 3, + name: r'id', + type: IsarType.string, + ), + r'operationType': PropertySchema( + id: 4, + name: r'operationType', + type: IsarType.string, + ), + r'retryCount': PropertySchema( + id: 5, + name: r'retryCount', + type: IsarType.long, + ), + r'version': PropertySchema( + id: 6, + name: r'version', + type: IsarType.long, + ) + }, + estimateSize: _pendingOperationCollectionEstimateSize, + serialize: _pendingOperationCollectionSerialize, + deserialize: _pendingOperationCollectionDeserialize, + deserializeProp: _pendingOperationCollectionDeserializeProp, + idName: r'isarId', + indexes: { + r'id': IndexSchema( + id: -3268401673993471357, + name: r'id', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'id', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _pendingOperationCollectionGetId, + getLinks: _pendingOperationCollectionGetLinks, + attach: _pendingOperationCollectionAttach, + version: '3.1.0+1', +); + +int _pendingOperationCollectionEstimateSize( + PendingOperationCollection object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + bytesCount += 3 + object.dataJson.length * 3; + bytesCount += 3 + object.endpoint.length * 3; + bytesCount += 3 + object.id.length * 3; + bytesCount += 3 + object.operationType.length * 3; + return bytesCount; +} + +void _pendingOperationCollectionSerialize( + PendingOperationCollection object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeLong(offsets[0], object.createdAtEpoch); + writer.writeString(offsets[1], object.dataJson); + writer.writeString(offsets[2], object.endpoint); + writer.writeString(offsets[3], object.id); + writer.writeString(offsets[4], object.operationType); + writer.writeLong(offsets[5], object.retryCount); + writer.writeLong(offsets[6], object.version); +} + +PendingOperationCollection _pendingOperationCollectionDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = PendingOperationCollection(); + object.createdAtEpoch = reader.readLong(offsets[0]); + object.dataJson = reader.readString(offsets[1]); + object.endpoint = reader.readString(offsets[2]); + object.id = reader.readString(offsets[3]); + object.isarId = id; + object.operationType = reader.readString(offsets[4]); + object.retryCount = reader.readLong(offsets[5]); + object.version = reader.readLong(offsets[6]); + return object; +} + +P _pendingOperationCollectionDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readLong(offset)) as P; + case 1: + return (reader.readString(offset)) as P; + case 2: + return (reader.readString(offset)) as P; + case 3: + return (reader.readString(offset)) as P; + case 4: + return (reader.readString(offset)) as P; + case 5: + return (reader.readLong(offset)) as P; + case 6: + return (reader.readLong(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _pendingOperationCollectionGetId(PendingOperationCollection object) { + return object.isarId; +} + +List> _pendingOperationCollectionGetLinks( + PendingOperationCollection object) { + return []; +} + +void _pendingOperationCollectionAttach( + IsarCollection col, Id id, PendingOperationCollection object) { + object.isarId = id; +} + +extension PendingOperationCollectionQueryWhereSort on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QWhere> { + QueryBuilder anyIsarId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension PendingOperationCollectionQueryWhere on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QWhereClause> { + QueryBuilder isarIdEqualTo(Id isarId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: isarId, + upper: isarId, + )); + }); + } + + QueryBuilder isarIdNotEqualTo(Id isarId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: false), + ); + } + }); + } + + QueryBuilder isarIdGreaterThan(Id isarId, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: isarId, includeLower: include), + ); + }); + } + + QueryBuilder isarIdLessThan(Id isarId, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: isarId, includeUpper: include), + ); + }); + } + + QueryBuilder isarIdBetween( + Id lowerIsarId, + Id upperIsarId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerIsarId, + includeLower: includeLower, + upper: upperIsarId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder idEqualTo(String id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'id', + value: [id], + )); + }); + } + + QueryBuilder idNotEqualTo(String id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [], + upper: [id], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [id], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [id], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'id', + lower: [], + upper: [id], + includeUpper: false, + )); + } + }); + } +} + +extension PendingOperationCollectionQueryFilter on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QFilterCondition> { + QueryBuilder createdAtEpochEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'createdAtEpoch', + value: value, + )); + }); + } + + QueryBuilder createdAtEpochBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'createdAtEpoch', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder dataJsonEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'dataJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder dataJsonGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'dataJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder dataJsonLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'dataJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder dataJsonBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'dataJson', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder dataJsonStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'dataJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder dataJsonEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'dataJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + dataJsonContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'dataJson', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + dataJsonMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'dataJson', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder dataJsonIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'dataJson', + value: '', + )); + }); + } + + QueryBuilder dataJsonIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'dataJson', + value: '', + )); + }); + } + + QueryBuilder endpointEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'endpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder endpointGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'endpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder endpointLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'endpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder endpointBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'endpoint', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder endpointStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'endpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder endpointEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'endpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + endpointContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'endpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + endpointMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'endpoint', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder endpointIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'endpoint', + value: '', + )); + }); + } + + QueryBuilder endpointIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'endpoint', + value: '', + )); + }); + } + + QueryBuilder idEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + idContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'id', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + idMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'id', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder idIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: '', + )); + }); + } + + QueryBuilder idIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'id', + value: '', + )); + }); + } + + QueryBuilder isarIdEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'isarId', + value: value, + )); + }); + } + + QueryBuilder isarIdBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'isarId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder operationTypeEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'operationType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder operationTypeGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'operationType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder operationTypeLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'operationType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder operationTypeBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'operationType', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder operationTypeStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'operationType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder operationTypeEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'operationType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + operationTypeContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'operationType', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + operationTypeMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'operationType', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder operationTypeIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'operationType', + value: '', + )); + }); + } + + QueryBuilder operationTypeIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'operationType', + value: '', + )); + }); + } + + QueryBuilder retryCountEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'retryCount', + value: value, + )); + }); + } + + QueryBuilder retryCountGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'retryCount', + value: value, + )); + }); + } + + QueryBuilder retryCountLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'retryCount', + value: value, + )); + }); + } + + QueryBuilder retryCountBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'retryCount', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder versionEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'version', + value: value, + )); + }); + } + + QueryBuilder versionBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'version', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } +} + +extension PendingOperationCollectionQueryObject on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QFilterCondition> {} + +extension PendingOperationCollectionQueryLinks on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QFilterCondition> {} + +extension PendingOperationCollectionQuerySortBy on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QSortBy> { + QueryBuilder sortByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.asc); + }); + } + + QueryBuilder sortByCreatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.desc); + }); + } + + QueryBuilder sortByDataJson() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dataJson', Sort.asc); + }); + } + + QueryBuilder sortByDataJsonDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dataJson', Sort.desc); + }); + } + + QueryBuilder sortByEndpoint() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'endpoint', Sort.asc); + }); + } + + QueryBuilder sortByEndpointDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'endpoint', Sort.desc); + }); + } + + QueryBuilder sortById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder sortByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder sortByOperationType() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'operationType', Sort.asc); + }); + } + + QueryBuilder sortByOperationTypeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'operationType', Sort.desc); + }); + } + + QueryBuilder sortByRetryCount() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'retryCount', Sort.asc); + }); + } + + QueryBuilder sortByRetryCountDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'retryCount', Sort.desc); + }); + } + + QueryBuilder sortByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.asc); + }); + } + + QueryBuilder sortByVersionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.desc); + }); + } +} + +extension PendingOperationCollectionQuerySortThenBy on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QSortThenBy> { + QueryBuilder thenByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.asc); + }); + } + + QueryBuilder thenByCreatedAtEpochDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'createdAtEpoch', Sort.desc); + }); + } + + QueryBuilder thenByDataJson() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dataJson', Sort.asc); + }); + } + + QueryBuilder thenByDataJsonDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'dataJson', Sort.desc); + }); + } + + QueryBuilder thenByEndpoint() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'endpoint', Sort.asc); + }); + } + + QueryBuilder thenByEndpointDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'endpoint', Sort.desc); + }); + } + + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder thenByIsarId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isarId', Sort.asc); + }); + } + + QueryBuilder thenByIsarIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isarId', Sort.desc); + }); + } + + QueryBuilder thenByOperationType() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'operationType', Sort.asc); + }); + } + + QueryBuilder thenByOperationTypeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'operationType', Sort.desc); + }); + } + + QueryBuilder thenByRetryCount() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'retryCount', Sort.asc); + }); + } + + QueryBuilder thenByRetryCountDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'retryCount', Sort.desc); + }); + } + + QueryBuilder thenByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.asc); + }); + } + + QueryBuilder thenByVersionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'version', Sort.desc); + }); + } +} + +extension PendingOperationCollectionQueryWhereDistinct on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QDistinct> { + QueryBuilder distinctByCreatedAtEpoch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'createdAtEpoch'); + }); + } + + QueryBuilder distinctByDataJson({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'dataJson', caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByEndpoint({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'endpoint', caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctById({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'id', caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByOperationType({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'operationType', + caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByRetryCount() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'retryCount'); + }); + } + + QueryBuilder distinctByVersion() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'version'); + }); + } +} + +extension PendingOperationCollectionQueryProperty on QueryBuilder< + PendingOperationCollection, PendingOperationCollection, QQueryProperty> { + QueryBuilder + isarIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isarId'); + }); + } + + QueryBuilder + createdAtEpochProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'createdAtEpoch'); + }); + } + + QueryBuilder + dataJsonProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'dataJson'); + }); + } + + QueryBuilder + endpointProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'endpoint'); + }); + } + + QueryBuilder + idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + operationTypeProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'operationType'); + }); + } + + QueryBuilder + retryCountProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'retryCount'); + }); + } + + QueryBuilder + versionProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'version'); + }); + } +} diff --git a/app/lib/data/local/isar_database.dart b/app/lib/data/local/isar_database.dart index b857add..9facc9f 100644 --- a/app/lib/data/local/isar_database.dart +++ b/app/lib/data/local/isar_database.dart @@ -1,41 +1,36 @@ // Isar 数据库初始化 — 本地持久化存储 // -// Isar 3.x 要求 open() 时传入 List 位置参数。 -// 由于我们使用手写不可变类而非 isar_generator 代码生成, -// 需要在调用 [init] 时传入 schema 列表。 -// 当前阶段使用 [ensureInitialized] 占位,待后续添加 Isar Collection 后正式注册。 +// Isar 3.x 要求 open() 时传入 List。 +// 通过 build_runner 生成 Schema,在 main.dart 启动时调用 init()。 import 'package:isar/isar.dart'; import 'package:path_provider/path_provider.dart'; +import 'collections/journal_entry_collection.dart'; +import 'collections/journal_element_collection.dart'; +import 'collections/pending_operation_collection.dart'; + /// Isar 数据库单例管理 -/// -/// 使用方式(Phase 1 — 无 schema 时): -/// ```dart -/// // 直接使用,不初始化 Isar(内存仓库模式) -/// ``` -/// -/// 使用方式(Phase 2 — 有 schema 后): -/// ```dart -/// final isar = await IsarDatabase.init(schemas: [JournalEntrySchema]); -/// ``` class IsarDatabase { IsarDatabase._(); static Isar? _instance; static bool _initialized = false; + /// 所有 Collection Schema(由 build_runner 生成) + static final List> schemas = [ + JournalEntryCollectionSchema, + JournalElementCollectionSchema, + PendingOperationCollectionSchema, + ]; + /// 是否已初始化 static bool get isInitialized => _initialized; - /// 初始化数据库(需在 app 启动时调用,传入所有 CollectionSchema) + /// 初始化数据库 /// - /// - [schemas]: Isar Collection Schema 列表(由 isar_generator 生成) - /// - 在应用文档目录下创建 isar 数据库文件 - /// - 开发模式开启 inspector(flutter pub global run isar_inspector) - static Future init({ - required List> schemas, - }) async { + /// 在 main() 中调用,open 之前需确保 WidgetsFlutterBinding 已初始化。 + static Future init() async { if (_instance != null && _instance!.isOpen) return _instance!; final dir = await getApplicationDocumentsDirectory(); @@ -50,20 +45,14 @@ class IsarDatabase { } /// 获取 Isar 实例(必须先调用 [init]) - /// - /// 如果未初始化会抛出 [StateError]。 static Isar get instance { if (_instance == null || !_instance!.isOpen) { - throw StateError( - 'IsarDatabase 未初始化,请先调用 IsarDatabase.init(schemas: [...])', - ); + throw StateError('IsarDatabase 未初始化,请先调用 IsarDatabase.init()'); } return _instance!; } /// 关闭数据库连接 - /// - /// 通常只在应用退出时调用。 static Future close() async { if (_instance != null && _instance!.isOpen) { await _instance!.close(); @@ -76,7 +65,7 @@ class IsarDatabase { static Future clearAll() async { if (_instance == null || !_instance!.isOpen) return; await _instance!.writeTxn(() async { - // TODO: 清空所有 collection + await _instance!.clear(); }); } } diff --git a/app/lib/data/repositories/isar_journal_repository.dart b/app/lib/data/repositories/isar_journal_repository.dart new file mode 100644 index 0000000..43d4887 --- /dev/null +++ b/app/lib/data/repositories/isar_journal_repository.dart @@ -0,0 +1,333 @@ +// Isar 本地日记仓库 — 本地优先数据存储 +// +// 实现 JournalRepository 抽象接口,所有数据存储在 Isar 本地数据库。 +// 核心逻辑参考 InMemoryJournalRepository,替换内存 Map 为 Isar 查询。 +// +// 转换层: +// - JournalEntry ↔ JournalEntryCollection(通过 toCollection/fromCollection) +// - JournalElement ↔ JournalElementCollection(通过 toCollection/fromCollection) + +import 'dart:convert'; + +import 'package:isar/isar.dart'; + +import '../local/isar_database.dart'; +import '../local/collections/journal_entry_collection.dart'; +import '../local/collections/journal_element_collection.dart'; +import '../models/journal_entry.dart'; +import '../models/journal_element.dart'; +import 'journal_repository.dart'; + +/// Isar 本地日记仓库 — JournalRepository 的 Isar 实现 +class IsarJournalRepository implements JournalRepository { + Isar get _isar => IsarDatabase.instance; + + // ============================================================ + // 日记 CRUD + // ============================================================ + + @override + Future> getJournals({ + DateTime? dateFrom, + DateTime? dateTo, + int? page, + int? pageSize, + }) async { + var query = _isar.journalEntryCollections + .where() + .filter() + .isDeletedEqualTo(false); + + // 日期范围过滤 + if (dateFrom != null) { + query = query.and().dateEpochGreaterThan(dateFrom.millisecondsSinceEpoch); + } + if (dateTo != null) { + query = query.and().dateEpochLessThan(dateTo.millisecondsSinceEpoch); + } + + // 按日期降序排列 + var results = await query + .sortByDateEpochDesc() + .findAll(); + + // 分页 + if (page != null && pageSize != null) { + final start = (page - 1) * pageSize; + if (start >= results.length) return []; + final end = (start + pageSize).clamp(0, results.length); + results = results.sublist(start, end); + } + + return results.map(_fromCollection).toList(); + } + + @override + Future getJournal(String id) async { + final col = await _isar.journalEntryCollections + .where() + .filter() + .idEqualTo(id) + .and() + .isDeletedEqualTo(false) + .findFirst(); + if (col == null) return null; + return _fromCollection(col); + } + + @override + Future createJournal(JournalEntry entry) async { + final col = _toEntryCollection(entry); + await _isar.writeTxn(() async { + await _isar.journalEntryCollections.put(col); + }); + return entry; + } + + @override + Future updateJournal(JournalEntry entry) async { + final existing = await _isar.journalEntryCollections + .where() + .filter() + .idEqualTo(entry.id) + .and() + .isDeletedEqualTo(false) + .findFirst(); + + if (existing == null) { + throw StateError('日记不存在: ${entry.id}'); + } + + // 乐观锁冲突检测 + if (existing.version != entry.version) { + throw StateError( + '版本冲突: 本地版本 ${entry.version}, 存储版本 ${existing.version}', + ); + } + + final updated = entry.copyWith( + version: entry.version + 1, + updatedAt: DateTime.now(), + ); + + final col = _toEntryCollection(updated); + col.isarId = existing.isarId; // 保留 Isar 主键 + + await _isar.writeTxn(() async { + await _isar.journalEntryCollections.put(col); + }); + + return updated; + } + + @override + Future deleteJournal(String id) async { + final existing = await _isar.journalEntryCollections + .where() + .filter() + .idEqualTo(id) + .findFirst(); + if (existing == null) return; + + // 软删除日记 + existing.isDeleted = true; + existing.updatedAtEpoch = DateTime.now().millisecondsSinceEpoch; + + // 软删除关联元素 + final elements = await _isar.journalElementCollections + .where() + .filter() + .journalIdEqualTo(id) + .and() + .isDeletedEqualTo(false) + .findAll(); + + await _isar.writeTxn(() async { + await _isar.journalEntryCollections.put(existing); + for (final el in elements) { + el.isDeleted = true; + el.updatedAtEpoch = DateTime.now().millisecondsSinceEpoch; + await _isar.journalElementCollections.put(el); + } + }); + } + + // ============================================================ + // 元素 CRUD + // ============================================================ + + @override + Future> getElements(String journalId) async { + final results = await _isar.journalElementCollections + .where() + .filter() + .journalIdEqualTo(journalId) + .and() + .isDeletedEqualTo(false) + .sortByZIndex() + .findAll(); + return results.map(_fromElementCollection).toList(); + } + + @override + Future addElement(JournalElement element) async { + final col = _toElementCollection(element); + await _isar.writeTxn(() async { + await _isar.journalElementCollections.put(col); + }); + return element; + } + + @override + Future updateElement(JournalElement element) async { + final existing = await _isar.journalElementCollections + .where() + .filter() + .idEqualTo(element.id) + .and() + .isDeletedEqualTo(false) + .findFirst(); + + if (existing == null) { + throw StateError('元素不存在: ${element.id}'); + } + + // 乐观锁冲突检测 + if (existing.version != element.version) { + throw StateError( + '版本冲突: 本地版本 ${element.version}, 存储版本 ${existing.version}', + ); + } + + final updated = element.copyWith( + version: element.version + 1, + updatedAt: DateTime.now(), + ); + + final col = _toElementCollection(updated); + col.isarId = existing.isarId; + + await _isar.writeTxn(() async { + await _isar.journalElementCollections.put(col); + }); + + return updated; + } + + @override + Future removeElement(String elementId) async { + final existing = await _isar.journalElementCollections + .where() + .filter() + .idEqualTo(elementId) + .findFirst(); + if (existing == null) return; + + // 软删除 + existing.isDeleted = true; + existing.updatedAtEpoch = DateTime.now().millisecondsSinceEpoch; + + await _isar.writeTxn(() async { + await _isar.journalElementCollections.put(existing); + }); + } + + // ============================================================ + // 转换函数:JournalEntry ↔ JournalEntryCollection + // ============================================================ + + /// JournalEntry → JournalEntryCollection + JournalEntryCollection _toEntryCollection(JournalEntry entry) { + return JournalEntryCollection() + ..id = entry.id + ..authorId = entry.authorId + ..classId = entry.classId + ..title = entry.title + ..dateEpoch = entry.date.millisecondsSinceEpoch + ..mood = entry.mood.value + ..weather = entry.weather.value + ..tagsJson = jsonEncode(entry.tags) + ..isPrivate = entry.isPrivate + ..sharedToClass = entry.sharedToClass + ..assignedTopicId = entry.assignedTopicId + ..version = entry.version + ..createdAtEpoch = entry.createdAt.millisecondsSinceEpoch + ..updatedAtEpoch = entry.updatedAt.millisecondsSinceEpoch + ..isDeleted = false; + } + + /// JournalEntryCollection → JournalEntry + JournalEntry _fromCollection(JournalEntryCollection col) { + return JournalEntry( + id: col.id, + authorId: col.authorId, + classId: col.classId, + title: col.title, + date: DateTime.fromMillisecondsSinceEpoch(col.dateEpoch), + mood: Mood.values.firstWhere( + (m) => m.value == col.mood, + orElse: () => Mood.calm, + ), + weather: Weather.values.firstWhere( + (w) => w.value == col.weather, + orElse: () => Weather.sunny, + ), + tags: List.from( + jsonDecode(col.tagsJson) as List? ?? [], + ), + isPrivate: col.isPrivate, + sharedToClass: col.sharedToClass, + assignedTopicId: col.assignedTopicId, + version: col.version, + createdAt: DateTime.fromMillisecondsSinceEpoch(col.createdAtEpoch), + updatedAt: DateTime.fromMillisecondsSinceEpoch(col.updatedAtEpoch), + ); + } + + // ============================================================ + // 转换函数:JournalElement ↔ JournalElementCollection + // ============================================================ + + /// JournalElement → JournalElementCollection + JournalElementCollection _toElementCollection(JournalElement element) { + return JournalElementCollection() + ..id = element.id + ..journalId = element.journalId + ..elementType = element.elementType.value + ..positionX = element.positionX + ..positionY = element.positionY + ..width = element.width + ..height = element.height + ..rotation = element.rotation + ..zIndex = element.zIndex + ..contentJson = jsonEncode(element.content) + ..version = element.version + ..createdAtEpoch = element.createdAt.millisecondsSinceEpoch + ..updatedAtEpoch = element.updatedAt.millisecondsSinceEpoch + ..isDeleted = false; + } + + /// JournalElementCollection → JournalElement + JournalElement _fromElementCollection(JournalElementCollection col) { + return JournalElement( + id: col.id, + journalId: col.journalId, + elementType: ElementType.values.firstWhere( + (e) => e.value == col.elementType, + orElse: () => ElementType.text, + ), + positionX: col.positionX, + positionY: col.positionY, + width: col.width, + height: col.height, + rotation: col.rotation, + zIndex: col.zIndex, + content: Map.from( + jsonDecode(col.contentJson) as Map? ?? {}, + ), + version: col.version, + createdAt: DateTime.fromMillisecondsSinceEpoch(col.createdAtEpoch), + updatedAt: DateTime.fromMillisecondsSinceEpoch(col.updatedAtEpoch), + ); + } +} diff --git a/app/lib/data/services/sync_engine.dart b/app/lib/data/services/sync_engine.dart index 7cad69c..2e9e4bc 100644 --- a/app/lib/data/services/sync_engine.dart +++ b/app/lib/data/services/sync_engine.dart @@ -1,20 +1,25 @@ -// 同步引擎 — WiFi 增量同步 + 操作队列 +// 同步引擎 — WiFi 增量同步 + 操作队列 + Isar 持久化 // // 设计思路: // - 所有本地修改先入队 [PendingOperation] // - 网络恢复时自动批量同步 // - 版本号冲突检测,Phase 1 使用"本地优先"策略 // - 最大重试次数限制,超过后标记为冲突供用户手动解决 +// - 队列持久化到 Isar,应用退出后不丢失 // // Phase 1 策略:本地优先 // - 离线时正常使用,操作入队等待 // - 联网后自动推送待同步操作 // - 版本冲突时本地版本覆盖远端(简单策略) +import 'dart:convert'; import 'dart:collection'; import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:isar/isar.dart'; +import '../local/isar_database.dart'; +import '../local/collections/pending_operation_collection.dart'; import '../remote/api_client.dart'; /// 同步操作类型 @@ -87,6 +92,9 @@ class PendingOperation { /// ```dart /// final engine = SyncEngine(apiClient: apiClient); /// +/// // 启动时恢复持久化队列 +/// await engine.restorePendingQueue(); +/// /// // 本地修改后入队 /// engine.enqueue(PendingOperation( /// id: 'op-1', @@ -99,6 +107,9 @@ class PendingOperation { /// /// // 网络恢复时触发同步 /// await engine.trySync(); +/// +/// // 应用退出时持久化 +/// await engine.persistPendingQueue(); /// ``` class SyncEngine { final ApiClient _apiClient; @@ -107,7 +118,7 @@ class SyncEngine { SyncStatus _status = SyncStatus.idle; String? _lastError; - SyncEngine({required this._apiClient}); + SyncEngine({required ApiClient apiClient}) : _apiClient = apiClient; /// 当前同步状态 SyncStatus get status => _status; @@ -200,9 +211,10 @@ class SyncEngine { } } - // 全部同步完成 + // 全部同步完成,更新持久化 _status = SyncStatus.idle; _lastError = null; + await persistPendingQueue(); } /// 执行单个同步操作 @@ -227,6 +239,100 @@ class SyncEngine { /// 获取当前队列中所有操作的快照(用于持久化到本地存储) /// /// 应用退出时调用此方法,将待同步操作保存到 Isar, - /// 下次启动时通过 [enqueueAll] 恢复。 + /// 下次启动时通过 [restorePendingQueue] 恢复。 List get snapshot => _pendingQueue.toList(); + + // ============================================================ + // Isar 持久化 + // ============================================================ + + /// 将当前内存队列持久化到 Isar + /// + /// 替换策略:先清空旧的持久化数据,再写入当前队列。 + /// 在 app 退出、isolate 暂停、或同步完成后调用。 + Future persistPendingQueue() async { + final isar = IsarDatabase.instance; + final ops = snapshot; + + await isar.writeTxn(() async { + // 清空旧数据 + await isar.pendingOperationCollections.clear(); + + // 写入当前队列 + for (final op in ops) { + final col = _operationToCollection(op); + await isar.pendingOperationCollections.put(col); + } + }); + } + + /// 从 Isar 恢复持久化队列到内存 + /// + /// 在 app 启动时调用,恢复上次退出时未同步的操作。 + Future restorePendingQueue() async { + final isar = IsarDatabase.instance; + final persisted = await isar.pendingOperationCollections + .where() + .anyIsarId() + .findAll(); + + for (final col in persisted) { + final op = _collectionToOperation(col); + _pendingQueue.add(op); + } + + if (_pendingQueue.isNotEmpty && _status == SyncStatus.idle) { + _status = SyncStatus.paused; + } + } + + // ============================================================ + // 转换函数 + // ============================================================ + + /// PendingOperation → PendingOperationCollection + PendingOperationCollection _operationToCollection(PendingOperation op) { + return PendingOperationCollection() + ..id = op.id + ..operationType = op.type.httpMethod + ..endpoint = op.endpoint + ..dataJson = _encodeJson(op.data) + ..version = op.version + ..createdAtEpoch = op.createdAt.millisecondsSinceEpoch + ..retryCount = op.retryCount; + } + + /// PendingOperationCollection → PendingOperation + PendingOperation _collectionToOperation(PendingOperationCollection col) { + return PendingOperation( + id: col.id, + type: SyncOperationType.values.firstWhere( + (t) => t.httpMethod == col.operationType, + orElse: () => SyncOperationType.create, + ), + endpoint: col.endpoint, + data: _decodeJson(col.dataJson), + version: col.version, + createdAt: DateTime.fromMillisecondsSinceEpoch(col.createdAtEpoch), + retryCount: col.retryCount, + ); + } + + /// 安全编码 JSON + String _encodeJson(Map data) { + try { + return jsonEncode(data); + } catch (_) { + return '{}'; + } + } + + /// 安全解码 JSON + Map _decodeJson(String json) { + try { + return jsonDecode(json) as Map; + } catch (_) { + return {}; + } + } } diff --git a/app/lib/features/editor/views/editor_page.dart b/app/lib/features/editor/views/editor_page.dart index 79c0e50..7316140 100644 --- a/app/lib/features/editor/views/editor_page.dart +++ b/app/lib/features/editor/views/editor_page.dart @@ -15,8 +15,11 @@ import 'package:go_router/go_router.dart'; import '../../../core/constants/design_tokens.dart'; import '../../../data/models/journal_element.dart'; +import '../../../data/models/journal_entry.dart'; +import '../../../data/repositories/journal_repository.dart'; import '../bloc/editor_bloc.dart'; import '../widgets/handwriting_canvas.dart'; +import '../widgets/stroke_model.dart'; import '../widgets/draggable_element.dart'; import '../widgets/editor_toolbar.dart'; @@ -28,22 +31,123 @@ class EditorPage extends StatelessWidget { @override Widget build(BuildContext context) { + // 从 Provider 树获取 JournalRepository(IsarJournalRepository) + final repo = context.read(); + + // 可变闭包变量:跟踪已保存的日记 ID + // 新建日记首次保存后赋值,后续自动更新使用此 ID + String? savedJournalId = journalId; + return BlocProvider( create: (_) => EditorBloc( - onSave: (state) { - // TODO: 通过 JournalRepository 保存到 Isar - debugPrint('自动保存: ${state.strokes.length} 笔画, ${state.elements.length} 元素'); + onSave: (state) async { + try { + await _persistState(repo, state, (id) => savedJournalId = id, savedJournalId); + } catch (e) { + debugPrint('自动保存失败: $e'); + } }, ), - child: _EditorView(journalId: journalId), + child: _EditorView( + journalId: journalId, + onSaveComplete: () => context.pop(), + ), ); } + + /// 持久化编辑器状态到 Isar + /// + /// 策略: + /// - 首次保存(savedJournalId == null)→ createJournal + addElement + /// - 后续保存 → updateJournal + upsert 元素 + /// - 笔画序列化为 handwriting_ref 元素 + Future _persistState( + JournalRepository repo, + EditorState state, + void Function(String) setId, + String? savedJournalId, + ) async { + final now = DateTime.now(); + + if (savedJournalId == null) { + // --- 新建日记 --- + final entry = JournalEntry.create( + authorId: 'local', // TODO: 从 AuthBloc 获取真实用户 ID + title: '${now.month}月${now.day}日的日记', + date: now, + ); + await repo.createJournal(entry); + setId(entry.id); + + // 保存笔画 + if (state.strokes.isNotEmpty) { + await _saveStrokesAsElement(repo, entry.id, state.strokes); + } + + // 保存其他元素 + for (final element in state.elements) { + await repo.addElement(element.copyWith(journalId: entry.id)); + } + } else { + // --- 更新已有日记 --- + final existing = await repo.getJournal(savedJournalId); + if (existing != null) { + await repo.updateJournal(existing); + } + + // 更新笔画 + if (state.strokes.isNotEmpty) { + await _saveStrokesAsElement(repo, savedJournalId, state.strokes); + } + + // upsert 元素(先尝试更新,失败则新建) + for (final element in state.elements) { + try { + await repo.updateElement(element); + } catch (_) { + await repo.addElement(element); + } + } + } + } + + /// 将笔画列表序列化为 handwriting_ref 元素并保存 + /// + /// 每次保存都替换整个笔画集(Phase 1 简化策略)。 + Future _saveStrokesAsElement( + JournalRepository repo, + String journalId, + List strokes, + ) async { + final now = DateTime.now(); + final strokesJson = strokes.map((s) => s.toJson()).toList(); + + final element = JournalElement( + id: '${journalId}_strokes', // 固定 ID,保证每次覆盖 + journalId: journalId, + elementType: ElementType.handwritingRef, + content: { + 'strokes': strokesJson, + 'strokeCount': strokes.length, + }, + version: 1, + createdAt: now, + updatedAt: now, + ); + + try { + await repo.updateElement(element); + } catch (_) { + await repo.addElement(element); + } + } } class _EditorView extends StatelessWidget { final String? journalId; + final VoidCallback onSaveComplete; - const _EditorView({this.journalId}); + const _EditorView({this.journalId, required this.onSaveComplete}); @override Widget build(BuildContext context) { @@ -117,10 +221,7 @@ class _EditorView extends StatelessWidget { // 完成按钮 FilledButton.tonal( - onPressed: () { - // TODO: 保存并返回 - context.pop(); - }, + onPressed: onSaveComplete, style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: DesignTokens.spacing16), minimumSize: const Size(0, 36), diff --git a/app/lib/main.dart b/app/lib/main.dart index 56d91fe..526facf 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -2,12 +2,15 @@ // // 初始化流程: // 1. 确保 Flutter 绑定就绪 -// 2. 运行 App(认证状态恢复在 AuthBloc.AppStarted 中处理) +// 2. 初始化 Isar 本地数据库 +// 3. 运行 App(认证状态恢复在 AuthBloc.AppStarted 中处理) import 'package:flutter/material.dart'; +import 'data/local/isar_database.dart'; import 'app.dart'; -void main() { +void main() async { WidgetsFlutterBinding.ensureInitialized(); + await IsarDatabase.init(); runApp(const NuanjiApp()); }