mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
feat(mobile): sqlite (#16861)
* refactor: user entity * chore: rebase fixes * refactor: remove int user Id * refactor: migrate store userId from int to string * refactor: rename uid to id * feat: drift * pr feedback * refactor: move common overrides to mixin --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
5cb5fcbf62
commit
5a456ef277
23 changed files with 321 additions and 30 deletions
3
.gitattributes
vendored
3
.gitattributes
vendored
|
|
@ -6,6 +6,9 @@ mobile/openapi/**/*.dart linguist-generated=true
|
||||||
mobile/lib/**/*.g.dart -diff -merge
|
mobile/lib/**/*.g.dart -diff -merge
|
||||||
mobile/lib/**/*.g.dart linguist-generated=true
|
mobile/lib/**/*.g.dart linguist-generated=true
|
||||||
|
|
||||||
|
mobile/lib/**/*.drift.dart -diff -merge
|
||||||
|
mobile/lib/**/*.drift.dart linguist-generated=true
|
||||||
|
|
||||||
open-api/typescript-sdk/fetch-client.ts -diff -merge
|
open-api/typescript-sdk/fetch-client.ts -diff -merge
|
||||||
open-api/typescript-sdk/fetch-client.ts linguist-generated=true
|
open-api/typescript-sdk/fetch-client.ts linguist-generated=true
|
||||||
|
|
||||||
|
|
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -39,6 +39,7 @@
|
||||||
],
|
],
|
||||||
"explorer.fileNesting.enabled": true,
|
"explorer.fileNesting.enabled": true,
|
||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
|
||||||
|
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,6 +36,8 @@ analyzer:
|
||||||
exclude:
|
exclude:
|
||||||
- openapi/**
|
- openapi/**
|
||||||
- lib/generated_plugin_registrant.dart
|
- lib/generated_plugin_registrant.dart
|
||||||
|
- lib/**/*.g.dart
|
||||||
|
- lib/**/*.drift.dart
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- custom_lint
|
- custom_lint
|
||||||
|
|
|
||||||
24
mobile/build.yaml
Normal file
24
mobile/build.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
targets:
|
||||||
|
$default:
|
||||||
|
builders:
|
||||||
|
#drift @DriftDatabase()
|
||||||
|
drift_dev:
|
||||||
|
# Disable default builder to use modular builder instead
|
||||||
|
enabled: false
|
||||||
|
drift_dev:analyzer:
|
||||||
|
enabled: true
|
||||||
|
options: &drift_options
|
||||||
|
store_date_time_values_as_text: true
|
||||||
|
named_parameters: true
|
||||||
|
write_from_json_string_constructor: false
|
||||||
|
data_class_to_companions: false
|
||||||
|
# Required for make-migrations
|
||||||
|
databases:
|
||||||
|
main: lib/infrastructure/repositories/db.repository.dart
|
||||||
|
generate_for: &drift_generate_for
|
||||||
|
- lib/infrastructure/entities/*.dart
|
||||||
|
- lib/infrastructure/repositories/db.repository.dart
|
||||||
|
drift_dev:modular:
|
||||||
|
enabled: true
|
||||||
|
options: *drift_options
|
||||||
|
generate_for: *drift_generate_for
|
||||||
BIN
mobile/drift_schemas/main/drift_schema_v1.json
Normal file
BIN
mobile/drift_schemas/main/drift_schema_v1.json
Normal file
Binary file not shown.
|
|
@ -1,32 +1,4 @@
|
||||||
import 'dart:ui';
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
|
|
||||||
enum AvatarColor {
|
|
||||||
// do not change this order or reuse indices for other purposes, adding is OK
|
|
||||||
primary,
|
|
||||||
pink,
|
|
||||||
red,
|
|
||||||
yellow,
|
|
||||||
blue,
|
|
||||||
green,
|
|
||||||
purple,
|
|
||||||
orange,
|
|
||||||
gray,
|
|
||||||
amber;
|
|
||||||
|
|
||||||
Color toColor({bool isDarkTheme = false}) => switch (this) {
|
|
||||||
AvatarColor.primary =>
|
|
||||||
isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
|
|
||||||
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
|
|
||||||
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
|
|
||||||
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
|
|
||||||
AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246),
|
|
||||||
AvatarColor.green => const Color.fromARGB(255, 22, 163, 74),
|
|
||||||
AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234),
|
|
||||||
AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12),
|
|
||||||
AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99),
|
|
||||||
AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Rename to User once Isar is removed
|
// TODO: Rename to User once Isar is removed
|
||||||
class UserDto {
|
class UserDto {
|
||||||
|
|
|
||||||
105
mobile/lib/domain/models/user_metadata.model.dart
Normal file
105
mobile/lib/domain/models/user_metadata.model.dart
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
enum AvatarColor {
|
||||||
|
// do not change this order or reuse indices for other purposes, adding is OK
|
||||||
|
primary("primary"),
|
||||||
|
pink("pink"),
|
||||||
|
red("red"),
|
||||||
|
yellow("yellow"),
|
||||||
|
blue("blue"),
|
||||||
|
green("green"),
|
||||||
|
purple("purple"),
|
||||||
|
orange("orange"),
|
||||||
|
gray("gray"),
|
||||||
|
amber("amber");
|
||||||
|
|
||||||
|
final String value;
|
||||||
|
const AvatarColor(this.value);
|
||||||
|
|
||||||
|
Color toColor({bool isDarkTheme = false}) => switch (this) {
|
||||||
|
AvatarColor.primary =>
|
||||||
|
isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
|
||||||
|
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
|
||||||
|
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
|
||||||
|
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
|
||||||
|
AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246),
|
||||||
|
AvatarColor.green => const Color.fromARGB(255, 22, 163, 74),
|
||||||
|
AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234),
|
||||||
|
AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12),
|
||||||
|
AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99),
|
||||||
|
AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserPreferences {
|
||||||
|
final bool foldersEnabled;
|
||||||
|
final bool memoriesEnabled;
|
||||||
|
final bool peopleEnabled;
|
||||||
|
final bool ratingsEnabled;
|
||||||
|
final bool sharedLinksEnabled;
|
||||||
|
final bool tagsEnabled;
|
||||||
|
final AvatarColor userAvatarColor;
|
||||||
|
final bool showSupportBadge;
|
||||||
|
|
||||||
|
const UserPreferences({
|
||||||
|
this.foldersEnabled = false,
|
||||||
|
this.memoriesEnabled = true,
|
||||||
|
this.peopleEnabled = true,
|
||||||
|
this.ratingsEnabled = false,
|
||||||
|
this.sharedLinksEnabled = true,
|
||||||
|
this.tagsEnabled = false,
|
||||||
|
this.userAvatarColor = AvatarColor.primary,
|
||||||
|
this.showSupportBadge = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
UserPreferences copyWith({
|
||||||
|
bool? foldersEnabled,
|
||||||
|
bool? memoriesEnabled,
|
||||||
|
bool? peopleEnabled,
|
||||||
|
bool? ratingsEnabled,
|
||||||
|
bool? sharedLinksEnabled,
|
||||||
|
bool? tagsEnabled,
|
||||||
|
AvatarColor? userAvatarColor,
|
||||||
|
bool? showSupportBadge,
|
||||||
|
}) {
|
||||||
|
return UserPreferences(
|
||||||
|
foldersEnabled: foldersEnabled ?? this.foldersEnabled,
|
||||||
|
memoriesEnabled: memoriesEnabled ?? this.memoriesEnabled,
|
||||||
|
peopleEnabled: peopleEnabled ?? this.peopleEnabled,
|
||||||
|
ratingsEnabled: ratingsEnabled ?? this.ratingsEnabled,
|
||||||
|
sharedLinksEnabled: sharedLinksEnabled ?? this.sharedLinksEnabled,
|
||||||
|
tagsEnabled: tagsEnabled ?? this.tagsEnabled,
|
||||||
|
userAvatarColor: userAvatarColor ?? this.userAvatarColor,
|
||||||
|
showSupportBadge: showSupportBadge ?? this.showSupportBadge,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object?> toMap() {
|
||||||
|
final preferences = <String, Object?>{};
|
||||||
|
preferences["folders-Enabled"] = foldersEnabled;
|
||||||
|
preferences["memories-Enabled"] = memoriesEnabled;
|
||||||
|
preferences["people-Enabled"] = peopleEnabled;
|
||||||
|
preferences["ratings-Enabled"] = ratingsEnabled;
|
||||||
|
preferences["sharedLinks-Enabled"] = sharedLinksEnabled;
|
||||||
|
preferences["tags-Enabled"] = tagsEnabled;
|
||||||
|
preferences["avatar-Color"] = userAvatarColor.value;
|
||||||
|
preferences["purchase-ShowSupportBadge"] = showSupportBadge;
|
||||||
|
return preferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory UserPreferences.fromMap(Map<String, Object?> map) {
|
||||||
|
return UserPreferences(
|
||||||
|
foldersEnabled: map["folders-Enabled"] as bool? ?? false,
|
||||||
|
memoriesEnabled: map["memories-Enabled"] as bool? ?? true,
|
||||||
|
peopleEnabled: map["people-Enabled"] as bool? ?? true,
|
||||||
|
ratingsEnabled: map["ratings-Enabled"] as bool? ?? false,
|
||||||
|
sharedLinksEnabled: map["sharedLinks-Enabled"] as bool? ?? true,
|
||||||
|
tagsEnabled: map["tags-Enabled"] as bool? ?? false,
|
||||||
|
userAvatarColor: AvatarColor.values.firstWhere(
|
||||||
|
(e) => e.value == map["avatar-Color"] as String?,
|
||||||
|
orElse: () => AvatarColor.primary,
|
||||||
|
),
|
||||||
|
showSupportBadge: map["purchase-ShowSupportBadge"] as bool? ?? true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
mobile/lib/infrastructure/entities/partner.entity.dart
Normal file
18
mobile/lib/infrastructure/entities/partner.entity.dart
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
|
class PartnerEntity extends Table with DriftDefaultsMixin {
|
||||||
|
const PartnerEntity();
|
||||||
|
|
||||||
|
BlobColumn get sharedById =>
|
||||||
|
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
BlobColumn get sharedWithId =>
|
||||||
|
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
BoolColumn get inTimeline => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {sharedById, sharedWithId};
|
||||||
|
}
|
||||||
BIN
mobile/lib/infrastructure/entities/partner.entity.drift.dart
generated
Normal file
BIN
mobile/lib/infrastructure/entities/partner.entity.drift.dart
generated
Normal file
Binary file not shown.
|
|
@ -1,4 +1,7 @@
|
||||||
|
import 'package:drift/drift.dart' hide Index;
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
|
|
@ -71,3 +74,20 @@ class User {
|
||||||
quotaSizeInBytes: quotaSizeInBytes,
|
quotaSizeInBytes: quotaSizeInBytes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserEntity extends Table with DriftDefaultsMixin {
|
||||||
|
const UserEntity();
|
||||||
|
|
||||||
|
BlobColumn get id => blob()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
BoolColumn get isAdmin => boolean().withDefault(const Constant(false))();
|
||||||
|
TextColumn get email => text()();
|
||||||
|
TextColumn get profileImagePath => text().nullable()();
|
||||||
|
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
// Quota
|
||||||
|
IntColumn get quotaSizeInBytes => integer().nullable()();
|
||||||
|
IntColumn get quotaUsageInBytes => integer().withDefault(const Constant(0))();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {id};
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
mobile/lib/infrastructure/entities/user.entity.drift.dart
generated
Normal file
BIN
mobile/lib/infrastructure/entities/user.entity.drift.dart
generated
Normal file
Binary file not shown.
21
mobile/lib/infrastructure/entities/user_metadata.entity.dart
Normal file
21
mobile/lib/infrastructure/entities/user_metadata.entity.dart
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
|
class UserMetadataEntity extends Table with DriftDefaultsMixin {
|
||||||
|
const UserMetadataEntity();
|
||||||
|
|
||||||
|
BlobColumn get userId =>
|
||||||
|
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
|
||||||
|
TextColumn get preferences => text().map(userPreferenceConverter)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {userId};
|
||||||
|
}
|
||||||
|
|
||||||
|
final JsonTypeConverter2<UserPreferences, String, Object?>
|
||||||
|
userPreferenceConverter = TypeConverter.json2(
|
||||||
|
fromJson: (json) => UserPreferences.fromMap(json as Map<String, Object?>),
|
||||||
|
toJson: (pref) => pref.toMap(),
|
||||||
|
);
|
||||||
BIN
mobile/lib/infrastructure/entities/user_metadata.entity.drift.dart
generated
Normal file
BIN
mobile/lib/infrastructure/entities/user_metadata.entity.drift.dart
generated
Normal file
Binary file not shown.
|
|
@ -1,8 +1,15 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift_flutter/drift_flutter.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
|
import 'db.repository.drift.dart';
|
||||||
|
|
||||||
// #zoneTxn is the symbol used by Isar to mark a transaction within the current zone
|
// #zoneTxn is the symbol used by Isar to mark a transaction within the current zone
|
||||||
// ref: isar/isar_common.dart
|
// ref: isar/isar_common.dart
|
||||||
const Symbol _kzoneTxn = #zoneTxn;
|
const Symbol _kzoneTxn = #zoneTxn;
|
||||||
|
|
@ -17,3 +24,35 @@ class IsarDatabaseRepository implements IDatabaseRepository {
|
||||||
Future<T> transaction<T>(Future<T> Function() callback) =>
|
Future<T> transaction<T>(Future<T> Function() callback) =>
|
||||||
Zone.current[_kzoneTxn] == null ? _db.writeTxn(callback) : callback();
|
Zone.current[_kzoneTxn] == null ? _db.writeTxn(callback) : callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DriftDatabase(tables: [UserEntity, UserMetadataEntity, PartnerEntity])
|
||||||
|
class Drift extends $Drift implements IDatabaseRepository {
|
||||||
|
Drift([QueryExecutor? executor])
|
||||||
|
: super(
|
||||||
|
executor ??
|
||||||
|
driftDatabase(
|
||||||
|
name: 'immich',
|
||||||
|
native: const DriftNativeOptions(shareAcrossIsolates: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get schemaVersion => 1;
|
||||||
|
|
||||||
|
@override
|
||||||
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
|
beforeOpen: (details) async {
|
||||||
|
await customStatement('PRAGMA journal_mode = WAL');
|
||||||
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DriftDatabaseRepository implements IDatabaseRepository {
|
||||||
|
final Drift _db;
|
||||||
|
const DriftDatabaseRepository(this._db);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<T> transaction<T>(Future<T> Function() callback) =>
|
||||||
|
_db.transaction(callback);
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
mobile/lib/infrastructure/repositories/db.repository.drift.dart
generated
Normal file
BIN
mobile/lib/infrastructure/repositories/db.repository.drift.dart
generated
Normal file
Binary file not shown.
9
mobile/lib/infrastructure/utils/drift_default.mixin.dart
Normal file
9
mobile/lib/infrastructure/utils/drift_default.mixin.dart
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
|
mixin DriftDefaultsMixin on Table {
|
||||||
|
@override
|
||||||
|
bool get isStrict => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get withoutRowId => true;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
|
// TODO: Move to repository once all classes are refactored
|
||||||
abstract final class ExifDtoConverter {
|
abstract final class ExifDtoConverter {
|
||||||
static ExifInfo fromDto(ExifResponseDto dto) {
|
static ExifInfo fromDto(ExifResponseDto dto) {
|
||||||
return ExifInfo(
|
return ExifInfo(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
|
// TODO: Move to repository once all classes are refactored
|
||||||
abstract final class UserConverter {
|
abstract final class UserConverter {
|
||||||
/// Base user dto used where the complete user object is not required
|
/// Base user dto used where the complete user object is not required
|
||||||
static UserDto fromSimpleUserDto(UserResponseDto dto) => UserDto(
|
static UserDto fromSimpleUserDto(UserResponseDto dto) => UserDto(
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
|
|
|
||||||
|
|
@ -14,3 +14,6 @@ create_splash:
|
||||||
|
|
||||||
build_release_android:
|
build_release_android:
|
||||||
flutter build appbundle
|
flutter build appbundle
|
||||||
|
|
||||||
|
migrations:
|
||||||
|
dart run drift_dev make-migrations
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
checked_yaml:
|
checked_yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -382,6 +390,30 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.2"
|
version: "7.0.2"
|
||||||
|
drift:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: drift
|
||||||
|
sha256: "14a61af39d4584faf1d73b5b35e4b758a43008cf4c0fdb0576ec8e7032c0d9a5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.26.0"
|
||||||
|
drift_dev:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: drift_dev
|
||||||
|
sha256: "0d3f8b33b76cf1c6a82ee34d9511c40957549c4674b8f1688609e6d6c7306588"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.26.0"
|
||||||
|
drift_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: drift_flutter
|
||||||
|
sha256: "0cadbf3b8733409a6cf61d18ba2e94e149df81df7de26f48ae0695b48fd71922"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.4"
|
||||||
dynamic_color:
|
dynamic_color:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -1288,6 +1320,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.5.0"
|
||||||
|
recase:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: recase
|
||||||
|
sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.0"
|
||||||
riverpod:
|
riverpod:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -1549,6 +1589,30 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "2.4.0"
|
||||||
|
sqlite3:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqlite3
|
||||||
|
sha256: "310af39c40dd0bb2058538333c9d9840a2725ae0b9f77e4fd09ad6696aa8f66e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.5"
|
||||||
|
sqlite3_flutter_libs:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqlite3_flutter_libs
|
||||||
|
sha256: "7adb4cc96dc08648a5eb1d80a7619070796ca6db03901ff2b6dcb15ee30468f3"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.31"
|
||||||
|
sqlparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqlparser
|
||||||
|
sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.41.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ dependencies:
|
||||||
isar_flutter_libs: # contains Isar Core
|
isar_flutter_libs: # contains Isar Core
|
||||||
version: *isar_version
|
version: *isar_version
|
||||||
hosted: https://pub.isar-community.dev/
|
hosted: https://pub.isar-community.dev/
|
||||||
|
# DB
|
||||||
|
drift: ^2.23.1
|
||||||
|
drift_flutter: ^0.2.4
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
analyzer: ^6.0.0
|
analyzer: ^6.0.0
|
||||||
|
|
@ -99,6 +102,8 @@ dev_dependencies:
|
||||||
immich_mobile_immich_lint:
|
immich_mobile_immich_lint:
|
||||||
path: './immich_lint'
|
path: './immich_lint'
|
||||||
fake_async: ^1.3.1
|
fake_async: ^1.3.1
|
||||||
|
# Drift generator
|
||||||
|
drift_dev: ^2.23.1
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
|
||||||
1
mobile/test/fixtures/user.stub.dart
vendored
1
mobile/test/fixtures/user.stub.dart
vendored
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
|
|
||||||
abstract final class UserStub {
|
abstract final class UserStub {
|
||||||
const UserStub._();
|
const UserStub._();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue