From 242817c49acff380269490c99081d13c86acf65b Mon Sep 17 00:00:00 2001 From: Daimolean <92239625+wuzihao051119@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:09:14 +0800 Subject: [PATCH] feat(mobile): remote album sync (#18876) * feat(mobile): remote album sync * fix: lint * missing createdAt field * lint --- .../interfaces/sync_stream.interface.dart | 9 + .../lib/domain/models/album/album.model.dart | 68 ++++++++ .../lib/domain/models/album_user.model.dart | 5 + .../domain/services/sync_stream.service.dart | 12 ++ .../entities/album_user.entity.dart | 20 +++ .../entities/album_user.entity.drift.dart | Bin 0 -> 23214 bytes .../entities/remote_album.entity.dart | 34 ++++ .../entities/remote_album.entity.drift.dart | Bin 0 -> 38486 bytes .../entities/remote_album_asset.entity.dart | 17 ++ .../remote_album_asset.entity.drift.dart | Bin 0 -> 22086 bytes .../repositories/db.repository.dart | 10 +- .../repositories/db.repository.drift.dart | Bin 5740 -> 8649 bytes .../repositories/sync_api.repository.dart | 9 + .../repositories/sync_stream.repository.dart | 156 +++++++++++++++++- .../pages/dev/feat_in_development.page.dart | 4 +- .../pages/dev/media_stat.page.dart | 4 + mobile/lib/repositories/auth.repository.dart | 4 +- 17 files changed, 346 insertions(+), 6 deletions(-) create mode 100644 mobile/lib/domain/models/album/album.model.dart create mode 100644 mobile/lib/domain/models/album_user.model.dart create mode 100644 mobile/lib/infrastructure/entities/album_user.entity.dart create mode 100644 mobile/lib/infrastructure/entities/album_user.entity.drift.dart create mode 100644 mobile/lib/infrastructure/entities/remote_album.entity.dart create mode 100644 mobile/lib/infrastructure/entities/remote_album.entity.drift.dart create mode 100644 mobile/lib/infrastructure/entities/remote_album_asset.entity.dart create mode 100644 mobile/lib/infrastructure/entities/remote_album_asset.entity.drift.dart diff --git a/mobile/lib/domain/interfaces/sync_stream.interface.dart b/mobile/lib/domain/interfaces/sync_stream.interface.dart index 5f61d6b52..502cf0ad4 100644 --- a/mobile/lib/domain/interfaces/sync_stream.interface.dart +++ b/mobile/lib/domain/interfaces/sync_stream.interface.dart @@ -15,4 +15,13 @@ abstract interface class ISyncStreamRepository implements IDatabaseRepository { Future updatePartnerAssetsV1(Iterable data); Future deletePartnerAssetsV1(Iterable data); Future updatePartnerAssetsExifV1(Iterable data); + + Future updateAlbumsV1(Iterable data); + Future deleteAlbumsV1(Iterable data); + + // Future updateAlbumAssetsV1(Iterable data); + // Future deleteAlbumAssetsV1(Iterable data); + + Future updateAlbumUsersV1(Iterable data); + Future deleteAlbumUsersV1(Iterable data); } diff --git a/mobile/lib/domain/models/album/album.model.dart b/mobile/lib/domain/models/album/album.model.dart new file mode 100644 index 000000000..47683121b --- /dev/null +++ b/mobile/lib/domain/models/album/album.model.dart @@ -0,0 +1,68 @@ +enum AssetOrder { + // do not change this order! + asc, + desc, +} + +// Model for an album stored in the server +class Album { + final String id; + final String name; + final String description; + final DateTime createdAt; + final DateTime updatedAt; + final String? thumbnailAssetId; + final bool isActivityEnabled; + final AssetOrder order; + + const Album({ + required this.id, + required this.name, + required this.description, + required this.createdAt, + required this.updatedAt, + this.thumbnailAssetId, + required this.isActivityEnabled, + required this.order, + }); + + @override + String toString() { + return '''Album { + id: $id, + name: $name, + description: $description, + createdAt: $createdAt, + updatedAt: $updatedAt, + isActivityEnabled: $isActivityEnabled, + order: $order, + thumbnailAssetId: ${thumbnailAssetId ?? ""} + }'''; + } + + @override + bool operator ==(Object other) { + if (other is! Album) return false; + if (identical(this, other)) return true; + return id == other.id && + name == other.name && + description == other.description && + createdAt == other.createdAt && + updatedAt == other.updatedAt && + thumbnailAssetId == other.thumbnailAssetId && + isActivityEnabled == other.isActivityEnabled && + order == other.order; + } + + @override + int get hashCode { + return id.hashCode ^ + name.hashCode ^ + description.hashCode ^ + createdAt.hashCode ^ + updatedAt.hashCode ^ + thumbnailAssetId.hashCode ^ + isActivityEnabled.hashCode ^ + order.hashCode; + } +} diff --git a/mobile/lib/domain/models/album_user.model.dart b/mobile/lib/domain/models/album_user.model.dart new file mode 100644 index 000000000..10c03a7c4 --- /dev/null +++ b/mobile/lib/domain/models/album_user.model.dart @@ -0,0 +1,5 @@ +enum AlbumUserRole { + // do not change this order! + editor, + viewer, +} diff --git a/mobile/lib/domain/services/sync_stream.service.dart b/mobile/lib/domain/services/sync_stream.service.dart index 99d7de6cc..f997bef13 100644 --- a/mobile/lib/domain/services/sync_stream.service.dart +++ b/mobile/lib/domain/services/sync_stream.service.dart @@ -81,6 +81,18 @@ class SyncStreamService { return _syncStreamRepository.deletePartnerAssetsV1(data.cast()); case SyncEntityType.partnerAssetExifV1: return _syncStreamRepository.updatePartnerAssetsExifV1(data.cast()); + case SyncEntityType.albumV1: + return _syncStreamRepository.updateAlbumsV1(data.cast()); + case SyncEntityType.albumDeleteV1: + return _syncStreamRepository.deleteAlbumsV1(data.cast()); + // case SyncEntityType.albumAssetV1: + // return _syncStreamRepository.updateAlbumAssetsV1(data.cast()); + // case SyncEntityType.albumAssetDeleteV1: + // return _syncStreamRepository.deleteAlbumAssetsV1(data.cast()); + case SyncEntityType.albumUserV1: + return _syncStreamRepository.updateAlbumUsersV1(data.cast()); + case SyncEntityType.albumUserDeleteV1: + return _syncStreamRepository.deleteAlbumUsersV1(data.cast()); default: _logger.warning("Unknown sync data type: $type"); } diff --git a/mobile/lib/infrastructure/entities/album_user.entity.dart b/mobile/lib/infrastructure/entities/album_user.entity.dart new file mode 100644 index 000000000..c9bbfbd22 --- /dev/null +++ b/mobile/lib/infrastructure/entities/album_user.entity.dart @@ -0,0 +1,20 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/domain/models/album_user.model.dart'; +import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart'; +import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; + +class AlbumUserEntity extends Table with DriftDefaultsMixin { + const AlbumUserEntity(); + + TextColumn get albumId => + text().references(RemoteAlbumEntity, #id, onDelete: KeyAction.cascade)(); + + TextColumn get userId => + text().references(UserEntity, #id, onDelete: KeyAction.cascade)(); + + IntColumn get role => intEnum()(); + + @override + Set get primaryKey => {albumId, userId}; +} diff --git a/mobile/lib/infrastructure/entities/album_user.entity.drift.dart b/mobile/lib/infrastructure/entities/album_user.entity.drift.dart new file mode 100644 index 0000000000000000000000000000000000000000..008e0bb52b9ff4a972cb438a6633f531af26a7cc GIT binary patch literal 23214 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 literal 0 HcmV?d00001 diff --git a/mobile/lib/infrastructure/entities/remote_album.entity.dart b/mobile/lib/infrastructure/entities/remote_album.entity.dart new file mode 100644 index 000000000..7f9f1efa6 --- /dev/null +++ b/mobile/lib/infrastructure/entities/remote_album.entity.dart @@ -0,0 +1,34 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/domain/models/album/album.model.dart'; +import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; +import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; + +class RemoteAlbumEntity extends Table with DriftDefaultsMixin { + const RemoteAlbumEntity(); + + TextColumn get id => text()(); + + TextColumn get name => text()(); + + TextColumn get description => text()(); + + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + + DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); + + TextColumn get ownerId => + text().references(UserEntity, #id, onDelete: KeyAction.cascade)(); + + TextColumn get thumbnailAssetId => text() + .references(RemoteAssetEntity, #id, onDelete: KeyAction.setNull) + .nullable()(); + + BoolColumn get isActivityEnabled => + boolean().withDefault(const Constant(true))(); + + IntColumn get order => intEnum()(); + + @override + Set get primaryKey => {id}; +} diff --git a/mobile/lib/infrastructure/entities/remote_album.entity.drift.dart b/mobile/lib/infrastructure/entities/remote_album.entity.drift.dart new file mode 100644 index 0000000000000000000000000000000000000000..cc7b642c9bf6d2771e4225a212f21d06cd0d007b GIT binary patch literal 38486 zcmeG_+j1PYvG4i{D8&kwRjj4#*l~)M$U{@qi5y!>NtE;8Qn7}+Lvifg9eQTgG7rsv zPj>@oG;XuAyvR|G^dO0Y2GHnxH!j@SQPZO7)LGrki%z|-rrr6Izdd@ev!kkai@GUK zpylMOnw7h%ySyl$%&JBApqgLQ&}s9cnEYJ4D|e?&b=K|B-(wtZQx&bM9(^4FR`Yo^ zIX{`#r!eA9wK!{vwriG?ZrPMO<)W*)s%&?fa$a}kNijQJ&d2oiax4aapx_Tq@Y$*f zruDq27CZBLTF%-X8c+W{rcVOb&sPn#7OqGF#_})m(3)OtGudgDu;_WY^UJbqE>BLE z)ofZe{!aqSFXEwwQFPgsO&=w{j0e^@0=LU%QOuBr%URI~Wd0iW8HS8yZ`+n#A5vd^ z{on!0+_XGX8yl}kC=O62j!;l8kBie;dDxUiS02{$i(*mLi*GamiS|!GK*muo2360N zi%AE4Mpppdl)o&irktwRT~jUIscO2N__`?OW$OF1Y$r{1fumt_^=SMT9yP~Tms`_%g@dm7z(0z4c7(|qMrUvN2A`AoigZ?94e*tW#eR0&zAFrdZIQ?s;-vuSDLa}F>xrK0KZXbm9Q9~)hT^WyfSlv@m)X%T z%VO4!EJ2XMIFBY1Qie!GK31z7%wK3CzieJCXS0#7VuZ9Aq&ib0J;W2W0MIS)p%BI` zl%b-Y%6tQ5Nb=B;&-5B^puU&mNquqouc|vAT{K|dy2-gVS-a{-ob#<-$+ff(U$F^8 zKj@i>&_!x{A^3DJrX!1xP)|fPrJm!D(2|5y)~-X#HU51IlX4qUS_FiJf#IyX3uGlJ zr2AxP!sV@Ja=7;i_;TPm8Xv78s7F>o)ssM%P_d-W3JdiW%WrlyAIMOx&7BWnx0v82 zEY>>zA7{Y8g!PAa&&aT2kX=L6K|B{>p8ftfWx=+4;=2CG&7YJKB#|PSC=P-+LWi>z z^Sz^hj+*qBpX$mcX1a#~ET+?MUDI*>s;)b`AP*3OnO{o*`>d(wAv9(zU}PSRwYS$x zXsy#H6|Sb}95*IJOvKWpEY=I@uwhqi&=SC4Y%7zI@2Zh*B=;IlV%q?NRVZK%vlbGR z^xQcbB4b($8`002_q(8w%abvt<6L^-YsZkgK~nW=*+49670^p>!6eCQ1N^w?Y<5QBJk=n2l@$GXps1#1VLiQCp)NU8 z12squBok)(DrWtv-}q&#TsQN#VSQ%LbBuFqfFZ7ox|{%$^$yA-_3_%8(~7SUNYjL$Ep7`!cZ4?G_RcPhTq_gu|0>m}?=Kre6=)(hINP!1vQu@0ei-yKyEvdH+eX0kYa!TYb;ccA0qnPiG=&C%rp**csO^SD66`yWO)QAm z$N$5}BfR}rUzT)_yEG*@qTp|DX$4_dvn^F#8P+piYj2rlW#Vr(W2ofXILU zTUGJIA6fFnN3wLK)XREk!^+5UV%sW+^RoL@Cb_V?Q++d-w zv~>VdiJT`kGizl%iS9N4y6Xz^r@Uv7>x?6w)DBS0w=mH8vG%-_jMCP8%w;$VNbRO7p45I@Ri_UfoElhSS56q96pE1i(CDD-Xt#^ z={}>>WiJTt3w;VQLlxf7Znt=aufmIFGzuAZIQaKZtTDlP^uO2j&#kyahEcS=jR0{t z{uI`#uDAM6T}nBz_9S(#6E3y%9qm+PTI?CyU4798ucOHEU*jozI|&*jtkw8uS!ft= zQ0_PuZ#%Ix_Wy$sD3IddqQW@4C%ov#MZ>Owfe z@VO6RUwH}Fr=C^i430M0<5_F2Jk}M-35~pQAN>T;nIGaow;vCS+3XaqEQKa&b31t!W1-+WWF*&;IX~j*^ zEze!P>*>A=(E&^4U$}KpEE>D+7_l@VN-^Vi-G6-u!`NLm=bkQwRvkn5_y(@SC}IyR zIdvb`^`JTh%&u?Zy6>K5>V-00v#QUh^R?JUX?Wtod25alwxLUx~k?xb~p|!aK)q4*|-8pdlzPNxp&ERn_9?=o(i$|XF zz;4yNxEPH}YV=uPHM@ijEpzK~6bC&PsyCKmbXvH}ylrAORoWoXjiJ<5_;K9T-&Jkk z`0cez3Uj4#abE8Xu9m{Z?a=yxOd3->|a`ofjY8;;A^!iv7=FI)~@_-}FI%f%#cDTu9^=f}4zCNbBo^#TO~xUm4o8&*9u zl)M>Ei-y-CGOrsrZvqg!>yG6l_w)+lgYp%nOe7?ZP5={uxWbejB{NK___v}vPys2t*un{rZZ5*zb-Cf;iLw+TXS?2xl|QJ@AOjBnU2Q`AaMZB!=i3 zQ4$IK`Qog8oDl}99Y(XDEa~#(|G-`Arm3bS3~OErNl33Mx~{O#a-cY)`e|^JQ7QfU z4SvsH0{)?D$KgQR>PPynyT2v9MJoc20J(})2`|o76FPA8ec2TX9#o)zWmPMH8Ex7} z7vu_OPzOycQ(ImxdQrVhDzV>g!x5ZeThXIG<@5zU7N%ois|9FeAP0Fgeu@v~z5Zo} zH)h8zJvp|`Z;(A*;uB=gDQSZ+rdgH)X@I%ArUFR>ZZp~nUqlOp)lX2YPYvt~A=v zo)p~;sWkp}HgKh`+RJ`ylK26ST^X=F1kzUVuw zkQ>Q`_Zh(7z_WK96i8yD1P^c7_UG-v?0s?BTIYu1zxnFu+0m<`7l%i$m3RdYg01P6 zdig>bNe0vpZyYM?+m8 zR%}lS^JpqO(1yjvekING7YDRTh)^G#yN7>2I{b$k{VB1eKdI+0)acQ+`fO`!(*wCCZ@2IT;1UKaoEvb+V<*GK)eYFZ#d%aSg+YcTH~Lz*1;&f5w}oB zsyf2L^}9CydE`B59dWjNEZQdaC9Vdt|d}X*F`5gasM1Cp<#hVy`r{6S<-AO{_s?^3@4 z-WW$dhacZH@U*fO1c2A68`_M=xzYhVa!iUeVU}H?oq+u*-5KAY4mVPCb`3&A2vGi& zz-&ZvWpi;rvA|HoOa^;BTBusBz_?glghxPh{`ewp`;YQcXUnc&Yo;Ba7mMkv9GQF@ zY6;UZ3c;kj=y1U=n>UM}7a&0+9Pmd>h~GZkw&}S&#CxsaJ@%4{|6;-MWb>+Rff9B$ zvoc+4#`H2*|5%}DV9r?@d4!f{rUL!^CqYMii%3kkptndR&Cib;sy z+{;@mkt!{KB4z5qlC5rtB{%e9DJCH-xz|uEIq&Gf(YS#SL-V;8KOUa269e5?T;v$5 zMTH%f3(fNj6>@*V9gU|87az7~s33-Ps>FRAQbZp9F6Lx9^+;MGoEvB+BCj1TGXhv= zohiI%q0y+ZwDKEYHAS7tJO3FAM^%s_8Y3A-m@sGCW&- zF@nP!rsTVAxBU0W5ZbWjN=Fd;`h*2;SyjLBK?m)h%d@i*6Ngf_g7YQEXnuOAANW=K zYEz$c)!)aPYFBM;YRR?-B{Dlc9B9CCmauj{#$XqZq=45HLP!Tp@Cb0S?yN1}##Mm% zHTv$Yhj!`cxbAsE?PlGS!bjZm%wi_FX14zQ(`)hydWVz-3hRQS@v1ScrQdM`V7q?r z^GlE7<~LTie|E9%o5`8;7H;OyDE6bUk^!yRV#$d*PbX|Mr^Aumx+OAH5XeeG(tJ9? zP+A3*yX=;6m}ZX8;IU-bY8r*MLh@}Lvq712j*vPn2eVCCRlk2uFIHo%CG=wq zT(wB4Nrw(k1M*`H$xU9jlML=JFj&3K~*e1F*BPzyPh2Ozh2M4qrgvq&sUytP4J-+FqxY(#U zpCqsK&R4d~2eZQ_w=2~6-;p@h!}=|PLTLbYPU&W*Q@Ys@%Qg~{A)Rcak62_5(_mx? z^rP%j$YqEHdU*8P1^l+17Tyg3>E+r4u?2tk!Et>+w^FPD(1Hb_8iZ9GsrkcPQOKt- zp3~(AEPvn~m!=|N*1`fRIW^@30@R^L1{515uwc#R+e{w;BfCmJAM~`+zc*se%AV3g zXL~Z!Wl!f{gMOA2MixvT%xfP?;;Y|(k5ovRK-MzG(3>Sl_|eRy3~JIIGrKN`XyzqK z@FBTTQh=A?sctja71=d|n{iD6I%wgo&SI{%hGXq&bgMM1pRXA=1&csqLEi5Ss+o0j zsggE>Tr_&5bOQ1dv{)UxB2fnS@fvE9;2Zz1Z1xqL?l=GET*Q5XQYt9`{XV}}`qvG< zq+eCnj!lu@jfME~k-8+VmR5Lm$4$a3uqS3lh_u!}j-ybGhIG=p$lZh{4e2ewA(Xdt zW0gt|;dD>q&ER4P)~#VfFt`}PC|Y^|tBo2111dU)3ez{r{+?k#*h!2RDNTAntzm|p zp`MB1NDtNtOpR`$z_Iv@QX)kvYN$fHKJe?GG+#;0(PHF0j6H!4zU5oguMep{?4K+W z)*4|^+@rNdj#URdlNH-d(uF=?@=Xjbg}<+tfOB&>p-**nD#CECs}uJAt_wIreg%H|J9_c`mF*zs0=xEoH!r@l#g+$i)7d;onHsnyUbu9kPX+poa zY~{jGR69-H{phl#{Vt@$E)~03N!WLBdb*jpEt~D&hNrU0`Zl8pH@=gH{Mzro>g5IY z`#Q3h7wdB5weAlB1-iS68zr?6V zEp8m+u;?F#r=KhgxtC-V1R0?I{e*l0H+kHgTdCS(V`UQ_CI`0ih0-;}Em_!KHKYXc z*)LQ;fQoS-c_?J28~!)!NZ-7!QYwYW$!8^LO3@Y$Dx18qMT4a$%cwz;e+~zA4c?Ia z*$&7;YzE|?!vS4`Hz0qu1F{OxvdvH7VD_^&RG=fF_!aeLr64mVi!^}q z|8t|WxB@W$KL^aBykSK%gF+~2FnIVWH%G*H=o@{@btc|J2l_WnaX6FaZY#st70Yo> ztEF5(s6_{g&WrZ^u%6Pd*?W2V6Kux8p_TR=3O@Rz2W;(0z6h#2ni@T0%EbgpERz;O zGAq%-U_{k$N4$Un0Q`c_k;X~Y-FexF7jxjk4g6aBNim~aG26EN_umaJBkBOIE_)qG z{rS(rJ`gy#5B!~?#!sXGP^cM%en^ZW2*$ATTcQh-l{>gE32-JogS#&YaKjh|wm&C8 zL)LMhs3Flg;xhM+TN2$#BDjl{k9>We;|1cQct-4v|MFGOu`;xUx=I>E({SQU)aIi` zWId`?rmx_30_v$L+{0_PbenH_(DgzwZxc{j$N3z679x=yBw#6Zi{rxtq?ZwxM{p1< zQ|o6|nWvVlipdLTxXlwht3+U0=fv%-9H5{&lr4F`>4zLVQ-2UNb72s)Rk0y>M5;BU zQ>;-#dKne#BaYsLhynrTpnV_ZinNY5JG3Bz*63&^{Ekdaw+OCj0Al(*@g_vex-41? zP5fb)!FYIjH86kZ|vmmO35}yUIlT~Zy_>l=W zp_Lp5f{`crZ?{i8Xcu&{Y`c1H3;_)1HnnU`52_JHj55tmnlb=lp?V2E99!V1D3gU_ z^-qmwtT0qY^mV3Qm{7t}z+{NCMHwGSESi~`3=YMc8YaRA;8(?a5+QS18aMX%$vfP? z0y*OiDqU{1^w+1I$pSkF{1GaDjtS;Ww2KqPaDo%iNBpFht-CsHce9vpc$-dCaAYrL ziI~oO)4do#_OjCMW}+{6t&D3q5V1+hLJ9$&#qm$liAh z_CZ^ib7ni0scOgSS3ohQXTYr^fQD zglaK7H(F>W`JmFMQ7~2}9@jIDaMLI_XA-Lp_Y6TTVv#;26ovFxvjJLW z1);uVW??YrzjE_2s4v#xj;9fc o6D_jFrFnSclB{za=`!G_x@_4!$J%r#v$@i0B(xv2E_?mp-vf6yegFUf literal 0 HcmV?d00001 diff --git a/mobile/lib/infrastructure/entities/remote_album_asset.entity.dart b/mobile/lib/infrastructure/entities/remote_album_asset.entity.dart new file mode 100644 index 000000000..1dcc336ed --- /dev/null +++ b/mobile/lib/infrastructure/entities/remote_album_asset.entity.dart @@ -0,0 +1,17 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; +import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; + +class RemoteAlbumAssetEntity extends Table with DriftDefaultsMixin { + const RemoteAlbumAssetEntity(); + + TextColumn get assetId => + text().references(RemoteAssetEntity, #id, onDelete: KeyAction.cascade)(); + + TextColumn get albumId => + text().references(RemoteAlbumEntity, #id, onDelete: KeyAction.cascade)(); + + @override + Set get primaryKey => {assetId, albumId}; +} diff --git a/mobile/lib/infrastructure/entities/remote_album_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/remote_album_asset.entity.drift.dart new file mode 100644 index 0000000000000000000000000000000000000000..ab50607c96814f1c84faed6c178c4a5a4e96597b GIT binary patch literal 22086 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 Nq$+}@5a`-kE&ve@--iGI delta 30 mcmX@<{6=R(81v?OmZ{8}eK}V%Zua5c$Fcd1lo%^hEf)a3(+b`I diff --git a/mobile/lib/infrastructure/repositories/sync_api.repository.dart b/mobile/lib/infrastructure/repositories/sync_api.repository.dart index ca24eef60..70f940c10 100644 --- a/mobile/lib/infrastructure/repositories/sync_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_api.repository.dart @@ -50,6 +50,9 @@ class SyncApiRepository implements ISyncApiRepository { SyncRequestType.partnerAssetsV1, SyncRequestType.assetExifsV1, SyncRequestType.partnerAssetExifsV1, + SyncRequestType.albumsV1, + // SyncRequestType.albumAssetsV1, + SyncRequestType.albumUsersV1, ], ).toJson(), ); @@ -140,4 +143,10 @@ const _kResponseMap = { SyncEntityType.partnerAssetV1: SyncAssetV1.fromJson, SyncEntityType.partnerAssetDeleteV1: SyncAssetDeleteV1.fromJson, SyncEntityType.partnerAssetExifV1: SyncAssetExifV1.fromJson, + SyncEntityType.albumV1: SyncAlbumV1.fromJson, + SyncEntityType.albumDeleteV1: SyncAlbumDeleteV1.fromJson, + // SyncEntityType.albumAssetV1: SyncAlbumAssetV1.fromJson, + // SyncEntityType.albumAssetDeleteV1: SyncAlbumAssetDeleteV1.fromJson, + SyncEntityType.albumUserV1: SyncAlbumUserV1.fromJson, + SyncEntityType.albumUserDeleteV1: SyncAlbumUserDeleteV1.fromJson, }; diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index 7aa8fc6ef..472bc9a6b 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -3,12 +3,19 @@ import 'package:immich_mobile/domain/interfaces/sync_stream.interface.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'; +import 'package:immich_mobile/domain/models/album/album.model.dart'; +import 'package:immich_mobile/domain/models/album_user.model.dart'; +import 'package:immich_mobile/infrastructure/entities/album_user.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart'; +// import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:logging/logging.dart'; -import 'package:openapi/api.dart' as api show AssetVisibility; -import 'package:openapi/api.dart' hide AssetVisibility; +import 'package:openapi/api.dart' as api + show AssetVisibility, AssetOrder, AlbumUserRole; +import 'package:openapi/api.dart' + hide AssetVisibility, AssetOrder, AlbumUserRole; class DriftSyncStreamRepository extends DriftDatabaseRepository implements ISyncStreamRepository { @@ -161,6 +168,135 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository } } + @override + Future updateAlbumsV1(Iterable data) async { + try { + await _db.batch((batch) { + for (final album in data) { + final companion = RemoteAlbumEntityCompanion( + name: Value(album.name), + description: Value(album.description), + ownerId: Value(album.ownerId), + thumbnailAssetId: Value(album.thumbnailAssetId), + createdAt: Value(album.createdAt), + updatedAt: Value(album.updatedAt), + isActivityEnabled: Value(album.isActivityEnabled), + order: Value(album.order.toAssetOrder()), + ); + + batch.insert( + _db.remoteAlbumEntity, + companion.copyWith(id: Value(album.id)), + onConflict: DoUpdate((_) => companion), + ); + } + }); + } catch (e, s) { + _logger.severe('Error while processing updateAlbumsV1', e, s); + rethrow; + } + } + + @override + Future deleteAlbumsV1(Iterable data) async { + try { + _db.batch((batch) { + for (final album in data) { + batch.delete( + _db.remoteAlbumEntity, + RemoteAlbumEntityCompanion(id: Value(album.albumId)), + ); + } + }); + } catch (e, s) { + _logger.severe('Error while processing deleteAlbumsV1', e, s); + rethrow; + } + } + + // @override + // Future updateAlbumAssetsV1(Iterable data) async { + // try { + // await _db.remoteAlbumAssetEntity.insertAll( + // data.map( + // (albumAsset) => RemoteAlbumAssetEntityCompanion.insert( + // albumId: albumAsset.albumId, + // assetId: albumAsset.assetId, + // ), + // ), + // mode: InsertMode.insertOrIgnore, + // ); + // } catch (e, s) { + // _logger.severe('Error while processing updateAlbumAssetsV1', e, s); + // rethrow; + // } + // } + + // @override + // Future deleteAlbumAssetsV1(Iterable data) async { + // try { + // await _db.batch((batch) { + // for (final albumAsset in data) { + // batch.delete( + // _db.remoteAlbumAssetEntity, + // RemoteAlbumAssetEntityCompanion( + // albumId: Value(albumAsset.albumId), + // assetId: Value(albumAsset.assetId), + // ), + // ); + // } + // }); + // } catch (e, s) { + // _logger.severe('Error while processing deleteAlbumAssetsV1', e, s); + // rethrow; + // } + // } + + @override + Future updateAlbumUsersV1(Iterable data) async { + try { + await _db.batch((batch) { + for (final albumUser in data) { + final companion = AlbumUserEntityCompanion( + role: Value(albumUser.role.toAlbumUserRole()), + ); + + batch.insert( + _db.albumUserEntity, + companion.copyWith( + albumId: Value(albumUser.albumId), + userId: Value(albumUser.userId), + ), + onConflict: DoUpdate((_) => companion), + ); + } + }); + } catch (e, s) { + _logger.severe('Error while processing updateAlbumUsersV1', e, s); + rethrow; + } + } + + @override + Future deleteAlbumUsersV1(Iterable data) async { + try { + await _db.batch((batch) { + for (final albumUser in data) { + batch.delete( + _db.albumUserEntity, + AlbumUserEntityCompanion( + albumId: Value(albumUser.albumId), + userId: Value(albumUser.userId), + ), + ); + } + }); + } catch (e, s) { + _logger.severe('Error while processing deleteAlbumUsersV1', e, s); + rethrow; + } + } + Future _updateAssetsV1(Iterable data) => _db.batch((batch) { for (final asset in data) { @@ -251,3 +387,19 @@ extension on api.AssetVisibility { _ => throw Exception('Unknown AssetVisibility value: $this'), }; } + +extension on api.AssetOrder { + AssetOrder toAssetOrder() => switch (this) { + api.AssetOrder.asc => AssetOrder.asc, + api.AssetOrder.desc => AssetOrder.desc, + _ => throw Exception('Unknown AssetOrder value: $this'), + }; +} + +extension on api.AlbumUserRole { + AlbumUserRole toAlbumUserRole() => switch (this) { + api.AlbumUserRole.editor => AlbumUserRole.editor, + api.AlbumUserRole.viewer => AlbumUserRole.viewer, + _ => throw Exception('Unknown AlbumUserRole value: $this'), + }; +} diff --git a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart index edbbd2379..0e532375d 100644 --- a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart +++ b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart @@ -63,8 +63,10 @@ final _features = [ icon: Icons.delete_sweep_rounded, onTap: (_, ref) async { final db = ref.read(driftProvider); - await db.remoteAssetEntity.deleteAll(); await db.remoteExifEntity.deleteAll(); + await db.remoteAssetEntity.deleteAll(); + await db.remoteAlbumEntity.deleteAll(); + await db.remoteAlbumAssetEntity.deleteAll(); }, ), _Feature( diff --git a/mobile/lib/presentation/pages/dev/media_stat.page.dart b/mobile/lib/presentation/pages/dev/media_stat.page.dart index c074e524b..4a1562900 100644 --- a/mobile/lib/presentation/pages/dev/media_stat.page.dart +++ b/mobile/lib/presentation/pages/dev/media_stat.page.dart @@ -132,6 +132,10 @@ final _remoteStats = [ name: 'Exif Entities', load: (db) => db.managers.remoteExifEntity.count(), ), + _Stat( + name: 'Remote Albums', + load: (db) => db.managers.remoteAlbumEntity.count(), + ), ]; @RoutePage() diff --git a/mobile/lib/repositories/auth.repository.dart b/mobile/lib/repositories/auth.repository.dart index 01d2684fa..69a2fa024 100644 --- a/mobile/lib/repositories/auth.repository.dart +++ b/mobile/lib/repositories/auth.repository.dart @@ -35,8 +35,10 @@ class AuthRepository extends DatabaseRepository implements IAuthRepository { db.albums.clear(), db.eTags.clear(), db.users.clear(), - _drift.remoteAssetEntity.deleteAll(), _drift.remoteExifEntity.deleteAll(), + _drift.remoteAssetEntity.deleteAll(), + _drift.remoteAlbumEntity.deleteAll(), + _drift.remoteAlbumAssetEntity.deleteAll(), ]); }); }