mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
chore: bump dart sdk to 3.8 (#20355)
* chore: bump dart sdk to 3.8 * chore: make build * make pigeon * chore: format files --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
9b3718120b
commit
e52b9d15b5
643 changed files with 6519 additions and 18431 deletions
|
|
@ -1,17 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
enum ImmichColorPreset {
|
enum ImmichColorPreset { indigo, deepPurple, pink, red, orange, yellow, lime, green, cyan, slateGray }
|
||||||
indigo,
|
|
||||||
deepPurple,
|
|
||||||
pink,
|
|
||||||
red,
|
|
||||||
orange,
|
|
||||||
yellow,
|
|
||||||
lime,
|
|
||||||
green,
|
|
||||||
cyan,
|
|
||||||
slateGray,
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImmichColorPreset defaultColorPreset = ImmichColorPreset.indigo;
|
const ImmichColorPreset defaultColorPreset = ImmichColorPreset.indigo;
|
||||||
const String defaultColorPresetName = "indigo";
|
const String defaultColorPresetName = "indigo";
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
enum SortOrder {
|
enum SortOrder { asc, desc }
|
||||||
asc,
|
|
||||||
desc,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TextSearchType {
|
enum TextSearchType { context, filename, description }
|
||||||
context,
|
|
||||||
filename,
|
|
||||||
description,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AssetVisibilityEnum { timeline, hidden, archive, locked }
|
enum AssetVisibilityEnum { timeline, hidden, archive, locked }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,511 +2,49 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
const List<ColorFilter> filters = [
|
const List<ColorFilter> filters = [
|
||||||
//Original
|
//Original
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Vintage
|
//Vintage
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.8, 0.1, 0.1, 0, 20, 0.1, 0.8, 0.1, 0, 20, 0.1, 0.1, 0.8, 0, 20, 0, 0, 0, 1, 0]),
|
||||||
0.8,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0.1,
|
|
||||||
0.8,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0.8,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Mood
|
//Mood
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.2, 0.1, 0.1, 0, 10, 0.1, 1, 0.1, 0, 10, 0.1, 0.1, 1, 0, 10, 0, 0, 0, 1, 0]),
|
||||||
1.2,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0.1,
|
|
||||||
1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Crisp
|
//Crisp
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.2, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Cool
|
//Cool
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.9, 0, 0.2, 0, 0, 0, 1, 0.1, 0, 0, 0.1, 0, 1.2, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.9,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Blush
|
//Blush
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.1, 0.1, 0.1, 0, 10, 0.1, 1, 0.1, 0, 10, 0.1, 0.1, 1, 0, 5, 0, 0, 0, 1, 0]),
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0.1,
|
|
||||||
1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Sunkissed
|
//Sunkissed
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.3, 0, 0.1, 0, 15, 0, 1.1, 0.1, 0, 10, 0, 0, 0.9, 0, 5, 0, 0, 0, 1, 0]),
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
15,
|
|
||||||
0,
|
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.9,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Fresh
|
//Fresh
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.2, 0, 0, 0, 20, 0, 1.2, 0, 0, 20, 0, 0, 1.1, 0, 20, 0, 0, 0, 1, 0]),
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Classic
|
//Classic
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.1, 0, -0.1, 0, 10, -0.1, 1.1, 0.1, 0, 5, 0, -0.1, 1.1, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
-0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
-0.1,
|
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
0,
|
|
||||||
-0.1,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Lomo-ish
|
//Lomo-ish
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.5, 0, 0.1, 0, 0, 0, 1.45, 0, 0, 0, 0.1, 0, 1.3, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.5,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.45,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Nashville
|
//Nashville
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.2, 0.15, -0.15, 0, 15, 0.1, 1.1, 0.1, 0, 10, -0.05, 0.2, 1.25, 0, 5, 0, 0, 0, 1, 0]),
|
||||||
1.2,
|
|
||||||
0.15,
|
|
||||||
-0.15,
|
|
||||||
0,
|
|
||||||
15,
|
|
||||||
0.1,
|
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
-0.05,
|
|
||||||
0.2,
|
|
||||||
1.25,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Valencia
|
//Valencia
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.15, 0.1, 0.1, 0, 20, 0.1, 1.1, 0, 0, 10, 0.1, 0.1, 1.2, 0, 5, 0, 0, 0, 1, 0]),
|
||||||
1.15,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0.1,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Clarendon
|
//Clarendon
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.2, 0, 0, 0, 10, 0, 1.25, 0, 0, 10, 0, 0, 1.3, 0, 10, 0, 0, 0, 1, 0]),
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
1.25,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Moon
|
//Moon
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.33, 0.33, 0.33, 0, 0, 0.33, 0.33, 0.33, 0, 0, 0.33, 0.33, 0.33, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.33,
|
|
||||||
0.33,
|
|
||||||
0.33,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.33,
|
|
||||||
0.33,
|
|
||||||
0.33,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.33,
|
|
||||||
0.33,
|
|
||||||
0.33,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Willow
|
//Willow
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.5, 0.5, 0.5, 0, 20, 0.5, 0.5, 0.5, 0, 20, 0.5, 0.5, 0.5, 0, 20, 0, 0, 0, 1, 0]),
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0,
|
|
||||||
20,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Kodak
|
//Kodak
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.3, 0.1, -0.1, 0, 10, 0, 1.25, 0.1, 0, 10, 0, -0.1, 1.1, 0, 5, 0, 0, 0, 1, 0]),
|
||||||
1.3,
|
|
||||||
0.1,
|
|
||||||
-0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
1.25,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
-0.1,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Frost
|
//Frost
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.8, 0.2, 0.1, 0, 0, 0.2, 1.1, 0.1, 0, 0, 0.1, 0.1, 1.2, 0, 10, 0, 0, 0, 1, 0]),
|
||||||
0.8,
|
|
||||||
0.2,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Night Vision
|
//Night Vision
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.1, 0.95, 0.2, 0, 0, 0.1, 1.5, 0.1, 0, 0, 0.2, 0.7, 0, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.1,
|
|
||||||
0.95,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
1.5,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
0.7,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Sunset
|
//Sunset
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.5, 0.2, 0, 0, 0, 0.1, 0.9, 0.1, 0, 0, -0.1, -0.2, 1.3, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.5,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0.9,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
-0.1,
|
|
||||||
-0.2,
|
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Noir
|
//Noir
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.3, -0.3, 0.1, 0, 0, -0.1, 1.2, -0.1, 0, 0, 0.1, -0.2, 1.3, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.3,
|
|
||||||
-0.3,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
-0.1,
|
|
||||||
1.2,
|
|
||||||
-0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
-0.2,
|
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Dreamy
|
//Dreamy
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.1, 0.1, 0.1, 0, 0, 0.1, 1.1, 0.1, 0, 0, 0.1, 0.1, 1.1, 0, 15, 0, 0, 0, 1, 0]),
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
1.1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
15,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Sepia
|
//Sepia
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.393,
|
|
||||||
0.769,
|
|
||||||
0.189,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.349,
|
|
||||||
0.686,
|
|
||||||
0.168,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.272,
|
|
||||||
0.534,
|
|
||||||
0.131,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Radium
|
//Radium
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([
|
||||||
1.438,
|
1.438,
|
||||||
|
|
@ -554,212 +92,23 @@ const List<ColorFilter> filters = [
|
||||||
0,
|
0,
|
||||||
]),
|
]),
|
||||||
//Purple Haze
|
//Purple Haze
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.3, 0, 1.2, 0, 0, 0, 1.1, 0, 0, 0, 0.2, 0, 1.3, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
1.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Lemonade
|
//Lemonade
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.2, 0.1, 0, 0, 0, 0, 1.1, 0.2, 0, 0, 0.1, 0, 0.7, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.2,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.1,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0.7,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Caramel
|
//Caramel
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.6, 0.2, 0, 0, 0, 0.1, 1.3, 0.1, 0, 0, 0, 0.1, 0.9, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.6,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
1.3,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0.9,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Peachy
|
//Peachy
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.3, 0.5, 0, 0, 0, 0.2, 1.1, 0.3, 0, 0, 0.1, 0.1, 1.2, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.3,
|
|
||||||
0.5,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
1.1,
|
|
||||||
0.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Neon
|
//Neon
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Cold Morning
|
//Cold Morning
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.9, 0.1, 0.2, 0, 0, 0, 1, 0.1, 0, 0, 0.1, 0, 1.2, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.9,
|
|
||||||
0.1,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Lush
|
//Lush
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.9, 0.2, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.1, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.9,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Urban Neon
|
//Urban Neon
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([1.1, 0, 0.3, 0, 0, 0, 0.9, 0.3, 0, 0, 0.3, 0.1, 1.2, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
1.1,
|
|
||||||
0,
|
|
||||||
0.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.9,
|
|
||||||
0.3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.3,
|
|
||||||
0.1,
|
|
||||||
1.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
//Monochrome
|
//Monochrome
|
||||||
ColorFilter.matrix([
|
ColorFilter.matrix([0.6, 0.2, 0.2, 0, 0, 0.2, 0.6, 0.2, 0, 0, 0.2, 0.2, 0.7, 0, 0, 0, 0, 0, 1, 0]),
|
||||||
0.6,
|
|
||||||
0.2,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
0.6,
|
|
||||||
0.2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.2,
|
|
||||||
0.2,
|
|
||||||
0.7,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
]),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const List<String> filterNames = [
|
const List<String> filterNames = [
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,4 @@ const Map<String, Locale> locales = {
|
||||||
|
|
||||||
const String translationsPath = 'assets/i18n';
|
const String translationsPath = 'assets/i18n';
|
||||||
|
|
||||||
const List<Locale> localesNotSupportedByOverpass = [
|
const List<Locale> localesNotSupportedByOverpass = [Locale('el', 'GR'), Locale('sr', 'Cyrl')];
|
||||||
Locale('el', 'GR'),
|
|
||||||
Locale('sr', 'Cyrl'),
|
|
||||||
];
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,7 @@ enum AssetType {
|
||||||
audio,
|
audio,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AssetState {
|
enum AssetState { local, remote, merged }
|
||||||
local,
|
|
||||||
remote,
|
|
||||||
merged,
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class BaseAsset {
|
sealed class BaseAsset {
|
||||||
final String name;
|
final String name;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
part of 'base_asset.model.dart';
|
part of 'base_asset.model.dart';
|
||||||
|
|
||||||
enum AssetVisibility {
|
enum AssetVisibility { timeline, hidden, archive, locked }
|
||||||
timeline,
|
|
||||||
hidden,
|
|
||||||
archive,
|
|
||||||
locked,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Model for an asset stored in the server
|
// Model for an asset stored in the server
|
||||||
class RemoteAsset extends BaseAsset {
|
class RemoteAsset extends BaseAsset {
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,7 @@ class DeviceAsset {
|
||||||
final Uint8List hash;
|
final Uint8List hash;
|
||||||
final DateTime modifiedTime;
|
final DateTime modifiedTime;
|
||||||
|
|
||||||
const DeviceAsset({
|
const DeviceAsset({required this.assetId, required this.hash, required this.modifiedTime});
|
||||||
required this.assetId,
|
|
||||||
required this.hash,
|
|
||||||
required this.modifiedTime,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(covariant DeviceAsset other) {
|
bool operator ==(covariant DeviceAsset other) {
|
||||||
|
|
@ -28,11 +24,7 @@ class DeviceAsset {
|
||||||
return 'DeviceAsset(assetId: $assetId, hash: $hash, modifiedTime: $modifiedTime)';
|
return 'DeviceAsset(assetId: $assetId, hash: $hash, modifiedTime: $modifiedTime)';
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceAsset copyWith({
|
DeviceAsset copyWith({String? assetId, Uint8List? hash, DateTime? modifiedTime}) {
|
||||||
String? assetId,
|
|
||||||
Uint8List? hash,
|
|
||||||
DateTime? modifiedTime,
|
|
||||||
}) {
|
|
||||||
return DeviceAsset(
|
return DeviceAsset(
|
||||||
assetId: assetId ?? this.assetId,
|
assetId: assetId ?? this.assetId,
|
||||||
hash: hash ?? this.hash,
|
hash: hash ?? this.hash,
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,5 @@
|
||||||
/// Log levels according to dart logging [Level]
|
/// Log levels according to dart logging [Level]
|
||||||
enum LogLevel {
|
enum LogLevel { all, finest, finer, fine, config, info, warning, severe, shout, off }
|
||||||
all,
|
|
||||||
finest,
|
|
||||||
finer,
|
|
||||||
fine,
|
|
||||||
config,
|
|
||||||
info,
|
|
||||||
warning,
|
|
||||||
severe,
|
|
||||||
shout,
|
|
||||||
off,
|
|
||||||
}
|
|
||||||
|
|
||||||
class LogMessage {
|
class LogMessage {
|
||||||
final String message;
|
final String message;
|
||||||
|
|
|
||||||
|
|
@ -13,28 +13,18 @@ enum MemoryTypeEnum {
|
||||||
class MemoryData {
|
class MemoryData {
|
||||||
final int year;
|
final int year;
|
||||||
|
|
||||||
const MemoryData({
|
const MemoryData({required this.year});
|
||||||
required this.year,
|
|
||||||
});
|
|
||||||
|
|
||||||
MemoryData copyWith({
|
MemoryData copyWith({int? year}) {
|
||||||
int? year,
|
return MemoryData(year: year ?? this.year);
|
||||||
}) {
|
|
||||||
return MemoryData(
|
|
||||||
year: year ?? this.year,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{'year': year};
|
||||||
'year': year,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory MemoryData.fromMap(Map<String, dynamic> map) {
|
factory MemoryData.fromMap(Map<String, dynamic> map) {
|
||||||
return MemoryData(
|
return MemoryData(year: map['year'] as int);
|
||||||
year: map['year'] as int,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String toJson() => json.encode(toMap());
|
String toJson() => json.encode(toMap());
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,12 @@ class SearchResult {
|
||||||
final List<BaseAsset> assets;
|
final List<BaseAsset> assets;
|
||||||
final int? nextPage;
|
final int? nextPage;
|
||||||
|
|
||||||
const SearchResult({
|
const SearchResult({required this.assets, this.nextPage});
|
||||||
required this.assets,
|
|
||||||
this.nextPage,
|
|
||||||
});
|
|
||||||
|
|
||||||
int get totalAssets => assets.length;
|
int get totalAssets => assets.length;
|
||||||
|
|
||||||
SearchResult copyWith({
|
SearchResult copyWith({List<BaseAsset>? assets, int? nextPage}) {
|
||||||
List<BaseAsset>? assets,
|
return SearchResult(assets: assets ?? this.assets, nextPage: nextPage ?? this.nextPage);
|
||||||
int? nextPage,
|
|
||||||
}) {
|
|
||||||
return SearchResult(
|
|
||||||
assets: assets ?? this.assets,
|
|
||||||
nextPage: nextPage ?? this.nextPage,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ enum Setting<T> {
|
||||||
loadOriginalVideo<bool>(StoreKey.loadOriginalVideo, false),
|
loadOriginalVideo<bool>(StoreKey.loadOriginalVideo, false),
|
||||||
preferRemoteImage<bool>(StoreKey.preferRemoteImage, false),
|
preferRemoteImage<bool>(StoreKey.preferRemoteImage, false),
|
||||||
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, false),
|
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, false),
|
||||||
enableBackup<bool>(StoreKey.enableBackup, false),
|
enableBackup<bool>(StoreKey.enableBackup, false);
|
||||||
;
|
|
||||||
|
|
||||||
const Setting(this.storeKey, this.defaultValue);
|
const Setting(this.storeKey, this.defaultValue);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,7 @@ class Stack {
|
||||||
required this.primaryAssetId,
|
required this.primaryAssetId,
|
||||||
});
|
});
|
||||||
|
|
||||||
Stack copyWith({
|
Stack copyWith({String? id, DateTime? createdAt, DateTime? updatedAt, String? ownerId, String? primaryAssetId}) {
|
||||||
String? id,
|
|
||||||
DateTime? createdAt,
|
|
||||||
DateTime? updatedAt,
|
|
||||||
String? ownerId,
|
|
||||||
String? primaryAssetId,
|
|
||||||
}) {
|
|
||||||
return Stack(
|
return Stack(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
|
@ -63,11 +57,7 @@ class StackResponse {
|
||||||
final String primaryAssetId;
|
final String primaryAssetId;
|
||||||
final List<String> assetIds;
|
final List<String> assetIds;
|
||||||
|
|
||||||
const StackResponse({
|
const StackResponse({required this.id, required this.primaryAssetId, required this.assetIds});
|
||||||
required this.id,
|
|
||||||
required this.primaryAssetId,
|
|
||||||
required this.assetIds,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(covariant StackResponse other) {
|
bool operator ==(covariant StackResponse other) {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,8 @@
|
||||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||||
|
|
||||||
enum GroupAssetsBy {
|
enum GroupAssetsBy { day, month, auto, none }
|
||||||
day,
|
|
||||||
month,
|
|
||||||
auto,
|
|
||||||
none;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum HeaderType {
|
enum HeaderType { none, month, day, monthAndDay }
|
||||||
none,
|
|
||||||
month,
|
|
||||||
day,
|
|
||||||
monthAndDay;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Bucket {
|
class Bucket {
|
||||||
final int assetCount;
|
final int assetCount;
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,7 @@ quotaSizeInBytes: $quotaSizeInBytes,
|
||||||
bool? isPartnerSharedWith,
|
bool? isPartnerSharedWith,
|
||||||
int? quotaUsageInBytes,
|
int? quotaUsageInBytes,
|
||||||
int? quotaSizeInBytes,
|
int? quotaSizeInBytes,
|
||||||
}) =>
|
}) => UserDto(
|
||||||
UserDto(
|
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
email: email ?? this.email,
|
email: email ?? this.email,
|
||||||
name: name ?? this.name,
|
name: name ?? this.name,
|
||||||
|
|
@ -143,13 +142,7 @@ class PartnerUserDto {
|
||||||
this.profileImagePath,
|
this.profileImagePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
PartnerUserDto copyWith({
|
PartnerUserDto copyWith({String? id, String? email, String? name, bool? inTimeline, String? profileImagePath}) {
|
||||||
String? id,
|
|
||||||
String? email,
|
|
||||||
String? name,
|
|
||||||
bool? inTimeline,
|
|
||||||
String? profileImagePath,
|
|
||||||
}) {
|
|
||||||
return PartnerUserDto(
|
return PartnerUserDto(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
email: email ?? this.email,
|
email: email ?? this.email,
|
||||||
|
|
|
||||||
|
|
@ -193,17 +193,9 @@ class License {
|
||||||
final String activationKey;
|
final String activationKey;
|
||||||
final String licenseKey;
|
final String licenseKey;
|
||||||
|
|
||||||
const License({
|
const License({required this.activatedAt, required this.activationKey, required this.licenseKey});
|
||||||
required this.activatedAt,
|
|
||||||
required this.activationKey,
|
|
||||||
required this.licenseKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
License copyWith({
|
License copyWith({DateTime? activatedAt, String? activationKey, String? licenseKey}) {
|
||||||
DateTime? activatedAt,
|
|
||||||
String? activationKey,
|
|
||||||
String? licenseKey,
|
|
||||||
}) {
|
|
||||||
return License(
|
return License(
|
||||||
activatedAt: activatedAt ?? this.activatedAt,
|
activatedAt: activatedAt ?? this.activatedAt,
|
||||||
activationKey: activationKey ?? this.activationKey,
|
activationKey: activationKey ?? this.activationKey,
|
||||||
|
|
@ -255,13 +247,8 @@ class UserMetadata {
|
||||||
final Preferences? preferences;
|
final Preferences? preferences;
|
||||||
final License? license;
|
final License? license;
|
||||||
|
|
||||||
const UserMetadata({
|
const UserMetadata({required this.userId, required this.key, this.onboarding, this.preferences, this.license})
|
||||||
required this.userId,
|
: assert(
|
||||||
required this.key,
|
|
||||||
this.onboarding,
|
|
||||||
this.preferences,
|
|
||||||
this.license,
|
|
||||||
}) : assert(
|
|
||||||
onboarding != null || preferences != null || license != null,
|
onboarding != null || preferences != null || license != null,
|
||||||
'One of onboarding, preferences and license must be provided',
|
'One of onboarding, preferences and license must be provided',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,7 @@ class HashService {
|
||||||
final Stopwatch stopwatch = Stopwatch()..start();
|
final Stopwatch stopwatch = Stopwatch()..start();
|
||||||
// Sorted by backupSelection followed by isCloud
|
// Sorted by backupSelection followed by isCloud
|
||||||
final localAlbums = await _localAlbumRepository.getAll(
|
final localAlbums = await _localAlbumRepository.getAll(
|
||||||
sortBy: {
|
sortBy: {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum},
|
||||||
SortLocalAlbumsBy.backupSelection,
|
|
||||||
SortLocalAlbumsBy.isIosSharedAlbum,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
for (final album in localAlbums) {
|
for (final album in localAlbums) {
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,7 @@ class LocalSyncService {
|
||||||
for (final album in cloudAlbums) {
|
for (final album in cloudAlbums) {
|
||||||
final dbAlbum = dbAlbums.firstWhereOrNull((a) => a.id == album.id);
|
final dbAlbum = dbAlbums.firstWhereOrNull((a) => a.id == album.id);
|
||||||
if (dbAlbum == null) {
|
if (dbAlbum == null) {
|
||||||
_log.warning(
|
_log.warning("Cloud album ${album.name} not found in local database. Skipping sync.");
|
||||||
"Cloud album ${album.name} not found in local database. Skipping sync.",
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await updateAlbum(dbAlbum, album);
|
await updateAlbum(dbAlbum, album);
|
||||||
|
|
@ -120,10 +118,7 @@ class LocalSyncService {
|
||||||
|
|
||||||
final assets = album.assetCount > 0 ? await _nativeSyncApi.getAssetsForAlbum(album.id) : <PlatformAsset>[];
|
final assets = album.assetCount > 0 ? await _nativeSyncApi.getAssetsForAlbum(album.id) : <PlatformAsset>[];
|
||||||
|
|
||||||
await _localAlbumRepository.upsert(
|
await _localAlbumRepository.upsert(album, toUpsert: assets.toLocalAssets());
|
||||||
album,
|
|
||||||
toUpsert: assets.toLocalAssets(),
|
|
||||||
);
|
|
||||||
_log.fine("Successfully added device album ${album.name}");
|
_log.fine("Successfully added device album ${album.name}");
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
_log.warning("Error while adding device album", e, s);
|
_log.warning("Error while adding device album", e, s);
|
||||||
|
|
@ -146,9 +141,7 @@ class LocalSyncService {
|
||||||
_log.fine("Syncing device album ${dbAlbum.name}");
|
_log.fine("Syncing device album ${dbAlbum.name}");
|
||||||
|
|
||||||
if (_albumsEqual(deviceAlbum, dbAlbum)) {
|
if (_albumsEqual(deviceAlbum, dbAlbum)) {
|
||||||
_log.fine(
|
_log.fine("Device album ${dbAlbum.name} has not changed. Skipping sync.");
|
||||||
"Device album ${dbAlbum.name} has not changed. Skipping sync.",
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,10 +165,7 @@ class LocalSyncService {
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
// The [deviceAlbum] is expected to be refreshed before calling this method
|
// The [deviceAlbum] is expected to be refreshed before calling this method
|
||||||
// with modified time and asset count
|
// with modified time and asset count
|
||||||
Future<bool> checkAddition(
|
Future<bool> checkAddition(LocalAlbum dbAlbum, LocalAlbum deviceAlbum) async {
|
||||||
LocalAlbum dbAlbum,
|
|
||||||
LocalAlbum deviceAlbum,
|
|
||||||
) async {
|
|
||||||
try {
|
try {
|
||||||
_log.fine("Fast syncing device album ${dbAlbum.name}");
|
_log.fine("Fast syncing device album ${dbAlbum.name}");
|
||||||
// Assets has been modified
|
// Assets has been modified
|
||||||
|
|
@ -189,9 +179,7 @@ class LocalSyncService {
|
||||||
|
|
||||||
// Early return if no new assets were found
|
// Early return if no new assets were found
|
||||||
if (newAssetsCount == 0) {
|
if (newAssetsCount == 0) {
|
||||||
_log.fine(
|
_log.fine("No new assets found despite album having changes. Proceeding to full sync for ${dbAlbum.name}");
|
||||||
"No new assets found despite album having changes. Proceeding to full sync for ${dbAlbum.name}",
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,10 +189,7 @@ class LocalSyncService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final newAssets = await _nativeSyncApi.getAssetsForAlbum(
|
final newAssets = await _nativeSyncApi.getAssetsForAlbum(deviceAlbum.id, updatedTimeCond: updatedTime);
|
||||||
deviceAlbum.id,
|
|
||||||
updatedTimeCond: updatedTime,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _localAlbumRepository.upsert(
|
await _localAlbumRepository.upsert(
|
||||||
deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection),
|
deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection),
|
||||||
|
|
@ -229,9 +214,7 @@ class LocalSyncService {
|
||||||
final assetsInDb = dbAlbum.assetCount > 0 ? await _localAlbumRepository.getAssets(dbAlbum.id) : <LocalAsset>[];
|
final assetsInDb = dbAlbum.assetCount > 0 ? await _localAlbumRepository.getAssets(dbAlbum.id) : <LocalAsset>[];
|
||||||
|
|
||||||
if (deviceAlbum.assetCount == 0) {
|
if (deviceAlbum.assetCount == 0) {
|
||||||
_log.fine(
|
_log.fine("Device album ${deviceAlbum.name} is empty. Removing assets from DB.");
|
||||||
"Device album ${deviceAlbum.name} is empty. Removing assets from DB.",
|
|
||||||
);
|
|
||||||
await _localAlbumRepository.upsert(
|
await _localAlbumRepository.upsert(
|
||||||
deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection),
|
deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection),
|
||||||
toDelete: assetsInDb.map((a) => a.id),
|
toDelete: assetsInDb.map((a) => a.id),
|
||||||
|
|
@ -239,18 +222,11 @@ class LocalSyncService {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final updatedDeviceAlbum = deviceAlbum.copyWith(
|
final updatedDeviceAlbum = deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection);
|
||||||
backupSelection: dbAlbum.backupSelection,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dbAlbum.assetCount == 0) {
|
if (dbAlbum.assetCount == 0) {
|
||||||
_log.fine(
|
_log.fine("Device album ${deviceAlbum.name} is empty. Adding assets to DB.");
|
||||||
"Device album ${deviceAlbum.name} is empty. Adding assets to DB.",
|
await _localAlbumRepository.upsert(updatedDeviceAlbum, toUpsert: assetsInDevice);
|
||||||
);
|
|
||||||
await _localAlbumRepository.upsert(
|
|
||||||
updatedDeviceAlbum,
|
|
||||||
toUpsert: assetsInDevice,
|
|
||||||
);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,18 +258,12 @@ class LocalSyncService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (assetsToUpsert.isEmpty && assetsToDelete.isEmpty) {
|
if (assetsToUpsert.isEmpty && assetsToDelete.isEmpty) {
|
||||||
_log.fine(
|
_log.fine("No asset changes detected in album ${deviceAlbum.name}. Updating metadata.");
|
||||||
"No asset changes detected in album ${deviceAlbum.name}. Updating metadata.",
|
|
||||||
);
|
|
||||||
_localAlbumRepository.upsert(updatedDeviceAlbum);
|
_localAlbumRepository.upsert(updatedDeviceAlbum);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _localAlbumRepository.upsert(
|
await _localAlbumRepository.upsert(updatedDeviceAlbum, toUpsert: assetsToUpsert, toDelete: assetsToDelete);
|
||||||
updatedDeviceAlbum,
|
|
||||||
toUpsert: assetsToUpsert,
|
|
||||||
toDelete: assetsToDelete,
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,7 @@ class LogService {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogService._(
|
LogService._(this._logRepository, this._storeRepository, this._shouldBuffer) {
|
||||||
this._logRepository,
|
|
||||||
this._storeRepository,
|
|
||||||
this._shouldBuffer,
|
|
||||||
) {
|
|
||||||
_logSubscription = Logger.root.onRecord.listen(_handleLogRecord);
|
_logSubscription = Logger.root.onRecord.listen(_handleLogRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,10 +85,7 @@ class LogService {
|
||||||
|
|
||||||
if (_shouldBuffer) {
|
if (_shouldBuffer) {
|
||||||
_msgBuffer.add(record);
|
_msgBuffer.add(record);
|
||||||
_flushTimer ??= Timer(
|
_flushTimer ??= Timer(const Duration(seconds: 5), () => unawaited(flushBuffer()));
|
||||||
const Duration(seconds: 5),
|
|
||||||
() => unawaited(flushBuffer()),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
unawaited(_logRepository.insert(record));
|
unawaited(_logRepository.insert(record));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@ class DriftPartnerService {
|
||||||
final DriftPartnerRepository _driftPartnerRepository;
|
final DriftPartnerRepository _driftPartnerRepository;
|
||||||
final PartnerApiRepository _partnerApiRepository;
|
final PartnerApiRepository _partnerApiRepository;
|
||||||
|
|
||||||
const DriftPartnerService(
|
const DriftPartnerService(this._driftPartnerRepository, this._partnerApiRepository);
|
||||||
this._driftPartnerRepository,
|
|
||||||
this._partnerApiRepository,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<List<PartnerUserDto>> getSharedWith(String userId) {
|
Future<List<PartnerUserDto>> getSharedWith(String userId) {
|
||||||
return _driftPartnerRepository.getSharedWith(userId);
|
return _driftPartnerRepository.getSharedWith(userId);
|
||||||
|
|
@ -20,9 +17,7 @@ class DriftPartnerService {
|
||||||
return _driftPartnerRepository.getSharedBy(userId);
|
return _driftPartnerRepository.getSharedBy(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<PartnerUserDto>> getAvailablePartners(
|
Future<List<PartnerUserDto>> getAvailablePartners(String currentUserId) async {
|
||||||
String currentUserId,
|
|
||||||
) async {
|
|
||||||
final otherUsers = await _driftPartnerRepository.getAvailablePartners(currentUserId);
|
final otherUsers = await _driftPartnerRepository.getAvailablePartners(currentUserId);
|
||||||
final currentPartners = await _driftPartnerRepository.getSharedBy(currentUserId);
|
final currentPartners = await _driftPartnerRepository.getSharedBy(currentUserId);
|
||||||
final available = otherUsers.where((user) {
|
final available = otherUsers.where((user) {
|
||||||
|
|
@ -39,10 +34,7 @@ class DriftPartnerService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _partnerApiRepository.update(
|
await _partnerApiRepository.update(partnerId, inTimeline: !partner.inTimeline);
|
||||||
partnerId,
|
|
||||||
inTimeline: !partner.inTimeline,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _driftPartnerRepository.toggleShowInTimeline(partner, userId);
|
await _driftPartnerRepository.toggleShowInTimeline(partner, userId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,7 @@ class RemoteAlbumService {
|
||||||
return _repository.get(albumId);
|
return _repository.get(albumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RemoteAlbum> sortAlbums(
|
List<RemoteAlbum> sortAlbums(List<RemoteAlbum> albums, RemoteAlbumSortMode sortMode, {bool isReverse = false}) {
|
||||||
List<RemoteAlbum> albums,
|
|
||||||
RemoteAlbumSortMode sortMode, {
|
|
||||||
bool isReverse = false,
|
|
||||||
}) {
|
|
||||||
return sortMode.sortFn(albums, isReverse);
|
return sortMode.sortFn(albums, isReverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,16 +65,8 @@ class RemoteAlbumService {
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<RemoteAlbum> createAlbum({
|
Future<RemoteAlbum> createAlbum({required String title, required List<String> assetIds, String? description}) async {
|
||||||
required String title,
|
final album = await _albumApiRepository.createDriftAlbum(title, description: description, assetIds: assetIds);
|
||||||
required List<String> assetIds,
|
|
||||||
String? description,
|
|
||||||
}) async {
|
|
||||||
final album = await _albumApiRepository.createDriftAlbum(
|
|
||||||
title,
|
|
||||||
description: description,
|
|
||||||
assetIds: assetIds,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _repository.create(album, assetIds);
|
await _repository.create(album, assetIds);
|
||||||
|
|
||||||
|
|
@ -120,14 +108,8 @@ class RemoteAlbumService {
|
||||||
return _repository.getAssets(albumId);
|
return _repository.getAssets(albumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> addAssets({
|
Future<int> addAssets({required String albumId, required List<String> assetIds}) async {
|
||||||
required String albumId,
|
final album = await _albumApiRepository.addAssets(albumId, assetIds);
|
||||||
required List<String> assetIds,
|
|
||||||
}) async {
|
|
||||||
final album = await _albumApiRepository.addAssets(
|
|
||||||
albumId,
|
|
||||||
assetIds,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _repository.addAssets(albumId, album.added);
|
await _repository.addAssets(albumId, album.added);
|
||||||
|
|
||||||
|
|
@ -140,10 +122,7 @@ class RemoteAlbumService {
|
||||||
await _repository.deleteAlbum(albumId);
|
await _repository.deleteAlbum(albumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addUsers({
|
Future<void> addUsers({required String albumId, required List<String> userIds}) async {
|
||||||
required String albumId,
|
|
||||||
required List<String> userIds,
|
|
||||||
}) async {
|
|
||||||
await _albumApiRepository.addUsers(albumId, userIds);
|
await _albumApiRepository.addUsers(albumId, userIds);
|
||||||
|
|
||||||
return _repository.addUsers(albumId, userIds);
|
return _repository.addUsers(albumId, userIds);
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,12 @@ class StoreService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace the implementation with the one from create after removing the typedef
|
// TODO: Replace the implementation with the one from create after removing the typedef
|
||||||
static Future<StoreService> init({
|
static Future<StoreService> init({required IsarStoreRepository storeRepository}) async {
|
||||||
required IsarStoreRepository storeRepository,
|
|
||||||
}) async {
|
|
||||||
_instance ??= await create(storeRepository: storeRepository);
|
_instance ??= await create(storeRepository: storeRepository);
|
||||||
return _instance!;
|
return _instance!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<StoreService> create({
|
static Future<StoreService> create({required IsarStoreRepository storeRepository}) async {
|
||||||
required IsarStoreRepository storeRepository,
|
|
||||||
}) async {
|
|
||||||
final instance = StoreService._(storeRepository: storeRepository);
|
final instance = StoreService._(storeRepository: storeRepository);
|
||||||
await instance._populateCache();
|
await instance._populateCache();
|
||||||
instance._storeUpdateSubscription = instance._listenForChange();
|
instance._storeUpdateSubscription = instance._listenForChange();
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,7 @@ class SyncStreamService {
|
||||||
Future<void> handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) async {
|
Future<void> handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) async {
|
||||||
if (batchData.isEmpty) return;
|
if (batchData.isEmpty) return;
|
||||||
|
|
||||||
_logger.info(
|
_logger.info('Processing batch of ${batchData.length} AssetUploadReadyV1 events');
|
||||||
'Processing batch of ${batchData.length} AssetUploadReadyV1 events',
|
|
||||||
);
|
|
||||||
|
|
||||||
final List<SyncAssetV1> assets = [];
|
final List<SyncAssetV1> assets = [];
|
||||||
final List<SyncAssetExifV1> exifs = [];
|
final List<SyncAssetExifV1> exifs = [];
|
||||||
|
|
@ -65,22 +63,12 @@ class SyncStreamService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assets.isNotEmpty && exifs.isNotEmpty) {
|
if (assets.isNotEmpty && exifs.isNotEmpty) {
|
||||||
await _syncStreamRepository.updateAssetsV1(
|
await _syncStreamRepository.updateAssetsV1(assets, debugLabel: 'websocket-batch');
|
||||||
assets,
|
await _syncStreamRepository.updateAssetsExifV1(exifs, debugLabel: 'websocket-batch');
|
||||||
debugLabel: 'websocket-batch',
|
|
||||||
);
|
|
||||||
await _syncStreamRepository.updateAssetsExifV1(
|
|
||||||
exifs,
|
|
||||||
debugLabel: 'websocket-batch',
|
|
||||||
);
|
|
||||||
_logger.info('Successfully processed ${assets.length} assets in batch');
|
_logger.info('Successfully processed ${assets.length} assets in batch');
|
||||||
}
|
}
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
_logger.severe(
|
_logger.severe("Error processing AssetUploadReadyV1 websocket batch events", error, stackTrace);
|
||||||
"Error processing AssetUploadReadyV1 websocket batch events",
|
|
||||||
error,
|
|
||||||
stackTrace,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,10 +102,7 @@ class SyncStreamService {
|
||||||
batch.clear();
|
batch.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleSyncData(
|
Future<void> _handleSyncData(SyncEntityType type, Iterable<Object> data) async {
|
||||||
SyncEntityType type,
|
|
||||||
Iterable<Object> data,
|
|
||||||
) async {
|
|
||||||
_logger.fine("Processing sync data for $type of length ${data.length}");
|
_logger.fine("Processing sync data for $type of length ${data.length}");
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SyncEntityType.userV1:
|
case SyncEntityType.userV1:
|
||||||
|
|
@ -135,30 +120,15 @@ class SyncStreamService {
|
||||||
case SyncEntityType.assetExifV1:
|
case SyncEntityType.assetExifV1:
|
||||||
return _syncStreamRepository.updateAssetsExifV1(data.cast());
|
return _syncStreamRepository.updateAssetsExifV1(data.cast());
|
||||||
case SyncEntityType.partnerAssetV1:
|
case SyncEntityType.partnerAssetV1:
|
||||||
return _syncStreamRepository.updateAssetsV1(
|
return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'partner');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner',
|
|
||||||
);
|
|
||||||
case SyncEntityType.partnerAssetBackfillV1:
|
case SyncEntityType.partnerAssetBackfillV1:
|
||||||
return _syncStreamRepository.updateAssetsV1(
|
return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'partner backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.partnerAssetDeleteV1:
|
case SyncEntityType.partnerAssetDeleteV1:
|
||||||
return _syncStreamRepository.deleteAssetsV1(
|
return _syncStreamRepository.deleteAssetsV1(data.cast(), debugLabel: "partner");
|
||||||
data.cast(),
|
|
||||||
debugLabel: "partner",
|
|
||||||
);
|
|
||||||
case SyncEntityType.partnerAssetExifV1:
|
case SyncEntityType.partnerAssetExifV1:
|
||||||
return _syncStreamRepository.updateAssetsExifV1(
|
return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'partner');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner',
|
|
||||||
);
|
|
||||||
case SyncEntityType.partnerAssetExifBackfillV1:
|
case SyncEntityType.partnerAssetExifBackfillV1:
|
||||||
return _syncStreamRepository.updateAssetsExifV1(
|
return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'partner backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumV1:
|
case SyncEntityType.albumV1:
|
||||||
return _syncStreamRepository.updateAlbumsV1(data.cast());
|
return _syncStreamRepository.updateAlbumsV1(data.cast());
|
||||||
case SyncEntityType.albumDeleteV1:
|
case SyncEntityType.albumDeleteV1:
|
||||||
|
|
@ -166,39 +136,21 @@ class SyncStreamService {
|
||||||
case SyncEntityType.albumUserV1:
|
case SyncEntityType.albumUserV1:
|
||||||
return _syncStreamRepository.updateAlbumUsersV1(data.cast());
|
return _syncStreamRepository.updateAlbumUsersV1(data.cast());
|
||||||
case SyncEntityType.albumUserBackfillV1:
|
case SyncEntityType.albumUserBackfillV1:
|
||||||
return _syncStreamRepository.updateAlbumUsersV1(
|
return _syncStreamRepository.updateAlbumUsersV1(data.cast(), debugLabel: 'backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumUserDeleteV1:
|
case SyncEntityType.albumUserDeleteV1:
|
||||||
return _syncStreamRepository.deleteAlbumUsersV1(data.cast());
|
return _syncStreamRepository.deleteAlbumUsersV1(data.cast());
|
||||||
case SyncEntityType.albumAssetV1:
|
case SyncEntityType.albumAssetV1:
|
||||||
return _syncStreamRepository.updateAssetsV1(
|
return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'album');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'album',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumAssetBackfillV1:
|
case SyncEntityType.albumAssetBackfillV1:
|
||||||
return _syncStreamRepository.updateAssetsV1(
|
return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'album backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'album backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumAssetExifV1:
|
case SyncEntityType.albumAssetExifV1:
|
||||||
return _syncStreamRepository.updateAssetsExifV1(
|
return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'album');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'album',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumAssetExifBackfillV1:
|
case SyncEntityType.albumAssetExifBackfillV1:
|
||||||
return _syncStreamRepository.updateAssetsExifV1(
|
return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'album backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'album backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumToAssetV1:
|
case SyncEntityType.albumToAssetV1:
|
||||||
return _syncStreamRepository.updateAlbumToAssetsV1(data.cast());
|
return _syncStreamRepository.updateAlbumToAssetsV1(data.cast());
|
||||||
case SyncEntityType.albumToAssetBackfillV1:
|
case SyncEntityType.albumToAssetBackfillV1:
|
||||||
return _syncStreamRepository.updateAlbumToAssetsV1(
|
return _syncStreamRepository.updateAlbumToAssetsV1(data.cast(), debugLabel: 'backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.albumToAssetDeleteV1:
|
case SyncEntityType.albumToAssetDeleteV1:
|
||||||
return _syncStreamRepository.deleteAlbumToAssetsV1(data.cast());
|
return _syncStreamRepository.deleteAlbumToAssetsV1(data.cast());
|
||||||
// No-op. SyncAckV1 entities are checkpoints in the sync stream
|
// No-op. SyncAckV1 entities are checkpoints in the sync stream
|
||||||
|
|
@ -218,28 +170,15 @@ class SyncStreamService {
|
||||||
case SyncEntityType.stackDeleteV1:
|
case SyncEntityType.stackDeleteV1:
|
||||||
return _syncStreamRepository.deleteStacksV1(data.cast());
|
return _syncStreamRepository.deleteStacksV1(data.cast());
|
||||||
case SyncEntityType.partnerStackV1:
|
case SyncEntityType.partnerStackV1:
|
||||||
return _syncStreamRepository.updateStacksV1(
|
return _syncStreamRepository.updateStacksV1(data.cast(), debugLabel: 'partner');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner',
|
|
||||||
);
|
|
||||||
case SyncEntityType.partnerStackBackfillV1:
|
case SyncEntityType.partnerStackBackfillV1:
|
||||||
return _syncStreamRepository.updateStacksV1(
|
return _syncStreamRepository.updateStacksV1(data.cast(), debugLabel: 'partner backfill');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner backfill',
|
|
||||||
);
|
|
||||||
case SyncEntityType.partnerStackDeleteV1:
|
case SyncEntityType.partnerStackDeleteV1:
|
||||||
return _syncStreamRepository.deleteStacksV1(
|
return _syncStreamRepository.deleteStacksV1(data.cast(), debugLabel: 'partner');
|
||||||
data.cast(),
|
|
||||||
debugLabel: 'partner',
|
|
||||||
);
|
|
||||||
case SyncEntityType.userMetadataV1:
|
case SyncEntityType.userMetadataV1:
|
||||||
return _syncStreamRepository.updateUserMetadatasV1(
|
return _syncStreamRepository.updateUserMetadatasV1(data.cast());
|
||||||
data.cast(),
|
|
||||||
);
|
|
||||||
case SyncEntityType.userMetadataDeleteV1:
|
case SyncEntityType.userMetadataDeleteV1:
|
||||||
return _syncStreamRepository.deleteUserMetadatasV1(
|
return _syncStreamRepository.deleteUserMetadatasV1(data.cast());
|
||||||
data.cast(),
|
|
||||||
);
|
|
||||||
case SyncEntityType.personV1:
|
case SyncEntityType.personV1:
|
||||||
return _syncStreamRepository.updatePeopleV1(data.cast());
|
return _syncStreamRepository.updatePeopleV1(data.cast());
|
||||||
case SyncEntityType.personDeleteV1:
|
case SyncEntityType.personDeleteV1:
|
||||||
|
|
|
||||||
|
|
@ -11,26 +11,18 @@ import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||||
import 'package:immich_mobile/utils/async_mutex.dart';
|
import 'package:immich_mobile/utils/async_mutex.dart';
|
||||||
|
|
||||||
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
|
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(int index, int count);
|
||||||
int index,
|
|
||||||
int count,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef TimelineBucketSource = Stream<List<Bucket>> Function();
|
typedef TimelineBucketSource = Stream<List<Bucket>> Function();
|
||||||
|
|
||||||
typedef TimelineQuery = ({
|
typedef TimelineQuery = ({TimelineAssetSource assetSource, TimelineBucketSource bucketSource});
|
||||||
TimelineAssetSource assetSource,
|
|
||||||
TimelineBucketSource bucketSource,
|
|
||||||
});
|
|
||||||
|
|
||||||
class TimelineFactory {
|
class TimelineFactory {
|
||||||
final DriftTimelineRepository _timelineRepository;
|
final DriftTimelineRepository _timelineRepository;
|
||||||
final SettingsService _settingsService;
|
final SettingsService _settingsService;
|
||||||
|
|
||||||
const TimelineFactory({
|
const TimelineFactory({required DriftTimelineRepository timelineRepository, required SettingsService settingsService})
|
||||||
required DriftTimelineRepository timelineRepository,
|
: _timelineRepository = timelineRepository,
|
||||||
required SettingsService settingsService,
|
|
||||||
}) : _timelineRepository = timelineRepository,
|
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
|
|
||||||
GroupAssetsBy get groupBy {
|
GroupAssetsBy get groupBy {
|
||||||
|
|
@ -75,16 +67,10 @@ class TimelineService {
|
||||||
int _totalAssets = 0;
|
int _totalAssets = 0;
|
||||||
int get totalAssets => _totalAssets;
|
int get totalAssets => _totalAssets;
|
||||||
|
|
||||||
TimelineService(TimelineQuery query)
|
TimelineService(TimelineQuery query) : this._(assetSource: query.assetSource, bucketSource: query.bucketSource);
|
||||||
: this._(
|
|
||||||
assetSource: query.assetSource,
|
|
||||||
bucketSource: query.bucketSource,
|
|
||||||
);
|
|
||||||
|
|
||||||
TimelineService._({
|
TimelineService._({required TimelineAssetSource assetSource, required TimelineBucketSource bucketSource})
|
||||||
required TimelineAssetSource assetSource,
|
: _assetSource = assetSource,
|
||||||
required TimelineBucketSource bucketSource,
|
|
||||||
}) : _assetSource = assetSource,
|
|
||||||
_bucketSource = bucketSource {
|
_bucketSource = bucketSource {
|
||||||
_bucketSubscription = _bucketSource().listen((buckets) {
|
_bucketSubscription = _bucketSource().listen((buckets) {
|
||||||
_mutex.run(() async {
|
_mutex.run(() async {
|
||||||
|
|
@ -103,10 +89,7 @@ class TimelineService {
|
||||||
count = kTimelineAssetLoadBatchSize;
|
count = kTimelineAssetLoadBatchSize;
|
||||||
} else {
|
} else {
|
||||||
offset = _bufferOffset;
|
offset = _bufferOffset;
|
||||||
count = math.min(
|
count = math.min(_buffer.length, totalAssets - _bufferOffset);
|
||||||
_buffer.length,
|
|
||||||
totalAssets - _bufferOffset,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_buffer = await _assetSource(offset, count);
|
_buffer = await _assetSource(offset, count);
|
||||||
_bufferOffset = offset;
|
_bufferOffset = offset;
|
||||||
|
|
@ -134,10 +117,7 @@ class TimelineService {
|
||||||
// make sure to load a meaningful amount of data (and not only the requested slice)
|
// make sure to load a meaningful amount of data (and not only the requested slice)
|
||||||
// otherwise, each call to [loadAssets] would result in DB call trashing performance
|
// otherwise, each call to [loadAssets] would result in DB call trashing performance
|
||||||
// fills small requests to [kTimelineAssetLoadBatchSize], adds some legroom into the opposite scroll direction for large requests
|
// fills small requests to [kTimelineAssetLoadBatchSize], adds some legroom into the opposite scroll direction for large requests
|
||||||
final len = math.max(
|
final len = math.max(kTimelineAssetLoadBatchSize, count + kTimelineAssetLoadOppositeSize);
|
||||||
kTimelineAssetLoadBatchSize,
|
|
||||||
count + kTimelineAssetLoadOppositeSize,
|
|
||||||
);
|
|
||||||
// when scrolling forward, start shortly before the requested offset
|
// when scrolling forward, start shortly before the requested offset
|
||||||
// when scrolling backward, end shortly after the requested offset to guard against the user scrolling
|
// when scrolling backward, end shortly after the requested offset to guard against the user scrolling
|
||||||
// in the other direction a tiny bit resulting in another required load from the DB
|
// in the other direction a tiny bit resulting in another required load from the DB
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,7 @@ class UserService {
|
||||||
|
|
||||||
Future<String?> createProfileImage(String name, Uint8List image) async {
|
Future<String?> createProfileImage(String name, Uint8List image) async {
|
||||||
try {
|
try {
|
||||||
final path = await _userApiRepository.createProfileImage(
|
final path = await _userApiRepository.createProfileImage(name: name, data: image);
|
||||||
name: name,
|
|
||||||
data: image,
|
|
||||||
);
|
|
||||||
final updatedUser = getMyUser().copyWith(profileImagePath: path);
|
final updatedUser = getMyUser().copyWith(profileImagePath: path);
|
||||||
await _storeService.put(StoreKey.currentUser, updatedUser);
|
await _storeService.put(StoreKey.currentUser, updatedUser);
|
||||||
await _isarUserRepository.update(updatedUser);
|
await _isarUserRepository.update(updatedUser);
|
||||||
|
|
|
||||||
|
|
@ -66,17 +66,15 @@ class BackgroundSyncManager {
|
||||||
// We use a ternary operator to avoid [_deviceAlbumSyncTask] from being
|
// We use a ternary operator to avoid [_deviceAlbumSyncTask] from being
|
||||||
// captured by the closure passed to [runInIsolateGentle].
|
// captured by the closure passed to [runInIsolateGentle].
|
||||||
_deviceAlbumSyncTask = full
|
_deviceAlbumSyncTask = full
|
||||||
? runInIsolateGentle(
|
? runInIsolateGentle(computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true))
|
||||||
computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true),
|
: runInIsolateGentle(computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false));
|
||||||
)
|
|
||||||
: runInIsolateGentle(
|
|
||||||
computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false),
|
|
||||||
);
|
|
||||||
|
|
||||||
return _deviceAlbumSyncTask!.whenComplete(() {
|
return _deviceAlbumSyncTask!
|
||||||
|
.whenComplete(() {
|
||||||
_deviceAlbumSyncTask = null;
|
_deviceAlbumSyncTask = null;
|
||||||
onLocalSyncComplete?.call();
|
onLocalSyncComplete?.call();
|
||||||
}).catchError((error) {
|
})
|
||||||
|
.catchError((error) {
|
||||||
onLocalSyncError?.call(error.toString());
|
onLocalSyncError?.call(error.toString());
|
||||||
_deviceAlbumSyncTask = null;
|
_deviceAlbumSyncTask = null;
|
||||||
});
|
});
|
||||||
|
|
@ -90,14 +88,14 @@ class BackgroundSyncManager {
|
||||||
|
|
||||||
onHashingStart?.call();
|
onHashingStart?.call();
|
||||||
|
|
||||||
_hashTask = runInIsolateGentle(
|
_hashTask = runInIsolateGentle(computation: (ref) => ref.read(hashServiceProvider).hashAssets());
|
||||||
computation: (ref) => ref.read(hashServiceProvider).hashAssets(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return _hashTask!.whenComplete(() {
|
return _hashTask!
|
||||||
|
.whenComplete(() {
|
||||||
onHashingComplete?.call();
|
onHashingComplete?.call();
|
||||||
_hashTask = null;
|
_hashTask = null;
|
||||||
}).catchError((error) {
|
})
|
||||||
|
.catchError((error) {
|
||||||
onHashingError?.call(error.toString());
|
onHashingError?.call(error.toString());
|
||||||
_hashTask = null;
|
_hashTask = null;
|
||||||
});
|
});
|
||||||
|
|
@ -110,13 +108,13 @@ class BackgroundSyncManager {
|
||||||
|
|
||||||
onRemoteSyncStart?.call();
|
onRemoteSyncStart?.call();
|
||||||
|
|
||||||
_syncTask = runInIsolateGentle(
|
_syncTask = runInIsolateGentle(computation: (ref) => ref.read(syncStreamServiceProvider).sync());
|
||||||
computation: (ref) => ref.read(syncStreamServiceProvider).sync(),
|
return _syncTask!
|
||||||
);
|
.whenComplete(() {
|
||||||
return _syncTask!.whenComplete(() {
|
|
||||||
onRemoteSyncComplete?.call();
|
onRemoteSyncComplete?.call();
|
||||||
_syncTask = null;
|
_syncTask = null;
|
||||||
}).catchError((error) {
|
})
|
||||||
|
.catchError((error) {
|
||||||
onRemoteSyncError?.call(error.toString());
|
onRemoteSyncError?.call(error.toString());
|
||||||
_syncTask = null;
|
_syncTask = null;
|
||||||
});
|
});
|
||||||
|
|
@ -133,9 +131,6 @@ class BackgroundSyncManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cancelable<void> _handleWsAssetUploadReadyV1Batch(
|
Cancelable<void> _handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) => runInIsolateGentle(
|
||||||
List<dynamic> batchData,
|
|
||||||
) =>
|
|
||||||
runInIsolateGentle(
|
|
||||||
computation: (ref) => ref.read(syncStreamServiceProvider).handleWsAssetUploadReadyV1Batch(batchData),
|
computation: (ref) => ref.read(syncStreamServiceProvider).handleWsAssetUploadReadyV1Batch(batchData),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,7 @@ class EventStream {
|
||||||
void Function()? onDone,
|
void Function()? onDone,
|
||||||
bool? cancelOnError,
|
bool? cancelOnError,
|
||||||
}) {
|
}) {
|
||||||
return where<T>().listen(
|
return where<T>().listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
||||||
onData,
|
|
||||||
onError: onError,
|
|
||||||
onDone: onDone,
|
|
||||||
cancelOnError: cancelOnError,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes the stream controller
|
/// Closes the stream controller
|
||||||
|
|
|
||||||
|
|
@ -113,10 +113,7 @@ class Album {
|
||||||
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
|
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
|
||||||
isAtSameMomentAs(startDate, other.startDate) &&
|
isAtSameMomentAs(startDate, other.startDate) &&
|
||||||
isAtSameMomentAs(endDate, other.endDate) &&
|
isAtSameMomentAs(endDate, other.endDate) &&
|
||||||
isAtSameMomentAs(
|
isAtSameMomentAs(lastModifiedAssetTimestamp, other.lastModifiedAssetTimestamp) &&
|
||||||
lastModifiedAssetTimestamp,
|
|
||||||
other.lastModifiedAssetTimestamp,
|
|
||||||
) &&
|
|
||||||
shared == other.shared &&
|
shared == other.shared &&
|
||||||
activityEnabled == other.activityEnabled &&
|
activityEnabled == other.activityEnabled &&
|
||||||
owner.value == other.owner.value &&
|
owner.value == other.owner.value &&
|
||||||
|
|
@ -169,9 +166,7 @@ class Album {
|
||||||
a.thumbnail.value = await db.assets.where().remoteIdEqualTo(dto.albumThumbnailAssetId).findFirst();
|
a.thumbnail.value = await db.assets.where().remoteIdEqualTo(dto.albumThumbnailAssetId).findFirst();
|
||||||
}
|
}
|
||||||
if (dto.albumUsers.isNotEmpty) {
|
if (dto.albumUsers.isNotEmpty) {
|
||||||
final users = await db.users.getAllById(
|
final users = await db.users.getAllById(dto.albumUsers.map((e) => e.user.id).toList(growable: false));
|
||||||
dto.albumUsers.map((e) => e.user.id).toList(growable: false),
|
|
||||||
);
|
|
||||||
a.sharedUsers.addAll(users.cast());
|
a.sharedUsers.addAll(users.cast());
|
||||||
}
|
}
|
||||||
if (dto.assets.isNotEmpty) {
|
if (dto.assets.isNotEmpty) {
|
||||||
|
|
|
||||||
BIN
mobile/lib/entities/album.entity.g.dart
generated
BIN
mobile/lib/entities/album.entity.g.dart
generated
Binary file not shown.
BIN
mobile/lib/entities/android_device_asset.entity.g.dart
generated
BIN
mobile/lib/entities/android_device_asset.entity.g.dart
generated
Binary file not shown.
|
|
@ -127,11 +127,7 @@ class Asset {
|
||||||
@Index(unique: false, replace: false, type: IndexType.hash)
|
@Index(unique: false, replace: false, type: IndexType.hash)
|
||||||
String? localId;
|
String? localId;
|
||||||
|
|
||||||
@Index(
|
@Index(unique: true, replace: false, composite: [CompositeIndex("checksum", type: IndexType.hash)])
|
||||||
unique: true,
|
|
||||||
replace: false,
|
|
||||||
composite: [CompositeIndex("checksum", type: IndexType.hash)],
|
|
||||||
)
|
|
||||||
int ownerId;
|
int ownerId;
|
||||||
|
|
||||||
DateTime fileCreatedAt;
|
DateTime fileCreatedAt;
|
||||||
|
|
@ -447,8 +443,7 @@ class Asset {
|
||||||
int? stackCount,
|
int? stackCount,
|
||||||
String? thumbhash,
|
String? thumbhash,
|
||||||
AssetVisibilityEnum? visibility,
|
AssetVisibilityEnum? visibility,
|
||||||
}) =>
|
}) => Asset(
|
||||||
Asset(
|
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
checksum: checksum ?? this.checksum,
|
checksum: checksum ?? this.checksum,
|
||||||
remoteId: remoteId ?? this.remoteId,
|
remoteId: remoteId ?? this.remoteId,
|
||||||
|
|
@ -494,10 +489,7 @@ class Asset {
|
||||||
return compareByChecksum(a, b);
|
return compareByChecksum(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compareByOwnerChecksumCreatedModified(
|
static int compareByOwnerChecksumCreatedModified(Asset a, Asset b) {
|
||||||
Asset a,
|
|
||||||
Asset b,
|
|
||||||
) {
|
|
||||||
final int ownerIdOrder = a.ownerId.compareTo(b.ownerId);
|
final int ownerIdOrder = a.ownerId.compareTo(b.ownerId);
|
||||||
if (ownerIdOrder != 0) return ownerIdOrder;
|
if (ownerIdOrder != 0) return ownerIdOrder;
|
||||||
final int checksumOrder = compareByChecksum(a, b);
|
final int checksumOrder = compareByChecksum(a, b);
|
||||||
|
|
@ -566,11 +558,7 @@ extension AssetTypeEnumHelper on AssetTypeEnum {
|
||||||
|
|
||||||
/// Describes where the information of this asset came from:
|
/// Describes where the information of this asset came from:
|
||||||
/// only from the local device, only from the remote server or merged from both
|
/// only from the local device, only from the remote server or merged from both
|
||||||
enum AssetState {
|
enum AssetState { local, remote, merged }
|
||||||
local,
|
|
||||||
remote,
|
|
||||||
merged,
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AssetsHelper on IsarCollection<Asset> {
|
extension AssetsHelper on IsarCollection<Asset> {
|
||||||
Future<int> deleteAllByRemoteId(Iterable<String> ids) => ids.isEmpty ? Future.value(0) : remote(ids).deleteAll();
|
Future<int> deleteAllByRemoteId(Iterable<String> ids) => ids.isEmpty ? Future.value(0) : remote(ids).deleteAll();
|
||||||
|
|
@ -579,13 +567,9 @@ extension AssetsHelper on IsarCollection<Asset> {
|
||||||
Future<List<Asset>> getAllByLocalId(Iterable<String> ids) => ids.isEmpty ? Future.value([]) : local(ids).findAll();
|
Future<List<Asset>> getAllByLocalId(Iterable<String> ids) => ids.isEmpty ? Future.value([]) : local(ids).findAll();
|
||||||
Future<Asset?> getByRemoteId(String id) => where().remoteIdEqualTo(id).findFirst();
|
Future<Asset?> getByRemoteId(String id) => where().remoteIdEqualTo(id).findFirst();
|
||||||
|
|
||||||
QueryBuilder<Asset, Asset, QAfterWhereClause> remote(
|
QueryBuilder<Asset, Asset, QAfterWhereClause> remote(Iterable<String> ids) =>
|
||||||
Iterable<String> ids,
|
|
||||||
) =>
|
|
||||||
where().anyOf(ids, (q, String e) => q.remoteIdEqualTo(e));
|
where().anyOf(ids, (q, String e) => q.remoteIdEqualTo(e));
|
||||||
QueryBuilder<Asset, Asset, QAfterWhereClause> local(
|
QueryBuilder<Asset, Asset, QAfterWhereClause> local(Iterable<String> ids) {
|
||||||
Iterable<String> ids,
|
|
||||||
) {
|
|
||||||
return where().anyOf(ids, (q, String e) => q.localIdEqualTo(e));
|
return where().anyOf(ids, (q, String e) => q.localIdEqualTo(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
mobile/lib/entities/asset.entity.g.dart
generated
BIN
mobile/lib/entities/asset.entity.g.dart
generated
Binary file not shown.
|
|
@ -14,21 +14,9 @@ class BackupAlbum {
|
||||||
|
|
||||||
Id get isarId => fastHash(id);
|
Id get isarId => fastHash(id);
|
||||||
|
|
||||||
BackupAlbum copyWith({
|
BackupAlbum copyWith({String? id, DateTime? lastBackup, BackupSelection? selection}) {
|
||||||
String? id,
|
return BackupAlbum(id ?? this.id, lastBackup ?? this.lastBackup, selection ?? this.selection);
|
||||||
DateTime? lastBackup,
|
|
||||||
BackupSelection? selection,
|
|
||||||
}) {
|
|
||||||
return BackupAlbum(
|
|
||||||
id ?? this.id,
|
|
||||||
lastBackup ?? this.lastBackup,
|
|
||||||
selection ?? this.selection,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BackupSelection {
|
enum BackupSelection { none, select, exclude }
|
||||||
none,
|
|
||||||
select,
|
|
||||||
exclude;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
BIN
mobile/lib/entities/backup_album.entity.g.dart
generated
BIN
mobile/lib/entities/backup_album.entity.g.dart
generated
Binary file not shown.
BIN
mobile/lib/entities/duplicated_asset.entity.g.dart
generated
BIN
mobile/lib/entities/duplicated_asset.entity.g.dart
generated
Binary file not shown.
BIN
mobile/lib/entities/etag.entity.g.dart
generated
BIN
mobile/lib/entities/etag.entity.g.dart
generated
Binary file not shown.
BIN
mobile/lib/entities/ios_device_asset.entity.g.dart
generated
BIN
mobile/lib/entities/ios_device_asset.entity.g.dart
generated
Binary file not shown.
|
|
@ -15,16 +15,10 @@ extension TZExtension on Asset {
|
||||||
final location = getLocation(exifInfo!.timeZone!);
|
final location = getLocation(exifInfo!.timeZone!);
|
||||||
dt = TZDateTime.from(dt, location);
|
dt = TZDateTime.from(dt, location);
|
||||||
} on LocationNotFoundException {
|
} on LocationNotFoundException {
|
||||||
RegExp re = RegExp(
|
RegExp re = RegExp(r'^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$', caseSensitive: false);
|
||||||
r'^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$',
|
|
||||||
caseSensitive: false,
|
|
||||||
);
|
|
||||||
final m = re.firstMatch(exifInfo!.timeZone!);
|
final m = re.firstMatch(exifInfo!.timeZone!);
|
||||||
if (m != null) {
|
if (m != null) {
|
||||||
final duration = Duration(
|
final duration = Duration(hours: int.parse(m.group(1) ?? '0'), minutes: int.parse(m.group(2) ?? '0'));
|
||||||
hours: int.parse(m.group(1) ?? '0'),
|
|
||||||
minutes: int.parse(m.group(2) ?? '0'),
|
|
||||||
);
|
|
||||||
dt = dt.add(duration);
|
dt = dt.add(duration);
|
||||||
return (dt, duration);
|
return (dt, duration);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,7 @@ import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
|
|
||||||
extension ListExtension<E> on List<E> {
|
extension ListExtension<E> on List<E> {
|
||||||
List<E> uniqueConsecutive({
|
List<E> uniqueConsecutive({int Function(E a, E b)? compare, void Function(E a, E b)? onDuplicate}) {
|
||||||
int Function(E a, E b)? compare,
|
|
||||||
void Function(E a, E b)? onDuplicate,
|
|
||||||
}) {
|
|
||||||
compare ??= (E a, E b) => a == b ? 0 : 1;
|
compare ??= (E a, E b) => a == b ? 0 : 1;
|
||||||
int i = 1, j = 1;
|
int i = 1, j = 1;
|
||||||
for (; i < length; i++) {
|
for (; i < length; i++) {
|
||||||
|
|
@ -45,9 +42,7 @@ extension IntListExtension on Iterable<int> {
|
||||||
|
|
||||||
extension AssetListExtension on Iterable<Asset> {
|
extension AssetListExtension on Iterable<Asset> {
|
||||||
/// Returns the assets that are already available in the Immich server
|
/// Returns the assets that are already available in the Immich server
|
||||||
Iterable<Asset> remoteOnly({
|
Iterable<Asset> remoteOnly({void Function()? errorCallback}) {
|
||||||
void Function()? errorCallback,
|
|
||||||
}) {
|
|
||||||
final bool onlyRemote = every((e) => e.isRemote);
|
final bool onlyRemote = every((e) => e.isRemote);
|
||||||
if (!onlyRemote) {
|
if (!onlyRemote) {
|
||||||
if (errorCallback != null) errorCallback();
|
if (errorCallback != null) errorCallback();
|
||||||
|
|
@ -58,10 +53,7 @@ extension AssetListExtension on Iterable<Asset> {
|
||||||
|
|
||||||
/// Returns the assets that are owned by the user passed to the [owner] param
|
/// Returns the assets that are owned by the user passed to the [owner] param
|
||||||
/// If [owner] is null, an empty list is returned
|
/// If [owner] is null, an empty list is returned
|
||||||
Iterable<Asset> ownedOnly(
|
Iterable<Asset> ownedOnly(UserDto? owner, {void Function()? errorCallback}) {
|
||||||
UserDto? owner, {
|
|
||||||
void Function()? errorCallback,
|
|
||||||
}) {
|
|
||||||
if (owner == null) return [];
|
if (owner == null) return [];
|
||||||
final isarUserId = fastHash(owner.id);
|
final isarUserId = fastHash(owner.id);
|
||||||
final bool onlyOwned = every((e) => e.ownerId == isarUserId);
|
final bool onlyOwned = every((e) => e.ownerId == isarUserId);
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,7 @@ extension DateRangeFormatting on DateTime {
|
||||||
/// - Date range of this year: "Mar 23-May 31"
|
/// - Date range of this year: "Mar 23-May 31"
|
||||||
/// - Date range of other year: "Aug 28 - Sep 30, 2023"
|
/// - Date range of other year: "Aug 28 - Sep 30, 2023"
|
||||||
/// - Date range over multiple years: "Apr 17, 2021 - Apr 9, 2022"
|
/// - Date range over multiple years: "Apr 17, 2021 - Apr 9, 2022"
|
||||||
static String formatDateRange(
|
static String formatDateRange(DateTime startDate, DateTime endDate, Locale? locale) {
|
||||||
DateTime startDate,
|
|
||||||
DateTime endDate,
|
|
||||||
Locale? locale,
|
|
||||||
) {
|
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final currentYear = now.year;
|
final currentYear = now.year;
|
||||||
final localeString = locale?.toString() ?? 'en_US';
|
final localeString = locale?.toString() ?? 'en_US';
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,7 @@ extension MapMarkers on MapLibreMapController {
|
||||||
Future<void> addGeoJSONSourceForMarkers(List<MapMarker> markers) async {
|
Future<void> addGeoJSONSourceForMarkers(List<MapMarker> markers) async {
|
||||||
return addSource(
|
return addSource(
|
||||||
MapUtils.defaultSourceId,
|
MapUtils.defaultSourceId,
|
||||||
GeojsonSourceProperties(
|
GeojsonSourceProperties(data: MapUtils.generateGeoJsonForMarkers(markers.toList())),
|
||||||
data: MapUtils.generateGeoJsonForMarkers(markers.toList()),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,23 +71,13 @@ extension MapMarkers on MapLibreMapController {
|
||||||
try {
|
try {
|
||||||
final ByteData bytes = await rootBundle.load("assets/location-pin.png");
|
final ByteData bytes = await rootBundle.load("assets/location-pin.png");
|
||||||
await addImage("mapMarker", bytes.buffer.asUint8List());
|
await addImage("mapMarker", bytes.buffer.asUint8List());
|
||||||
return addSymbol(
|
return addSymbol(SymbolOptions(geometry: centre, iconImage: "mapMarker", iconSize: 0.15, iconAnchor: "bottom"));
|
||||||
SymbolOptions(
|
|
||||||
geometry: centre,
|
|
||||||
iconImage: "mapMarker",
|
|
||||||
iconSize: 0.15,
|
|
||||||
iconAnchor: "bottom",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<LatLngBounds> getBoundsFromPoint(
|
Future<LatLngBounds> getBoundsFromPoint(Point<double> point, double distance) async {
|
||||||
Point<double> point,
|
|
||||||
double distance,
|
|
||||||
) async {
|
|
||||||
final southWestPx = Point(point.x - distance, point.y + distance);
|
final southWestPx = Point(point.x - distance, point.y + distance);
|
||||||
final northEastPx = Point(point.x + distance, point.y - distance);
|
final northEastPx = Point(point.x + distance, point.y - distance);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,7 @@ class FastScrollPhysics extends ScrollPhysics {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SpringDescription get spring => const SpringDescription(
|
SpringDescription get spring => const SpringDescription(mass: 1, stiffness: 402.49984375, damping: 40);
|
||||||
mass: 1,
|
|
||||||
stiffness: 402.49984375,
|
|
||||||
damping: 40,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FastClampingScrollPhysics extends ClampingScrollPhysics {
|
class FastClampingScrollPhysics extends ClampingScrollPhysics {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
extension StringExtension on String {
|
extension StringExtension on String {
|
||||||
String capitalize() {
|
String capitalize() {
|
||||||
return split(" ")
|
return split(" ").map((str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1)).join(" ");
|
||||||
.map(
|
|
||||||
(str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1),
|
|
||||||
)
|
|
||||||
.join(" ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,10 @@ extension ImmichColorSchemeExtensions on ColorScheme {
|
||||||
|
|
||||||
extension ColorExtensions on Color {
|
extension ColorExtensions on Color {
|
||||||
Color lighten({double amount = 0.1}) {
|
Color lighten({double amount = 0.1}) {
|
||||||
return Color.alphaBlend(
|
return Color.alphaBlend(Colors.white.withValues(alpha: amount), this);
|
||||||
Colors.white.withValues(alpha: amount),
|
|
||||||
this,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Color darken({double amount = 0.1}) {
|
Color darken({double amount = 0.1}) {
|
||||||
return Color.alphaBlend(
|
return Color.alphaBlend(Colors.black.withValues(alpha: amount), this);
|
||||||
Colors.black.withValues(alpha: amount),
|
|
||||||
this,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,7 @@ extension TextTranslateExtension on Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _translateHelper(
|
String _translateHelper(BuildContext? context, String key, [Map<String, Object>? args]) {
|
||||||
BuildContext? context,
|
|
||||||
String key, [
|
|
||||||
Map<String, Object>? args,
|
|
||||||
]) {
|
|
||||||
if (key.isEmpty) {
|
if (key.isEmpty) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -16,21 +16,10 @@ class DeviceAssetEntity {
|
||||||
final List<byte> hash;
|
final List<byte> hash;
|
||||||
final DateTime modifiedTime;
|
final DateTime modifiedTime;
|
||||||
|
|
||||||
const DeviceAssetEntity({
|
const DeviceAssetEntity({required this.assetId, required this.hash, required this.modifiedTime});
|
||||||
required this.assetId,
|
|
||||||
required this.hash,
|
|
||||||
required this.modifiedTime,
|
|
||||||
});
|
|
||||||
|
|
||||||
DeviceAsset toModel() => DeviceAsset(
|
DeviceAsset toModel() => DeviceAsset(assetId: assetId, hash: Uint8List.fromList(hash), modifiedTime: modifiedTime);
|
||||||
assetId: assetId,
|
|
||||||
hash: Uint8List.fromList(hash),
|
|
||||||
modifiedTime: modifiedTime,
|
|
||||||
);
|
|
||||||
|
|
||||||
static DeviceAssetEntity fromDto(DeviceAsset dto) => DeviceAssetEntity(
|
static DeviceAssetEntity fromDto(DeviceAsset dto) =>
|
||||||
assetId: dto.assetId,
|
DeviceAssetEntity(assetId: dto.assetId, hash: dto.hash, modifiedTime: dto.modifiedTime);
|
||||||
hash: dto.hash,
|
|
||||||
modifiedTime: dto.modifiedTime,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
BIN
mobile/lib/infrastructure/entities/exif.entity.g.dart
generated
BIN
mobile/lib/infrastructure/entities/exif.entity.g.dart
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mobile/lib/infrastructure/entities/log.entity.g.dart
generated
BIN
mobile/lib/infrastructure/entities/log.entity.g.dart
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -5,11 +5,7 @@ import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
@TableIndex(
|
@TableIndex(name: 'UQ_remote_asset_owner_checksum', columns: {#checksum, #ownerId}, unique: true)
|
||||||
name: 'UQ_remote_asset_owner_checksum',
|
|
||||||
columns: {#checksum, #ownerId},
|
|
||||||
unique: true,
|
|
||||||
)
|
|
||||||
@TableIndex(name: 'idx_remote_asset_checksum', columns: {#checksum})
|
@TableIndex(name: 'idx_remote_asset_checksum', columns: {#checksum})
|
||||||
class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
|
class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
|
||||||
const RemoteAssetEntity();
|
const RemoteAssetEntity();
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
BIN
mobile/lib/infrastructure/entities/store.entity.g.dart
generated
BIN
mobile/lib/infrastructure/entities/store.entity.g.dart
generated
Binary file not shown.
Binary file not shown.
BIN
mobile/lib/infrastructure/entities/user.entity.g.dart
generated
BIN
mobile/lib/infrastructure/entities/user.entity.g.dart
generated
Binary file not shown.
Binary file not shown.
|
|
@ -6,12 +6,7 @@ import 'package:photo_manager/photo_manager.dart';
|
||||||
class AssetMediaRepository {
|
class AssetMediaRepository {
|
||||||
const AssetMediaRepository();
|
const AssetMediaRepository();
|
||||||
|
|
||||||
Future<Uint8List?> getThumbnail(
|
Future<Uint8List?> getThumbnail(String id, {int quality = 80, Size size = const Size.square(256)}) => AssetEntity(
|
||||||
String id, {
|
|
||||||
int quality = 80,
|
|
||||||
Size size = const Size.square(256),
|
|
||||||
}) =>
|
|
||||||
AssetEntity(
|
|
||||||
id: id,
|
id: id,
|
||||||
// The below fields are not used in thumbnailDataWithSize but are required
|
// The below fields are not used in thumbnailDataWithSize but are required
|
||||||
// to create an AssetEntity instance. It is faster to create a dummy AssetEntity
|
// to create an AssetEntity instance. It is faster to create a dummy AssetEntity
|
||||||
|
|
@ -19,8 +14,5 @@ class AssetMediaRepository {
|
||||||
typeInt: AssetType.image.index,
|
typeInt: AssetType.image.index,
|
||||||
width: size.width.toInt(),
|
width: size.width.toInt(),
|
||||||
height: size.height.toInt(),
|
height: size.height.toInt(),
|
||||||
).thumbnailDataWithSize(
|
).thumbnailDataWithSize(ThumbnailSize(size.width.toInt(), size.height.toInt()), quality: quality);
|
||||||
ThumbnailSize(size.width.toInt(), size.height.toInt()),
|
|
||||||
quality: quality,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,7 @@ class DriftBackupRepository extends DriftDatabaseRepository {
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
..where(
|
..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.excluded));
|
||||||
_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.excluded),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> getTotalCount() async {
|
Future<int> getTotalCount() async {
|
||||||
|
|
@ -79,9 +77,7 @@ class DriftBackupRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<int> getBackupCount(String userId) async {
|
Future<int> getBackupCount(String userId) async {
|
||||||
final query = _db.localAlbumAssetEntity.selectOnly(distinct: true)
|
final query = _db.localAlbumAssetEntity.selectOnly(distinct: true)
|
||||||
..addColumns(
|
..addColumns([_db.localAlbumAssetEntity.assetId])
|
||||||
[_db.localAlbumAssetEntity.assetId],
|
|
||||||
)
|
|
||||||
..join([
|
..join([
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.localAlbumEntity,
|
_db.localAlbumEntity,
|
||||||
|
|
@ -112,9 +108,7 @@ class DriftBackupRepository extends DriftDatabaseRepository {
|
||||||
Future<List<LocalAsset>> getCandidates(String userId) async {
|
Future<List<LocalAsset>> getCandidates(String userId) async {
|
||||||
final selectedAlbumIds = _db.localAlbumEntity.selectOnly(distinct: true)
|
final selectedAlbumIds = _db.localAlbumEntity.selectOnly(distinct: true)
|
||||||
..addColumns([_db.localAlbumEntity.id])
|
..addColumns([_db.localAlbumEntity.id])
|
||||||
..where(
|
..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected));
|
||||||
_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected),
|
|
||||||
);
|
|
||||||
|
|
||||||
final query = _db.localAssetEntity.select()
|
final query = _db.localAssetEntity.select()
|
||||||
..where(
|
..where(
|
||||||
|
|
@ -138,11 +132,7 @@ class DriftBackupRepository extends DriftDatabaseRepository {
|
||||||
) &
|
) &
|
||||||
lae.id.isNotInQuery(_getExcludedSubquery()),
|
lae.id.isNotInQuery(_getExcludedSubquery()),
|
||||||
)
|
)
|
||||||
..orderBy(
|
..orderBy([(localAsset) => OrderingTerm.desc(localAsset.createdAt)]);
|
||||||
[
|
|
||||||
(localAsset) => OrderingTerm.desc(localAsset.createdAt),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
return query.map((localAsset) => localAsset.toDto()).get();
|
return query.map((localAsset) => localAsset.toDto()).get();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,19 +59,11 @@ class IsarDatabaseRepository implements IDatabaseRepository {
|
||||||
PersonEntity,
|
PersonEntity,
|
||||||
AssetFaceEntity,
|
AssetFaceEntity,
|
||||||
],
|
],
|
||||||
include: {
|
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
||||||
'package:immich_mobile/infrastructure/entities/merged_asset.drift',
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
class Drift extends $Drift implements IDatabaseRepository {
|
class Drift extends $Drift implements IDatabaseRepository {
|
||||||
Drift([QueryExecutor? executor])
|
Drift([QueryExecutor? executor])
|
||||||
: super(
|
: super(executor ?? driftDatabase(name: 'immich', native: const DriftNativeOptions(shareAcrossIsolates: true)));
|
||||||
executor ??
|
|
||||||
driftDatabase(
|
|
||||||
name: 'immich',
|
|
||||||
native: const DriftNativeOptions(shareAcrossIsolates: true),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 4;
|
int get schemaVersion => 4;
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -33,9 +33,7 @@ class IsarExifRepository extends IsarDatabaseRepository {
|
||||||
|
|
||||||
Future<List<ExifInfo>> updateAll(List<ExifInfo> exifInfos) {
|
Future<List<ExifInfo>> updateAll(List<ExifInfo> exifInfos) {
|
||||||
return transaction(() async {
|
return transaction(() async {
|
||||||
await _db.exifInfos.putAll(
|
await _db.exifInfos.putAll(exifInfos.map(entity.ExifInfo.fromDto).toList());
|
||||||
exifInfos.map(entity.ExifInfo.fromDto).toList(),
|
|
||||||
);
|
|
||||||
return exifInfos;
|
return exifInfos;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,24 +34,18 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
if (sortBy.isNotEmpty) {
|
if (sortBy.isNotEmpty) {
|
||||||
final orderings = <OrderingTerm>[];
|
final orderings = <OrderingTerm>[];
|
||||||
for (final sort in sortBy) {
|
for (final sort in sortBy) {
|
||||||
orderings.add(
|
orderings.add(switch (sort) {
|
||||||
switch (sort) {
|
|
||||||
SortLocalAlbumsBy.id => OrderingTerm.asc(_db.localAlbumEntity.id),
|
SortLocalAlbumsBy.id => OrderingTerm.asc(_db.localAlbumEntity.id),
|
||||||
SortLocalAlbumsBy.backupSelection => OrderingTerm.asc(_db.localAlbumEntity.backupSelection),
|
SortLocalAlbumsBy.backupSelection => OrderingTerm.asc(_db.localAlbumEntity.backupSelection),
|
||||||
SortLocalAlbumsBy.isIosSharedAlbum => OrderingTerm.asc(_db.localAlbumEntity.isIosSharedAlbum),
|
SortLocalAlbumsBy.isIosSharedAlbum => OrderingTerm.asc(_db.localAlbumEntity.isIosSharedAlbum),
|
||||||
SortLocalAlbumsBy.name => OrderingTerm.asc(_db.localAlbumEntity.name),
|
SortLocalAlbumsBy.name => OrderingTerm.asc(_db.localAlbumEntity.name),
|
||||||
SortLocalAlbumsBy.assetCount => OrderingTerm.desc(assetCount),
|
SortLocalAlbumsBy.assetCount => OrderingTerm.desc(assetCount),
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
query.orderBy(orderings);
|
query.orderBy(orderings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query
|
return query.map((row) => row.readTable(_db.localAlbumEntity).toDto(assetCount: row.read(assetCount) ?? 0)).get();
|
||||||
.map(
|
|
||||||
(row) => row.readTable(_db.localAlbumEntity).toDto(assetCount: row.read(assetCount) ?? 0),
|
|
||||||
)
|
|
||||||
.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> delete(String albumId) => transaction(() async {
|
Future<void> delete(String albumId) => transaction(() async {
|
||||||
|
|
@ -65,10 +59,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
await _db.managers.localAlbumEntity.filter((a) => a.id.equals(albumId)).delete();
|
await _db.managers.localAlbumEntity.filter((a) => a.id.equals(albumId)).delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<void> syncDeletes(
|
Future<void> syncDeletes(String albumId, Iterable<String> assetIdsToKeep) async {
|
||||||
String albumId,
|
|
||||||
Iterable<String> assetIdsToKeep,
|
|
||||||
) async {
|
|
||||||
if (assetIdsToKeep.isEmpty) {
|
if (assetIdsToKeep.isEmpty) {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
|
|
@ -77,12 +68,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
deleteSmt.where((localAsset) {
|
deleteSmt.where((localAsset) {
|
||||||
final subQuery = _db.localAlbumAssetEntity.selectOnly()
|
final subQuery = _db.localAlbumAssetEntity.selectOnly()
|
||||||
..addColumns([_db.localAlbumAssetEntity.assetId])
|
..addColumns([_db.localAlbumAssetEntity.assetId])
|
||||||
..join([
|
..join([innerJoin(_db.localAlbumEntity, _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id))]);
|
||||||
innerJoin(
|
|
||||||
_db.localAlbumEntity,
|
|
||||||
_db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
subQuery.where(
|
subQuery.where(
|
||||||
_db.localAlbumEntity.id.equals(albumId) & _db.localAlbumAssetEntity.assetId.isNotIn(assetIdsToKeep),
|
_db.localAlbumEntity.id.equals(albumId) & _db.localAlbumAssetEntity.assetId.isNotIn(assetIdsToKeep),
|
||||||
);
|
);
|
||||||
|
|
@ -109,12 +95,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
if (toUpsert.isNotEmpty) {
|
if (toUpsert.isNotEmpty) {
|
||||||
await _upsertAssets(toUpsert);
|
await _upsertAssets(toUpsert);
|
||||||
await _db.localAlbumAssetEntity.insertAll(
|
await _db.localAlbumAssetEntity.insertAll(
|
||||||
toUpsert.map(
|
toUpsert.map((a) => LocalAlbumAssetEntityCompanion.insert(assetId: a.id, albumId: localAlbum.id)),
|
||||||
(a) => LocalAlbumAssetEntityCompanion.insert(
|
|
||||||
assetId: a.id,
|
|
||||||
albumId: localAlbum.id,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
mode: InsertMode.insertOrIgnore,
|
mode: InsertMode.insertOrIgnore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -162,10 +143,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
final subQuery = _db.localAlbumAssetEntity.selectOnly()
|
final subQuery = _db.localAlbumAssetEntity.selectOnly()
|
||||||
..addColumns([_db.localAlbumAssetEntity.assetId])
|
..addColumns([_db.localAlbumAssetEntity.assetId])
|
||||||
..join([
|
..join([
|
||||||
innerJoin(
|
innerJoin(_db.localAlbumEntity, _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id)),
|
||||||
_db.localAlbumEntity,
|
|
||||||
_db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id),
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
subQuery.where(_db.localAlbumEntity.marker_.isNotNull());
|
subQuery.where(_db.localAlbumEntity.marker_.isNotNull());
|
||||||
return localAsset.id.isInQuery(subQuery);
|
return localAsset.id.isInQuery(subQuery);
|
||||||
|
|
@ -178,14 +156,10 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocalAsset>> getAssets(String albumId) {
|
Future<List<LocalAsset>> getAssets(String albumId) {
|
||||||
final query = _db.localAlbumAssetEntity.select().join(
|
final query =
|
||||||
[
|
_db.localAlbumAssetEntity.select().join([
|
||||||
innerJoin(
|
innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)),
|
||||||
_db.localAssetEntity,
|
])
|
||||||
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
..where(_db.localAlbumAssetEntity.albumId.equals(albumId))
|
..where(_db.localAlbumAssetEntity.albumId.equals(albumId))
|
||||||
..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]);
|
..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]);
|
||||||
return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get();
|
return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get();
|
||||||
|
|
@ -224,10 +198,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
batch.insertAll(
|
batch.insertAll(
|
||||||
_db.localAlbumAssetEntity,
|
_db.localAlbumAssetEntity,
|
||||||
albumIds.cast<String?>().nonNulls.map(
|
albumIds.cast<String?>().nonNulls.map(
|
||||||
(albumId) => LocalAlbumAssetEntityCompanion.insert(
|
(albumId) => LocalAlbumAssetEntityCompanion.insert(assetId: assetId, albumId: albumId),
|
||||||
assetId: assetId,
|
|
||||||
albumId: albumId,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
onConflict: DoNothing(),
|
onConflict: DoNothing(),
|
||||||
);
|
);
|
||||||
|
|
@ -237,17 +208,11 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocalAsset>> getAssetsToHash(String albumId) {
|
Future<List<LocalAsset>> getAssetsToHash(String albumId) {
|
||||||
final query = _db.localAlbumAssetEntity.select().join(
|
final query =
|
||||||
[
|
_db.localAlbumAssetEntity.select().join([
|
||||||
innerJoin(
|
innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)),
|
||||||
_db.localAssetEntity,
|
])
|
||||||
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
..where(_db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAssetEntity.checksum.isNull())
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
..where(
|
|
||||||
_db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAssetEntity.checksum.isNull(),
|
|
||||||
)
|
|
||||||
..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]);
|
..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]);
|
||||||
|
|
||||||
return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get();
|
return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get();
|
||||||
|
|
@ -275,10 +240,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
batch.insert<$LocalAssetEntityTable, LocalAssetEntityData>(
|
batch.insert<$LocalAssetEntityTable, LocalAssetEntityData>(
|
||||||
_db.localAssetEntity,
|
_db.localAssetEntity,
|
||||||
companion,
|
companion,
|
||||||
onConflict: DoUpdate(
|
onConflict: DoUpdate((_) => companion, where: (old) => old.updatedAt.isNotValue(asset.updatedAt)),
|
||||||
(_) => companion,
|
|
||||||
where: (old) => old.updatedAt.isNotValue(asset.updatedAt),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -351,11 +313,9 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<LocalAsset?> getThumbnail(String albumId) async {
|
Future<LocalAsset?> getThumbnail(String albumId) async {
|
||||||
final query = _db.localAlbumAssetEntity.select().join([
|
final query =
|
||||||
innerJoin(
|
_db.localAlbumAssetEntity.select().join([
|
||||||
_db.localAssetEntity,
|
innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)),
|
||||||
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
..where(_db.localAlbumAssetEntity.albumId.equals(albumId))
|
..where(_db.localAlbumAssetEntity.albumId.equals(albumId))
|
||||||
..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)])
|
..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)])
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,11 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
_db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum),
|
_db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
])
|
])..where(_db.localAssetEntity.id.equals(id));
|
||||||
..where(_db.localAssetEntity.id.equals(id));
|
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final asset = row.readTable(_db.localAssetEntity).toDto();
|
final asset = row.readTable(_db.localAssetEntity).toDto();
|
||||||
return asset.copyWith(
|
return asset.copyWith(remoteId: row.read(_db.remoteAssetEntity.id));
|
||||||
remoteId: row.read(_db.remoteAssetEntity.id),
|
|
||||||
);
|
|
||||||
}).watchSingleOrNull();
|
}).watchSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,9 @@ class DriftMemoryRepository extends DriftDatabaseRepository {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final localUtc = DateTime.utc(now.year, now.month, now.day, 0, 0, 0);
|
final localUtc = DateTime.utc(now.year, now.month, now.day, 0, 0, 0);
|
||||||
|
|
||||||
final query = _db.select(_db.memoryEntity).join([
|
final query =
|
||||||
leftOuterJoin(
|
_db.select(_db.memoryEntity).join([
|
||||||
_db.memoryAssetEntity,
|
leftOuterJoin(_db.memoryAssetEntity, _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id)),
|
||||||
_db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id),
|
|
||||||
),
|
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.remoteAssetEntity,
|
_db.remoteAssetEntity,
|
||||||
_db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) &
|
_db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) &
|
||||||
|
|
@ -27,16 +25,9 @@ class DriftMemoryRepository extends DriftDatabaseRepository {
|
||||||
])
|
])
|
||||||
..where(_db.memoryEntity.ownerId.equals(ownerId))
|
..where(_db.memoryEntity.ownerId.equals(ownerId))
|
||||||
..where(_db.memoryEntity.deletedAt.isNull())
|
..where(_db.memoryEntity.deletedAt.isNull())
|
||||||
..where(
|
..where(_db.memoryEntity.showAt.isSmallerOrEqualValue(localUtc))
|
||||||
_db.memoryEntity.showAt.isSmallerOrEqualValue(localUtc),
|
..where(_db.memoryEntity.hideAt.isBiggerOrEqualValue(localUtc))
|
||||||
)
|
..orderBy([OrderingTerm.desc(_db.memoryEntity.memoryAt), OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]);
|
||||||
..where(
|
|
||||||
_db.memoryEntity.hideAt.isBiggerOrEqualValue(localUtc),
|
|
||||||
)
|
|
||||||
..orderBy([
|
|
||||||
OrderingTerm.desc(_db.memoryEntity.memoryAt),
|
|
||||||
OrderingTerm.asc(_db.remoteAssetEntity.createdAt),
|
|
||||||
]);
|
|
||||||
|
|
||||||
final rows = await query.get();
|
final rows = await query.get();
|
||||||
|
|
||||||
|
|
@ -59,11 +50,9 @@ class DriftMemoryRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DriftMemory?> get(String memoryId) async {
|
Future<DriftMemory?> get(String memoryId) async {
|
||||||
final query = _db.select(_db.memoryEntity).join([
|
final query =
|
||||||
leftOuterJoin(
|
_db.select(_db.memoryEntity).join([
|
||||||
_db.memoryAssetEntity,
|
leftOuterJoin(_db.memoryAssetEntity, _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id)),
|
||||||
_db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id),
|
|
||||||
),
|
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.remoteAssetEntity,
|
_db.remoteAssetEntity,
|
||||||
_db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) &
|
_db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) &
|
||||||
|
|
@ -73,10 +62,7 @@ class DriftMemoryRepository extends DriftDatabaseRepository {
|
||||||
])
|
])
|
||||||
..where(_db.memoryEntity.id.equals(memoryId))
|
..where(_db.memoryEntity.id.equals(memoryId))
|
||||||
..where(_db.memoryEntity.deletedAt.isNull())
|
..where(_db.memoryEntity.deletedAt.isNull())
|
||||||
..orderBy([
|
..orderBy([OrderingTerm.desc(_db.memoryEntity.memoryAt), OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]);
|
||||||
OrderingTerm.desc(_db.memoryEntity.memoryAt),
|
|
||||||
OrderingTerm.asc(_db.remoteAssetEntity.createdAt),
|
|
||||||
]);
|
|
||||||
|
|
||||||
final rows = await query.get();
|
final rows = await query.get();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,13 @@ class DriftPartnerRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<List<PartnerUserDto>> getPartners(String userId) {
|
Future<List<PartnerUserDto>> getPartners(String userId) {
|
||||||
final query = _db.select(_db.partnerEntity).join([
|
final query = _db.select(_db.partnerEntity).join([
|
||||||
innerJoin(
|
innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)),
|
||||||
_db.userEntity,
|
])..where(_db.partnerEntity.sharedWithId.equals(userId));
|
||||||
_db.userEntity.id.equalsExp(_db.partnerEntity.sharedById),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
..where(
|
|
||||||
_db.partnerEntity.sharedWithId.equals(userId),
|
|
||||||
);
|
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final user = row.readTable(_db.userEntity);
|
final user = row.readTable(_db.userEntity);
|
||||||
final partner = row.readTable(_db.partnerEntity);
|
final partner = row.readTable(_db.partnerEntity);
|
||||||
return PartnerUserDto(
|
return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline);
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
inTimeline: partner.inTimeline,
|
|
||||||
);
|
|
||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,60 +24,33 @@ class DriftPartnerRepository extends DriftDatabaseRepository {
|
||||||
final query = _db.select(_db.userEntity)..where((row) => row.id.equals(currentUserId).not());
|
final query = _db.select(_db.userEntity)..where((row) => row.id.equals(currentUserId).not());
|
||||||
|
|
||||||
return query.map((user) {
|
return query.map((user) {
|
||||||
return PartnerUserDto(
|
return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: false);
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
inTimeline: false,
|
|
||||||
);
|
|
||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get users who are sharing their photos WITH the current user
|
// Get users who are sharing their photos WITH the current user
|
||||||
Future<List<PartnerUserDto>> getSharedWith(String partnerId) {
|
Future<List<PartnerUserDto>> getSharedWith(String partnerId) {
|
||||||
final query = _db.select(_db.partnerEntity).join([
|
final query = _db.select(_db.partnerEntity).join([
|
||||||
innerJoin(
|
innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)),
|
||||||
_db.userEntity,
|
])..where(_db.partnerEntity.sharedWithId.equals(partnerId));
|
||||||
_db.userEntity.id.equalsExp(_db.partnerEntity.sharedById),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
..where(
|
|
||||||
_db.partnerEntity.sharedWithId.equals(partnerId),
|
|
||||||
);
|
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final user = row.readTable(_db.userEntity);
|
final user = row.readTable(_db.userEntity);
|
||||||
final partner = row.readTable(_db.partnerEntity);
|
final partner = row.readTable(_db.partnerEntity);
|
||||||
return PartnerUserDto(
|
return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline);
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
inTimeline: partner.inTimeline,
|
|
||||||
);
|
|
||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get users who the current user is sharing their photos TO
|
// Get users who the current user is sharing their photos TO
|
||||||
Future<List<PartnerUserDto>> getSharedBy(String userId) {
|
Future<List<PartnerUserDto>> getSharedBy(String userId) {
|
||||||
final query = _db.select(_db.partnerEntity).join([
|
final query = _db.select(_db.partnerEntity).join([
|
||||||
innerJoin(
|
innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedWithId)),
|
||||||
_db.userEntity,
|
])..where(_db.partnerEntity.sharedById.equals(userId));
|
||||||
_db.userEntity.id.equalsExp(_db.partnerEntity.sharedWithId),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
..where(
|
|
||||||
_db.partnerEntity.sharedById.equals(userId),
|
|
||||||
);
|
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final user = row.readTable(_db.userEntity);
|
final user = row.readTable(_db.userEntity);
|
||||||
final partner = row.readTable(_db.partnerEntity);
|
final partner = row.readTable(_db.partnerEntity);
|
||||||
return PartnerUserDto(
|
return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline);
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
inTimeline: partner.inTimeline,
|
|
||||||
);
|
|
||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,24 +70,13 @@ class DriftPartnerRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<PartnerUserDto?> getPartner(String partnerId, String userId) {
|
Future<PartnerUserDto?> getPartner(String partnerId, String userId) {
|
||||||
final query = _db.select(_db.partnerEntity).join([
|
final query = _db.select(_db.partnerEntity).join([
|
||||||
innerJoin(
|
innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)),
|
||||||
_db.userEntity,
|
])..where(_db.partnerEntity.sharedById.equals(partnerId) & _db.partnerEntity.sharedWithId.equals(userId));
|
||||||
_db.userEntity.id.equalsExp(_db.partnerEntity.sharedById),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
..where(
|
|
||||||
_db.partnerEntity.sharedById.equals(partnerId) & _db.partnerEntity.sharedWithId.equals(userId),
|
|
||||||
);
|
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final user = row.readTable(_db.userEntity);
|
final user = row.readTable(_db.userEntity);
|
||||||
final partner = row.readTable(_db.partnerEntity);
|
final partner = row.readTable(_db.partnerEntity);
|
||||||
return PartnerUserDto(
|
return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline);
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
inTimeline: partner.inTimeline,
|
|
||||||
);
|
|
||||||
}).getSingleOrNull();
|
}).getSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,8 +101,6 @@ class DriftPartnerRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> delete(String partnerId, String userId) {
|
Future<void> delete(String partnerId, String userId) {
|
||||||
return _db.partnerEntity.deleteWhere(
|
return _db.partnerEntity.deleteWhere((t) => t.sharedById.equals(userId) & t.sharedWithId.equals(partnerId));
|
||||||
(t) => t.sharedById.equals(userId) & t.sharedWithId.equals(partnerId),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
const DriftRemoteAlbumRepository(this._db) : super(_db);
|
const DriftRemoteAlbumRepository(this._db) : super(_db);
|
||||||
|
|
||||||
Future<List<RemoteAlbum>> getAll({
|
Future<List<RemoteAlbum>> getAll({Set<SortRemoteAlbumsBy> sortBy = const {SortRemoteAlbumsBy.updatedAt}}) {
|
||||||
Set<SortRemoteAlbumsBy> sortBy = const {SortRemoteAlbumsBy.updatedAt},
|
|
||||||
}) {
|
|
||||||
final assetCount = _db.remoteAlbumAssetEntity.assetId.count();
|
final assetCount = _db.remoteAlbumAssetEntity.assetId.count();
|
||||||
|
|
||||||
final query = _db.remoteAlbumEntity.select().join([
|
final query = _db.remoteAlbumEntity.select().join([
|
||||||
|
|
@ -32,11 +30,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
_db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId),
|
_db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
leftOuterJoin(
|
leftOuterJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), useColumns: false),
|
||||||
_db.userEntity,
|
|
||||||
_db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId),
|
|
||||||
useColumns: false,
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
query
|
query
|
||||||
..where(_db.remoteAssetEntity.deletedAt.isNull())
|
..where(_db.remoteAssetEntity.deletedAt.isNull())
|
||||||
|
|
@ -47,22 +41,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
if (sortBy.isNotEmpty) {
|
if (sortBy.isNotEmpty) {
|
||||||
final orderings = <OrderingTerm>[];
|
final orderings = <OrderingTerm>[];
|
||||||
for (final sort in sortBy) {
|
for (final sort in sortBy) {
|
||||||
orderings.add(
|
orderings.add(switch (sort) {
|
||||||
switch (sort) {
|
|
||||||
SortRemoteAlbumsBy.id => OrderingTerm.asc(_db.remoteAlbumEntity.id),
|
SortRemoteAlbumsBy.id => OrderingTerm.asc(_db.remoteAlbumEntity.id),
|
||||||
SortRemoteAlbumsBy.updatedAt => OrderingTerm.desc(_db.remoteAlbumEntity.updatedAt),
|
SortRemoteAlbumsBy.updatedAt => OrderingTerm.desc(_db.remoteAlbumEntity.updatedAt),
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
query.orderBy(orderings);
|
query.orderBy(orderings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query
|
return query
|
||||||
.map(
|
.map(
|
||||||
(row) => row.readTable(_db.remoteAlbumEntity).toDto(
|
(row) => row
|
||||||
assetCount: row.read(assetCount) ?? 0,
|
.readTable(_db.remoteAlbumEntity)
|
||||||
ownerName: row.read(_db.userEntity.name)!,
|
.toDto(assetCount: row.read(assetCount) ?? 0, ownerName: row.read(_db.userEntity.name)!),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +61,8 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
Future<RemoteAlbum?> get(String albumId) {
|
Future<RemoteAlbum?> get(String albumId) {
|
||||||
final assetCount = _db.remoteAlbumAssetEntity.assetId.count();
|
final assetCount = _db.remoteAlbumAssetEntity.assetId.count();
|
||||||
|
|
||||||
final query = _db.remoteAlbumEntity.select().join([
|
final query =
|
||||||
|
_db.remoteAlbumEntity.select().join([
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.remoteAlbumAssetEntity,
|
_db.remoteAlbumAssetEntity,
|
||||||
_db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
|
_db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
|
||||||
|
|
@ -94,18 +86,14 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
return query
|
return query
|
||||||
.map(
|
.map(
|
||||||
(row) => row.readTable(_db.remoteAlbumEntity).toDto(
|
(row) => row
|
||||||
assetCount: row.read(assetCount) ?? 0,
|
.readTable(_db.remoteAlbumEntity)
|
||||||
ownerName: row.read(_db.userEntity.name)!,
|
.toDto(assetCount: row.read(assetCount) ?? 0, ownerName: row.read(_db.userEntity.name)!),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> create(
|
Future<void> create(RemoteAlbum album, List<String> assetIds) async {
|
||||||
RemoteAlbum album,
|
|
||||||
List<String> assetIds,
|
|
||||||
) async {
|
|
||||||
await _db.transaction(() async {
|
await _db.transaction(() async {
|
||||||
final entity = RemoteAlbumEntityCompanion(
|
final entity = RemoteAlbumEntityCompanion(
|
||||||
id: Value(album.id),
|
id: Value(album.id),
|
||||||
|
|
@ -123,17 +111,11 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
if (assetIds.isNotEmpty) {
|
if (assetIds.isNotEmpty) {
|
||||||
final albumAssets = assetIds.map(
|
final albumAssets = assetIds.map(
|
||||||
(assetId) => RemoteAlbumAssetEntityCompanion(
|
(assetId) => RemoteAlbumAssetEntityCompanion(albumId: Value(album.id), assetId: Value(assetId)),
|
||||||
albumId: Value(album.id),
|
|
||||||
assetId: Value(assetId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
batch.insertAll(
|
batch.insertAll(_db.remoteAlbumAssetEntity, albumAssets);
|
||||||
_db.remoteAlbumAssetEntity,
|
|
||||||
albumAssets,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -156,23 +138,15 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> removeAssets(String albumId, List<String> assetIds) {
|
Future<int> removeAssets(String albumId, List<String> assetIds) {
|
||||||
return _db.remoteAlbumAssetEntity.deleteWhere(
|
return _db.remoteAlbumAssetEntity.deleteWhere((tbl) => tbl.albumId.equals(albumId) & tbl.assetId.isIn(assetIds));
|
||||||
(tbl) => tbl.albumId.equals(albumId) & tbl.assetId.isIn(assetIds),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<(DateTime, DateTime)> getDateRange(String albumId) {
|
FutureOr<(DateTime, DateTime)> getDateRange(String albumId) {
|
||||||
final query = _db.remoteAlbumAssetEntity.selectOnly()
|
final query = _db.remoteAlbumAssetEntity.selectOnly()
|
||||||
..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId))
|
..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId))
|
||||||
..addColumns([
|
..addColumns([_db.remoteAssetEntity.createdAt.min(), _db.remoteAssetEntity.createdAt.max()])
|
||||||
_db.remoteAssetEntity.createdAt.min(),
|
|
||||||
_db.remoteAssetEntity.createdAt.max(),
|
|
||||||
])
|
|
||||||
..join([
|
..join([
|
||||||
innerJoin(
|
innerJoin(_db.remoteAssetEntity, _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId)),
|
||||||
_db.remoteAssetEntity,
|
|
||||||
_db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId),
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
|
|
@ -183,8 +157,9 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<UserDto>> getSharedUsers(String albumId) async {
|
Future<List<UserDto>> getSharedUsers(String albumId) async {
|
||||||
final albumUserRows =
|
final albumUserRows = await (_db.select(
|
||||||
await (_db.select(_db.remoteAlbumUserEntity)..where((row) => row.albumId.equals(albumId))).get();
|
_db.remoteAlbumUserEntity,
|
||||||
|
)..where((row) => row.albumId.equals(albumId))).get();
|
||||||
|
|
||||||
if (albumUserRows.isEmpty) {
|
if (albumUserRows.isEmpty) {
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -214,29 +189,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<List<RemoteAsset>> getAssets(String albumId) {
|
Future<List<RemoteAsset>> getAssets(String albumId) {
|
||||||
final query = _db.remoteAlbumAssetEntity.select().join([
|
final query = _db.remoteAlbumAssetEntity.select().join([
|
||||||
innerJoin(
|
innerJoin(_db.remoteAssetEntity, _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId)),
|
||||||
_db.remoteAssetEntity,
|
])..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId));
|
||||||
_db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId));
|
|
||||||
|
|
||||||
return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get();
|
return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> addAssets(String albumId, List<String> assetIds) async {
|
Future<int> addAssets(String albumId, List<String> assetIds) async {
|
||||||
final albumAssets = assetIds.map(
|
final albumAssets = assetIds.map(
|
||||||
(assetId) => RemoteAlbumAssetEntityCompanion(
|
(assetId) => RemoteAlbumAssetEntityCompanion(albumId: Value(albumId), assetId: Value(assetId)),
|
||||||
albumId: Value(albumId),
|
|
||||||
assetId: Value(assetId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
batch.insertAll(
|
batch.insertAll(_db.remoteAlbumAssetEntity, albumAssets);
|
||||||
_db.remoteAlbumAssetEntity,
|
|
||||||
albumAssets,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return assetIds.length;
|
return assetIds.length;
|
||||||
|
|
@ -252,23 +217,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
);
|
);
|
||||||
|
|
||||||
return _db.batch((batch) {
|
return _db.batch((batch) {
|
||||||
batch.insertAll(
|
batch.insertAll(_db.remoteAlbumUserEntity, albumUsers);
|
||||||
_db.remoteAlbumUserEntity,
|
|
||||||
albumUsers,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteAlbum(String albumId) async {
|
Future<void> deleteAlbum(String albumId) async {
|
||||||
return _db.transaction(() async {
|
return _db.transaction(() async {
|
||||||
await _db.remoteAlbumEntity.deleteWhere(
|
await _db.remoteAlbumEntity.deleteWhere((table) => table.id.equals(albumId));
|
||||||
(table) => table.id.equals(albumId),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<RemoteAlbum?> watchAlbum(String albumId) {
|
Stream<RemoteAlbum?> watchAlbum(String albumId) {
|
||||||
final query = _db.remoteAlbumEntity.select().join([
|
final query =
|
||||||
|
_db.remoteAlbumEntity.select().join([
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.remoteAlbumAssetEntity,
|
_db.remoteAlbumAssetEntity,
|
||||||
_db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
|
_db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
|
||||||
|
|
@ -290,9 +251,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
..groupBy([_db.remoteAlbumEntity.id]);
|
..groupBy([_db.remoteAlbumEntity.id]);
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final album = row.readTable(_db.remoteAlbumEntity).toDto(
|
final album = row.readTable(_db.remoteAlbumEntity).toDto(ownerName: row.read(_db.userEntity.name)!);
|
||||||
ownerName: row.read(_db.userEntity.name)!,
|
|
||||||
);
|
|
||||||
return album;
|
return album;
|
||||||
}).watchSingleOrNull();
|
}).watchSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,8 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleOrNullSelectable<RemoteAsset?> _assetSelectable(String id) {
|
SingleOrNullSelectable<RemoteAsset?> _assetSelectable(String id) {
|
||||||
final query = _db.remoteAssetEntity.select().addColumns([
|
final query =
|
||||||
_db.localAssetEntity.id,
|
_db.remoteAssetEntity.select().addColumns([_db.localAssetEntity.id]).join([
|
||||||
]).join([
|
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.localAssetEntity,
|
_db.localAssetEntity,
|
||||||
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
||||||
|
|
@ -57,9 +56,8 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<RemoteAsset?> watchAsset(String id) {
|
Stream<RemoteAsset?> watchAsset(String id) {
|
||||||
final query = _db.remoteAssetEntity.select().addColumns([
|
final query =
|
||||||
_db.localAssetEntity.id,
|
_db.remoteAssetEntity.select().addColumns([_db.localAssetEntity.id]).join([
|
||||||
]).join([
|
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.localAssetEntity,
|
_db.localAssetEntity,
|
||||||
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
||||||
|
|
@ -81,9 +79,7 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.select()
|
final query = _db.remoteAssetEntity.select()
|
||||||
..where(
|
..where((row) => row.stackId.equals(asset.stackId!) & row.id.equals(asset.id).not())
|
||||||
(row) => row.stackId.equals(asset.stackId!) & row.id.equals(asset.id).not(),
|
|
||||||
)
|
|
||||||
..orderBy([(row) => OrderingTerm.desc(row.createdAt)]);
|
..orderBy([(row) => OrderingTerm.desc(row.createdAt)]);
|
||||||
|
|
||||||
return query.map((row) => row.toDto()).get();
|
return query.map((row) => row.toDto()).get();
|
||||||
|
|
@ -102,17 +98,15 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
"asset",
|
"asset",
|
||||||
);
|
);
|
||||||
|
|
||||||
final query = asset.selectOnly().join([
|
final query =
|
||||||
|
asset.selectOnly().join([
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.remoteExifEntity,
|
_db.remoteExifEntity,
|
||||||
_db.remoteExifEntity.assetId.equalsExp(asset.ref(_db.remoteAssetEntity.id)),
|
_db.remoteExifEntity.assetId.equalsExp(asset.ref(_db.remoteAssetEntity.id)),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
..addColumns([
|
..addColumns([_db.remoteExifEntity.city, _db.remoteExifEntity.assetId])
|
||||||
_db.remoteExifEntity.city,
|
|
||||||
_db.remoteExifEntity.assetId,
|
|
||||||
])
|
|
||||||
..where(
|
..where(
|
||||||
_db.remoteExifEntity.city.isNotNull() &
|
_db.remoteExifEntity.city.isNotNull() &
|
||||||
asset.ref(_db.remoteAssetEntity.deletedAt).isNull() &
|
asset.ref(_db.remoteAssetEntity.deletedAt).isNull() &
|
||||||
|
|
@ -185,10 +179,7 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
for (final id in ids) {
|
for (final id in ids) {
|
||||||
batch.update(
|
batch.update(
|
||||||
_db.remoteExifEntity,
|
_db.remoteExifEntity,
|
||||||
RemoteExifEntityCompanion(
|
RemoteExifEntityCompanion(latitude: Value(location.latitude), longitude: Value(location.longitude)),
|
||||||
latitude: Value(location.latitude),
|
|
||||||
longitude: Value(location.longitude),
|
|
||||||
),
|
|
||||||
where: (e) => e.assetId.equals(id),
|
where: (e) => e.assetId.equals(id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -205,23 +196,14 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds));
|
await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds));
|
||||||
|
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
final companion = StackEntityCompanion(
|
final companion = StackEntityCompanion(ownerId: Value(userId), primaryAssetId: Value(stack.primaryAssetId));
|
||||||
ownerId: Value(userId),
|
|
||||||
primaryAssetId: Value(stack.primaryAssetId),
|
|
||||||
);
|
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(_db.stackEntity, companion.copyWith(id: Value(stack.id)), onConflict: DoUpdate((_) => companion));
|
||||||
_db.stackEntity,
|
|
||||||
companion.copyWith(id: Value(stack.id)),
|
|
||||||
onConflict: DoUpdate((_) => companion),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (final assetId in stack.assetIds) {
|
for (final assetId in stack.assetIds) {
|
||||||
batch.update(
|
batch.update(
|
||||||
_db.remoteAssetEntity,
|
_db.remoteAssetEntity,
|
||||||
RemoteAssetEntityCompanion(
|
RemoteAssetEntityCompanion(stackId: Value(stack.id)),
|
||||||
stackId: Value(stack.id),
|
|
||||||
),
|
|
||||||
where: (e) => e.id.equals(assetId),
|
where: (e) => e.id.equals(assetId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,12 +66,5 @@ class SearchApiRepository extends ApiRepository {
|
||||||
String? state,
|
String? state,
|
||||||
String? make,
|
String? make,
|
||||||
String? model,
|
String? model,
|
||||||
}) =>
|
}) => _api.getSearchSuggestions(type, country: country, state: state, make: make, model: model);
|
||||||
_api.getSearchSuggestions(
|
|
||||||
type,
|
|
||||||
country: country,
|
|
||||||
state: state,
|
|
||||||
make: make,
|
|
||||||
model: model,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,6 @@ class DriftStackRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
extension on StackEntityData {
|
extension on StackEntityData {
|
||||||
Stack toDto() {
|
Stack toDto() {
|
||||||
return Stack(
|
return Stack(id: id, createdAt: createdAt, updatedAt: updatedAt, ownerId: ownerId, primaryAssetId: primaryAssetId);
|
||||||
id: id,
|
|
||||||
createdAt: createdAt,
|
|
||||||
updatedAt: updatedAt,
|
|
||||||
ownerId: ownerId,
|
|
||||||
primaryAssetId: primaryAssetId,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,7 @@ class IsarStoreRepository extends IsarDatabaseRepository {
|
||||||
.filter()
|
.filter()
|
||||||
.anyOf(validStoreKeys, (query, id) => query.idEqualTo(id))
|
.anyOf(validStoreKeys, (query, id) => query.idEqualTo(id))
|
||||||
.watch(fireImmediately: true)
|
.watch(fireImmediately: true)
|
||||||
.asyncExpand(
|
.asyncExpand((entities) => Stream.fromFutures(entities.map((e) async => _toUpdateEvent(e))));
|
||||||
(entities) => Stream.fromFutures(
|
|
||||||
entities.map((e) async => _toUpdateEvent(e)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> delete<T>(StoreKey<T> key) async {
|
Future<void> delete<T>(StoreKey<T> key) async {
|
||||||
|
|
@ -68,14 +64,17 @@ class IsarStoreRepository extends IsarDatabaseRepository {
|
||||||
return StoreDto(key, value);
|
return StoreDto(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<T?> _toValue<T>(StoreKey<T> key, StoreValue entity) async => switch (key.type) {
|
Future<T?> _toValue<T>(StoreKey<T> key, StoreValue entity) async =>
|
||||||
|
switch (key.type) {
|
||||||
const (int) => entity.intValue,
|
const (int) => entity.intValue,
|
||||||
const (String) => entity.strValue,
|
const (String) => entity.strValue,
|
||||||
const (bool) => entity.intValue == 1,
|
const (bool) => entity.intValue == 1,
|
||||||
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
|
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
|
||||||
const (UserDto) => entity.strValue == null ? null : await IsarUserRepository(_db).getByUserId(entity.strValue!),
|
const (UserDto) =>
|
||||||
|
entity.strValue == null ? null : await IsarUserRepository(_db).getByUserId(entity.strValue!),
|
||||||
_ => null,
|
_ => null,
|
||||||
} as T?;
|
}
|
||||||
|
as T?;
|
||||||
|
|
||||||
Future<StoreValue> _fromValue<T>(StoreKey<T> key, T value) async {
|
Future<StoreValue> _fromValue<T>(StoreKey<T> key, T value) async {
|
||||||
final (int? intValue, String? strValue) = switch (key.type) {
|
final (int? intValue, String? strValue) = switch (key.type) {
|
||||||
|
|
@ -83,13 +82,8 @@ class IsarStoreRepository extends IsarDatabaseRepository {
|
||||||
const (String) => (null, value as String),
|
const (String) => (null, value as String),
|
||||||
const (bool) => ((value as bool) ? 1 : 0, null),
|
const (bool) => ((value as bool) ? 1 : 0, null),
|
||||||
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
|
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
|
||||||
const (UserDto) => (
|
const (UserDto) => (null, (await IsarUserRepository(_db).update(value as UserDto)).id),
|
||||||
null,
|
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
|
||||||
(await IsarUserRepository(_db).update(value as UserDto)).id,
|
|
||||||
),
|
|
||||||
_ => throw UnsupportedError(
|
|
||||||
"Unsupported primitive type: ${key.type} for key: ${key.name}",
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
return StoreValue(key.id, intValue: intValue, strValue: strValue);
|
return StoreValue(key.id, intValue: intValue, strValue: strValue);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,7 @@ class SyncApiRepository {
|
||||||
final client = httpClient ?? http.Client();
|
final client = httpClient ?? http.Client();
|
||||||
final endpoint = "${_api.apiClient.basePath}/sync/stream";
|
final endpoint = "${_api.apiClient.basePath}/sync/stream";
|
||||||
|
|
||||||
final headers = {
|
final headers = {'Content-Type': 'application/json', 'Accept': 'application/jsonlines+json'};
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/jsonlines+json',
|
|
||||||
};
|
|
||||||
|
|
||||||
final headerParams = <String, String>{};
|
final headerParams = <String, String>{};
|
||||||
await _api.applyToParams([], headerParams);
|
await _api.applyToParams([], headerParams);
|
||||||
|
|
@ -78,10 +75,7 @@ class SyncApiRepository {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
final errorBody = await response.stream.bytesToString();
|
final errorBody = await response.stream.bytesToString();
|
||||||
throw ApiException(
|
throw ApiException(response.statusCode, 'Failed to get sync stream: $errorBody');
|
||||||
response.statusCode,
|
|
||||||
'Failed to get sync stream: $errorBody',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await for (final chunk in response.stream.transform(utf8.decoder)) {
|
await for (final chunk in response.stream.transform(utf8.decoder)) {
|
||||||
|
|
|
||||||
|
|
@ -42,16 +42,9 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final user in data) {
|
for (final user in data) {
|
||||||
final companion = UserEntityCompanion(
|
final companion = UserEntityCompanion(name: Value(user.name), email: Value(user.email));
|
||||||
name: Value(user.name),
|
|
||||||
email: Value(user.email),
|
|
||||||
);
|
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(_db.userEntity, companion.copyWith(id: Value(user.id)), onConflict: DoUpdate((_) => companion));
|
||||||
_db.userEntity,
|
|
||||||
companion.copyWith(id: Value(user.id)),
|
|
||||||
onConflict: DoUpdate((_) => companion),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
|
|
@ -66,10 +59,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
for (final partner in data) {
|
for (final partner in data) {
|
||||||
batch.delete(
|
batch.delete(
|
||||||
_db.partnerEntity,
|
_db.partnerEntity,
|
||||||
PartnerEntityCompanion(
|
PartnerEntityCompanion(sharedById: Value(partner.sharedById), sharedWithId: Value(partner.sharedWithId)),
|
||||||
sharedById: Value(partner.sharedById),
|
|
||||||
sharedWithId: Value(partner.sharedWithId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -87,10 +77,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(
|
||||||
_db.partnerEntity,
|
_db.partnerEntity,
|
||||||
companion.copyWith(
|
companion.copyWith(sharedById: Value(partner.sharedById), sharedWithId: Value(partner.sharedWithId)),
|
||||||
sharedById: Value(partner.sharedById),
|
|
||||||
sharedWithId: Value(partner.sharedWithId),
|
|
||||||
),
|
|
||||||
onConflict: DoUpdate((_) => companion),
|
onConflict: DoUpdate((_) => companion),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -101,24 +88,16 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteAssetsV1(
|
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncAssetDeleteV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.remoteAssetEntity.deleteWhere(
|
await _db.remoteAssetEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.assetId)));
|
||||||
(row) => row.id.isIn(data.map((e) => e.assetId)),
|
|
||||||
);
|
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stack);
|
_logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateAssetsV1(
|
Future<void> updateAssetsV1(Iterable<SyncAssetV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncAssetV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final asset in data) {
|
for (final asset in data) {
|
||||||
|
|
@ -152,10 +131,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateAssetsExifV1(
|
Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncAssetExifV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final exif in data) {
|
for (final exif in data) {
|
||||||
|
|
@ -191,20 +167,14 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe(
|
_logger.severe('Error: updateAssetsExifV1 - $debugLabel', error, stack);
|
||||||
'Error: updateAssetsExifV1 - $debugLabel',
|
|
||||||
error,
|
|
||||||
stack,
|
|
||||||
);
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteAlbumsV1(Iterable<SyncAlbumDeleteV1> data) async {
|
Future<void> deleteAlbumsV1(Iterable<SyncAlbumDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.remoteAlbumEntity.deleteWhere(
|
await _db.remoteAlbumEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.albumId)));
|
||||||
(row) => row.id.isIn(data.map((e) => e.albumId)),
|
|
||||||
);
|
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteAlbumsV1', error, stack);
|
_logger.severe('Error: deleteAlbumsV1', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
@ -245,10 +215,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
for (final album in data) {
|
for (final album in data) {
|
||||||
batch.delete(
|
batch.delete(
|
||||||
_db.remoteAlbumUserEntity,
|
_db.remoteAlbumUserEntity,
|
||||||
RemoteAlbumUserEntityCompanion(
|
RemoteAlbumUserEntityCompanion(albumId: Value(album.albumId), userId: Value(album.userId)),
|
||||||
albumId: Value(album.albumId),
|
|
||||||
userId: Value(album.userId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -258,49 +225,32 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateAlbumUsersV1(
|
Future<void> updateAlbumUsersV1(Iterable<SyncAlbumUserV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncAlbumUserV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final album in data) {
|
for (final album in data) {
|
||||||
final companion = RemoteAlbumUserEntityCompanion(
|
final companion = RemoteAlbumUserEntityCompanion(role: Value(album.role.toAlbumUserRole()));
|
||||||
role: Value(album.role.toAlbumUserRole()),
|
|
||||||
);
|
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(
|
||||||
_db.remoteAlbumUserEntity,
|
_db.remoteAlbumUserEntity,
|
||||||
companion.copyWith(
|
companion.copyWith(albumId: Value(album.albumId), userId: Value(album.userId)),
|
||||||
albumId: Value(album.albumId),
|
|
||||||
userId: Value(album.userId),
|
|
||||||
),
|
|
||||||
onConflict: DoUpdate((_) => companion),
|
onConflict: DoUpdate((_) => companion),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe(
|
_logger.severe('Error: updateAlbumUsersV1 - $debugLabel', error, stack);
|
||||||
'Error: updateAlbumUsersV1 - $debugLabel',
|
|
||||||
error,
|
|
||||||
stack,
|
|
||||||
);
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteAlbumToAssetsV1(
|
Future<void> deleteAlbumToAssetsV1(Iterable<SyncAlbumToAssetDeleteV1> data) async {
|
||||||
Iterable<SyncAlbumToAssetDeleteV1> data,
|
|
||||||
) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final album in data) {
|
for (final album in data) {
|
||||||
batch.delete(
|
batch.delete(
|
||||||
_db.remoteAlbumAssetEntity,
|
_db.remoteAlbumAssetEntity,
|
||||||
RemoteAlbumAssetEntityCompanion(
|
RemoteAlbumAssetEntityCompanion(albumId: Value(album.albumId), assetId: Value(album.assetId)),
|
||||||
albumId: Value(album.albumId),
|
|
||||||
assetId: Value(album.assetId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -310,10 +260,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateAlbumToAssetsV1(
|
Future<void> updateAlbumToAssetsV1(Iterable<SyncAlbumToAssetV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncAlbumToAssetV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final album in data) {
|
for (final album in data) {
|
||||||
|
|
@ -322,19 +269,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
assetId: Value(album.assetId),
|
assetId: Value(album.assetId),
|
||||||
);
|
);
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(_db.remoteAlbumAssetEntity, companion, onConflict: DoNothing());
|
||||||
_db.remoteAlbumAssetEntity,
|
|
||||||
companion,
|
|
||||||
onConflict: DoNothing(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe(
|
_logger.severe('Error: updateAlbumToAssetsV1 - $debugLabel', error, stack);
|
||||||
'Error: updateAlbumToAssetsV1 - $debugLabel',
|
|
||||||
error,
|
|
||||||
stack,
|
|
||||||
);
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -371,9 +310,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> deleteMemoriesV1(Iterable<SyncMemoryDeleteV1> data) async {
|
Future<void> deleteMemoriesV1(Iterable<SyncMemoryDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.memoryEntity.deleteWhere(
|
await _db.memoryEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.memoryId)));
|
||||||
(row) => row.id.isIn(data.map((e) => e.memoryId)),
|
|
||||||
);
|
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteMemoriesV1', error, stack);
|
_logger.severe('Error: deleteMemoriesV1', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
@ -384,16 +321,9 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final asset in data) {
|
for (final asset in data) {
|
||||||
final companion = MemoryAssetEntityCompanion(
|
final companion = MemoryAssetEntityCompanion(memoryId: Value(asset.memoryId), assetId: Value(asset.assetId));
|
||||||
memoryId: Value(asset.memoryId),
|
|
||||||
assetId: Value(asset.assetId),
|
|
||||||
);
|
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(_db.memoryAssetEntity, companion, onConflict: DoNothing());
|
||||||
_db.memoryAssetEntity,
|
|
||||||
companion,
|
|
||||||
onConflict: DoNothing(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
|
|
@ -402,18 +332,13 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteMemoryAssetsV1(
|
Future<void> deleteMemoryAssetsV1(Iterable<SyncMemoryAssetDeleteV1> data) async {
|
||||||
Iterable<SyncMemoryAssetDeleteV1> data,
|
|
||||||
) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final asset in data) {
|
for (final asset in data) {
|
||||||
batch.delete(
|
batch.delete(
|
||||||
_db.memoryAssetEntity,
|
_db.memoryAssetEntity,
|
||||||
MemoryAssetEntityCompanion(
|
MemoryAssetEntityCompanion(memoryId: Value(asset.memoryId), assetId: Value(asset.assetId)),
|
||||||
memoryId: Value(asset.memoryId),
|
|
||||||
assetId: Value(asset.assetId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -423,10 +348,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateStacksV1(
|
Future<void> updateStacksV1(Iterable<SyncStackV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncStackV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final stack in data) {
|
for (final stack in data) {
|
||||||
|
|
@ -450,36 +372,24 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteStacksV1(
|
Future<void> deleteStacksV1(Iterable<SyncStackDeleteV1> data, {String debugLabel = 'user'}) async {
|
||||||
Iterable<SyncStackDeleteV1> data, {
|
|
||||||
String debugLabel = 'user',
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.stackEntity.deleteWhere(
|
await _db.stackEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.stackId)));
|
||||||
(row) => row.id.isIn(data.map((e) => e.stackId)),
|
|
||||||
);
|
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteStacksV1 - $debugLabel', error, stack);
|
_logger.severe('Error: deleteStacksV1 - $debugLabel', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateUserMetadatasV1(
|
Future<void> updateUserMetadatasV1(Iterable<SyncUserMetadataV1> data) async {
|
||||||
Iterable<SyncUserMetadataV1> data,
|
|
||||||
) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final userMetadata in data) {
|
for (final userMetadata in data) {
|
||||||
final companion = UserMetadataEntityCompanion(
|
final companion = UserMetadataEntityCompanion(value: Value(userMetadata.value as Map<String, Object?>));
|
||||||
value: Value(userMetadata.value as Map<String, Object?>),
|
|
||||||
);
|
|
||||||
|
|
||||||
batch.insert(
|
batch.insert(
|
||||||
_db.userMetadataEntity,
|
_db.userMetadataEntity,
|
||||||
companion.copyWith(
|
companion.copyWith(userId: Value(userMetadata.userId), key: Value(userMetadata.key.toUserMetadataKey())),
|
||||||
userId: Value(userMetadata.userId),
|
|
||||||
key: Value(userMetadata.key.toUserMetadataKey()),
|
|
||||||
),
|
|
||||||
onConflict: DoUpdate((_) => companion),
|
onConflict: DoUpdate((_) => companion),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -490,9 +400,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteUserMetadatasV1(
|
Future<void> deleteUserMetadatasV1(Iterable<SyncUserMetadataDeleteV1> data) async {
|
||||||
Iterable<SyncUserMetadataDeleteV1> data,
|
|
||||||
) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final userMetadata in data) {
|
for (final userMetadata in data) {
|
||||||
|
|
@ -540,16 +448,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deletePeopleV1(
|
Future<void> deletePeopleV1(Iterable<SyncPersonDeleteV1> data) async {
|
||||||
Iterable<SyncPersonDeleteV1> data,
|
|
||||||
) async {
|
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final person in data) {
|
for (final person in data) {
|
||||||
batch.deleteWhere(
|
batch.deleteWhere(_db.personEntity, (row) => row.id.equals(person.personId));
|
||||||
_db.personEntity,
|
|
||||||
(row) => row.id.equals(person.personId),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
|
|
@ -591,10 +494,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final assetFace in data) {
|
for (final assetFace in data) {
|
||||||
batch.deleteWhere(
|
batch.deleteWhere(_db.assetFaceEntity, (row) => row.id.equals(assetFace.assetFaceId));
|
||||||
_db.assetFaceEntity,
|
|
||||||
(row) => row.id.equals(assetFace.assetFaceId),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
Stream<List<String>> watchTimelineUserIds(String userId) {
|
Stream<List<String>> watchTimelineUserIds(String userId) {
|
||||||
final query = _db.partnerEntity.selectOnly()
|
final query = _db.partnerEntity.selectOnly()
|
||||||
..addColumns([_db.partnerEntity.sharedById])
|
..addColumns([_db.partnerEntity.sharedById])
|
||||||
..where(
|
..where(_db.partnerEntity.inTimeline.equals(true) & _db.partnerEntity.sharedWithId.equals(userId));
|
||||||
_db.partnerEntity.inTimeline.equals(true) & _db.partnerEntity.sharedWithId.equals(userId),
|
|
||||||
);
|
|
||||||
|
|
||||||
return query
|
return query
|
||||||
.map((row) => row.read(_db.partnerEntity.sharedById)!)
|
.map((row) => row.read(_db.partnerEntity.sharedById)!)
|
||||||
|
|
@ -33,25 +31,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineQuery main(List<String> userIds, GroupAssetsBy groupBy) => (
|
TimelineQuery main(List<String> userIds, GroupAssetsBy groupBy) => (
|
||||||
bucketSource: () => _watchMainBucket(
|
bucketSource: () => _watchMainBucket(userIds, groupBy: groupBy),
|
||||||
userIds,
|
assetSource: (offset, count) => _getMainBucketAssets(userIds, offset: offset, count: count),
|
||||||
groupBy: groupBy,
|
|
||||||
),
|
|
||||||
assetSource: (offset, count) => _getMainBucketAssets(
|
|
||||||
userIds,
|
|
||||||
offset: offset,
|
|
||||||
count: count,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Stream<List<Bucket>> _watchMainBucket(
|
Stream<List<Bucket>> _watchMainBucket(List<String> userIds, {GroupAssetsBy groupBy = GroupAssetsBy.day}) {
|
||||||
List<String> userIds, {
|
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
|
||||||
}) {
|
|
||||||
if (groupBy == GroupAssetsBy.none) {
|
if (groupBy == GroupAssetsBy.none) {
|
||||||
throw UnsupportedError(
|
throw UnsupportedError("GroupAssetsBy.none is not supported for watchMainBucket");
|
||||||
"GroupAssetsBy.none is not supported for watchMainBucket",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _db.mergedAssetDrift
|
return _db.mergedAssetDrift
|
||||||
|
|
@ -64,11 +50,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
.throttle(const Duration(seconds: 3), trailing: true);
|
.throttle(const Duration(seconds: 3), trailing: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<BaseAsset>> _getMainBucketAssets(
|
Future<List<BaseAsset>> _getMainBucketAssets(List<String> userIds, {required int offset, required int count}) {
|
||||||
List<String> userIds, {
|
|
||||||
required int offset,
|
|
||||||
required int count,
|
|
||||||
}) {
|
|
||||||
return _db.mergedAssetDrift
|
return _db.mergedAssetDrift
|
||||||
.mergedAsset(userIds, limit: (_) => Limit(count, offset))
|
.mergedAsset(userIds, limit: (_) => Limit(count, offset))
|
||||||
.map(
|
.map(
|
||||||
|
|
@ -109,21 +91,11 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineQuery localAlbum(String albumId, GroupAssetsBy groupBy) => (
|
TimelineQuery localAlbum(String albumId, GroupAssetsBy groupBy) => (
|
||||||
bucketSource: () => _watchLocalAlbumBucket(
|
bucketSource: () => _watchLocalAlbumBucket(albumId, groupBy: groupBy),
|
||||||
albumId,
|
assetSource: (offset, count) => _getLocalAlbumBucketAssets(albumId, offset: offset, count: count),
|
||||||
groupBy: groupBy,
|
|
||||||
),
|
|
||||||
assetSource: (offset, count) => _getLocalAlbumBucketAssets(
|
|
||||||
albumId,
|
|
||||||
offset: offset,
|
|
||||||
count: count,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Stream<List<Bucket>> _watchLocalAlbumBucket(
|
Stream<List<Bucket>> _watchLocalAlbumBucket(String albumId, {GroupAssetsBy groupBy = GroupAssetsBy.day}) {
|
||||||
String albumId, {
|
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
|
||||||
}) {
|
|
||||||
if (groupBy == GroupAssetsBy.none) {
|
if (groupBy == GroupAssetsBy.none) {
|
||||||
return _db.localAlbumAssetEntity
|
return _db.localAlbumAssetEntity
|
||||||
.count(where: (row) => row.albumId.equals(albumId))
|
.count(where: (row) => row.albumId.equals(albumId))
|
||||||
|
|
@ -134,7 +106,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
final assetCountExp = _db.localAssetEntity.id.count();
|
final assetCountExp = _db.localAssetEntity.id.count();
|
||||||
final dateExp = _db.localAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.localAssetEntity.createdAt.dateFmt(groupBy);
|
||||||
|
|
||||||
final query = _db.localAssetEntity.selectOnly().join([
|
final query =
|
||||||
|
_db.localAssetEntity.selectOnly().join([
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.localAlbumAssetEntity,
|
_db.localAlbumAssetEntity,
|
||||||
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
||||||
|
|
@ -158,13 +131,9 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}).watch();
|
}).watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<BaseAsset>> _getLocalAlbumBucketAssets(
|
Future<List<BaseAsset>> _getLocalAlbumBucketAssets(String albumId, {required int offset, required int count}) {
|
||||||
String albumId, {
|
final query =
|
||||||
required int offset,
|
_db.localAssetEntity.select().join([
|
||||||
required int count,
|
|
||||||
}) {
|
|
||||||
final query = _db.localAssetEntity.select().join(
|
|
||||||
[
|
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.localAlbumAssetEntity,
|
_db.localAlbumAssetEntity,
|
||||||
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
||||||
|
|
@ -175,8 +144,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
_db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum),
|
_db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
],
|
])
|
||||||
)
|
|
||||||
..addColumns([_db.remoteAssetEntity.id])
|
..addColumns([_db.remoteAssetEntity.id])
|
||||||
..where(_db.localAlbumAssetEntity.albumId.equals(albumId))
|
..where(_db.localAlbumAssetEntity.albumId.equals(albumId))
|
||||||
..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)])
|
..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)])
|
||||||
|
|
@ -184,28 +152,16 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
return query.map((row) {
|
return query.map((row) {
|
||||||
final asset = row.readTable(_db.localAssetEntity).toDto();
|
final asset = row.readTable(_db.localAssetEntity).toDto();
|
||||||
return asset.copyWith(
|
return asset.copyWith(remoteId: row.read(_db.remoteAssetEntity.id));
|
||||||
remoteId: row.read(_db.remoteAssetEntity.id),
|
|
||||||
);
|
|
||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineQuery remoteAlbum(String albumId, GroupAssetsBy groupBy) => (
|
TimelineQuery remoteAlbum(String albumId, GroupAssetsBy groupBy) => (
|
||||||
bucketSource: () => _watchRemoteAlbumBucket(
|
bucketSource: () => _watchRemoteAlbumBucket(albumId, groupBy: groupBy),
|
||||||
albumId,
|
assetSource: (offset, count) => _getRemoteAlbumBucketAssets(albumId, offset: offset, count: count),
|
||||||
groupBy: groupBy,
|
|
||||||
),
|
|
||||||
assetSource: (offset, count) => _getRemoteAlbumBucketAssets(
|
|
||||||
albumId,
|
|
||||||
offset: offset,
|
|
||||||
count: count,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Stream<List<Bucket>> _watchRemoteAlbumBucket(
|
Stream<List<Bucket>> _watchRemoteAlbumBucket(String albumId, {GroupAssetsBy groupBy = GroupAssetsBy.day}) {
|
||||||
String albumId, {
|
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
|
||||||
}) {
|
|
||||||
if (groupBy == GroupAssetsBy.none) {
|
if (groupBy == GroupAssetsBy.none) {
|
||||||
return _db.remoteAlbumAssetEntity
|
return _db.remoteAlbumAssetEntity
|
||||||
.count(where: (row) => row.albumId.equals(albumId))
|
.count(where: (row) => row.albumId.equals(albumId))
|
||||||
|
|
@ -217,7 +173,9 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))).watch().switchMap((albums) {
|
return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId)))
|
||||||
|
.watch()
|
||||||
|
.switchMap((albums) {
|
||||||
if (albums.isEmpty) {
|
if (albums.isEmpty) {
|
||||||
return Stream.value(<Bucket>[]);
|
return Stream.value(<Bucket>[]);
|
||||||
}
|
}
|
||||||
|
|
@ -236,9 +194,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
..where(
|
..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId))
|
||||||
_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId),
|
|
||||||
)
|
|
||||||
..groupBy([dateExp]);
|
..groupBy([dateExp]);
|
||||||
|
|
||||||
if (isAscending) {
|
if (isAscending) {
|
||||||
|
|
@ -252,17 +208,14 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
final assetCount = row.read(assetCountExp)!;
|
final assetCount = row.read(assetCountExp)!;
|
||||||
return TimeBucket(date: timeline, assetCount: assetCount);
|
return TimeBucket(date: timeline, assetCount: assetCount);
|
||||||
}).watch();
|
}).watch();
|
||||||
}).handleError((error) {
|
})
|
||||||
|
.handleError((error) {
|
||||||
// If there's an error (e.g., album was deleted), return empty buckets
|
// If there's an error (e.g., album was deleted), return empty buckets
|
||||||
return <Bucket>[];
|
return <Bucket>[];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<BaseAsset>> _getRemoteAlbumBucketAssets(
|
Future<List<BaseAsset>> _getRemoteAlbumBucketAssets(String albumId, {required int offset, required int count}) async {
|
||||||
String albumId, {
|
|
||||||
required int offset,
|
|
||||||
required int count,
|
|
||||||
}) async {
|
|
||||||
final albumData = await (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))).getSingleOrNull();
|
final albumData = await (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))).getSingleOrNull();
|
||||||
|
|
||||||
// If album doesn't exist (was deleted), return empty list
|
// If album doesn't exist (was deleted), return empty list
|
||||||
|
|
@ -272,17 +225,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
final isAscending = albumData.order == AlbumAssetOrder.asc;
|
final isAscending = albumData.order == AlbumAssetOrder.asc;
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.select().join(
|
final query = _db.remoteAssetEntity.select().join([
|
||||||
[
|
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.remoteAlbumAssetEntity,
|
_db.remoteAlbumAssetEntity,
|
||||||
_db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
|
_db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
],
|
])..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId));
|
||||||
)..where(
|
|
||||||
_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isAscending) {
|
if (isAscending) {
|
||||||
query.orderBy([OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]);
|
query.orderBy([OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]);
|
||||||
|
|
@ -339,26 +288,14 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
);
|
);
|
||||||
|
|
||||||
TimelineQuery place(String place, GroupAssetsBy groupBy) => (
|
TimelineQuery place(String place, GroupAssetsBy groupBy) => (
|
||||||
bucketSource: () => _watchPlaceBucket(
|
bucketSource: () => _watchPlaceBucket(place, groupBy: groupBy),
|
||||||
place,
|
assetSource: (offset, count) => _getPlaceBucketAssets(place, offset: offset, count: count),
|
||||||
groupBy: groupBy,
|
|
||||||
),
|
|
||||||
assetSource: (offset, count) => _getPlaceBucketAssets(
|
|
||||||
place,
|
|
||||||
offset: offset,
|
|
||||||
count: count,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Stream<List<Bucket>> _watchPlaceBucket(
|
Stream<List<Bucket>> _watchPlaceBucket(String place, {GroupAssetsBy groupBy = GroupAssetsBy.day}) {
|
||||||
String place, {
|
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
|
||||||
}) {
|
|
||||||
if (groupBy == GroupAssetsBy.none) {
|
if (groupBy == GroupAssetsBy.none) {
|
||||||
// TODO: implement GroupAssetBy for place
|
// TODO: implement GroupAssetBy for place
|
||||||
throw UnsupportedError(
|
throw UnsupportedError("GroupAssetsBy.none is not supported for watchPlaceBucket");
|
||||||
"GroupAssetsBy.none is not supported for watchPlaceBucket",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||||
|
|
@ -388,20 +325,15 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}).watch();
|
}).watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<BaseAsset>> _getPlaceBucketAssets(
|
Future<List<BaseAsset>> _getPlaceBucketAssets(String place, {required int offset, required int count}) {
|
||||||
String place, {
|
final query =
|
||||||
required int offset,
|
_db.remoteAssetEntity.select().join([
|
||||||
required int count,
|
|
||||||
}) {
|
|
||||||
final query = _db.remoteAssetEntity.select().join(
|
|
||||||
[
|
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.remoteExifEntity,
|
_db.remoteExifEntity,
|
||||||
_db.remoteExifEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
|
_db.remoteExifEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
],
|
])
|
||||||
)
|
|
||||||
..where(
|
..where(
|
||||||
_db.remoteAssetEntity.deletedAt.isNull() &
|
_db.remoteAssetEntity.deletedAt.isNull() &
|
||||||
_db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) &
|
_db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) &
|
||||||
|
|
@ -419,12 +351,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
bucketSource: () => _watchRemoteBucket(filter: filter, groupBy: groupBy),
|
bucketSource: () => _watchRemoteBucket(filter: filter, groupBy: groupBy),
|
||||||
assetSource: (offset, count) => _getRemoteAssets(
|
assetSource: (offset, count) =>
|
||||||
filter: filter,
|
_getRemoteAssets(filter: filter, offset: offset, count: count, joinLocal: joinLocal),
|
||||||
offset: offset,
|
|
||||||
count: count,
|
|
||||||
joinLocal: joinLocal,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,7 +388,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
bool joinLocal = false,
|
bool joinLocal = false,
|
||||||
}) {
|
}) {
|
||||||
if (joinLocal) {
|
if (joinLocal) {
|
||||||
final query = _db.remoteAssetEntity.select().join([
|
final query =
|
||||||
|
_db.remoteAssetEntity.select().join([
|
||||||
leftOuterJoin(
|
leftOuterJoin(
|
||||||
_db.localAssetEntity,
|
_db.localAssetEntity,
|
||||||
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
||||||
|
|
@ -507,9 +436,7 @@ extension on Expression<DateTime> {
|
||||||
return switch (groupBy) {
|
return switch (groupBy) {
|
||||||
GroupAssetsBy.day || GroupAssetsBy.auto => localTimeExp.date,
|
GroupAssetsBy.day || GroupAssetsBy.auto => localTimeExp.date,
|
||||||
GroupAssetsBy.month => localTimeExp.strftime("%Y-%m"),
|
GroupAssetsBy.month => localTimeExp.strftime("%Y-%m"),
|
||||||
GroupAssetsBy.none => throw ArgumentError(
|
GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"),
|
||||||
"GroupAssetsBy.none is not supported for date formatting",
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -519,9 +446,7 @@ extension on String {
|
||||||
final format = switch (groupBy) {
|
final format = switch (groupBy) {
|
||||||
GroupAssetsBy.day || GroupAssetsBy.auto => "y-M-d",
|
GroupAssetsBy.day || GroupAssetsBy.auto => "y-M-d",
|
||||||
GroupAssetsBy.month => "y-M",
|
GroupAssetsBy.month => "y-M",
|
||||||
GroupAssetsBy.none => throw ArgumentError(
|
GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"),
|
||||||
"GroupAssetsBy.none is not supported for date formatting",
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
return DateFormat(format).parse(this);
|
return DateFormat(format).parse(this);
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,8 @@ class UserApiRepository extends ApiRepository {
|
||||||
return UserConverter.fromAdminDto(adminDto, preferenceDto);
|
return UserConverter.fromAdminDto(adminDto, preferenceDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> createProfileImage({
|
Future<String> createProfileImage({required String name, required Uint8List data}) async {
|
||||||
required String name,
|
final res = await checkNull(_api.createProfileImage(MultipartFile.fromBytes('file', data, filename: name)));
|
||||||
required Uint8List data,
|
|
||||||
}) async {
|
|
||||||
final res = await checkNull(
|
|
||||||
_api.createProfileImage(
|
|
||||||
MultipartFile.fromBytes('file', data, filename: name),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return res.profileImagePath;
|
return res.profileImagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,8 @@ class DriftUserMetadataRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
extension on UserMetadataEntityData {
|
extension on UserMetadataEntityData {
|
||||||
UserMetadata toDto() => switch (key) {
|
UserMetadata toDto() => switch (key) {
|
||||||
UserMetadataKey.onboarding => UserMetadata(
|
UserMetadataKey.onboarding => UserMetadata(userId: userId, key: key, onboarding: Onboarding.fromMap(value)),
|
||||||
userId: userId,
|
UserMetadataKey.preferences => UserMetadata(userId: userId, key: key, preferences: Preferences.fromMap(value)),
|
||||||
key: key,
|
UserMetadataKey.license => UserMetadata(userId: userId, key: key, license: License.fromMap(value)),
|
||||||
onboarding: Onboarding.fromMap(value),
|
|
||||||
),
|
|
||||||
UserMetadataKey.preferences => UserMetadata(
|
|
||||||
userId: userId,
|
|
||||||
key: key,
|
|
||||||
preferences: Preferences.fromMap(value),
|
|
||||||
),
|
|
||||||
UserMetadataKey.license => UserMetadata(
|
|
||||||
userId: userId,
|
|
||||||
key: key,
|
|
||||||
license: License.fromMap(value),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,7 @@ abstract final class UserConverter {
|
||||||
avatarColor: dto.avatarColor.toAvatarColor(),
|
avatarColor: dto.avatarColor.toAvatarColor(),
|
||||||
);
|
);
|
||||||
|
|
||||||
static UserDto fromAdminDto(
|
static UserDto fromAdminDto(UserAdminResponseDto adminDto, [UserPreferencesResponseDto? preferenceDto]) => UserDto(
|
||||||
UserAdminResponseDto adminDto, [
|
|
||||||
UserPreferencesResponseDto? preferenceDto,
|
|
||||||
]) =>
|
|
||||||
UserDto(
|
|
||||||
id: adminDto.id,
|
id: adminDto.id,
|
||||||
email: adminDto.email,
|
email: adminDto.email,
|
||||||
name: adminDto.name,
|
name: adminDto.name,
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,7 @@ void main() async {
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [dbProvider.overrideWithValue(db), isarProvider.overrideWithValue(db)],
|
||||||
dbProvider.overrideWithValue(db),
|
|
||||||
isarProvider.overrideWithValue(db),
|
|
||||||
],
|
|
||||||
child: const MainWidget(),
|
child: const MainWidget(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -100,23 +97,15 @@ Future<void> initApp() async {
|
||||||
globalConfig: (Config.holdingQueue, (1000, 1000, 1000)),
|
globalConfig: (Config.holdingQueue, (1000, 1000, 1000)),
|
||||||
);
|
);
|
||||||
|
|
||||||
await FileDownloader().trackTasksInGroup(
|
await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false);
|
||||||
kDownloadGroupLivePhoto,
|
|
||||||
markDownloadedComplete: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
await FileDownloader().trackTasks();
|
await FileDownloader().trackTasks();
|
||||||
|
|
||||||
LicenseRegistry.addLicense(
|
LicenseRegistry.addLicense(() async* {
|
||||||
() async* {
|
|
||||||
for (final license in nonPubLicenses.entries) {
|
for (final license in nonPubLicenses.entries) {
|
||||||
yield LicenseEntryWithLineBreaks(
|
yield LicenseEntryWithLineBreaks([license.key], license.value);
|
||||||
[license.key],
|
|
||||||
license.value,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImmichApp extends ConsumerStatefulWidget {
|
class ImmichApp extends ConsumerStatefulWidget {
|
||||||
|
|
@ -160,9 +149,7 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||||
|
|
||||||
// Sets the navigation bar color
|
// Sets the navigation bar color
|
||||||
SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle(
|
SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle(systemNavigationBarColor: Colors.transparent);
|
||||||
systemNavigationBarColor: Colors.transparent,
|
|
||||||
);
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
// Android 8 does not support transparent app bars
|
// Android 8 does not support transparent app bars
|
||||||
final info = await DeviceInfoPlugin().androidInfo;
|
final info = await DeviceInfoPlugin().androidInfo;
|
||||||
|
|
@ -177,40 +164,22 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
||||||
void _configureFileDownloaderNotifications() {
|
void _configureFileDownloaderNotifications() {
|
||||||
FileDownloader().configureNotificationForGroup(
|
FileDownloader().configureNotificationForGroup(
|
||||||
kDownloadGroupImage,
|
kDownloadGroupImage,
|
||||||
running: TaskNotification(
|
running: TaskNotification('downloading_media'.tr(), '${'file_name'.tr()}: {filename}'),
|
||||||
'downloading_media'.tr(),
|
complete: TaskNotification('download_finished'.tr(), '${'file_name'.tr()}: {filename}'),
|
||||||
'${'file_name'.tr()}: {filename}',
|
|
||||||
),
|
|
||||||
complete: TaskNotification(
|
|
||||||
'download_finished'.tr(),
|
|
||||||
'${'file_name'.tr()}: {filename}',
|
|
||||||
),
|
|
||||||
progressBar: true,
|
progressBar: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
FileDownloader().configureNotificationForGroup(
|
FileDownloader().configureNotificationForGroup(
|
||||||
kDownloadGroupVideo,
|
kDownloadGroupVideo,
|
||||||
running: TaskNotification(
|
running: TaskNotification('downloading_media'.tr(), '${'file_name'.tr()}: {filename}'),
|
||||||
'downloading_media'.tr(),
|
complete: TaskNotification('download_finished'.tr(), '${'file_name'.tr()}: {filename}'),
|
||||||
'${'file_name'.tr()}: {filename}',
|
|
||||||
),
|
|
||||||
complete: TaskNotification(
|
|
||||||
'download_finished'.tr(),
|
|
||||||
'${'file_name'.tr()}: {filename}',
|
|
||||||
),
|
|
||||||
progressBar: true,
|
progressBar: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
FileDownloader().configureNotificationForGroup(
|
FileDownloader().configureNotificationForGroup(
|
||||||
kManualUploadGroup,
|
kManualUploadGroup,
|
||||||
running: TaskNotification(
|
running: TaskNotification('uploading_media'.tr(), '${'file_name'.tr()}: {displayName}'),
|
||||||
'uploading_media'.tr(),
|
complete: TaskNotification('upload_finished'.tr(), '${'file_name'.tr()}: {displayName}'),
|
||||||
'${'file_name'.tr()}: {displayName}',
|
|
||||||
),
|
|
||||||
complete: TaskNotification(
|
|
||||||
'upload_finished'.tr(),
|
|
||||||
'${'file_name'.tr()}: {displayName}',
|
|
||||||
),
|
|
||||||
progressBar: true,
|
progressBar: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -222,19 +191,13 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
||||||
final isColdStart = currentRouteName == null || currentRouteName == SplashScreenRoute.name;
|
final isColdStart = currentRouteName == null || currentRouteName == SplashScreenRoute.name;
|
||||||
|
|
||||||
if (deepLink.uri.scheme == "immich") {
|
if (deepLink.uri.scheme == "immich") {
|
||||||
final proposedRoute = await deepLinkHandler.handleScheme(
|
final proposedRoute = await deepLinkHandler.handleScheme(deepLink, isColdStart);
|
||||||
deepLink,
|
|
||||||
isColdStart,
|
|
||||||
);
|
|
||||||
|
|
||||||
return proposedRoute;
|
return proposedRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deepLink.uri.host == "my.immich.app") {
|
if (deepLink.uri.host == "my.immich.app") {
|
||||||
final proposedRoute = await deepLinkHandler.handleMyImmichApp(
|
final proposedRoute = await deepLinkHandler.handleMyImmichApp(deepLink, isColdStart);
|
||||||
deepLink,
|
|
||||||
isColdStart,
|
|
||||||
);
|
|
||||||
|
|
||||||
return proposedRoute;
|
return proposedRoute;
|
||||||
}
|
}
|
||||||
|
|
@ -275,9 +238,7 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
||||||
final immichTheme = ref.watch(immichThemeProvider);
|
final immichTheme = ref.watch(immichThemeProvider);
|
||||||
|
|
||||||
return ProviderScope(
|
return ProviderScope(
|
||||||
overrides: [
|
overrides: [localeProvider.overrideWithValue(context.locale)],
|
||||||
localeProvider.overrideWithValue(context.locale),
|
|
||||||
],
|
|
||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
title: 'Immich',
|
title: 'Immich',
|
||||||
debugShowCheckedModeBanner: true,
|
debugShowCheckedModeBanner: true,
|
||||||
|
|
@ -285,14 +246,8 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
locale: context.locale,
|
locale: context.locale,
|
||||||
themeMode: ref.watch(immichThemeModeProvider),
|
themeMode: ref.watch(immichThemeModeProvider),
|
||||||
darkTheme: getThemeData(
|
darkTheme: getThemeData(colorScheme: immichTheme.dark, locale: context.locale),
|
||||||
colorScheme: immichTheme.dark,
|
theme: getThemeData(colorScheme: immichTheme.light, locale: context.locale),
|
||||||
locale: context.locale,
|
|
||||||
),
|
|
||||||
theme: getThemeData(
|
|
||||||
colorScheme: immichTheme.light,
|
|
||||||
locale: context.locale,
|
|
||||||
),
|
|
||||||
routerConfig: router.config(
|
routerConfig: router.config(
|
||||||
deepLinkBuilder: _deepLinkBuilder,
|
deepLinkBuilder: _deepLinkBuilder,
|
||||||
navigatorObservers: () => [AppNavigationObserver(ref: ref), HeroController()],
|
navigatorObservers: () => [AppNavigationObserver(ref: ref), HeroController()],
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,9 @@ class AlbumAddAssetsResponse {
|
||||||
List<String> alreadyInAlbum;
|
List<String> alreadyInAlbum;
|
||||||
int successfullyAdded;
|
int successfullyAdded;
|
||||||
|
|
||||||
AlbumAddAssetsResponse({
|
AlbumAddAssetsResponse({required this.alreadyInAlbum, required this.successfullyAdded});
|
||||||
required this.alreadyInAlbum,
|
|
||||||
required this.successfullyAdded,
|
|
||||||
});
|
|
||||||
|
|
||||||
AlbumAddAssetsResponse copyWith({
|
AlbumAddAssetsResponse copyWith({List<String>? alreadyInAlbum, int? successfullyAdded}) {
|
||||||
List<String>? alreadyInAlbum,
|
|
||||||
int? successfullyAdded,
|
|
||||||
}) {
|
|
||||||
return AlbumAddAssetsResponse(
|
return AlbumAddAssetsResponse(
|
||||||
alreadyInAlbum: alreadyInAlbum ?? this.alreadyInAlbum,
|
alreadyInAlbum: alreadyInAlbum ?? this.alreadyInAlbum,
|
||||||
successfullyAdded: successfullyAdded ?? this.successfullyAdded,
|
successfullyAdded: successfullyAdded ?? this.successfullyAdded,
|
||||||
|
|
@ -23,10 +17,7 @@ class AlbumAddAssetsResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{'alreadyInAlbum': alreadyInAlbum, 'successfullyAdded': successfullyAdded};
|
||||||
'alreadyInAlbum': alreadyInAlbum,
|
|
||||||
'successfullyAdded': successfullyAdded,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String toJson() => json.encode(toMap());
|
String toJson() => json.encode(toMap());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1 @@
|
||||||
enum QuickFilterMode {
|
enum QuickFilterMode { all, sharedWithMe, myAlbums }
|
||||||
all,
|
|
||||||
sharedWithMe,
|
|
||||||
myAlbums,
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,7 @@ class AlbumViewerPageState {
|
||||||
required this.editDescriptionText,
|
required this.editDescriptionText,
|
||||||
});
|
});
|
||||||
|
|
||||||
AlbumViewerPageState copyWith({
|
AlbumViewerPageState copyWith({bool? isEditAlbum, String? editTitleText, String? editDescriptionText}) {
|
||||||
bool? isEditAlbum,
|
|
||||||
String? editTitleText,
|
|
||||||
String? editDescriptionText,
|
|
||||||
}) {
|
|
||||||
return AlbumViewerPageState(
|
return AlbumViewerPageState(
|
||||||
isEditAlbum: isEditAlbum ?? this.isEditAlbum,
|
isEditAlbum: isEditAlbum ?? this.isEditAlbum,
|
||||||
editTitleText: editTitleText ?? this.editTitleText,
|
editTitleText: editTitleText ?? this.editTitleText,
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
class AssetSelectionPageResult {
|
class AssetSelectionPageResult {
|
||||||
final Set<Asset> selectedAssets;
|
final Set<Asset> selectedAssets;
|
||||||
|
|
||||||
const AssetSelectionPageResult({
|
const AssetSelectionPageResult({required this.selectedAssets});
|
||||||
required this.selectedAssets,
|
|
||||||
});
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
if (identical(this, other)) return true;
|
if (identical(this, other)) return true;
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,7 @@ class AssetSelectionState {
|
||||||
this.selectedCount = 0,
|
this.selectedCount = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
AssetSelectionState copyWith({
|
AssetSelectionState copyWith({bool? hasRemote, bool? hasLocal, bool? hasMerged, int? selectedCount}) {
|
||||||
bool? hasRemote,
|
|
||||||
bool? hasLocal,
|
|
||||||
bool? hasMerged,
|
|
||||||
int? selectedCount,
|
|
||||||
}) {
|
|
||||||
return AssetSelectionState(
|
return AssetSelectionState(
|
||||||
hasRemote: hasRemote ?? this.hasRemote,
|
hasRemote: hasRemote ?? this.hasRemote,
|
||||||
hasLocal: hasLocal ?? this.hasLocal,
|
hasLocal: hasLocal ?? this.hasLocal,
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,10 @@ class AuxilaryEndpoint {
|
||||||
final String url;
|
final String url;
|
||||||
final AuxCheckStatus status;
|
final AuxCheckStatus status;
|
||||||
|
|
||||||
const AuxilaryEndpoint({
|
const AuxilaryEndpoint({required this.url, required this.status});
|
||||||
required this.url,
|
|
||||||
required this.status,
|
|
||||||
});
|
|
||||||
|
|
||||||
AuxilaryEndpoint copyWith({
|
AuxilaryEndpoint copyWith({String? url, AuxCheckStatus? status}) {
|
||||||
String? url,
|
return AuxilaryEndpoint(url: url ?? this.url, status: status ?? this.status);
|
||||||
AuxCheckStatus? status,
|
|
||||||
}) {
|
|
||||||
return AuxilaryEndpoint(
|
|
||||||
url: url ?? this.url,
|
|
||||||
status: status ?? this.status,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -34,10 +25,7 @@ class AuxilaryEndpoint {
|
||||||
int get hashCode => url.hashCode ^ status.hashCode;
|
int get hashCode => url.hashCode ^ status.hashCode;
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{'url': url, 'status': status.toMap()};
|
||||||
'url': url,
|
|
||||||
'status': status.toMap(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AuxilaryEndpoint.fromMap(Map<String, dynamic> map) {
|
factory AuxilaryEndpoint.fromMap(Map<String, dynamic> map) {
|
||||||
|
|
@ -55,9 +43,7 @@ class AuxilaryEndpoint {
|
||||||
|
|
||||||
class AuxCheckStatus {
|
class AuxCheckStatus {
|
||||||
final String name;
|
final String name;
|
||||||
const AuxCheckStatus({
|
const AuxCheckStatus({required this.name});
|
||||||
required this.name,
|
|
||||||
});
|
|
||||||
const AuxCheckStatus._(this.name);
|
const AuxCheckStatus._(this.name);
|
||||||
|
|
||||||
static const loading = AuxCheckStatus._('loading');
|
static const loading = AuxCheckStatus._('loading');
|
||||||
|
|
@ -75,24 +61,16 @@ class AuxCheckStatus {
|
||||||
@override
|
@override
|
||||||
int get hashCode => name.hashCode;
|
int get hashCode => name.hashCode;
|
||||||
|
|
||||||
AuxCheckStatus copyWith({
|
AuxCheckStatus copyWith({String? name}) {
|
||||||
String? name,
|
return AuxCheckStatus(name: name ?? this.name);
|
||||||
}) {
|
|
||||||
return AuxCheckStatus(
|
|
||||||
name: name ?? this.name,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{'name': name};
|
||||||
'name': name,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AuxCheckStatus.fromMap(Map<String, dynamic> map) {
|
factory AuxCheckStatus.fromMap(Map<String, dynamic> map) {
|
||||||
return AuxCheckStatus(
|
return AuxCheckStatus(name: map['name'] as String);
|
||||||
name: map['name'] as String,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String toJson() => json.encode(toMap());
|
String toJson() => json.encode(toMap());
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,12 @@ class BiometricStatus {
|
||||||
final List<BiometricType> availableBiometrics;
|
final List<BiometricType> availableBiometrics;
|
||||||
final bool canAuthenticate;
|
final bool canAuthenticate;
|
||||||
|
|
||||||
const BiometricStatus({
|
const BiometricStatus({required this.availableBiometrics, required this.canAuthenticate});
|
||||||
required this.availableBiometrics,
|
|
||||||
required this.canAuthenticate,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'BiometricStatus(availableBiometrics: $availableBiometrics, canAuthenticate: $canAuthenticate)';
|
String toString() => 'BiometricStatus(availableBiometrics: $availableBiometrics, canAuthenticate: $canAuthenticate)';
|
||||||
|
|
||||||
BiometricStatus copyWith({
|
BiometricStatus copyWith({List<BiometricType>? availableBiometrics, bool? canAuthenticate}) {
|
||||||
List<BiometricType>? availableBiometrics,
|
|
||||||
bool? canAuthenticate,
|
|
||||||
}) {
|
|
||||||
return BiometricStatus(
|
return BiometricStatus(
|
||||||
availableBiometrics: availableBiometrics ?? this.availableBiometrics,
|
availableBiometrics: availableBiometrics ?? this.availableBiometrics,
|
||||||
canAuthenticate: canAuthenticate ?? this.canAuthenticate,
|
canAuthenticate: canAuthenticate ?? this.canAuthenticate,
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,9 @@ class AvailableAlbum {
|
||||||
final Album album;
|
final Album album;
|
||||||
final int assetCount;
|
final int assetCount;
|
||||||
final DateTime? lastBackup;
|
final DateTime? lastBackup;
|
||||||
const AvailableAlbum({
|
const AvailableAlbum({required this.album, required this.assetCount, this.lastBackup});
|
||||||
required this.album,
|
|
||||||
required this.assetCount,
|
|
||||||
this.lastBackup,
|
|
||||||
});
|
|
||||||
|
|
||||||
AvailableAlbum copyWith({
|
AvailableAlbum copyWith({Album? album, int? assetCount, DateTime? lastBackup}) {
|
||||||
Album? album,
|
|
||||||
int? assetCount,
|
|
||||||
DateTime? lastBackup,
|
|
||||||
}) {
|
|
||||||
return AvailableAlbum(
|
return AvailableAlbum(
|
||||||
album: album ?? this.album,
|
album: album ?? this.album,
|
||||||
assetCount: assetCount ?? this.assetCount,
|
assetCount: assetCount ?? this.assetCount,
|
||||||
|
|
|
||||||
|
|
@ -148,10 +148,7 @@ class BackUpState {
|
||||||
collectionEquals(other.selectedBackupAlbums, selectedBackupAlbums) &&
|
collectionEquals(other.selectedBackupAlbums, selectedBackupAlbums) &&
|
||||||
collectionEquals(other.excludedBackupAlbums, excludedBackupAlbums) &&
|
collectionEquals(other.excludedBackupAlbums, excludedBackupAlbums) &&
|
||||||
collectionEquals(other.allUniqueAssets, allUniqueAssets) &&
|
collectionEquals(other.allUniqueAssets, allUniqueAssets) &&
|
||||||
collectionEquals(
|
collectionEquals(other.selectedAlbumsBackupAssetsIds, selectedAlbumsBackupAssetsIds) &&
|
||||||
other.selectedAlbumsBackupAssetsIds,
|
|
||||||
selectedAlbumsBackupAssetsIds,
|
|
||||||
) &&
|
|
||||||
other.currentUploadAsset == currentUploadAsset;
|
other.currentUploadAsset == currentUploadAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,9 @@ class SuccessUploadAsset {
|
||||||
final String remoteAssetId;
|
final String remoteAssetId;
|
||||||
final bool isDuplicate;
|
final bool isDuplicate;
|
||||||
|
|
||||||
const SuccessUploadAsset({
|
const SuccessUploadAsset({required this.candidate, required this.remoteAssetId, required this.isDuplicate});
|
||||||
required this.candidate,
|
|
||||||
required this.remoteAssetId,
|
|
||||||
required this.isDuplicate,
|
|
||||||
});
|
|
||||||
|
|
||||||
SuccessUploadAsset copyWith({
|
SuccessUploadAsset copyWith({BackupCandidate? candidate, String? remoteAssetId, bool? isDuplicate}) {
|
||||||
BackupCandidate? candidate,
|
|
||||||
String? remoteAssetId,
|
|
||||||
bool? isDuplicate,
|
|
||||||
}) {
|
|
||||||
return SuccessUploadAsset(
|
return SuccessUploadAsset(
|
||||||
candidate: candidate ?? this.candidate,
|
candidate: candidate ?? this.candidate,
|
||||||
remoteAssetId: remoteAssetId ?? this.remoteAssetId,
|
remoteAssetId: remoteAssetId ?? this.remoteAssetId,
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue