From ebecb60f39819e8b56cfe29dd8b118b065ef487d Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 29 Aug 2024 14:29:04 -0500 Subject: [PATCH] feat: user's features preferences (#12099) * feat: metadata in UserPreference * feat: web metadata settings * feat: web metadata settings * fix: typo * patch openapi * fix: missing translation key * new organization of preference strucutre * feature settings on web * localization * added and used feature settings * add default value to response dto * patch openapi * format en.json file * implement helper method * use tags preference logic * Fix logic bug and add tests * fix preference can be null in detail panel --- mobile/lib/utils/openapi_patching.dart | 30 +++- mobile/openapi/README.md | Bin 31345 -> 31605 bytes mobile/openapi/lib/api.dart | Bin 11018 -> 11226 bytes mobile/openapi/lib/api_client.dart | Bin 28517 -> 28993 bytes .../openapi/lib/model/folders_response.dart | Bin 0 -> 3044 bytes mobile/openapi/lib/model/folders_update.dart | Bin 0 -> 3880 bytes ...y_response.dart => memories_response.dart} | Bin 2761 -> 2795 bytes ...ating_update.dart => memories_update.dart} | Bin 3157 -> 3193 bytes mobile/openapi/lib/model/people_response.dart | Bin 0 -> 3025 bytes mobile/openapi/lib/model/people_update.dart | Bin 0 -> 3862 bytes ...ng_response.dart => ratings_response.dart} | Bin 2760 -> 2778 bytes ...memory_update.dart => ratings_update.dart} | Bin 3157 -> 3175 bytes mobile/openapi/lib/model/tags_response.dart | Bin 0 -> 2988 bytes mobile/openapi/lib/model/tags_update.dart | Bin 0 -> 3826 bytes .../model/user_preferences_response_dto.dart | Bin 4386 -> 5086 bytes .../model/user_preferences_update_dto.dart | Bin 6942 -> 8920 bytes .../modules/utils/openapi_patching_test.dart | 49 ++++++ open-api/immich-openapi-specs.json | 162 +++++++++++++++--- open-api/typescript-sdk/src/fetch-client.ts | 46 ++++- server/src/dtos/user-preferences.dto.ts | 85 +++++++-- server/src/entities/user-metadata.entity.ts | 28 ++- .../detail-panel-star-rating.svelte | 2 +- .../asset-viewer/detail-panel.svelte | 10 +- .../settings/setting-accordion.svelte | 17 +- .../side-bar/side-bar.svelte | 38 ++-- .../user-settings-page/app-settings.svelte | 43 ----- .../feature-settings.svelte | 124 ++++++++++++++ .../memories-settings.svelte | 46 ----- .../user-settings-list.svelte | 7 +- web/src/lib/i18n/en.json | 9 +- web/src/lib/stores/preferences.store.ts | 5 - .../(user)/photos/[[assetId=id]]/+page.svelte | 4 +- 32 files changed, 519 insertions(+), 186 deletions(-) create mode 100644 mobile/openapi/lib/model/folders_response.dart create mode 100644 mobile/openapi/lib/model/folders_update.dart rename mobile/openapi/lib/model/{memory_response.dart => memories_response.dart} (62%) rename mobile/openapi/lib/model/{rating_update.dart => memories_update.dart} (68%) create mode 100644 mobile/openapi/lib/model/people_response.dart create mode 100644 mobile/openapi/lib/model/people_update.dart rename mobile/openapi/lib/model/{rating_response.dart => ratings_response.dart} (63%) rename mobile/openapi/lib/model/{memory_update.dart => ratings_update.dart} (69%) create mode 100644 mobile/openapi/lib/model/tags_response.dart create mode 100644 mobile/openapi/lib/model/tags_update.dart create mode 100644 mobile/test/modules/utils/openapi_patching_test.dart create mode 100644 web/src/lib/components/user-settings-page/feature-settings.svelte delete mode 100644 web/src/lib/components/user-settings-page/memories-settings.svelte diff --git a/mobile/lib/utils/openapi_patching.dart b/mobile/lib/utils/openapi_patching.dart index 7a2f7396e..349b2322a 100644 --- a/mobile/lib/utils/openapi_patching.dart +++ b/mobile/lib/utils/openapi_patching.dart @@ -4,14 +4,30 @@ dynamic upgradeDto(dynamic value, String targetType) { switch (targetType) { case 'UserPreferencesResponseDto': if (value is Map) { - if (value['rating'] == null) { - value['rating'] = RatingResponse().toJson(); - } - - if (value['download']['includeEmbeddedVideos'] == null) { - value['download']['includeEmbeddedVideos'] = false; - } + addDefault(value, 'download.includeEmbeddedVideos', false); + addDefault(value, 'folders', FoldersResponse().toJson()); + addDefault(value, 'memories', MemoriesResponse().toJson()); + addDefault(value, 'ratings', RatingsResponse().toJson()); + addDefault(value, 'people', PeopleResponse().toJson()); + addDefault(value, 'tags', TagsResponse().toJson()); } break; } } + +addDefault(dynamic value, String keys, dynamic defaultValue) { + // Loop through the keys and assign the default value if the key is not present + List keyList = keys.split('.'); + dynamic current = value; + + for (int i = 0; i < keyList.length - 1; i++) { + if (current[keyList[i]] == null) { + current[keyList[i]] = {}; + } + current = current[keyList[i]]; + } + + if (current[keyList.last] == null) { + current[keyList.last] = defaultValue; + } +} diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 1f8958dd95d4d69c176ec83d188f268bfd19d1c8..b831f60b9a2a040f633782e280c981aff7b6f0fc 100644 GIT binary patch delta 362 zcmezPh4Je*#tpY({N3_%Qc{bGgHnqN^7D#QV>MFpllAq{MD=o0G`SRX6{4Zyp#>?4 zC1`3PVw*3 za{^NH3vyDSZk#NU>>-RI0kzsYIhn~B-Qu9clFYnxxG3BwP;nG@K*ct{O`X8&l!(v- WwJZcl2yPBY5XBILz~URukV|hn_pBJlv-SnpI4kZSurtN2t_8e zASJP6b6KJk)8swL2Af4v{FroLs-X&l5=%1k(qV#nxha}l3c3o>5aG!a(}XuKO`E_w Nd3Oot=B|?0Yyev>Hi-ZL diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index 532d7e22cddf407262a0a238af61ed93ecd372bf..d6ce89624cee6a1a7567c5b1465d084967558405 100644 GIT binary patch delta 137 zcmeAQyA{6Sh7em?eojhi(PS$@Id%xMc=CKn>CHEUW-&2krh>#da#M5ji!xKe5|j6d zvQI7%jhy^J)MfGvHHpo+VjYZ=T?9oY^GdK!ek-m!d6}fhW?qTwj3BL(?@6*TLJU-r W^5tSmOb3awlq9A@1oKqpumJ#J*e^!_ delta 71 zcmV-N0J#6!SBh4!*b=iI6Pf~&7F(0(5)_jl76+447EF`p6&tge7N!A{8y6Upz!(m* dsTj!tliv~@laLw)li(E_v$7gZ3bQ{Yn+DQH8bkm9 diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index 54873a59557f2d395cc09392565744620e236654..47375f0b504f1cd6317be5ba5b95eaed63279799 100644 GIT binary patch delta 274 zcmaEQkMZCm#toq+Y;O5EDXB%17aGX2Lzu;rH#%#;*$JZwyvsUY=} zFIclOXQqPHbNHs_<`;oDKn-vSeH)$0Nme^1&o&bWim^>@x9*#qE)8Mp+W`3r%A1$l zlrv9mcM)L?NX;+EnY_VSYqFq2;^gPfqLc4Ba8EY1QJ5^?z&3dw5QDVdao_=I1Bq?k z=Wvi2?C_w(lFYpH;>inL^ccY|V26rqe(zE)#*~;2QpFOI2vh>}8-xLLCxij?)#B7> F5day!WiS8$ delta 126 zcmX^3i1Fz?#toq+o4=ayuuWcSy>s$S7m>*dwrrCx#%N3qu-Q3ziwTI&Gx@5C!sG?k zY@3;F4>M1mX(>Kg!HI410|$=D){gp<)1^Utp3OHMUolU<=pr-ufh)uWemAzs>rAA; X{PQMin`7Mq#U?L^<=pHY`%M@Cz11=t diff --git a/mobile/openapi/lib/model/folders_response.dart b/mobile/openapi/lib/model/folders_response.dart new file mode 100644 index 0000000000000000000000000000000000000000..5bfc4c793deedb35cb4ce63c207aefcdbed1c0b0 GIT binary patch literal 3044 zcmbVOZExE)5dQ98aRG{2K~;I%ry{Mq7K<~qYhoaEHw=a$&=O^_lSPfBY8a{i`|e1+ zS@xQ20g~9{z43XTJ907^O(yW}^J4z;*V*0d{@r4B4L9#U&V0C@!`*xVxAW`wH-BEB z8Ckwfm@?r{!H=&-^i^yMsd$u16{RBQS5Os|=1IhJzU77So9|*{I>3bMoF@=M%5u&9Zb##>)=d4u*Zs}IB~}KomNJLhw_E63 z?AlxTl`Dl|8V5X|Vn!+mLvOzR!eczO$+)_Na0(8^nB^W7<~KXvzPV2zPO*6Y+?H!& zbSDX$!r*AXD-P2`_wA%qQ5e{80~yoVFEZg+oK4e;jk;S9aNPN0g%spq|JFqk>MhkZb{_?vZ&3Xda$LPZ9*;nD#Xi^}v{7eEghXO+dU+aZ85?Sduus^gJD|4ZcSx*Iq`_sk{cLD`-C1D7M>b z3i@MWh!)A_ED=qm4ivQNkB?!LW{mVP$E@Fl+;S5-O8%`0a9-3ef-7h*?+EWtd?wIy zz>Vf3`fye48v^n6z`4tHa~R^p9q3UaZJfZG^=Ns7P=pC*I2I86#rHHqt-sSF<^B$< z=-Rdpo*KW>II|#0cc<=z$#98Uhh7x}4qiGdbgBm>UIb`OuPX}H4YS+cr9lchX`m_D z)6Q94`0%s_#Tb3XoX_-sbn`?>JVjph5bZVpqw2w99Wy+jAs~8M;CdqR+y3l2)o+#M zgmKj7n5id-2`n<+a^Jjb0cED~o@U5#g|b+4z{^czTIv7>A3n|R=%rW>0(;}()NzmE c-^jOp6HFg08tntX-4o;9?57ocF5qPO2h;1>CIA2c literal 0 HcmV?d00001 diff --git a/mobile/openapi/lib/model/folders_update.dart b/mobile/openapi/lib/model/folders_update.dart new file mode 100644 index 0000000000000000000000000000000000000000..088c98a4d8fd255eee352df10c10b15357deb1be GIT binary patch literal 3880 zcmeHK-*4MC5PtVxaVd(%!4#+4Q{mQ5i#8eBHSy4-8-^edXo-&1%A`h8F^tsz`@SP3 zOG=y{7_hfJ)Q!ozddItye?(6wv|JS3_qc88yk3P`x$InL*eVEYc zA3h%cwF5J@e47g6M!yVxe%0fz*_F~p#xrf=S(eKom8!Hdjb$zuQn{%9o-GP(+*S{f zFU88nMd@NA|1L8FcO@41EQG=TP8y5g#%^~{w6abp7iTFB%x0N1-ra6JEYFm*ajw-B z%-me4_|?lenG0ikJsjsq&qxe+l=;LGIe>L%tIz&KZl2izj+*8&jhYpUi%f<2Q%-qty@wq9Y2lN8&!w=E zly*S-93iMM$k@0Q*|{$Bl;+}E(o{+XBek!}Jm({J=qyu-#Ho^OArl~#2$yL^Ok5Q_ z)zWfke3*EL?iN|w2o#X&uJ=>@8mS+&9MPyl`^?i;n8EP--Bl$V@RZFFx!#<^1kPS{s8!6 z8;~)2ObY_zbEzYI4n)L2|lNy^e-|i%uDMwe*LAiGR zo<%(x`(rkZk^7;NiL_Rj756iwJ(o7K-mG6qj!$9D(;>a2VV%>?pboo7KLz_Hm0K>& zM$79?x@XS#;??1gzK3$R1Jp&8(&%~Jm|FKAJ#Wsr-1Xs4MDZp>izr>8ZD+|CrS{2c zh47)z%`zo&`i3PM(H-lX^=p5*Y(}2U4LdsllsXFe2p49zN^JKM(b_FEgjti!(H_Ie z;9;8=V_jKyk8Z9<_nqFDGzm0o59iR>dEeV<7(Y#X!W?H^_5CMK84@a`FlH@f&W46< zX=d~S(YS?P_#TeIG=sq|kF5*vcNqoo`RZC`wrY&kXdj}v%Nd5HpR=Y+P?9$0VvR9& zQG+oi^jxQ`=&;bOyhERW*F&X`kXTJC(;h|(Y8Khl>x8k?l8rYRB*MBo0_uke$>m)k z*im%fQ_Q=SaE7!H#UDJ)CbM%4m^a-1$9>jkM2)=m!boPvhPOw28^hg=JF?>#YyVj# zSTpY_u2B1&;clJG$CP9382okM3yI!v)^ug`l7~A=0i)E)XkFtM&@_*vjBVSyG ztQdWc#|@JcKp*t_8)WuWyQ4+nR&_uSf@a*W;_4-jT6S&rYsvzhqpl7HtV4efq+DUb zxHSCVsW{#a7Z_mX2bHuu1EMvu9egVR{E+3^0e!Gozkz%oIrJ%ld00dU; z=GKkTZgDl*IPpQSz1=8~ai8o_)J>JvZ{--zRlLgi^&O^6hd8X7RZSgQEhd7r^;H<~ zaGgge^ic-hs71&lR01MQ7aTwME?3;Vy?@XlpZoxyaBX!&ri7c9he(H~!7_7mEOEi` z6TXB0ez1W{)fD+Hh=(md_YtaTTqmtz#>%->G-I~r^{sk{=xHU17;U9&JLli%<%v>w zima-J*(&!(Rf9`)x$O`zU|KeywZs!`Dzd4~Xrrhgh)!YSoR$y{@cTz@IIn*^669s^ xG7w;we`8D~k1&g4S@(iIolQ>p?O*j>KiAM_!Y|L?*mv_v8Q;JT?-R6&e*jF=<`Dn@ literal 0 HcmV?d00001 diff --git a/mobile/openapi/lib/model/memory_response.dart b/mobile/openapi/lib/model/memories_response.dart similarity index 62% rename from mobile/openapi/lib/model/memory_response.dart rename to mobile/openapi/lib/model/memories_response.dart index fb34bc1518876a70c3b39584e94c733993e8d147..e215a66a03f678bc91d682e88f0e5cdad27b053c 100644 GIT binary patch delta 207 zcmX>p`dV~@4kL4BYVl-UMpb7Z9h6#Jke^qa8mo|*S6q^qmz=7{rJ&%OnwwvQB&$&k z6jV?s$;d3$OU+A6%1KR8uvI82Dovd{nXw3L9vjm(Fuj*)FPN@oUI?aTSsKCge3lw8 zEyEfGrpsB2!Srj^?O=K_n+uqJ!FB>nZ)D#Arn5NQ!Sp7M3@|Otc?nFv&U>|`wllK)w^1Ie9iE{v6v*iQhNr`dM^$uy@$P9R$ef^(WJ7{O6t&p~jev2Q?dd^l_ooPLgj2u>L1Mg)hK%K^a&=1N3xc5$6X JaJsoq0RVu!SkM3f delta 222 zcmew+w1BsEqcGq1QLF)uk)k4ph6v$>G*30y-g z^D(I2&DtznaA8~4Sui8-vsS^FiEJe>=3Ta67}J712gY2(z5&Ke;jo1xGWp+2af4i7n!_B)7Gas(!a5rDT?fm-P&0iO2 zMwV|9rcC%_@WaayeHEKRDjua$MXAX76;wr~c@puQZ+T(-=DXOIQkk^hJ zihr(zLid7g@o&i#{x@7{46gKf_gEI%u);(l!Gt0eTv>O0Hd!tTuA^KQ8#FT+E25X* zM{&lK9*r=a0hxj3KG^ZIQF2GKs~t~= z21AFS;=0NW$@wVsa^>nG3Me2kKqcV7urdsUzLRFQEzQ1(h^*k)^6J2Hhr`vHcKZ!) zj??f+4FSo~o&<}oVIgQb6uAsfHBfK&3 zVL%T6H<1V2;i}pA4o6vgUh*lq8sAoU!# z&Xmk)PiBCUFM_PYL2<>0A?^bR=)h?*9*o`C$eF}oJ^ zTU9wx4Eh@r^~5lNMaEm+n@235#57*b3<<7K5^D~4p=nG@;%D&w6m*N6J4pv(aY& literal 0 HcmV?d00001 diff --git a/mobile/openapi/lib/model/people_update.dart b/mobile/openapi/lib/model/people_update.dart new file mode 100644 index 0000000000000000000000000000000000000000..7803e6297036abef41aa4e24e67a1d466c413b4c GIT binary patch literal 3862 zcmeHK-*4MC5PtVxaVd(%!4#+4Q<2tAizXe~HF43T8wMi~XoddItye=F7!+|M!!#lh1E1PLAo_`;R9P9gpd3d_kw< zy5!#xj>nsa#Zl&z6NYZtDq= zuf*EMMd@NAzn7W8aV3`cEQG=TP8tj6#%@2JXl0#HF3wT}%x0N1{EQGPW9>O`&Gtz}rqR0mL_p;YZa$zlflDf#{mm(ET(shsM0GIzPU1^jh zK}xP@(zdyz%%_#e0gT%_eLhX(7MUF&&NP>4)T~(CVk*pEa>|Q0dq}{?3ZL{Tm%>U? z+5zedxS+xyUE|hd7rM+-T8Jx2Qz;dU)V?b7oI~u;d8QJHsFG|U6Tp-RmuW@JTID>| z(z0u$p5$dJaj#U)M43Cf5_u`9U)oH~y^|-^&f$|y273`L^h#by6M2)lRMG&hv~q8C zX^=vq;dxnFM>CPpI-+;18ncTYY;4#u~K{AjrB+@jPZAk!m-*G`70Ozp{ z$QV6l1&;AK)jB_-ii!W>_QL+p;cjH^5r3_r8UunVKDY!S9c^eh?2o5kWrD(lcFi6Q zM+7?*dLr^Z(;3w}KYoP22o$#qj-EY(TMC7~)1=C1__S_It?Lh;HeoJzz4ud5yb8`DO4sPvSu#SQeXv@= zd+2hrOo^PnVu^-y%li7}rN3J?BTwaqoSlG4?S;IDiP^0Z+r5Ohb^{G=Zb;^6jv+E= z*mjDcuB^MEo9oeC(HoN{foARg92z@+_UAN=pCmqE_H$Ep{l`rh5-O!IU@c|NhHh3}ezySW_mbM;mjc#u&IL zz!19k&o}yP^ly2Rg=o3hp~csMKbj|VI;Lg<4p#MuMhP#{NNREBn_|Gc8 zns(1`h1tgpS8FFeq8v-_KwbyDkmofgO>?7HJl0VL7@}52H#K?zJ0mSmZIoQc@#He( z#L%-l?vxxJ9nec}kl8csPL_pR*Z#l;x^Ta8t5-Z@`Dn9W^A)%pb~G?x3Hn~eiJdW`~#Y3DQ++nzMSi`DW*Sw*{Vh~7M--O`~ zx4EA`?_}U@T5LSPBLKosLG-~lx#phj&j$^1;Csl#(N-g5Lbz#pgmichtTMO264wep z+S};w2NRsAdLh66@R;TIJv=r2>a;b&ST)^p8L=@hZ`DFXkE=!aXscvPn17>{N6O$a zlB)V-tIi)(4DQq=wvGOPDcL~Q5>B)!#il5ujhccOIu(sDEfE~x2anwFUH?=hNXz0e wAV4kusF+F~TNYti@`65`kI(qAUv*nQ%g|uL@612=?B-!Ix`rK|BhdP{VJE+b>{WL-uzx#FPI;)49V;?!7$%)H`~#JuEGJuU@>pv02Qy!7J9`Ha(m z3R#)91Iay1`+#H>^CBQA!_ovK=dsiRNom$-AX&y*0wiCt?f{aD*j$0+bGDN}as&HL XAeqVG0VFqaWCBSk&dWgZE$3|j>pC#% delta 120 zcmca5dO~!AF5_f9Mm3qB)Z&8tyyDbYh0MI-lEl2^R6Q;Qg`mWe%)Io;MU2xXb24q8 ze2{71D<%VgpQ^=Wofx}^PKC8gw2G)|vUs-odUdQG-`3u|0$@|!M WPOjkan0$~UbFwz)<;nj!Zvy~#;x9S? diff --git a/mobile/openapi/lib/model/memory_update.dart b/mobile/openapi/lib/model/ratings_update.dart similarity index 69% rename from mobile/openapi/lib/model/memory_update.dart rename to mobile/openapi/lib/model/ratings_update.dart index f2529186c0432db7c348cb2f75849bc1e196b924..bde51bad1b3609aba19f1ccd236a6f4d7f6f5dd6 100644 GIT binary patch delta 225 zcmcaA@mykqIwN~fVo7FRdhujkMmab;kWmE2-ki<&1feLD`50V6k%bE(VaPfQCNcRU zYZaUw$W{VppJoe&vsKu0;OuGa8{ljo4qG_8pW`5$9mcs4&gSKEfU|?S65;G!T&Lme HZthb692QYZ delta 235 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 delta 229 zcmcbozDQ{U57T6ICfUhxOp23dFqN|Trsn1sRZcc!7N4BNtjr&jT3nEySDdO)lvt9P zmp*w7^Owm7Sd=F-vZ`|_*xJH`{aBYz=3|qd?8qiRxtwjrWJPvS#nPhWjKtzpTa^MR zO9!gjRt0KUDf`pOjT~B&FL3AysK+YUDwJeo7VAMIHyd(hFipPB&CgglIe}YpG82#Z vZ7F=@)XG+qyhu_9ob|CT$$Tn7uGL72^SWZer`oUxx%84S zmZ+zjE*600$AT54)iTjAtGcUzbD{Qq&`e9U1BxipKx=%q$Wvm(AIY3H#^#DGkpnFy u!xb556TXlr%CxnuC^pbG3>GFY+E|)WXZQ@m9MdukRHSbv RatingUpdate) - rating?: RatingUpdate; + @Type(() => FoldersUpdate) + folders?: FoldersUpdate; + + @Optional() + @ValidateNested() + @Type(() => MemoriesUpdate) + memories?: MemoriesUpdate; + + @Optional() + @ValidateNested() + @Type(() => PeopleUpdate) + people?: PeopleUpdate; + + @Optional() + @ValidateNested() + @Type(() => RatingsUpdate) + ratings?: RatingsUpdate; + + @Optional() + @ValidateNested() + @Type(() => TagsUpdate) + tags?: TagsUpdate; @Optional() @ValidateNested() @Type(() => AvatarUpdate) avatar?: AvatarUpdate; - @Optional() - @ValidateNested() - @Type(() => MemoryUpdate) - memories?: MemoryUpdate; - @Optional() @ValidateNested() @Type(() => EmailNotificationsUpdate) @@ -90,12 +129,27 @@ class AvatarResponse { color!: UserAvatarColor; } -class RatingResponse { +class RatingsResponse { enabled: boolean = false; } -class MemoryResponse { - enabled!: boolean; +class MemoriesResponse { + enabled: boolean = true; +} + +class FoldersResponse { + enabled: boolean = false; + sidebarWeb: boolean = false; +} + +class PeopleResponse { + enabled: boolean = true; + sidebarWeb: boolean = false; +} + +class TagsResponse { + enabled: boolean = true; + sidebarWeb: boolean = true; } class EmailNotificationsResponse { @@ -117,8 +171,11 @@ class PurchaseResponse { } export class UserPreferencesResponseDto implements UserPreferences { - rating!: RatingResponse; - memories!: MemoryResponse; + folders!: FoldersResponse; + memories!: MemoriesResponse; + people!: PeopleResponse; + ratings!: RatingsResponse; + tags!: TagsResponse; avatar!: AvatarResponse; emailNotifications!: EmailNotificationsResponse; download!: DownloadResponse; diff --git a/server/src/entities/user-metadata.entity.ts b/server/src/entities/user-metadata.entity.ts index eadcdeec5..c342cb71f 100644 --- a/server/src/entities/user-metadata.entity.ts +++ b/server/src/entities/user-metadata.entity.ts @@ -19,12 +19,24 @@ export class UserMetadataEntity } export interface UserPreferences { - rating: { + folders: { enabled: boolean; + sidebarWeb: boolean; }; memories: { enabled: boolean; }; + people: { + enabled: boolean; + sidebarWeb: boolean; + }; + ratings: { + enabled: boolean; + }; + tags: { + enabled: boolean; + sidebarWeb: boolean; + }; avatar: { color: UserAvatarColor; }; @@ -50,12 +62,24 @@ export const getDefaultPreferences = (user: { email: string }): UserPreferences ); return { - rating: { + folders: { enabled: false, + sidebarWeb: false, }, memories: { enabled: true, }, + people: { + enabled: true, + sidebarWeb: false, + }, + ratings: { + enabled: false, + }, + tags: { + enabled: false, + sidebarWeb: false, + }, avatar: { color: values[randomIndex], }, diff --git a/web/src/lib/components/asset-viewer/detail-panel-star-rating.svelte b/web/src/lib/components/asset-viewer/detail-panel-star-rating.svelte index 8b18d14f0..b73fe7171 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-star-rating.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-star-rating.svelte @@ -20,7 +20,7 @@ }; -{#if !isSharedLink() && $preferences?.rating?.enabled} +{#if !isSharedLink() && $preferences?.ratings.enabled}
handlePromiseError(handleChangeRating(rating))} />
diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index 0a105430c..5ffc5120b 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -6,7 +6,7 @@ import { boundingBoxesArray } from '$lib/stores/people.store'; import { locale } from '$lib/stores/preferences.store'; import { featureFlags } from '$lib/stores/server-config.store'; - import { user } from '$lib/stores/user.store'; + import { preferences, user } from '$lib/stores/user.store'; import { getAssetThumbnailUrl, getPeopleThumbnailUrl, handlePromiseError, isSharedLink } from '$lib/utils'; import { delay, isFlipped } from '$lib/utils/asset-utils'; import { @@ -502,9 +502,11 @@ {/if} -
- -
+{#if $preferences?.tags?.enabled} +
+ +
+{/if} {#if showEditFaces} { - accordionElement.scrollIntoView({ - behavior: 'smooth', - block: 'start', - }); - }, 200); + if (autoScrollTo) { + setTimeout(() => { + accordionElement.scrollIntoView({ + behavior: 'smooth', + block: 'start', + }); + }, 200); + } } else { $accordionState.delete(key); $accordionState = $accordionState; @@ -72,7 +75,7 @@ {#if isOpen} -
    +
    {/if} diff --git a/web/src/lib/components/shared-components/side-bar/side-bar.svelte b/web/src/lib/components/shared-components/side-bar/side-bar.svelte index dd777d125..fab7c6ed6 100644 --- a/web/src/lib/components/shared-components/side-bar/side-bar.svelte +++ b/web/src/lib/components/shared-components/side-bar/side-bar.svelte @@ -1,5 +1,4 @@
    @@ -189,29 +169,6 @@ bind:checked={$showDeleteModal} /> - -
    - -
    -
    - -
    -
    - handleRatingChange(enabled)} - /> -
    diff --git a/web/src/lib/components/user-settings-page/feature-settings.svelte b/web/src/lib/components/user-settings-page/feature-settings.svelte new file mode 100644 index 000000000..dc11dab15 --- /dev/null +++ b/web/src/lib/components/user-settings-page/feature-settings.svelte @@ -0,0 +1,124 @@ + + +
    +
    +
    +
    + +
    + +
    + + {#if foldersEnabled} +
    + +
    + {/if} +
    + + +
    + +
    +
    + + +
    + +
    + + {#if peopleEnabled} +
    + +
    + {/if} +
    + + +
    + +
    +
    + + +
    + +
    + {#if tagsEnabled} +
    + +
    + {/if} +
    + +
    + +
    +
    +
    +
    +
    diff --git a/web/src/lib/components/user-settings-page/memories-settings.svelte b/web/src/lib/components/user-settings-page/memories-settings.svelte deleted file mode 100644 index e8a58bf01..000000000 --- a/web/src/lib/components/user-settings-page/memories-settings.svelte +++ /dev/null @@ -1,46 +0,0 @@ - - -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    diff --git a/web/src/lib/components/user-settings-page/user-settings-list.svelte b/web/src/lib/components/user-settings-page/user-settings-list.svelte index df32126a2..596efaede 100644 --- a/web/src/lib/components/user-settings-page/user-settings-list.svelte +++ b/web/src/lib/components/user-settings-page/user-settings-list.svelte @@ -10,7 +10,6 @@ import AppSettings from './app-settings.svelte'; import ChangePasswordSettings from './change-password-settings.svelte'; import DeviceList from './device-list.svelte'; - import MemoriesSettings from './memories-settings.svelte'; import OAuthSettings from './oauth-settings.svelte'; import PartnerSettings from './partner-settings.svelte'; import UserAPIKeyList from './user-api-key-list.svelte'; @@ -19,6 +18,7 @@ import { t } from 'svelte-i18n'; import DownloadSettings from '$lib/components/user-settings-page/download-settings.svelte'; import UserPurchaseSettings from '$lib/components/user-settings-page/user-purchase-settings.svelte'; + import FeatureSettings from '$lib/components/user-settings-page/feature-settings.svelte'; export let keys: ApiKeyResponseDto[] = []; export let sessions: SessionResponseDto[] = []; @@ -53,8 +53,8 @@ - - + + @@ -84,6 +84,7 @@ key="user-purchase-settings" title={$t('user_purchase_settings')} subtitle={$t('user_purchase_settings_description')} + autoScrollTo={true} > diff --git a/web/src/lib/i18n/en.json b/web/src/lib/i18n/en.json index 684cb0e31..dcefccf2e 100644 --- a/web/src/lib/i18n/en.json +++ b/web/src/lib/i18n/en.json @@ -701,6 +701,8 @@ "favorite_or_unfavorite_photo": "Favorite or unfavorite photo", "favorites": "Favorites", "feature_photo_updated": "Feature photo updated", + "features": "Features", + "features_setting_description": "Manage the app features", "file_name": "File name", "file_name_or_extension": "File name or extension", "filename": "Filename", @@ -709,6 +711,7 @@ "find_them_fast": "Find them fast by name with search", "fix_incorrect_match": "Fix incorrect match", "folders": "Folders", + "folders_feature_description": "Browsing the folder view for the photos and videos on the file system", "force_re-scan_library_files": "Force Re-scan All Library Files", "forward": "Forward", "general": "General", @@ -912,6 +915,7 @@ "pending": "Pending", "people": "People", "people_edits_count": "Edited {count, plural, one {# person} other {# people}}", + "people_feature_description": "Browsing photos and videos grouped by people", "people_sidebar_description": "Display a link to People in the sidebar", "permanent_deletion_warning": "Permanent deletion warning", "permanent_deletion_warning_setting_description": "Show a warning when permanently deleting assets", @@ -981,7 +985,7 @@ "rating": "Star rating", "rating_clear": "Clear rating", "rating_count": "{count, plural, one {# star} other {# stars}}", - "rating_description": "Display the exif rating in the info panel", + "rating_description": "Display the EXIF rating in the info panel", "reaction_options": "Reaction options", "read_changelog": "Read Changelog", "reassign": "Reassign", @@ -1130,6 +1134,8 @@ "show_supporter_badge": "Supporter badge", "show_supporter_badge_description": "Show a supporter badge", "shuffle": "Shuffle", + "sidebar": "Sidebar", + "sidebar_display_description": "Display a link to the view in the sidebar", "sign_out": "Sign Out", "sign_up": "Sign up", "size": "Size", @@ -1169,6 +1175,7 @@ "tag": "Tag", "tag_assets": "Tag assets", "tag_created": "Created tag: {tag}", + "tag_feature_description": "Browsing photos and videos grouped by logical tag topics", "tag_updated": "Updated tag: {tag}", "tagged_assets": "Tagged {count, plural, one {# asset} other {# assets}}", "tags": "Tags", diff --git a/web/src/lib/stores/preferences.store.ts b/web/src/lib/stores/preferences.store.ts index 11473f806..de80702b9 100644 --- a/web/src/lib/stores/preferences.store.ts +++ b/web/src/lib/stores/preferences.store.ts @@ -96,11 +96,6 @@ export interface SidebarSettings { sharing: boolean; } -export const sidebarSettings = persisted('sidebar-settings-1', { - people: false, - sharing: true, -}); - export enum SortOrder { Asc = 'asc', Desc = 'desc', diff --git a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte index e15c20cbb..70e74f84f 100644 --- a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte @@ -81,7 +81,9 @@ assetStore.removeAssets(assetIds)} /> - + {#if $preferences.tags.enabled} + + {/if} assetStore.removeAssets(assetIds)} />