mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
Merge branch 'main' of github.com:immich-app/immich into new-upload
This commit is contained in:
commit
2b6672293b
142
cli/package-lock.json
generated
142
cli/package-lock.json
generated
@ -1370,17 +1370,17 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
|
||||||
"integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==",
|
"integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/type-utils": "8.33.0",
|
"@typescript-eslint/type-utils": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^7.0.0",
|
"ignore": "^7.0.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@ -1394,7 +1394,7 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.33.0",
|
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
@ -1410,16 +1410,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
|
||||||
"integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==",
|
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1434,34 +1434,15 @@
|
|||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/project-service": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/tsconfig-utils": "^8.33.0",
|
|
||||||
"@typescript-eslint/types": "^8.33.0",
|
|
||||||
"debug": "^4.3.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
|
||||||
"integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==",
|
"integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0"
|
"@typescript-eslint/visitor-keys": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -1471,32 +1452,15 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==",
|
"integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.1.0"
|
"ts-api-utils": "^2.1.0"
|
||||||
},
|
},
|
||||||
@ -1513,9 +1477,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz",
|
||||||
"integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==",
|
"integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1527,16 +1491,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
|
||||||
"integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==",
|
"integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/project-service": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/tsconfig-utils": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@ -1582,16 +1544,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==",
|
"integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.7.0",
|
"@eslint-community/eslint-utils": "^4.7.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0"
|
"@typescript-eslint/typescript-estree": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -1606,13 +1568,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
|
||||||
"integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==",
|
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -2794,9 +2756,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "16.2.0",
|
"version": "16.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
|
||||||
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
|
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -4238,15 +4200,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz",
|
||||||
"integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==",
|
"integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.33.0",
|
"@typescript-eslint/eslint-plugin": "8.32.1",
|
||||||
"@typescript-eslint/parser": "8.33.0",
|
"@typescript-eslint/parser": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0"
|
"@typescript-eslint/utils": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
994
docs/package-lock.json
generated
994
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -16,8 +16,8 @@
|
|||||||
"write-heading-ids": "docusaurus write-heading-ids"
|
"write-heading-ids": "docusaurus write-heading-ids"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "~3.8.0",
|
"@docusaurus/core": "~3.7.0",
|
||||||
"@docusaurus/preset-classic": "~3.8.0",
|
"@docusaurus/preset-classic": "~3.7.0",
|
||||||
"@mdi/js": "^7.3.67",
|
"@mdi/js": "^7.3.67",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
@ -35,7 +35,7 @@
|
|||||||
"url": "^0.11.0"
|
"url": "^0.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "~3.8.0",
|
"@docusaurus/module-type-aliases": "~3.7.0",
|
||||||
"@docusaurus/tsconfig": "^3.7.0",
|
"@docusaurus/tsconfig": "^3.7.0",
|
||||||
"@docusaurus/types": "^3.7.0",
|
"@docusaurus/types": "^3.7.0",
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^3.2.4",
|
||||||
|
142
e2e/package-lock.json
generated
142
e2e/package-lock.json
generated
@ -1709,17 +1709,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
|
||||||
"integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==",
|
"integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/type-utils": "8.33.0",
|
"@typescript-eslint/type-utils": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^7.0.0",
|
"ignore": "^7.0.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@ -1733,7 +1733,7 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.33.0",
|
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
@ -1749,16 +1749,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
|
||||||
"integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==",
|
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1773,34 +1773,15 @@
|
|||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/project-service": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/tsconfig-utils": "^8.33.0",
|
|
||||||
"@typescript-eslint/types": "^8.33.0",
|
|
||||||
"debug": "^4.3.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
|
||||||
"integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==",
|
"integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0"
|
"@typescript-eslint/visitor-keys": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -1810,32 +1791,15 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==",
|
"integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.1.0"
|
"ts-api-utils": "^2.1.0"
|
||||||
},
|
},
|
||||||
@ -1852,9 +1816,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz",
|
||||||
"integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==",
|
"integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1866,16 +1830,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
|
||||||
"integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==",
|
"integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/project-service": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/tsconfig-utils": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@ -1921,16 +1883,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==",
|
"integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.7.0",
|
"@eslint-community/eslint-utils": "^4.7.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0"
|
"@typescript-eslint/typescript-estree": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -1945,13 +1907,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
|
||||||
"integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==",
|
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -3872,9 +3834,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "16.2.0",
|
"version": "16.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
|
||||||
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
|
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -6817,15 +6779,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz",
|
||||||
"integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==",
|
"integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.33.0",
|
"@typescript-eslint/eslint-plugin": "8.32.1",
|
||||||
"@typescript-eslint/parser": "8.33.0",
|
"@typescript-eslint/parser": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0"
|
"@typescript-eslint/utils": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -463,6 +463,8 @@
|
|||||||
"assets_count": "{count, plural, one {# asset} other {# assets}}",
|
"assets_count": "{count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_deleted_permanently": "{count} asset(s) deleted permanently",
|
"assets_deleted_permanently": "{count} asset(s) deleted permanently",
|
||||||
"assets_deleted_permanently_from_server": "{count} asset(s) deleted permanently from the Immich server",
|
"assets_deleted_permanently_from_server": "{count} asset(s) deleted permanently from the Immich server",
|
||||||
|
"assets_downloaded_failed": "{count, plural, one {Downloaded # file - {error} file failed} other {Downloaded # files - {error} files failed}}",
|
||||||
|
"assets_downloaded_successfully": "{count, plural, one {Downloaded # file successfully} other {Downloaded # files successfully}}",
|
||||||
"assets_moved_to_trash_count": "Moved {count, plural, one {# asset} other {# assets}} to trash",
|
"assets_moved_to_trash_count": "Moved {count, plural, one {# asset} other {# assets}} to trash",
|
||||||
"assets_permanently_deleted_count": "Permanently deleted {count, plural, one {# asset} other {# assets}}",
|
"assets_permanently_deleted_count": "Permanently deleted {count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_removed_count": "Removed {count, plural, one {# asset} other {# assets}}",
|
"assets_removed_count": "Removed {count, plural, one {# asset} other {# assets}}",
|
||||||
@ -694,6 +696,7 @@
|
|||||||
"daily_title_text_date": "E, MMM dd",
|
"daily_title_text_date": "E, MMM dd",
|
||||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||||
"dark": "Dark",
|
"dark": "Dark",
|
||||||
|
"darkTheme": "Toggle dark theme",
|
||||||
"date_after": "Date after",
|
"date_after": "Date after",
|
||||||
"date_and_time": "Date and Time",
|
"date_and_time": "Date and Time",
|
||||||
"date_before": "Date before",
|
"date_before": "Date before",
|
||||||
@ -1169,7 +1172,7 @@
|
|||||||
"look": "Look",
|
"look": "Look",
|
||||||
"loop_videos": "Loop videos",
|
"loop_videos": "Loop videos",
|
||||||
"loop_videos_description": "Enable to automatically loop a video in the detail viewer.",
|
"loop_videos_description": "Enable to automatically loop a video in the detail viewer.",
|
||||||
"main_branch_warning": "You’re using a development version; we strongly recommend using a release version!",
|
"main_branch_warning": "You're using a development version; we strongly recommend using a release version!",
|
||||||
"main_menu": "Main menu",
|
"main_menu": "Main menu",
|
||||||
"make": "Make",
|
"make": "Make",
|
||||||
"manage_shared_links": "Manage shared links",
|
"manage_shared_links": "Manage shared links",
|
||||||
@ -1434,7 +1437,7 @@
|
|||||||
"purchase_lifetime_description": "Lifetime purchase",
|
"purchase_lifetime_description": "Lifetime purchase",
|
||||||
"purchase_option_title": "PURCHASE OPTIONS",
|
"purchase_option_title": "PURCHASE OPTIONS",
|
||||||
"purchase_panel_info_1": "Building Immich takes a lot of time and effort, and we have full-time engineers working on it to make it as good as we possibly can. Our mission is for open-source software and ethical business practices to become a sustainable income source for developers and to create a privacy-respecting ecosystem with real alternatives to exploitative cloud services.",
|
"purchase_panel_info_1": "Building Immich takes a lot of time and effort, and we have full-time engineers working on it to make it as good as we possibly can. Our mission is for open-source software and ethical business practices to become a sustainable income source for developers and to create a privacy-respecting ecosystem with real alternatives to exploitative cloud services.",
|
||||||
"purchase_panel_info_2": "As we’re committed not to add paywalls, this purchase will not grant you any additional features in Immich. We rely on users like you to support Immich’s ongoing development.",
|
"purchase_panel_info_2": "As we're committed not to add paywalls, this purchase will not grant you any additional features in Immich. We rely on users like you to support Immich's ongoing development.",
|
||||||
"purchase_panel_title": "Support the project",
|
"purchase_panel_title": "Support the project",
|
||||||
"purchase_per_server": "Per server",
|
"purchase_per_server": "Per server",
|
||||||
"purchase_per_user": "Per user",
|
"purchase_per_user": "Per user",
|
||||||
@ -1817,7 +1820,6 @@
|
|||||||
"to_parent": "Go to parent",
|
"to_parent": "Go to parent",
|
||||||
"to_trash": "Trash",
|
"to_trash": "Trash",
|
||||||
"toggle_settings": "Toggle settings",
|
"toggle_settings": "Toggle settings",
|
||||||
"toggle_theme": "Toggle dark theme",
|
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
"total_usage": "Total usage",
|
"total_usage": "Total usage",
|
||||||
"trash": "Trash",
|
"trash": "Trash",
|
||||||
@ -1839,6 +1841,7 @@
|
|||||||
"unable_to_setup_pin_code": "Unable to setup PIN code",
|
"unable_to_setup_pin_code": "Unable to setup PIN code",
|
||||||
"unarchive": "Unarchive",
|
"unarchive": "Unarchive",
|
||||||
"unarchived_count": "{count, plural, other {Unarchived #}}",
|
"unarchived_count": "{count, plural, other {Unarchived #}}",
|
||||||
|
"undo": "Undo",
|
||||||
"unfavorite": "Unfavorite",
|
"unfavorite": "Unfavorite",
|
||||||
"unhide_person": "Unhide person",
|
"unhide_person": "Unhide person",
|
||||||
"unknown": "Unknown",
|
"unknown": "Unknown",
|
||||||
|
@ -19,6 +19,7 @@ class Album {
|
|||||||
required this.name,
|
required this.name,
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
required this.modifiedAt,
|
required this.modifiedAt,
|
||||||
|
this.description,
|
||||||
this.startDate,
|
this.startDate,
|
||||||
this.endDate,
|
this.endDate,
|
||||||
this.lastModifiedAssetTimestamp,
|
this.lastModifiedAssetTimestamp,
|
||||||
@ -34,6 +35,7 @@ class Album {
|
|||||||
@Index(unique: false, replace: false, type: IndexType.hash)
|
@Index(unique: false, replace: false, type: IndexType.hash)
|
||||||
String? localId;
|
String? localId;
|
||||||
String name;
|
String name;
|
||||||
|
String? description;
|
||||||
DateTime createdAt;
|
DateTime createdAt;
|
||||||
DateTime modifiedAt;
|
DateTime modifiedAt;
|
||||||
DateTime? startDate;
|
DateTime? startDate;
|
||||||
@ -108,6 +110,7 @@ class Album {
|
|||||||
remoteId == other.remoteId &&
|
remoteId == other.remoteId &&
|
||||||
localId == other.localId &&
|
localId == other.localId &&
|
||||||
name == other.name &&
|
name == other.name &&
|
||||||
|
description == other.description &&
|
||||||
createdAt.isAtSameMomentAs(other.createdAt) &&
|
createdAt.isAtSameMomentAs(other.createdAt) &&
|
||||||
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
|
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
|
||||||
isAtSameMomentAs(startDate, other.startDate) &&
|
isAtSameMomentAs(startDate, other.startDate) &&
|
||||||
@ -135,6 +138,7 @@ class Album {
|
|||||||
modifiedAt.hashCode ^
|
modifiedAt.hashCode ^
|
||||||
startDate.hashCode ^
|
startDate.hashCode ^
|
||||||
endDate.hashCode ^
|
endDate.hashCode ^
|
||||||
|
description.hashCode ^
|
||||||
lastModifiedAssetTimestamp.hashCode ^
|
lastModifiedAssetTimestamp.hashCode ^
|
||||||
shared.hashCode ^
|
shared.hashCode ^
|
||||||
activityEnabled.hashCode ^
|
activityEnabled.hashCode ^
|
||||||
@ -150,6 +154,7 @@ class Album {
|
|||||||
name: dto.albumName,
|
name: dto.albumName,
|
||||||
createdAt: dto.createdAt,
|
createdAt: dto.createdAt,
|
||||||
modifiedAt: dto.updatedAt,
|
modifiedAt: dto.updatedAt,
|
||||||
|
description: dto.description,
|
||||||
lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp,
|
lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp,
|
||||||
shared: dto.shared,
|
shared: dto.shared,
|
||||||
startDate: dto.startDate,
|
startDate: dto.startDate,
|
||||||
@ -184,7 +189,8 @@ class Album {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => name;
|
String toString() =>
|
||||||
|
'remoteId: $remoteId name: $name description: $description';
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AssetsHelper on IsarCollection<Album> {
|
extension AssetsHelper on IsarCollection<Album> {
|
||||||
|
271
mobile/lib/entities/album.entity.g.dart
generated
271
mobile/lib/entities/album.entity.g.dart
generated
@ -27,49 +27,54 @@ const AlbumSchema = CollectionSchema(
|
|||||||
name: r'createdAt',
|
name: r'createdAt',
|
||||||
type: IsarType.dateTime,
|
type: IsarType.dateTime,
|
||||||
),
|
),
|
||||||
r'endDate': PropertySchema(
|
r'description': PropertySchema(
|
||||||
id: 2,
|
id: 2,
|
||||||
|
name: r'description',
|
||||||
|
type: IsarType.string,
|
||||||
|
),
|
||||||
|
r'endDate': PropertySchema(
|
||||||
|
id: 3,
|
||||||
name: r'endDate',
|
name: r'endDate',
|
||||||
type: IsarType.dateTime,
|
type: IsarType.dateTime,
|
||||||
),
|
),
|
||||||
r'lastModifiedAssetTimestamp': PropertySchema(
|
r'lastModifiedAssetTimestamp': PropertySchema(
|
||||||
id: 3,
|
id: 4,
|
||||||
name: r'lastModifiedAssetTimestamp',
|
name: r'lastModifiedAssetTimestamp',
|
||||||
type: IsarType.dateTime,
|
type: IsarType.dateTime,
|
||||||
),
|
),
|
||||||
r'localId': PropertySchema(
|
r'localId': PropertySchema(
|
||||||
id: 4,
|
id: 5,
|
||||||
name: r'localId',
|
name: r'localId',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'modifiedAt': PropertySchema(
|
r'modifiedAt': PropertySchema(
|
||||||
id: 5,
|
id: 6,
|
||||||
name: r'modifiedAt',
|
name: r'modifiedAt',
|
||||||
type: IsarType.dateTime,
|
type: IsarType.dateTime,
|
||||||
),
|
),
|
||||||
r'name': PropertySchema(
|
r'name': PropertySchema(
|
||||||
id: 6,
|
id: 7,
|
||||||
name: r'name',
|
name: r'name',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'remoteId': PropertySchema(
|
r'remoteId': PropertySchema(
|
||||||
id: 7,
|
id: 8,
|
||||||
name: r'remoteId',
|
name: r'remoteId',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'shared': PropertySchema(
|
r'shared': PropertySchema(
|
||||||
id: 8,
|
id: 9,
|
||||||
name: r'shared',
|
name: r'shared',
|
||||||
type: IsarType.bool,
|
type: IsarType.bool,
|
||||||
),
|
),
|
||||||
r'sortOrder': PropertySchema(
|
r'sortOrder': PropertySchema(
|
||||||
id: 9,
|
id: 10,
|
||||||
name: r'sortOrder',
|
name: r'sortOrder',
|
||||||
type: IsarType.byte,
|
type: IsarType.byte,
|
||||||
enumMap: _AlbumsortOrderEnumValueMap,
|
enumMap: _AlbumsortOrderEnumValueMap,
|
||||||
),
|
),
|
||||||
r'startDate': PropertySchema(
|
r'startDate': PropertySchema(
|
||||||
id: 10,
|
id: 11,
|
||||||
name: r'startDate',
|
name: r'startDate',
|
||||||
type: IsarType.dateTime,
|
type: IsarType.dateTime,
|
||||||
)
|
)
|
||||||
@ -146,6 +151,12 @@ int _albumEstimateSize(
|
|||||||
Map<Type, List<int>> allOffsets,
|
Map<Type, List<int>> allOffsets,
|
||||||
) {
|
) {
|
||||||
var bytesCount = offsets.last;
|
var bytesCount = offsets.last;
|
||||||
|
{
|
||||||
|
final value = object.description;
|
||||||
|
if (value != null) {
|
||||||
|
bytesCount += 3 + value.length * 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
final value = object.localId;
|
final value = object.localId;
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@ -170,15 +181,16 @@ void _albumSerialize(
|
|||||||
) {
|
) {
|
||||||
writer.writeBool(offsets[0], object.activityEnabled);
|
writer.writeBool(offsets[0], object.activityEnabled);
|
||||||
writer.writeDateTime(offsets[1], object.createdAt);
|
writer.writeDateTime(offsets[1], object.createdAt);
|
||||||
writer.writeDateTime(offsets[2], object.endDate);
|
writer.writeString(offsets[2], object.description);
|
||||||
writer.writeDateTime(offsets[3], object.lastModifiedAssetTimestamp);
|
writer.writeDateTime(offsets[3], object.endDate);
|
||||||
writer.writeString(offsets[4], object.localId);
|
writer.writeDateTime(offsets[4], object.lastModifiedAssetTimestamp);
|
||||||
writer.writeDateTime(offsets[5], object.modifiedAt);
|
writer.writeString(offsets[5], object.localId);
|
||||||
writer.writeString(offsets[6], object.name);
|
writer.writeDateTime(offsets[6], object.modifiedAt);
|
||||||
writer.writeString(offsets[7], object.remoteId);
|
writer.writeString(offsets[7], object.name);
|
||||||
writer.writeBool(offsets[8], object.shared);
|
writer.writeString(offsets[8], object.remoteId);
|
||||||
writer.writeByte(offsets[9], object.sortOrder.index);
|
writer.writeBool(offsets[9], object.shared);
|
||||||
writer.writeDateTime(offsets[10], object.startDate);
|
writer.writeByte(offsets[10], object.sortOrder.index);
|
||||||
|
writer.writeDateTime(offsets[11], object.startDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
Album _albumDeserialize(
|
Album _albumDeserialize(
|
||||||
@ -190,16 +202,18 @@ Album _albumDeserialize(
|
|||||||
final object = Album(
|
final object = Album(
|
||||||
activityEnabled: reader.readBool(offsets[0]),
|
activityEnabled: reader.readBool(offsets[0]),
|
||||||
createdAt: reader.readDateTime(offsets[1]),
|
createdAt: reader.readDateTime(offsets[1]),
|
||||||
endDate: reader.readDateTimeOrNull(offsets[2]),
|
description: reader.readStringOrNull(offsets[2]),
|
||||||
lastModifiedAssetTimestamp: reader.readDateTimeOrNull(offsets[3]),
|
endDate: reader.readDateTimeOrNull(offsets[3]),
|
||||||
localId: reader.readStringOrNull(offsets[4]),
|
lastModifiedAssetTimestamp: reader.readDateTimeOrNull(offsets[4]),
|
||||||
modifiedAt: reader.readDateTime(offsets[5]),
|
localId: reader.readStringOrNull(offsets[5]),
|
||||||
name: reader.readString(offsets[6]),
|
modifiedAt: reader.readDateTime(offsets[6]),
|
||||||
remoteId: reader.readStringOrNull(offsets[7]),
|
name: reader.readString(offsets[7]),
|
||||||
shared: reader.readBool(offsets[8]),
|
remoteId: reader.readStringOrNull(offsets[8]),
|
||||||
sortOrder: _AlbumsortOrderValueEnumMap[reader.readByteOrNull(offsets[9])] ??
|
shared: reader.readBool(offsets[9]),
|
||||||
SortOrder.desc,
|
sortOrder:
|
||||||
startDate: reader.readDateTimeOrNull(offsets[10]),
|
_AlbumsortOrderValueEnumMap[reader.readByteOrNull(offsets[10])] ??
|
||||||
|
SortOrder.desc,
|
||||||
|
startDate: reader.readDateTimeOrNull(offsets[11]),
|
||||||
);
|
);
|
||||||
object.id = id;
|
object.id = id;
|
||||||
return object;
|
return object;
|
||||||
@ -217,23 +231,25 @@ P _albumDeserializeProp<P>(
|
|||||||
case 1:
|
case 1:
|
||||||
return (reader.readDateTime(offset)) as P;
|
return (reader.readDateTime(offset)) as P;
|
||||||
case 2:
|
case 2:
|
||||||
return (reader.readDateTimeOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 3:
|
case 3:
|
||||||
return (reader.readDateTimeOrNull(offset)) as P;
|
return (reader.readDateTimeOrNull(offset)) as P;
|
||||||
case 4:
|
case 4:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readDateTimeOrNull(offset)) as P;
|
||||||
case 5:
|
case 5:
|
||||||
return (reader.readDateTime(offset)) as P;
|
|
||||||
case 6:
|
|
||||||
return (reader.readString(offset)) as P;
|
|
||||||
case 7:
|
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
|
case 6:
|
||||||
|
return (reader.readDateTime(offset)) as P;
|
||||||
|
case 7:
|
||||||
|
return (reader.readString(offset)) as P;
|
||||||
case 8:
|
case 8:
|
||||||
return (reader.readBool(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 9:
|
case 9:
|
||||||
|
return (reader.readBool(offset)) as P;
|
||||||
|
case 10:
|
||||||
return (_AlbumsortOrderValueEnumMap[reader.readByteOrNull(offset)] ??
|
return (_AlbumsortOrderValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||||
SortOrder.desc) as P;
|
SortOrder.desc) as P;
|
||||||
case 10:
|
case 11:
|
||||||
return (reader.readDateTimeOrNull(offset)) as P;
|
return (reader.readDateTimeOrNull(offset)) as P;
|
||||||
default:
|
default:
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
throw IsarError('Unknown property with id $propertyId');
|
||||||
@ -535,6 +551,152 @@ extension AlbumQueryFilter on QueryBuilder<Album, Album, QFilterCondition> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionIsNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
property: r'description',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionIsNotNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||||
|
property: r'description',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionEqualTo(
|
||||||
|
String? value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'description',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionGreaterThan(
|
||||||
|
String? value, {
|
||||||
|
bool include = false,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
include: include,
|
||||||
|
property: r'description',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionLessThan(
|
||||||
|
String? value, {
|
||||||
|
bool include = false,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.lessThan(
|
||||||
|
include: include,
|
||||||
|
property: r'description',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionBetween(
|
||||||
|
String? lower,
|
||||||
|
String? upper, {
|
||||||
|
bool includeLower = true,
|
||||||
|
bool includeUpper = true,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.between(
|
||||||
|
property: r'description',
|
||||||
|
lower: lower,
|
||||||
|
includeLower: includeLower,
|
||||||
|
upper: upper,
|
||||||
|
includeUpper: includeUpper,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionStartsWith(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.startsWith(
|
||||||
|
property: r'description',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionEndsWith(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.endsWith(
|
||||||
|
property: r'description',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionContains(
|
||||||
|
String value,
|
||||||
|
{bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.contains(
|
||||||
|
property: r'description',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionMatches(
|
||||||
|
String pattern,
|
||||||
|
{bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.matches(
|
||||||
|
property: r'description',
|
||||||
|
wildcard: pattern,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionIsEmpty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'description',
|
||||||
|
value: '',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterFilterCondition> descriptionIsNotEmpty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
property: r'description',
|
||||||
|
value: '',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Album, Album, QAfterFilterCondition> endDateIsNull() {
|
QueryBuilder<Album, Album, QAfterFilterCondition> endDateIsNull() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addFilterCondition(const FilterCondition.isNull(
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
@ -1502,6 +1664,18 @@ extension AlbumQuerySortBy on QueryBuilder<Album, Album, QSortBy> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterSortBy> sortByDescription() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'description', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterSortBy> sortByDescriptionDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'description', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Album, Album, QAfterSortBy> sortByEndDate() {
|
QueryBuilder<Album, Album, QAfterSortBy> sortByEndDate() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'endDate', Sort.asc);
|
return query.addSortBy(r'endDate', Sort.asc);
|
||||||
@ -1637,6 +1811,18 @@ extension AlbumQuerySortThenBy on QueryBuilder<Album, Album, QSortThenBy> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterSortBy> thenByDescription() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'description', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QAfterSortBy> thenByDescriptionDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'description', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Album, Album, QAfterSortBy> thenByEndDate() {
|
QueryBuilder<Album, Album, QAfterSortBy> thenByEndDate() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'endDate', Sort.asc);
|
return query.addSortBy(r'endDate', Sort.asc);
|
||||||
@ -1772,6 +1958,13 @@ extension AlbumQueryWhereDistinct on QueryBuilder<Album, Album, QDistinct> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, Album, QDistinct> distinctByDescription(
|
||||||
|
{bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addDistinctBy(r'description', caseSensitive: caseSensitive);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Album, Album, QDistinct> distinctByEndDate() {
|
QueryBuilder<Album, Album, QDistinct> distinctByEndDate() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addDistinctBy(r'endDate');
|
return query.addDistinctBy(r'endDate');
|
||||||
@ -1849,6 +2042,12 @@ extension AlbumQueryProperty on QueryBuilder<Album, Album, QQueryProperty> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Album, String?, QQueryOperations> descriptionProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'description');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Album, DateTime?, QQueryOperations> endDateProperty() {
|
QueryBuilder<Album, DateTime?, QQueryOperations> endDateProperty() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addPropertyName(r'endDate');
|
return query.addPropertyName(r'endDate');
|
||||||
|
@ -7,6 +7,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.
|
|||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:logging/logging.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' hide AssetVisibility;
|
||||||
|
|
||||||
class DriftSyncStreamRepository extends DriftDatabaseRepository
|
class DriftSyncStreamRepository extends DriftDatabaseRepository
|
||||||
@ -231,22 +232,22 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on SyncAssetV1TypeEnum {
|
extension on AssetTypeEnum {
|
||||||
AssetType toAssetType() => switch (this) {
|
AssetType toAssetType() => switch (this) {
|
||||||
SyncAssetV1TypeEnum.IMAGE => AssetType.image,
|
AssetTypeEnum.IMAGE => AssetType.image,
|
||||||
SyncAssetV1TypeEnum.VIDEO => AssetType.video,
|
AssetTypeEnum.VIDEO => AssetType.video,
|
||||||
SyncAssetV1TypeEnum.AUDIO => AssetType.audio,
|
AssetTypeEnum.AUDIO => AssetType.audio,
|
||||||
SyncAssetV1TypeEnum.OTHER => AssetType.other,
|
AssetTypeEnum.OTHER => AssetType.other,
|
||||||
_ => throw Exception('Unknown SyncAssetV1TypeEnum value: $this'),
|
_ => throw Exception('Unknown AssetType value: $this'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on SyncAssetV1VisibilityEnum {
|
extension on api.AssetVisibility {
|
||||||
AssetVisibility toAssetVisibility() => switch (this) {
|
AssetVisibility toAssetVisibility() => switch (this) {
|
||||||
SyncAssetV1VisibilityEnum.timeline => AssetVisibility.timeline,
|
api.AssetVisibility.timeline => AssetVisibility.timeline,
|
||||||
SyncAssetV1VisibilityEnum.hidden => AssetVisibility.hidden,
|
api.AssetVisibility.hidden => AssetVisibility.hidden,
|
||||||
SyncAssetV1VisibilityEnum.archive => AssetVisibility.archive,
|
api.AssetVisibility.archive => AssetVisibility.archive,
|
||||||
SyncAssetV1VisibilityEnum.locked => AssetVisibility.locked,
|
api.AssetVisibility.locked => AssetVisibility.locked,
|
||||||
_ => throw Exception('Unknown SyncAssetV1VisibilityEnum value: $this'),
|
_ => throw Exception('Unknown AssetVisibility value: $this'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ abstract interface class IDownloadRepository {
|
|||||||
void Function(TaskProgressUpdate)? onTaskProgress;
|
void Function(TaskProgressUpdate)? onTaskProgress;
|
||||||
|
|
||||||
Future<List<TaskRecord>> getLiveVideoTasks();
|
Future<List<TaskRecord>> getLiveVideoTasks();
|
||||||
Future<bool> download(DownloadTask task);
|
Future<List<bool>> downloadAll(List<DownloadTask> tasks);
|
||||||
|
|
||||||
Future<bool> cancel(String id);
|
Future<bool> cancel(String id);
|
||||||
Future<void> deleteAllTrackingRecords();
|
Future<void> deleteAllTrackingRecords();
|
||||||
Future<void> deleteRecordsWithIds(List<String> id);
|
Future<void> deleteRecordsWithIds(List<String> id);
|
||||||
|
@ -3,18 +3,23 @@ import 'dart:convert';
|
|||||||
class AlbumViewerPageState {
|
class AlbumViewerPageState {
|
||||||
final bool isEditAlbum;
|
final bool isEditAlbum;
|
||||||
final String editTitleText;
|
final String editTitleText;
|
||||||
|
final String editDescriptionText;
|
||||||
|
|
||||||
AlbumViewerPageState({
|
AlbumViewerPageState({
|
||||||
required this.isEditAlbum,
|
required this.isEditAlbum,
|
||||||
required this.editTitleText,
|
required this.editTitleText,
|
||||||
|
required this.editDescriptionText,
|
||||||
});
|
});
|
||||||
|
|
||||||
AlbumViewerPageState copyWith({
|
AlbumViewerPageState copyWith({
|
||||||
bool? isEditAlbum,
|
bool? isEditAlbum,
|
||||||
String? editTitleText,
|
String? editTitleText,
|
||||||
|
String? editDescriptionText,
|
||||||
}) {
|
}) {
|
||||||
return AlbumViewerPageState(
|
return AlbumViewerPageState(
|
||||||
isEditAlbum: isEditAlbum ?? this.isEditAlbum,
|
isEditAlbum: isEditAlbum ?? this.isEditAlbum,
|
||||||
editTitleText: editTitleText ?? this.editTitleText,
|
editTitleText: editTitleText ?? this.editTitleText,
|
||||||
|
editDescriptionText: editDescriptionText ?? this.editDescriptionText,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +28,7 @@ class AlbumViewerPageState {
|
|||||||
|
|
||||||
result.addAll({'isEditAlbum': isEditAlbum});
|
result.addAll({'isEditAlbum': isEditAlbum});
|
||||||
result.addAll({'editTitleText': editTitleText});
|
result.addAll({'editTitleText': editTitleText});
|
||||||
|
result.addAll({'editDescriptionText': editDescriptionText});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -31,6 +37,7 @@ class AlbumViewerPageState {
|
|||||||
return AlbumViewerPageState(
|
return AlbumViewerPageState(
|
||||||
isEditAlbum: map['isEditAlbum'] ?? false,
|
isEditAlbum: map['isEditAlbum'] ?? false,
|
||||||
editTitleText: map['editTitleText'] ?? '',
|
editTitleText: map['editTitleText'] ?? '',
|
||||||
|
editDescriptionText: map['editDescriptionText'] ?? '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +48,7 @@ class AlbumViewerPageState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'AlbumViewerPageState(isEditAlbum: $isEditAlbum, editTitleText: $editTitleText)';
|
'AlbumViewerPageState(isEditAlbum: $isEditAlbum, editTitleText: $editTitleText, editDescriptionText: $editDescriptionText)';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
@ -49,9 +56,13 @@ class AlbumViewerPageState {
|
|||||||
|
|
||||||
return other is AlbumViewerPageState &&
|
return other is AlbumViewerPageState &&
|
||||||
other.isEditAlbum == isEditAlbum &&
|
other.isEditAlbum == isEditAlbum &&
|
||||||
other.editTitleText == editTitleText;
|
other.editTitleText == editTitleText &&
|
||||||
|
other.editDescriptionText == editDescriptionText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => isEditAlbum.hashCode ^ editTitleText.hashCode;
|
int get hashCode =>
|
||||||
|
isEditAlbum.hashCode ^
|
||||||
|
editTitleText.hashCode ^
|
||||||
|
editDescriptionText.hashCode;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ class AssetSelectionState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'SelectionAssetState(hasRemote: $hasRemote, hasMerged: $hasMerged, hasMerged: $hasMerged, selectedCount: $selectedCount)';
|
'SelectionAssetState(hasRemote: $hasRemote, hasLocal: $hasLocal, hasMerged: $hasMerged, selectedCount: $selectedCount)';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(covariant AssetSelectionState other) {
|
bool operator ==(covariant AssetSelectionState other) {
|
||||||
|
@ -26,9 +26,9 @@ class AlbumControlButton extends ConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(left: 16.0, top: 8, bottom: 16),
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 36,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
children: [
|
children: [
|
||||||
|
@ -30,15 +30,12 @@ class AlbumDateRange extends ConsumerWidget {
|
|||||||
final (startDate, endDate, shared) = data;
|
final (startDate, endDate, shared) = data;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: shared
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
? const EdgeInsets.only(
|
|
||||||
left: 16.0,
|
|
||||||
bottom: 0.0,
|
|
||||||
)
|
|
||||||
: const EdgeInsets.only(left: 16.0, bottom: 8.0),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
_getDateRangeText(startDate, endDate),
|
_getDateRangeText(startDate, endDate),
|
||||||
style: context.textTheme.labelLarge,
|
style: context.textTheme.labelLarge?.copyWith(
|
||||||
|
color: context.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
45
mobile/lib/pages/album/album_description.dart
Normal file
45
mobile/lib/pages/album/album_description.dart
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
|
import 'package:immich_mobile/providers/album/current_album.provider.dart';
|
||||||
|
import 'package:immich_mobile/widgets/album/album_viewer_editable_description.dart';
|
||||||
|
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||||
|
|
||||||
|
class AlbumDescription extends ConsumerWidget {
|
||||||
|
const AlbumDescription({super.key, required this.descriptionFocusNode});
|
||||||
|
|
||||||
|
final FocusNode descriptionFocusNode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final userId = ref.watch(authProvider).userId;
|
||||||
|
final (isOwner, isRemote, albumDescription) = ref.watch(
|
||||||
|
currentAlbumProvider.select((album) {
|
||||||
|
if (album == null) {
|
||||||
|
return const (false, false, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return (album.ownerId == userId, album.isRemote, album.description);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isOwner && isRemote) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8, right: 8),
|
||||||
|
child: AlbumViewerEditableDescription(
|
||||||
|
albumDescription: albumDescription ?? 'add_a_description'.tr(),
|
||||||
|
descriptionFocusNode: descriptionFocusNode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16, right: 8),
|
||||||
|
child: Text(
|
||||||
|
albumDescription ?? 'add_a_description'.tr(),
|
||||||
|
style: context.textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -36,7 +36,7 @@ class AlbumSharedUserIcons extends HookConsumerWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 50,
|
height: 50,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.only(left: 16),
|
padding: const EdgeInsets.only(left: 16, bottom: 8),
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemBuilder: ((context, index) {
|
itemBuilder: ((context, index) {
|
||||||
return Padding(
|
return Padding(
|
||||||
|
@ -19,7 +19,11 @@ class AlbumTitle extends ConsumerWidget {
|
|||||||
return const (false, false, '');
|
return const (false, false, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (album.ownerId == userId, album.isRemote, album.name);
|
return (
|
||||||
|
album.ownerId == userId,
|
||||||
|
album.isRemote,
|
||||||
|
album.name,
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -35,7 +39,12 @@ class AlbumTitle extends ConsumerWidget {
|
|||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(left: 16, right: 8),
|
padding: const EdgeInsets.only(left: 16, right: 8),
|
||||||
child: Text(albumName, style: context.textTheme.headlineMedium),
|
child: Text(
|
||||||
|
albumName,
|
||||||
|
style: context.textTheme.headlineLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart';
|
import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart';
|
||||||
import 'package:immich_mobile/pages/album/album_control_button.dart';
|
import 'package:immich_mobile/pages/album/album_control_button.dart';
|
||||||
import 'package:immich_mobile/pages/album/album_date_range.dart';
|
import 'package:immich_mobile/pages/album/album_date_range.dart';
|
||||||
|
import 'package:immich_mobile/pages/album/album_description.dart';
|
||||||
import 'package:immich_mobile/pages/album/album_shared_user_icons.dart';
|
import 'package:immich_mobile/pages/album/album_shared_user_icons.dart';
|
||||||
import 'package:immich_mobile/pages/album/album_title.dart';
|
import 'package:immich_mobile/pages/album/album_title.dart';
|
||||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||||
@ -36,6 +37,7 @@ class AlbumViewer extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final titleFocusNode = useFocusNode();
|
final titleFocusNode = useFocusNode();
|
||||||
|
final descriptionFocusNode = useFocusNode();
|
||||||
final userId = ref.watch(authProvider).userId;
|
final userId = ref.watch(authProvider).userId;
|
||||||
final isMultiselecting = ref.watch(multiselectProvider);
|
final isMultiselecting = ref.watch(multiselectProvider);
|
||||||
final isProcessing = useProcessingOverlay();
|
final isProcessing = useProcessingOverlay();
|
||||||
@ -106,23 +108,44 @@ class AlbumViewer extends HookConsumerWidget {
|
|||||||
MultiselectGrid(
|
MultiselectGrid(
|
||||||
key: const ValueKey("albumViewerMultiselectGrid"),
|
key: const ValueKey("albumViewerMultiselectGrid"),
|
||||||
renderListProvider: albumTimelineProvider(album.id),
|
renderListProvider: albumTimelineProvider(album.id),
|
||||||
topWidget: Column(
|
topWidget: Container(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
decoration: BoxDecoration(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
gradient: LinearGradient(
|
||||||
children: [
|
begin: Alignment.topCenter,
|
||||||
AlbumTitle(
|
end: Alignment.bottomCenter,
|
||||||
key: const ValueKey("albumTitle"),
|
colors: [
|
||||||
titleFocusNode: titleFocusNode,
|
context.primaryColor.withValues(alpha: 0.04),
|
||||||
|
context.primaryColor.withValues(alpha: 0.02),
|
||||||
|
Colors.orange.withValues(alpha: 0.02),
|
||||||
|
Colors.transparent,
|
||||||
|
],
|
||||||
|
stops: const [0.0, 0.3, 0.7, 1.0],
|
||||||
),
|
),
|
||||||
const AlbumDateRange(),
|
),
|
||||||
const AlbumSharedUserIcons(),
|
child: Column(
|
||||||
if (album.isRemote)
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
AlbumControlButton(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
key: const ValueKey("albumControlButton"),
|
children: [
|
||||||
onAddPhotosPressed: onAddPhotosPressed,
|
const SizedBox(height: 32),
|
||||||
onAddUsersPressed: onAddUsersPressed,
|
const AlbumDateRange(),
|
||||||
|
AlbumTitle(
|
||||||
|
key: const ValueKey("albumTitle"),
|
||||||
|
titleFocusNode: titleFocusNode,
|
||||||
),
|
),
|
||||||
],
|
AlbumDescription(
|
||||||
|
key: const ValueKey("albumDescription"),
|
||||||
|
descriptionFocusNode: descriptionFocusNode,
|
||||||
|
),
|
||||||
|
const AlbumSharedUserIcons(),
|
||||||
|
if (album.isRemote)
|
||||||
|
AlbumControlButton(
|
||||||
|
key: const ValueKey("albumControlButton"),
|
||||||
|
onAddPhotosPressed: onAddPhotosPressed,
|
||||||
|
onAddUsersPressed: onAddUsersPressed,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onRemoveFromAlbum: onRemoveFromAlbumPressed,
|
onRemoveFromAlbum: onRemoveFromAlbumPressed,
|
||||||
editEnabled: album.ownerId == userId,
|
editEnabled: album.ownerId == userId,
|
||||||
@ -136,6 +159,7 @@ class AlbumViewer extends HookConsumerWidget {
|
|||||||
child: AlbumViewerAppbar(
|
child: AlbumViewerAppbar(
|
||||||
key: const ValueKey("albumViewerAppbar"),
|
key: const ValueKey("albumViewerAppbar"),
|
||||||
titleFocusNode: titleFocusNode,
|
titleFocusNode: titleFocusNode,
|
||||||
|
descriptionFocusNode: descriptionFocusNode,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
onAddPhotos: onAddPhotosPressed,
|
onAddPhotos: onAddPhotosPressed,
|
||||||
onAddUsers: onAddUsersPressed,
|
onAddUsers: onAddUsersPressed,
|
||||||
|
@ -8,9 +8,11 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart';
|
import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart';
|
||||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/album/album_title.provider.dart';
|
import 'package:immich_mobile/providers/album/album_title.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/album/album_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/widgets/album/album_action_filled_button.dart';
|
import 'package:immich_mobile/widgets/album/album_action_filled_button.dart';
|
||||||
import 'package:immich_mobile/widgets/album/album_title_text_field.dart';
|
import 'package:immich_mobile/widgets/album/album_title_text_field.dart';
|
||||||
|
import 'package:immich_mobile/widgets/album/album_viewer_editable_description.dart';
|
||||||
import 'package:immich_mobile/widgets/album/shared_album_thumbnail_image.dart';
|
import 'package:immich_mobile/widgets/album/shared_album_thumbnail_image.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
@ -28,6 +30,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
final albumTitleController =
|
final albumTitleController =
|
||||||
useTextEditingController.fromValue(TextEditingValue.empty);
|
useTextEditingController.fromValue(TextEditingValue.empty);
|
||||||
final albumTitleTextFieldFocusNode = useFocusNode();
|
final albumTitleTextFieldFocusNode = useFocusNode();
|
||||||
|
final albumDescriptionTextFieldFocusNode = useFocusNode();
|
||||||
final isAlbumTitleTextFieldFocus = useState(false);
|
final isAlbumTitleTextFieldFocus = useState(false);
|
||||||
final isAlbumTitleEmpty = useState(true);
|
final isAlbumTitleEmpty = useState(true);
|
||||||
final selectedAssets = useState<Set<Asset>>(
|
final selectedAssets = useState<Set<Asset>>(
|
||||||
@ -36,6 +39,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
void onBackgroundTapped() {
|
void onBackgroundTapped() {
|
||||||
albumTitleTextFieldFocusNode.unfocus();
|
albumTitleTextFieldFocusNode.unfocus();
|
||||||
|
albumDescriptionTextFieldFocusNode.unfocus();
|
||||||
isAlbumTitleTextFieldFocus.value = false;
|
isAlbumTitleTextFieldFocus.value = false;
|
||||||
|
|
||||||
if (albumTitleController.text.isEmpty) {
|
if (albumTitleController.text.isEmpty) {
|
||||||
@ -77,6 +81,19 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildDescriptionInputField() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
right: 10,
|
||||||
|
left: 10,
|
||||||
|
),
|
||||||
|
child: AlbumViewerEditableDescription(
|
||||||
|
albumDescription: '',
|
||||||
|
descriptionFocusNode: albumDescriptionTextFieldFocusNode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
buildTitle() {
|
buildTitle() {
|
||||||
if (selectedAssets.value.isEmpty) {
|
if (selectedAssets.value.isEmpty) {
|
||||||
return SliverToBoxAdapter(
|
return SliverToBoxAdapter(
|
||||||
@ -178,18 +195,18 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
return const SliverToBoxAdapter();
|
return const SliverToBoxAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
createNonSharedAlbum() async {
|
Future<void> createAlbum() async {
|
||||||
onBackgroundTapped();
|
onBackgroundTapped();
|
||||||
var newAlbum = await ref.watch(albumProvider.notifier).createAlbum(
|
var newAlbum = await ref.watch(albumProvider.notifier).createAlbum(
|
||||||
ref.watch(albumTitleProvider),
|
ref.read(albumTitleProvider),
|
||||||
selectedAssets.value,
|
selectedAssets.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newAlbum != null) {
|
if (newAlbum != null) {
|
||||||
ref.watch(albumProvider.notifier).refreshRemoteAlbums();
|
ref.read(albumProvider.notifier).refreshRemoteAlbums();
|
||||||
selectedAssets.value = {};
|
selectedAssets.value = {};
|
||||||
ref.watch(albumTitleProvider.notifier).clearAlbumTitle();
|
ref.read(albumTitleProvider.notifier).clearAlbumTitle();
|
||||||
|
ref.read(albumViewerProvider.notifier).disableEditAlbum();
|
||||||
context.replaceRoute(AlbumViewerRoute(albumId: newAlbum.id));
|
context.replaceRoute(AlbumViewerRoute(albumId: newAlbum.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,9 +228,8 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
).tr(),
|
).tr(),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: albumTitleController.text.isNotEmpty
|
onPressed:
|
||||||
? createNonSharedAlbum
|
albumTitleController.text.isNotEmpty ? createAlbum : null,
|
||||||
: null,
|
|
||||||
child: Text(
|
child: Text(
|
||||||
'create'.tr(),
|
'create'.tr(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -237,10 +253,11 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
pinned: true,
|
pinned: true,
|
||||||
floating: false,
|
floating: false,
|
||||||
bottom: PreferredSize(
|
bottom: PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(96.0),
|
preferredSize: const Size.fromHeight(125.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
buildTitleInputField(),
|
buildTitleInputField(),
|
||||||
|
buildDescriptionInputField(),
|
||||||
if (selectedAssets.value.isNotEmpty) buildControlButton(),
|
if (selectedAssets.value.isNotEmpty) buildControlButton(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -72,7 +72,9 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.replaceRoute(const TabControllerRoute());
|
if (context.router.current.name != ShareIntentRoute.name) {
|
||||||
|
context.replaceRoute(const TabControllerRoute());
|
||||||
|
}
|
||||||
|
|
||||||
final hasPermission =
|
final hasPermission =
|
||||||
await ref.read(galleryPermissionNotifier.notifier).hasPermission;
|
await ref.read(galleryPermissionNotifier.notifier).hasPermission;
|
||||||
|
@ -7,6 +7,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart';
|
import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart';
|
||||||
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
|
||||||
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/utils/url_helper.dart';
|
import 'package:immich_mobile/utils/url_helper.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
@ -20,6 +21,11 @@ class ShareIntentPage extends HookConsumerWidget {
|
|||||||
final currentEndpoint = getServerUrl() ?? '--';
|
final currentEndpoint = getServerUrl() ?? '--';
|
||||||
final candidates = ref.watch(shareIntentUploadProvider);
|
final candidates = ref.watch(shareIntentUploadProvider);
|
||||||
final isUploaded = useState(false);
|
final isUploaded = useState(false);
|
||||||
|
useOnAppLifecycleStateChange((previous, current) {
|
||||||
|
if (current == AppLifecycleState.resumed) {
|
||||||
|
isUploaded.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
void removeAttachment(ShareIntentAttachment attachment) {
|
void removeAttachment(ShareIntentAttachment attachment) {
|
||||||
ref.read(shareIntentUploadProvider.notifier).removeAttachment(attachment);
|
ref.read(shareIntentUploadProvider.notifier).removeAttachment(attachment);
|
||||||
@ -66,6 +72,14 @@ class ShareIntentPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.navigateTo(
|
||||||
|
const TabControllerRoute(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: ListView.builder(
|
body: ListView.builder(
|
||||||
itemCount: attachments.length,
|
itemCount: attachments.length,
|
||||||
|
@ -5,7 +5,13 @@ import 'package:immich_mobile/entities/album.entity.dart';
|
|||||||
|
|
||||||
class AlbumViewerNotifier extends StateNotifier<AlbumViewerPageState> {
|
class AlbumViewerNotifier extends StateNotifier<AlbumViewerPageState> {
|
||||||
AlbumViewerNotifier(this.ref)
|
AlbumViewerNotifier(this.ref)
|
||||||
: super(AlbumViewerPageState(editTitleText: "", isEditAlbum: false));
|
: super(
|
||||||
|
AlbumViewerPageState(
|
||||||
|
editTitleText: "",
|
||||||
|
isEditAlbum: false,
|
||||||
|
editDescriptionText: "",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
final Ref ref;
|
final Ref ref;
|
||||||
|
|
||||||
@ -21,12 +27,24 @@ class AlbumViewerNotifier extends StateNotifier<AlbumViewerPageState> {
|
|||||||
state = state.copyWith(editTitleText: newTitle);
|
state = state.copyWith(editTitleText: newTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setEditDescriptionText(String newDescription) {
|
||||||
|
state = state.copyWith(editDescriptionText: newDescription);
|
||||||
|
}
|
||||||
|
|
||||||
void remoteEditTitleText() {
|
void remoteEditTitleText() {
|
||||||
state = state.copyWith(editTitleText: "");
|
state = state.copyWith(editTitleText: "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remoteEditDescriptionText() {
|
||||||
|
state = state.copyWith(editDescriptionText: "");
|
||||||
|
}
|
||||||
|
|
||||||
void resetState() {
|
void resetState() {
|
||||||
state = state.copyWith(editTitleText: "", isEditAlbum: false);
|
state = state.copyWith(
|
||||||
|
editTitleText: "",
|
||||||
|
isEditAlbum: false,
|
||||||
|
editDescriptionText: "",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> changeAlbumTitle(
|
Future<bool> changeAlbumTitle(
|
||||||
@ -46,6 +64,28 @@ class AlbumViewerNotifier extends StateNotifier<AlbumViewerPageState> {
|
|||||||
state = state.copyWith(editTitleText: "", isEditAlbum: false);
|
state = state.copyWith(editTitleText: "", isEditAlbum: false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> changeAlbumDescription(
|
||||||
|
Album album,
|
||||||
|
String newAlbumDescription,
|
||||||
|
) async {
|
||||||
|
AlbumService service = ref.watch(albumServiceProvider);
|
||||||
|
|
||||||
|
bool isSuccess = await service.changeDescriptionAlbum(
|
||||||
|
album,
|
||||||
|
newAlbumDescription,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isSuccess) {
|
||||||
|
state = state.copyWith(editDescriptionText: "", isEditAlbum: false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = state.copyWith(editDescriptionText: "", isEditAlbum: false);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final albumViewerProvider =
|
final albumViewerProvider =
|
||||||
|
@ -140,6 +140,10 @@ class DownloadStateNotifier extends StateNotifier<DownloadState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<bool>> downloadAllAsset(List<Asset> assets) async {
|
||||||
|
return await _downloadService.downloadAll(assets);
|
||||||
|
}
|
||||||
|
|
||||||
void downloadAsset(Asset asset, BuildContext context) async {
|
void downloadAsset(Asset asset, BuildContext context) async {
|
||||||
await _downloadService.download(asset);
|
await _downloadService.download(asset);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository {
|
|||||||
String name, {
|
String name, {
|
||||||
required Iterable<String> assetIds,
|
required Iterable<String> assetIds,
|
||||||
Iterable<String> sharedUserIds = const [],
|
Iterable<String> sharedUserIds = const [],
|
||||||
|
String? description,
|
||||||
}) async {
|
}) async {
|
||||||
final users = sharedUserIds.map(
|
final users = sharedUserIds.map(
|
||||||
(id) => AlbumUserCreateDto(userId: id, role: AlbumUserRole.editor),
|
(id) => AlbumUserCreateDto(userId: id, role: AlbumUserRole.editor),
|
||||||
@ -44,6 +45,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository {
|
|||||||
_api.createAlbum(
|
_api.createAlbum(
|
||||||
CreateAlbumDto(
|
CreateAlbumDto(
|
||||||
albumName: name,
|
albumName: name,
|
||||||
|
description: description,
|
||||||
assetIds: assetIds.toList(),
|
assetIds: assetIds.toList(),
|
||||||
albumUsers: users.toList(),
|
albumUsers: users.toList(),
|
||||||
),
|
),
|
||||||
@ -161,6 +163,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository {
|
|||||||
lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp,
|
lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp,
|
||||||
shared: dto.shared,
|
shared: dto.shared,
|
||||||
startDate: dto.startDate,
|
startDate: dto.startDate,
|
||||||
|
description: dto.description,
|
||||||
endDate: dto.endDate,
|
endDate: dto.endDate,
|
||||||
activityEnabled: dto.isActivityEnabled,
|
activityEnabled: dto.isActivityEnabled,
|
||||||
sortOrder: dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc,
|
sortOrder: dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc,
|
||||||
@ -174,6 +177,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository {
|
|||||||
album.sharedUsers.addAll(users.map(entity.User.fromDto));
|
album.sharedUsers.addAll(users.map(entity.User.fromDto));
|
||||||
final assets = dto.assets.map(Asset.remote).toList();
|
final assets = dto.assets.map(Asset.remote).toList();
|
||||||
album.assets.addAll(assets);
|
album.assets.addAll(assets);
|
||||||
|
|
||||||
return album;
|
return album;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ class DownloadRepository implements IDownloadRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> download(DownloadTask task) {
|
Future<List<bool>> downloadAll(List<DownloadTask> tasks) {
|
||||||
return FileDownloader().enqueue(task);
|
return FileDownloader().enqueueAll(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -422,6 +422,25 @@ class AlbumService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> changeDescriptionAlbum(
|
||||||
|
Album album,
|
||||||
|
String newAlbumDescription,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
final updatedAlbum = await _albumApiRepository.update(
|
||||||
|
album.remoteId!,
|
||||||
|
description: newAlbumDescription,
|
||||||
|
);
|
||||||
|
|
||||||
|
album.description = updatedAlbum.description;
|
||||||
|
await _albumRepository.update(album);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("Error changeDescriptionAlbum ${e.toString()}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<Album?> getAlbumByName(
|
Future<Album?> getAlbumByName(
|
||||||
String name, {
|
String name, {
|
||||||
bool? remote,
|
bool? remote,
|
||||||
|
@ -159,9 +159,19 @@ class DownloadService {
|
|||||||
return await FileDownloader().cancelTaskWithId(id);
|
return await FileDownloader().cancelTaskWithId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<bool>> downloadAll(List<Asset> assets) async {
|
||||||
|
return await _downloadRepository
|
||||||
|
.downloadAll(assets.expand(_createDownloadTasks).toList());
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> download(Asset asset) async {
|
Future<void> download(Asset asset) async {
|
||||||
|
final tasks = _createDownloadTasks(asset);
|
||||||
|
await _downloadRepository.downloadAll(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DownloadTask> _createDownloadTasks(Asset asset) {
|
||||||
if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) {
|
if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) {
|
||||||
await _downloadRepository.download(
|
return [
|
||||||
_buildDownloadTask(
|
_buildDownloadTask(
|
||||||
asset.remoteId!,
|
asset.remoteId!,
|
||||||
asset.fileName,
|
asset.fileName,
|
||||||
@ -171,9 +181,6 @@ class DownloadService {
|
|||||||
id: asset.remoteId!,
|
id: asset.remoteId!,
|
||||||
).toJson(),
|
).toJson(),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
|
|
||||||
await _downloadRepository.download(
|
|
||||||
_buildDownloadTask(
|
_buildDownloadTask(
|
||||||
asset.livePhotoVideoId!,
|
asset.livePhotoVideoId!,
|
||||||
asset.fileName
|
asset.fileName
|
||||||
@ -185,16 +192,20 @@ class DownloadService {
|
|||||||
id: asset.remoteId!,
|
id: asset.remoteId!,
|
||||||
).toJson(),
|
).toJson(),
|
||||||
),
|
),
|
||||||
);
|
];
|
||||||
} else {
|
|
||||||
await _downloadRepository.download(
|
|
||||||
_buildDownloadTask(
|
|
||||||
asset.remoteId!,
|
|
||||||
asset.fileName,
|
|
||||||
group: asset.isImage ? downloadGroupImage : downloadGroupVideo,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (asset.remoteId == null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
_buildDownloadTask(
|
||||||
|
asset.remoteId!,
|
||||||
|
asset.fileName,
|
||||||
|
group: asset.isImage ? downloadGroupImage : downloadGroupVideo,
|
||||||
|
),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadTask _buildDownloadTask(
|
DownloadTask _buildDownloadTask(
|
||||||
|
@ -451,6 +451,7 @@ class SyncService {
|
|||||||
final usersToLink = await _userRepository.getByUserIds(userIdsToAdd);
|
final usersToLink = await _userRepository.getByUserIds(userIdsToAdd);
|
||||||
|
|
||||||
album.name = dto.name;
|
album.name = dto.name;
|
||||||
|
album.description = dto.description;
|
||||||
album.shared = dto.shared;
|
album.shared = dto.shared;
|
||||||
album.createdAt = dto.createdAt;
|
album.createdAt = dto.createdAt;
|
||||||
album.modifiedAt = dto.modifiedAt;
|
album.modifiedAt = dto.modifiedAt;
|
||||||
@ -643,6 +644,7 @@ class SyncService {
|
|||||||
toUpdate.isEmpty &&
|
toUpdate.isEmpty &&
|
||||||
toDelete.isEmpty &&
|
toDelete.isEmpty &&
|
||||||
dbAlbum.name == deviceAlbum.name &&
|
dbAlbum.name == deviceAlbum.name &&
|
||||||
|
dbAlbum.description == deviceAlbum.description &&
|
||||||
dbAlbum.modifiedAt.isAtSameMomentAs(deviceAlbum.modifiedAt)) {
|
dbAlbum.modifiedAt.isAtSameMomentAs(deviceAlbum.modifiedAt)) {
|
||||||
// changes only affeted excluded albums
|
// changes only affeted excluded albums
|
||||||
_log.info(
|
_log.info(
|
||||||
@ -670,6 +672,7 @@ class SyncService {
|
|||||||
deleteCandidates.addAll(toDelete);
|
deleteCandidates.addAll(toDelete);
|
||||||
existing.addAll(existingInDb);
|
existing.addAll(existingInDb);
|
||||||
dbAlbum.name = deviceAlbum.name;
|
dbAlbum.name = deviceAlbum.name;
|
||||||
|
dbAlbum.description = deviceAlbum.description;
|
||||||
dbAlbum.modifiedAt = deviceAlbum.modifiedAt;
|
dbAlbum.modifiedAt = deviceAlbum.modifiedAt;
|
||||||
if (dbAlbum.thumbnail.value != null &&
|
if (dbAlbum.thumbnail.value != null &&
|
||||||
toDelete.contains(dbAlbum.thumbnail.value)) {
|
toDelete.contains(dbAlbum.thumbnail.value)) {
|
||||||
@ -943,6 +946,7 @@ class SyncService {
|
|||||||
Album dbAlbum,
|
Album dbAlbum,
|
||||||
) async {
|
) async {
|
||||||
return deviceAlbum.name != dbAlbum.name ||
|
return deviceAlbum.name != dbAlbum.name ||
|
||||||
|
deviceAlbum.description != dbAlbum.description ||
|
||||||
!deviceAlbum.modifiedAt.isAtSameMomentAs(dbAlbum.modifiedAt) ||
|
!deviceAlbum.modifiedAt.isAtSameMomentAs(dbAlbum.modifiedAt) ||
|
||||||
await _albumMediaRepository.getAssetCount(deviceAlbum.localId!) !=
|
await _albumMediaRepository.getAssetCount(deviceAlbum.localId!) !=
|
||||||
(await _eTagRepository.getById(deviceAlbum.eTagKeyAssetCount))
|
(await _eTagRepository.getById(deviceAlbum.eTagKeyAssetCount))
|
||||||
@ -1101,6 +1105,7 @@ class SyncService {
|
|||||||
bool _hasRemoteAlbumChanged(Album remoteAlbum, Album dbAlbum) {
|
bool _hasRemoteAlbumChanged(Album remoteAlbum, Album dbAlbum) {
|
||||||
return remoteAlbum.remoteAssetCount != dbAlbum.assetCount ||
|
return remoteAlbum.remoteAssetCount != dbAlbum.assetCount ||
|
||||||
remoteAlbum.name != dbAlbum.name ||
|
remoteAlbum.name != dbAlbum.name ||
|
||||||
|
remoteAlbum.description != dbAlbum.description ||
|
||||||
remoteAlbum.remoteThumbnailAssetId != dbAlbum.thumbnail.value?.remoteId ||
|
remoteAlbum.remoteThumbnailAssetId != dbAlbum.thumbnail.value?.remoteId ||
|
||||||
remoteAlbum.shared != dbAlbum.shared ||
|
remoteAlbum.shared != dbAlbum.shared ||
|
||||||
remoteAlbum.remoteUsers.length != dbAlbum.sharedUsers.length ||
|
remoteAlbum.remoteUsers.length != dbAlbum.sharedUsers.length ||
|
||||||
|
@ -16,7 +16,7 @@ class AlbumActionFilledButton extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 16.0),
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: FilledButton.icon(
|
child: FilledButton.icon(
|
||||||
style: FilledButton.styleFrom(
|
style: FilledButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 16),
|
||||||
@ -32,9 +32,7 @@ class AlbumActionFilledButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
labelText,
|
labelText,
|
||||||
style: context.textTheme.labelMedium?.copyWith(
|
style: context.textTheme.labelLarge?.copyWith(),
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
),
|
),
|
||||||
|
@ -18,6 +18,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
super.key,
|
super.key,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.titleFocusNode,
|
required this.titleFocusNode,
|
||||||
|
required this.descriptionFocusNode,
|
||||||
this.onAddPhotos,
|
this.onAddPhotos,
|
||||||
this.onAddUsers,
|
this.onAddUsers,
|
||||||
required this.onActivities,
|
required this.onActivities,
|
||||||
@ -25,6 +26,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
|
|
||||||
final String userId;
|
final String userId;
|
||||||
final FocusNode titleFocusNode;
|
final FocusNode titleFocusNode;
|
||||||
|
final FocusNode descriptionFocusNode;
|
||||||
final void Function()? onAddPhotos;
|
final void Function()? onAddPhotos;
|
||||||
final void Function()? onAddUsers;
|
final void Function()? onAddUsers;
|
||||||
final void Function() onActivities;
|
final void Function() onActivities;
|
||||||
@ -48,6 +50,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
|
|
||||||
final albumViewer = ref.watch(albumViewerProvider);
|
final albumViewer = ref.watch(albumViewerProvider);
|
||||||
final newAlbumTitle = albumViewer.editTitleText;
|
final newAlbumTitle = albumViewer.editTitleText;
|
||||||
|
final newAlbumDescription = albumViewer.editDescriptionText;
|
||||||
final isEditAlbum = albumViewer.isEditAlbum;
|
final isEditAlbum = albumViewer.isEditAlbum;
|
||||||
|
|
||||||
final comments = album.shared
|
final comments = album.shared
|
||||||
@ -277,20 +280,37 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
if (isEditAlbum) {
|
if (isEditAlbum) {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
bool isSuccess = await ref
|
if (newAlbumTitle.isNotEmpty) {
|
||||||
.watch(albumViewerProvider.notifier)
|
bool isSuccess = await ref
|
||||||
.changeAlbumTitle(album, newAlbumTitle);
|
.watch(albumViewerProvider.notifier)
|
||||||
|
.changeAlbumTitle(album, newAlbumTitle);
|
||||||
if (!isSuccess) {
|
if (!isSuccess) {
|
||||||
ImmichToast.show(
|
ImmichToast.show(
|
||||||
context: context,
|
context: context,
|
||||||
msg: "album_viewer_appbar_share_err_title".tr(),
|
msg: "album_viewer_appbar_share_err_title".tr(),
|
||||||
gravity: ToastGravity.BOTTOM,
|
gravity: ToastGravity.BOTTOM,
|
||||||
toastType: ToastType.error,
|
toastType: ToastType.error,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
titleFocusNode.unfocus();
|
||||||
|
} else if (newAlbumDescription.isNotEmpty) {
|
||||||
|
bool isSuccessDescription = await ref
|
||||||
|
.watch(albumViewerProvider.notifier)
|
||||||
|
.changeAlbumDescription(album, newAlbumDescription);
|
||||||
|
if (!isSuccessDescription) {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: "album_viewer_appbar_share_err_description".tr(),
|
||||||
|
gravity: ToastGravity.BOTTOM,
|
||||||
|
toastType: ToastType.error,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
descriptionFocusNode.unfocus();
|
||||||
|
} else {
|
||||||
|
titleFocusNode.unfocus();
|
||||||
|
descriptionFocusNode.unfocus();
|
||||||
|
ref.read(albumViewerProvider.notifier).disableEditAlbum();
|
||||||
}
|
}
|
||||||
|
|
||||||
titleFocusNode.unfocus();
|
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.check_rounded),
|
icon: const Icon(Icons.check_rounded),
|
||||||
splashRadius: 25,
|
splashRadius: 25,
|
||||||
|
102
mobile/lib/widgets/album/album_viewer_editable_description.dart
Normal file
102
mobile/lib/widgets/album/album_viewer_editable_description.dart
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
|
import 'package:immich_mobile/providers/album/album_viewer.provider.dart';
|
||||||
|
|
||||||
|
class AlbumViewerEditableDescription extends HookConsumerWidget {
|
||||||
|
final String albumDescription;
|
||||||
|
final FocusNode descriptionFocusNode;
|
||||||
|
const AlbumViewerEditableDescription({
|
||||||
|
super.key,
|
||||||
|
required this.albumDescription,
|
||||||
|
required this.descriptionFocusNode,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final albumViewerState = ref.watch(albumViewerProvider);
|
||||||
|
|
||||||
|
final descriptionTextEditController = useTextEditingController(
|
||||||
|
text: albumViewerState.isEditAlbum &&
|
||||||
|
albumViewerState.editDescriptionText.isNotEmpty
|
||||||
|
? albumViewerState.editDescriptionText
|
||||||
|
: albumDescription,
|
||||||
|
);
|
||||||
|
|
||||||
|
void onFocusModeChange() {
|
||||||
|
if (!descriptionFocusNode.hasFocus &&
|
||||||
|
descriptionTextEditController.text.isEmpty) {
|
||||||
|
ref.watch(albumViewerProvider.notifier).setEditDescriptionText("");
|
||||||
|
descriptionTextEditController.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() {
|
||||||
|
descriptionFocusNode.addListener(onFocusModeChange);
|
||||||
|
return () {
|
||||||
|
descriptionFocusNode.removeListener(onFocusModeChange);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value.isEmpty) {
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.watch(albumViewerProvider.notifier)
|
||||||
|
.setEditDescriptionText(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
focusNode: descriptionFocusNode,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
maxLines: 3,
|
||||||
|
minLines: 1,
|
||||||
|
controller: descriptionTextEditController,
|
||||||
|
onTap: () {
|
||||||
|
context.focusScope.requestFocus(descriptionFocusNode);
|
||||||
|
|
||||||
|
ref
|
||||||
|
.watch(albumViewerProvider.notifier)
|
||||||
|
.setEditDescriptionText(albumDescription);
|
||||||
|
ref.watch(albumViewerProvider.notifier).enableEditAlbum();
|
||||||
|
|
||||||
|
if (descriptionTextEditController.text == '') {
|
||||||
|
descriptionTextEditController.clear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: const EdgeInsets.all(8),
|
||||||
|
suffixIcon: descriptionFocusNode.hasFocus
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
descriptionTextEditController.clear();
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.cancel_rounded,
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
splashRadius: 10,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
enabledBorder: const OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.transparent),
|
||||||
|
),
|
||||||
|
focusedBorder: const OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.transparent),
|
||||||
|
),
|
||||||
|
focusColor: Colors.grey[300],
|
||||||
|
fillColor: context.scaffoldBackgroundColor,
|
||||||
|
filled: descriptionFocusNode.hasFocus,
|
||||||
|
hintText: 'add_a_description'.tr(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -52,7 +52,9 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
focusNode: titleFocusNode,
|
focusNode: titleFocusNode,
|
||||||
style: context.textTheme.headlineMedium,
|
style: context.textTheme.headlineLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
controller: titleTextEditController,
|
controller: titleTextEditController,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.focusScope.requestFocus(titleFocusNode);
|
context.focusScope.requestFocus(titleFocusNode);
|
||||||
@ -65,8 +67,10 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding:
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
horizontal: 8,
|
||||||
|
vertical: 0,
|
||||||
|
),
|
||||||
suffixIcon: titleFocusNode.hasFocus
|
suffixIcon: titleFocusNode.hasFocus
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
@ -39,6 +39,7 @@ class ControlBottomAppBar extends HookConsumerWidget {
|
|||||||
final void Function()? onEditLocation;
|
final void Function()? onEditLocation;
|
||||||
final void Function()? onRemoveFromAlbum;
|
final void Function()? onRemoveFromAlbum;
|
||||||
final void Function()? onToggleLocked;
|
final void Function()? onToggleLocked;
|
||||||
|
final void Function()? onDownload;
|
||||||
|
|
||||||
final bool enabled;
|
final bool enabled;
|
||||||
final bool unfavorite;
|
final bool unfavorite;
|
||||||
@ -56,6 +57,7 @@ class ControlBottomAppBar extends HookConsumerWidget {
|
|||||||
required this.onAddToAlbum,
|
required this.onAddToAlbum,
|
||||||
required this.onCreateNewAlbum,
|
required this.onCreateNewAlbum,
|
||||||
required this.onUpload,
|
required this.onUpload,
|
||||||
|
this.onDownload,
|
||||||
this.onStack,
|
this.onStack,
|
||||||
this.onEditTime,
|
this.onEditTime,
|
||||||
this.onEditLocation,
|
this.onEditLocation,
|
||||||
@ -158,6 +160,15 @@ class ControlBottomAppBar extends HookConsumerWidget {
|
|||||||
label: (unfavorite ? "unfavorite" : "favorite").tr(),
|
label: (unfavorite ? "unfavorite" : "favorite").tr(),
|
||||||
onPressed: enabled ? onFavorite : null,
|
onPressed: enabled ? onFavorite : null,
|
||||||
),
|
),
|
||||||
|
if (hasRemote && onDownload != null)
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 90),
|
||||||
|
child: ControlBoxButton(
|
||||||
|
iconData: Icons.download,
|
||||||
|
label: "download".tr(),
|
||||||
|
onPressed: onDownload,
|
||||||
|
),
|
||||||
|
),
|
||||||
if (hasLocal && hasRemote && onDelete != null && !isInLockedView)
|
if (hasLocal && hasRemote && onDelete != null && !isInLockedView)
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxWidth: 90),
|
constraints: const BoxConstraints(maxWidth: 90),
|
||||||
|
@ -14,6 +14,7 @@ import 'package:immich_mobile/extensions/collection_extensions.dart';
|
|||||||
import 'package:immich_mobile/models/asset_selection_state.dart';
|
import 'package:immich_mobile/models/asset_selection_state.dart';
|
||||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset.provider.dart';
|
import 'package:immich_mobile/providers/asset.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/asset_viewer/download.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/manual_upload.provider.dart';
|
import 'package:immich_mobile/providers/backup/manual_upload.provider.dart';
|
||||||
import 'package:immich_mobile/providers/multiselect.provider.dart';
|
import 'package:immich_mobile/providers/multiselect.provider.dart';
|
||||||
import 'package:immich_mobile/providers/routes.provider.dart';
|
import 'package:immich_mobile/providers/routes.provider.dart';
|
||||||
@ -23,6 +24,7 @@ import 'package:immich_mobile/services/album.service.dart';
|
|||||||
import 'package:immich_mobile/services/stack.service.dart';
|
import 'package:immich_mobile/services/stack.service.dart';
|
||||||
import 'package:immich_mobile/utils/immich_loading_overlay.dart';
|
import 'package:immich_mobile/utils/immich_loading_overlay.dart';
|
||||||
import 'package:immich_mobile/utils/selection_handlers.dart';
|
import 'package:immich_mobile/utils/selection_handlers.dart';
|
||||||
|
import 'package:immich_mobile/utils/translation.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart';
|
import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart';
|
||||||
@ -44,6 +46,7 @@ class MultiselectGrid extends HookConsumerWidget {
|
|||||||
this.editEnabled = false,
|
this.editEnabled = false,
|
||||||
this.unarchive = false,
|
this.unarchive = false,
|
||||||
this.unfavorite = false,
|
this.unfavorite = false,
|
||||||
|
this.downloadEnabled = true,
|
||||||
this.emptyIndicator,
|
this.emptyIndicator,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,6 +60,7 @@ class MultiselectGrid extends HookConsumerWidget {
|
|||||||
final bool archiveEnabled;
|
final bool archiveEnabled;
|
||||||
final bool unarchive;
|
final bool unarchive;
|
||||||
final bool deleteEnabled;
|
final bool deleteEnabled;
|
||||||
|
final bool downloadEnabled;
|
||||||
final bool favoriteEnabled;
|
final bool favoriteEnabled;
|
||||||
final bool unfavorite;
|
final bool unfavorite;
|
||||||
final bool editEnabled;
|
final bool editEnabled;
|
||||||
@ -239,6 +243,39 @@ class MultiselectGrid extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onDownload() async {
|
||||||
|
processing.value = true;
|
||||||
|
try {
|
||||||
|
final toDownload = selection.value.toList();
|
||||||
|
|
||||||
|
final results = await ref
|
||||||
|
.read(downloadStateProvider.notifier)
|
||||||
|
.downloadAllAsset(toDownload);
|
||||||
|
|
||||||
|
final totalCount = toDownload.length;
|
||||||
|
final successCount = results.where((e) => e).length;
|
||||||
|
final failedCount = totalCount - successCount;
|
||||||
|
|
||||||
|
final msg = failedCount > 0
|
||||||
|
? t('assets_downloaded_failed', {
|
||||||
|
'count': successCount,
|
||||||
|
'error': failedCount,
|
||||||
|
})
|
||||||
|
: t('assets_downloaded_successfully', {
|
||||||
|
'count': successCount,
|
||||||
|
});
|
||||||
|
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: msg,
|
||||||
|
gravity: ToastGravity.BOTTOM,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
processing.value = false;
|
||||||
|
selectionEnabledHook.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onDeleteRemote([bool shouldDeletePermanently = false]) async {
|
void onDeleteRemote([bool shouldDeletePermanently = false]) async {
|
||||||
processing.value = true;
|
processing.value = true;
|
||||||
try {
|
try {
|
||||||
@ -474,6 +511,7 @@ class MultiselectGrid extends HookConsumerWidget {
|
|||||||
onArchive: archiveEnabled ? onArchiveAsset : null,
|
onArchive: archiveEnabled ? onArchiveAsset : null,
|
||||||
onDelete: deleteEnabled ? onDelete : null,
|
onDelete: deleteEnabled ? onDelete : null,
|
||||||
onDeleteServer: deleteEnabled ? onDeleteRemote : null,
|
onDeleteServer: deleteEnabled ? onDeleteRemote : null,
|
||||||
|
onDownload: downloadEnabled ? onDownload : null,
|
||||||
|
|
||||||
/// local file deletion is allowed irrespective of [deleteEnabled] since it has
|
/// local file deletion is allowed irrespective of [deleteEnabled] since it has
|
||||||
/// nothing to do with the state of the asset in the Immich server
|
/// nothing to do with the state of the asset in the Immich server
|
||||||
|
20
mobile/openapi/lib/api/timeline_api.dart
generated
20
mobile/openapi/lib/api/timeline_api.dart
generated
@ -31,10 +31,6 @@ class TimelineApi {
|
|||||||
///
|
///
|
||||||
/// * [AssetOrder] order:
|
/// * [AssetOrder] order:
|
||||||
///
|
///
|
||||||
/// * [num] page:
|
|
||||||
///
|
|
||||||
/// * [num] pageSize:
|
|
||||||
///
|
|
||||||
/// * [String] personId:
|
/// * [String] personId:
|
||||||
///
|
///
|
||||||
/// * [String] tagId:
|
/// * [String] tagId:
|
||||||
@ -46,7 +42,7 @@ class TimelineApi {
|
|||||||
/// * [bool] withPartners:
|
/// * [bool] withPartners:
|
||||||
///
|
///
|
||||||
/// * [bool] withStacked:
|
/// * [bool] withStacked:
|
||||||
Future<Response> getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, num? page, num? pageSize, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async {
|
Future<Response> getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async {
|
||||||
// ignore: prefer_const_declarations
|
// ignore: prefer_const_declarations
|
||||||
final apiPath = r'/timeline/bucket';
|
final apiPath = r'/timeline/bucket';
|
||||||
|
|
||||||
@ -72,12 +68,6 @@ class TimelineApi {
|
|||||||
if (order != null) {
|
if (order != null) {
|
||||||
queryParams.addAll(_queryParams('', 'order', order));
|
queryParams.addAll(_queryParams('', 'order', order));
|
||||||
}
|
}
|
||||||
if (page != null) {
|
|
||||||
queryParams.addAll(_queryParams('', 'page', page));
|
|
||||||
}
|
|
||||||
if (pageSize != null) {
|
|
||||||
queryParams.addAll(_queryParams('', 'pageSize', pageSize));
|
|
||||||
}
|
|
||||||
if (personId != null) {
|
if (personId != null) {
|
||||||
queryParams.addAll(_queryParams('', 'personId', personId));
|
queryParams.addAll(_queryParams('', 'personId', personId));
|
||||||
}
|
}
|
||||||
@ -126,10 +116,6 @@ class TimelineApi {
|
|||||||
///
|
///
|
||||||
/// * [AssetOrder] order:
|
/// * [AssetOrder] order:
|
||||||
///
|
///
|
||||||
/// * [num] page:
|
|
||||||
///
|
|
||||||
/// * [num] pageSize:
|
|
||||||
///
|
|
||||||
/// * [String] personId:
|
/// * [String] personId:
|
||||||
///
|
///
|
||||||
/// * [String] tagId:
|
/// * [String] tagId:
|
||||||
@ -141,8 +127,8 @@ class TimelineApi {
|
|||||||
/// * [bool] withPartners:
|
/// * [bool] withPartners:
|
||||||
///
|
///
|
||||||
/// * [bool] withStacked:
|
/// * [bool] withStacked:
|
||||||
Future<TimeBucketAssetResponseDto?> getTimeBucket(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, num? page, num? pageSize, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async {
|
Future<TimeBucketAssetResponseDto?> getTimeBucket(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async {
|
||||||
final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, page: page, pageSize: pageSize, personId: personId, tagId: tagId, userId: userId, visibility: visibility, withPartners: withPartners, withStacked: withStacked, );
|
final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, tagId: tagId, userId: userId, visibility: visibility, withPartners: withPartners, withStacked: withStacked, );
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
}
|
}
|
||||||
|
@ -14,25 +14,31 @@ class ActivityStatisticsResponseDto {
|
|||||||
/// Returns a new [ActivityStatisticsResponseDto] instance.
|
/// Returns a new [ActivityStatisticsResponseDto] instance.
|
||||||
ActivityStatisticsResponseDto({
|
ActivityStatisticsResponseDto({
|
||||||
required this.comments,
|
required this.comments,
|
||||||
|
required this.likes,
|
||||||
});
|
});
|
||||||
|
|
||||||
int comments;
|
int comments;
|
||||||
|
|
||||||
|
int likes;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is ActivityStatisticsResponseDto &&
|
bool operator ==(Object other) => identical(this, other) || other is ActivityStatisticsResponseDto &&
|
||||||
other.comments == comments;
|
other.comments == comments &&
|
||||||
|
other.likes == likes;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(comments.hashCode);
|
(comments.hashCode) +
|
||||||
|
(likes.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'ActivityStatisticsResponseDto[comments=$comments]';
|
String toString() => 'ActivityStatisticsResponseDto[comments=$comments, likes=$likes]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
json[r'comments'] = this.comments;
|
json[r'comments'] = this.comments;
|
||||||
|
json[r'likes'] = this.likes;
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +52,7 @@ class ActivityStatisticsResponseDto {
|
|||||||
|
|
||||||
return ActivityStatisticsResponseDto(
|
return ActivityStatisticsResponseDto(
|
||||||
comments: mapValueOfType<int>(json, r'comments')!,
|
comments: mapValueOfType<int>(json, r'comments')!,
|
||||||
|
likes: mapValueOfType<int>(json, r'likes')!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -94,6 +101,7 @@ class ActivityStatisticsResponseDto {
|
|||||||
/// The list of required keys that must be present in a JSON.
|
/// The list of required keys that must be present in a JSON.
|
||||||
static const requiredKeys = <String>{
|
static const requiredKeys = <String>{
|
||||||
'comments',
|
'comments',
|
||||||
|
'likes',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
78
mobile/openapi/lib/model/sync_album_user_v1.dart
generated
78
mobile/openapi/lib/model/sync_album_user_v1.dart
generated
@ -20,7 +20,7 @@ class SyncAlbumUserV1 {
|
|||||||
|
|
||||||
String albumId;
|
String albumId;
|
||||||
|
|
||||||
SyncAlbumUserV1RoleEnum role;
|
AlbumUserRole role;
|
||||||
|
|
||||||
String userId;
|
String userId;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ class SyncAlbumUserV1 {
|
|||||||
|
|
||||||
return SyncAlbumUserV1(
|
return SyncAlbumUserV1(
|
||||||
albumId: mapValueOfType<String>(json, r'albumId')!,
|
albumId: mapValueOfType<String>(json, r'albumId')!,
|
||||||
role: SyncAlbumUserV1RoleEnum.fromJson(json[r'role'])!,
|
role: AlbumUserRole.fromJson(json[r'role'])!,
|
||||||
userId: mapValueOfType<String>(json, r'userId')!,
|
userId: mapValueOfType<String>(json, r'userId')!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -113,77 +113,3 @@ class SyncAlbumUserV1 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SyncAlbumUserV1RoleEnum {
|
|
||||||
/// Instantiate a new enum with the provided [value].
|
|
||||||
const SyncAlbumUserV1RoleEnum._(this.value);
|
|
||||||
|
|
||||||
/// The underlying value of this enum member.
|
|
||||||
final String value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => value;
|
|
||||||
|
|
||||||
String toJson() => value;
|
|
||||||
|
|
||||||
static const editor = SyncAlbumUserV1RoleEnum._(r'editor');
|
|
||||||
static const viewer = SyncAlbumUserV1RoleEnum._(r'viewer');
|
|
||||||
|
|
||||||
/// List of all possible values in this [enum][SyncAlbumUserV1RoleEnum].
|
|
||||||
static const values = <SyncAlbumUserV1RoleEnum>[
|
|
||||||
editor,
|
|
||||||
viewer,
|
|
||||||
];
|
|
||||||
|
|
||||||
static SyncAlbumUserV1RoleEnum? fromJson(dynamic value) => SyncAlbumUserV1RoleEnumTypeTransformer().decode(value);
|
|
||||||
|
|
||||||
static List<SyncAlbumUserV1RoleEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <SyncAlbumUserV1RoleEnum>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = SyncAlbumUserV1RoleEnum.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transformation class that can [encode] an instance of [SyncAlbumUserV1RoleEnum] to String,
|
|
||||||
/// and [decode] dynamic data back to [SyncAlbumUserV1RoleEnum].
|
|
||||||
class SyncAlbumUserV1RoleEnumTypeTransformer {
|
|
||||||
factory SyncAlbumUserV1RoleEnumTypeTransformer() => _instance ??= const SyncAlbumUserV1RoleEnumTypeTransformer._();
|
|
||||||
|
|
||||||
const SyncAlbumUserV1RoleEnumTypeTransformer._();
|
|
||||||
|
|
||||||
String encode(SyncAlbumUserV1RoleEnum data) => data.value;
|
|
||||||
|
|
||||||
/// Decodes a [dynamic value][data] to a SyncAlbumUserV1RoleEnum.
|
|
||||||
///
|
|
||||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
|
||||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
|
||||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
|
||||||
///
|
|
||||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
|
||||||
/// and users are still using an old app with the old code.
|
|
||||||
SyncAlbumUserV1RoleEnum? decode(dynamic data, {bool allowNull = true}) {
|
|
||||||
if (data != null) {
|
|
||||||
switch (data) {
|
|
||||||
case r'editor': return SyncAlbumUserV1RoleEnum.editor;
|
|
||||||
case r'viewer': return SyncAlbumUserV1RoleEnum.viewer;
|
|
||||||
default:
|
|
||||||
if (!allowNull) {
|
|
||||||
throw ArgumentError('Unknown enum value to decode: $data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Singleton [SyncAlbumUserV1RoleEnumTypeTransformer] instance.
|
|
||||||
static SyncAlbumUserV1RoleEnumTypeTransformer? _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
168
mobile/openapi/lib/model/sync_asset_v1.dart
generated
168
mobile/openapi/lib/model/sync_asset_v1.dart
generated
@ -47,9 +47,9 @@ class SyncAssetV1 {
|
|||||||
|
|
||||||
String? thumbhash;
|
String? thumbhash;
|
||||||
|
|
||||||
SyncAssetV1TypeEnum type;
|
AssetTypeEnum type;
|
||||||
|
|
||||||
SyncAssetV1VisibilityEnum visibility;
|
AssetVisibility visibility;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is SyncAssetV1 &&
|
bool operator ==(Object other) => identical(this, other) || other is SyncAssetV1 &&
|
||||||
@ -141,8 +141,8 @@ class SyncAssetV1 {
|
|||||||
originalFileName: mapValueOfType<String>(json, r'originalFileName')!,
|
originalFileName: mapValueOfType<String>(json, r'originalFileName')!,
|
||||||
ownerId: mapValueOfType<String>(json, r'ownerId')!,
|
ownerId: mapValueOfType<String>(json, r'ownerId')!,
|
||||||
thumbhash: mapValueOfType<String>(json, r'thumbhash'),
|
thumbhash: mapValueOfType<String>(json, r'thumbhash'),
|
||||||
type: SyncAssetV1TypeEnum.fromJson(json[r'type'])!,
|
type: AssetTypeEnum.fromJson(json[r'type'])!,
|
||||||
visibility: SyncAssetV1VisibilityEnum.fromJson(json[r'visibility'])!,
|
visibility: AssetVisibility.fromJson(json[r'visibility'])!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -205,163 +205,3 @@ class SyncAssetV1 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SyncAssetV1TypeEnum {
|
|
||||||
/// Instantiate a new enum with the provided [value].
|
|
||||||
const SyncAssetV1TypeEnum._(this.value);
|
|
||||||
|
|
||||||
/// The underlying value of this enum member.
|
|
||||||
final String value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => value;
|
|
||||||
|
|
||||||
String toJson() => value;
|
|
||||||
|
|
||||||
static const IMAGE = SyncAssetV1TypeEnum._(r'IMAGE');
|
|
||||||
static const VIDEO = SyncAssetV1TypeEnum._(r'VIDEO');
|
|
||||||
static const AUDIO = SyncAssetV1TypeEnum._(r'AUDIO');
|
|
||||||
static const OTHER = SyncAssetV1TypeEnum._(r'OTHER');
|
|
||||||
|
|
||||||
/// List of all possible values in this [enum][SyncAssetV1TypeEnum].
|
|
||||||
static const values = <SyncAssetV1TypeEnum>[
|
|
||||||
IMAGE,
|
|
||||||
VIDEO,
|
|
||||||
AUDIO,
|
|
||||||
OTHER,
|
|
||||||
];
|
|
||||||
|
|
||||||
static SyncAssetV1TypeEnum? fromJson(dynamic value) => SyncAssetV1TypeEnumTypeTransformer().decode(value);
|
|
||||||
|
|
||||||
static List<SyncAssetV1TypeEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <SyncAssetV1TypeEnum>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = SyncAssetV1TypeEnum.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transformation class that can [encode] an instance of [SyncAssetV1TypeEnum] to String,
|
|
||||||
/// and [decode] dynamic data back to [SyncAssetV1TypeEnum].
|
|
||||||
class SyncAssetV1TypeEnumTypeTransformer {
|
|
||||||
factory SyncAssetV1TypeEnumTypeTransformer() => _instance ??= const SyncAssetV1TypeEnumTypeTransformer._();
|
|
||||||
|
|
||||||
const SyncAssetV1TypeEnumTypeTransformer._();
|
|
||||||
|
|
||||||
String encode(SyncAssetV1TypeEnum data) => data.value;
|
|
||||||
|
|
||||||
/// Decodes a [dynamic value][data] to a SyncAssetV1TypeEnum.
|
|
||||||
///
|
|
||||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
|
||||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
|
||||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
|
||||||
///
|
|
||||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
|
||||||
/// and users are still using an old app with the old code.
|
|
||||||
SyncAssetV1TypeEnum? decode(dynamic data, {bool allowNull = true}) {
|
|
||||||
if (data != null) {
|
|
||||||
switch (data) {
|
|
||||||
case r'IMAGE': return SyncAssetV1TypeEnum.IMAGE;
|
|
||||||
case r'VIDEO': return SyncAssetV1TypeEnum.VIDEO;
|
|
||||||
case r'AUDIO': return SyncAssetV1TypeEnum.AUDIO;
|
|
||||||
case r'OTHER': return SyncAssetV1TypeEnum.OTHER;
|
|
||||||
default:
|
|
||||||
if (!allowNull) {
|
|
||||||
throw ArgumentError('Unknown enum value to decode: $data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Singleton [SyncAssetV1TypeEnumTypeTransformer] instance.
|
|
||||||
static SyncAssetV1TypeEnumTypeTransformer? _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SyncAssetV1VisibilityEnum {
|
|
||||||
/// Instantiate a new enum with the provided [value].
|
|
||||||
const SyncAssetV1VisibilityEnum._(this.value);
|
|
||||||
|
|
||||||
/// The underlying value of this enum member.
|
|
||||||
final String value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => value;
|
|
||||||
|
|
||||||
String toJson() => value;
|
|
||||||
|
|
||||||
static const archive = SyncAssetV1VisibilityEnum._(r'archive');
|
|
||||||
static const timeline = SyncAssetV1VisibilityEnum._(r'timeline');
|
|
||||||
static const hidden = SyncAssetV1VisibilityEnum._(r'hidden');
|
|
||||||
static const locked = SyncAssetV1VisibilityEnum._(r'locked');
|
|
||||||
|
|
||||||
/// List of all possible values in this [enum][SyncAssetV1VisibilityEnum].
|
|
||||||
static const values = <SyncAssetV1VisibilityEnum>[
|
|
||||||
archive,
|
|
||||||
timeline,
|
|
||||||
hidden,
|
|
||||||
locked,
|
|
||||||
];
|
|
||||||
|
|
||||||
static SyncAssetV1VisibilityEnum? fromJson(dynamic value) => SyncAssetV1VisibilityEnumTypeTransformer().decode(value);
|
|
||||||
|
|
||||||
static List<SyncAssetV1VisibilityEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <SyncAssetV1VisibilityEnum>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = SyncAssetV1VisibilityEnum.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transformation class that can [encode] an instance of [SyncAssetV1VisibilityEnum] to String,
|
|
||||||
/// and [decode] dynamic data back to [SyncAssetV1VisibilityEnum].
|
|
||||||
class SyncAssetV1VisibilityEnumTypeTransformer {
|
|
||||||
factory SyncAssetV1VisibilityEnumTypeTransformer() => _instance ??= const SyncAssetV1VisibilityEnumTypeTransformer._();
|
|
||||||
|
|
||||||
const SyncAssetV1VisibilityEnumTypeTransformer._();
|
|
||||||
|
|
||||||
String encode(SyncAssetV1VisibilityEnum data) => data.value;
|
|
||||||
|
|
||||||
/// Decodes a [dynamic value][data] to a SyncAssetV1VisibilityEnum.
|
|
||||||
///
|
|
||||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
|
||||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
|
||||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
|
||||||
///
|
|
||||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
|
||||||
/// and users are still using an old app with the old code.
|
|
||||||
SyncAssetV1VisibilityEnum? decode(dynamic data, {bool allowNull = true}) {
|
|
||||||
if (data != null) {
|
|
||||||
switch (data) {
|
|
||||||
case r'archive': return SyncAssetV1VisibilityEnum.archive;
|
|
||||||
case r'timeline': return SyncAssetV1VisibilityEnum.timeline;
|
|
||||||
case r'hidden': return SyncAssetV1VisibilityEnum.hidden;
|
|
||||||
case r'locked': return SyncAssetV1VisibilityEnum.locked;
|
|
||||||
default:
|
|
||||||
if (!allowNull) {
|
|
||||||
throw ArgumentError('Unknown enum value to decode: $data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Singleton [SyncAssetV1VisibilityEnumTypeTransformer] instance.
|
|
||||||
static SyncAssetV1VisibilityEnumTypeTransformer? _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7380,24 +7380,6 @@
|
|||||||
"$ref": "#/components/schemas/AssetOrder"
|
"$ref": "#/components/schemas/AssetOrder"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "page",
|
|
||||||
"required": false,
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"minimum": 1,
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "pageSize",
|
|
||||||
"required": false,
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"minimum": 1,
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "personId",
|
"name": "personId",
|
||||||
"required": false,
|
"required": false,
|
||||||
@ -8500,10 +8482,14 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"comments": {
|
"comments": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"likes": {
|
||||||
|
"type": "integer"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"comments"
|
"comments",
|
||||||
|
"likes"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@ -13006,11 +12992,11 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"enum": [
|
"allOf": [
|
||||||
"editor",
|
{
|
||||||
"viewer"
|
"$ref": "#/components/schemas/AlbumUserRole"
|
||||||
],
|
}
|
||||||
"type": "string"
|
]
|
||||||
},
|
},
|
||||||
"userId": {
|
"userId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -13259,22 +13245,18 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"enum": [
|
"allOf": [
|
||||||
"IMAGE",
|
{
|
||||||
"VIDEO",
|
"$ref": "#/components/schemas/AssetTypeEnum"
|
||||||
"AUDIO",
|
}
|
||||||
"OTHER"
|
]
|
||||||
],
|
|
||||||
"type": "string"
|
|
||||||
},
|
},
|
||||||
"visibility": {
|
"visibility": {
|
||||||
"enum": [
|
"allOf": [
|
||||||
"archive",
|
{
|
||||||
"timeline",
|
"$ref": "#/components/schemas/AssetVisibility"
|
||||||
"hidden",
|
}
|
||||||
"locked"
|
]
|
||||||
],
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -38,6 +38,7 @@ export type ActivityCreateDto = {
|
|||||||
};
|
};
|
||||||
export type ActivityStatisticsResponseDto = {
|
export type ActivityStatisticsResponseDto = {
|
||||||
comments: number;
|
comments: number;
|
||||||
|
likes: number;
|
||||||
};
|
};
|
||||||
export type NotificationCreateDto = {
|
export type NotificationCreateDto = {
|
||||||
data?: object;
|
data?: object;
|
||||||
@ -3435,14 +3436,12 @@ export function tagAssets({ id, bulkIdsDto }: {
|
|||||||
body: bulkIdsDto
|
body: bulkIdsDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, page, pageSize, personId, tagId, timeBucket, userId, visibility, withPartners, withStacked }: {
|
export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, personId, tagId, timeBucket, userId, visibility, withPartners, withStacked }: {
|
||||||
albumId?: string;
|
albumId?: string;
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
isTrashed?: boolean;
|
isTrashed?: boolean;
|
||||||
key?: string;
|
key?: string;
|
||||||
order?: AssetOrder;
|
order?: AssetOrder;
|
||||||
page?: number;
|
|
||||||
pageSize?: number;
|
|
||||||
personId?: string;
|
personId?: string;
|
||||||
tagId?: string;
|
tagId?: string;
|
||||||
timeBucket: string;
|
timeBucket: string;
|
||||||
@ -3460,8 +3459,6 @@ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, page
|
|||||||
isTrashed,
|
isTrashed,
|
||||||
key,
|
key,
|
||||||
order,
|
order,
|
||||||
page,
|
|
||||||
pageSize,
|
|
||||||
personId,
|
personId,
|
||||||
tagId,
|
tagId,
|
||||||
timeBucket,
|
timeBucket,
|
||||||
|
214
server/package-lock.json
generated
214
server/package-lock.json
generated
@ -2349,12 +2349,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/common": {
|
"node_modules/@nestjs/common": {
|
||||||
"version": "11.1.2",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.1.tgz",
|
||||||
"integrity": "sha512-cHh4OPH44PjaHM93D1jgE1HO/B7XTZVRDxy/cPuGgyMEA4p2zXO+qqcOgTMC5FYcp7dX9jLeCjXAU0ToFAnODw==",
|
"integrity": "sha512-crzp+1qeZ5EGL0nFTPy9NrVMAaUWewV5AwtQyv6SQ9yQPXwRl9W9hm1pt0nAtUu5QbYMbSuo7lYcF81EjM+nCA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"file-type": "21.0.0",
|
"file-type": "20.5.0",
|
||||||
"iterare": "1.2.1",
|
"iterare": "1.2.1",
|
||||||
"load-esm": "1.0.2",
|
"load-esm": "1.0.2",
|
||||||
"tslib": "2.8.1",
|
"tslib": "2.8.1",
|
||||||
@ -2380,9 +2380,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/core": {
|
"node_modules/@nestjs/core": {
|
||||||
"version": "11.1.2",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.1.tgz",
|
||||||
"integrity": "sha512-QRuyxwu0BjNfmmmunsw1ylX7RSyfDQHt+xD+tKncdtgiMOOzAu+LA1gB4WoZnw4frQkk+qZbhEbM61cIjOxD3w==",
|
"integrity": "sha512-UFoUAgLKFT+RwHTANJdr0dF7p0qS9QjkaUPjg8aafnjM/qxxxrUVDB49nVvyMlk+Hr1+vvcNaOHbWWQBxoZcHA==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2454,14 +2454,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/platform-express": {
|
"node_modules/@nestjs/platform-express": {
|
||||||
"version": "11.1.2",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.1.tgz",
|
||||||
"integrity": "sha512-GlNwOT4htRp8RpZ+TpqGtSHwGKw/abdxxBRse40XE2SWs5ikaoujr9Yd+5sJWDNXB4QTftwb+FplXhyk1Ra+4A==",
|
"integrity": "sha512-IUxk380qnUtz0PCRQ5i+o9UHlGMrFzGPIJxDwyt3JZZwx2AngOlcEcm5e+7YeJQEr2QYX2QyC4tUQg0zde+D7A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"express": "5.1.0",
|
"express": "5.1.0",
|
||||||
"multer": "2.0.0",
|
"multer": "1.4.5-lts.2",
|
||||||
"path-to-regexp": "8.2.0",
|
"path-to-regexp": "8.2.0",
|
||||||
"tslib": "2.8.1"
|
"tslib": "2.8.1"
|
||||||
},
|
},
|
||||||
@ -2475,9 +2475,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/platform-socket.io": {
|
"node_modules/@nestjs/platform-socket.io": {
|
||||||
"version": "11.1.2",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.1.tgz",
|
||||||
"integrity": "sha512-IkeDPRRddY0In6lE+5H/DJodtF5cEx+ga+GWehs4Il5Y3kK7MVR2/WgUABAhyRsbJYOhIhZD7Dai0V2t9ref1Q==",
|
"integrity": "sha512-Bsc8ouysUFasWiO8RKEvppqYM5LNkHfbyIJQTy3V6+PUdYhblkvmOq8QtjuHpv6DiBI4siUcxACx/90/CdXLkQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"socket.io": "4.8.1",
|
"socket.io": "4.8.1",
|
||||||
@ -2663,9 +2663,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/testing": {
|
"node_modules/@nestjs/testing": {
|
||||||
"version": "11.1.2",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.1.tgz",
|
||||||
"integrity": "sha512-BQxVKUVW6gzEbbHAvmg5RgcP3s++pRgTCmsgaDF/DtcLRUeKi8SjAdqzLm14xbkMeibxOf3fNqM2iwqUKj8ffw==",
|
"integrity": "sha512-stzm8YrLDGAijHYQw+8Z9dD6lGdvahL0hIjGVZ/0KBxLZht0/rvRjgV31UK+DUqXaF7yhJTw9ryrPaITxI1J6A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2691,9 +2691,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/websockets": {
|
"node_modules/@nestjs/websockets": {
|
||||||
"version": "11.1.2",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.1.tgz",
|
||||||
"integrity": "sha512-Ywl7u0C3+qnKIrk0mD3jHWnowO+GScFT1FeP6cNgarA0ujHEfusph9IIbnUJiEiusfnKVpK9fYMGZRSDwnRGPQ==",
|
"integrity": "sha512-gxwQoGx5bW5IvparzrX1UOGXz87eqY0fK5Y6yb14z6tSSubQTciNjCDm5osDEkRyRCG6ZB0F+eXF6dRUjwTlBQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"iterare": "1.2.1",
|
"iterare": "1.2.1",
|
||||||
@ -5576,9 +5576,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "19.1.6",
|
"version": "19.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz",
|
||||||
"integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==",
|
"integrity": "sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -5735,17 +5735,17 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
|
||||||
"integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==",
|
"integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/type-utils": "8.33.0",
|
"@typescript-eslint/type-utils": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^7.0.0",
|
"ignore": "^7.0.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@ -5759,7 +5759,7 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.33.0",
|
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
@ -5775,16 +5775,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
|
||||||
"integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==",
|
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -5799,34 +5799,15 @@
|
|||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/project-service": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/tsconfig-utils": "^8.33.0",
|
|
||||||
"@typescript-eslint/types": "^8.33.0",
|
|
||||||
"debug": "^4.3.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
|
||||||
"integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==",
|
"integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0"
|
"@typescript-eslint/visitor-keys": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -5836,32 +5817,15 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==",
|
"integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.1.0"
|
"ts-api-utils": "^2.1.0"
|
||||||
},
|
},
|
||||||
@ -5878,9 +5842,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz",
|
||||||
"integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==",
|
"integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -5892,16 +5856,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
|
||||||
"integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==",
|
"integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/project-service": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/tsconfig-utils": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@ -5947,16 +5909,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==",
|
"integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.7.0",
|
"@eslint-community/eslint-utils": "^4.7.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0"
|
"@typescript-eslint/typescript-estree": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -5971,13 +5933,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
|
||||||
"integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==",
|
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -9610,18 +9572,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/file-type": {
|
"node_modules/file-type": {
|
||||||
"version": "21.0.0",
|
"version": "20.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz",
|
||||||
"integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==",
|
"integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tokenizer/inflate": "^0.2.7",
|
"@tokenizer/inflate": "^0.2.6",
|
||||||
"strtok3": "^10.2.2",
|
"strtok3": "^10.2.0",
|
||||||
"token-types": "^6.0.0",
|
"token-types": "^6.0.0",
|
||||||
"uint8array-extras": "^1.4.0"
|
"uint8array-extras": "^1.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
||||||
@ -10239,9 +10201,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "16.2.0",
|
"version": "16.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
|
||||||
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
|
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -12163,9 +12125,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/multer": {
|
"node_modules/multer": {
|
||||||
"version": "2.0.0",
|
"version": "1.4.5-lts.2",
|
||||||
"resolved": "https://registry.npmjs.org/multer/-/multer-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz",
|
||||||
"integrity": "sha512-bS8rPZurbAuHGAnApbM9d4h1wSoYqrOqkE+6a64KLMK9yWU7gJXBDDVklKQ3TPi9DRb85cRs6yXaC0+cjxRtRg==",
|
"integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"append-field": "^1.0.0",
|
"append-field": "^1.0.0",
|
||||||
@ -12177,7 +12139,7 @@
|
|||||||
"xtend": "^4.0.0"
|
"xtend": "^4.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.16.0"
|
"node": ">= 6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/multer/node_modules/concat-stream": {
|
"node_modules/multer/node_modules/concat-stream": {
|
||||||
@ -17090,15 +17052,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz",
|
||||||
"integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==",
|
"integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.33.0",
|
"@typescript-eslint/eslint-plugin": "8.32.1",
|
||||||
"@typescript-eslint/parser": "8.33.0",
|
"@typescript-eslint/parser": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0"
|
"@typescript-eslint/utils": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -17417,9 +17379,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/validator": {
|
"node_modules/validator": {
|
||||||
"version": "13.15.15",
|
"version": "13.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz",
|
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz",
|
||||||
"integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==",
|
"integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
|
@ -29,6 +29,9 @@ export class ActivityResponseDto {
|
|||||||
export class ActivityStatisticsResponseDto {
|
export class ActivityStatisticsResponseDto {
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
comments!: number;
|
comments!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
likes!: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ActivityDto {
|
export class ActivityDto {
|
||||||
|
@ -65,9 +65,11 @@ export class SyncAssetV1 {
|
|||||||
fileCreatedAt!: Date | null;
|
fileCreatedAt!: Date | null;
|
||||||
fileModifiedAt!: Date | null;
|
fileModifiedAt!: Date | null;
|
||||||
localDateTime!: Date | null;
|
localDateTime!: Date | null;
|
||||||
|
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
|
||||||
type!: AssetType;
|
type!: AssetType;
|
||||||
deletedAt!: Date | null;
|
deletedAt!: Date | null;
|
||||||
isFavorite!: boolean;
|
isFavorite!: boolean;
|
||||||
|
@ApiProperty({ enumName: 'AssetVisibility', enum: AssetVisibility })
|
||||||
visibility!: AssetVisibility;
|
visibility!: AssetVisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +127,7 @@ export class SyncAlbumUserDeleteV1 {
|
|||||||
export class SyncAlbumUserV1 {
|
export class SyncAlbumUserV1 {
|
||||||
albumId!: string;
|
albumId!: string;
|
||||||
userId!: string;
|
userId!: string;
|
||||||
|
@ApiProperty({ enumName: 'AlbumUserRole', enum: AlbumUserRole })
|
||||||
role!: AlbumUserRole;
|
role!: AlbumUserRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
import { IsEnum, IsInt, IsString, Min } from 'class-validator';
|
import { IsEnum, IsString } from 'class-validator';
|
||||||
import { AssetOrder, AssetVisibility } from 'src/enum';
|
import { AssetOrder, AssetVisibility } from 'src/enum';
|
||||||
import { Optional, ValidateAssetVisibility, ValidateBoolean, ValidateUUID } from 'src/validation';
|
import { Optional, ValidateAssetVisibility, ValidateBoolean, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
@ -41,16 +41,6 @@ export class TimeBucketDto {
|
|||||||
export class TimeBucketAssetDto extends TimeBucketDto {
|
export class TimeBucketAssetDto extends TimeBucketDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
timeBucket!: string;
|
timeBucket!: string;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
@Min(1)
|
|
||||||
@Optional()
|
|
||||||
page?: number;
|
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
@Min(1)
|
|
||||||
@Optional()
|
|
||||||
pageSize?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TimelineStackResponseDto {
|
export class TimelineStackResponseDto {
|
||||||
|
@ -62,15 +62,21 @@ where
|
|||||||
|
|
||||||
-- ActivityRepository.getStatistics
|
-- ActivityRepository.getStatistics
|
||||||
select
|
select
|
||||||
count(*) as "count"
|
count(*) filter (
|
||||||
|
where
|
||||||
|
"activity"."isLiked" = $1
|
||||||
|
) as "comments",
|
||||||
|
count(*) filter (
|
||||||
|
where
|
||||||
|
"activity"."isLiked" = $2
|
||||||
|
) as "likes"
|
||||||
from
|
from
|
||||||
"activity"
|
"activity"
|
||||||
inner join "users" on "users"."id" = "activity"."userId"
|
inner join "users" on "users"."id" = "activity"."userId"
|
||||||
and "users"."deletedAt" is null
|
and "users"."deletedAt" is null
|
||||||
left join "assets" on "assets"."id" = "activity"."assetId"
|
left join "assets" on "assets"."id" = "activity"."assetId"
|
||||||
where
|
where
|
||||||
"activity"."assetId" = $1
|
"activity"."assetId" = $3
|
||||||
and "activity"."albumId" = $2
|
and "activity"."albumId" = $4
|
||||||
and "activity"."isLiked" = $3
|
|
||||||
and "assets"."deletedAt" is null
|
and "assets"."deletedAt" is null
|
||||||
and "assets"."visibility" != 'locked'
|
and "assets"."visibility" != 'locked'
|
||||||
|
@ -67,19 +67,27 @@ export class ActivityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ albumId: DummyValue.UUID, assetId: DummyValue.UUID }] })
|
@GenerateSql({ params: [{ albumId: DummyValue.UUID, assetId: DummyValue.UUID }] })
|
||||||
async getStatistics({ albumId, assetId }: { albumId: string; assetId?: string }): Promise<number> {
|
async getStatistics({
|
||||||
const { count } = await this.db
|
albumId,
|
||||||
|
assetId,
|
||||||
|
}: {
|
||||||
|
albumId: string;
|
||||||
|
assetId?: string;
|
||||||
|
}): Promise<{ comments: number; likes: number }> {
|
||||||
|
const result = await this.db
|
||||||
.selectFrom('activity')
|
.selectFrom('activity')
|
||||||
.select((eb) => eb.fn.countAll<number>().as('count'))
|
.select((eb) => [
|
||||||
|
eb.fn.countAll<number>().filterWhere('activity.isLiked', '=', false).as('comments'),
|
||||||
|
eb.fn.countAll<number>().filterWhere('activity.isLiked', '=', true).as('likes'),
|
||||||
|
])
|
||||||
.innerJoin('users', (join) => join.onRef('users.id', '=', 'activity.userId').on('users.deletedAt', 'is', null))
|
.innerJoin('users', (join) => join.onRef('users.id', '=', 'activity.userId').on('users.deletedAt', 'is', null))
|
||||||
.leftJoin('assets', 'assets.id', 'activity.assetId')
|
.leftJoin('assets', 'assets.id', 'activity.assetId')
|
||||||
.$if(!!assetId, (qb) => qb.where('activity.assetId', '=', assetId!))
|
.$if(!!assetId, (qb) => qb.where('activity.assetId', '=', assetId!))
|
||||||
.where('activity.albumId', '=', albumId)
|
.where('activity.albumId', '=', albumId)
|
||||||
.where('activity.isLiked', '=', false)
|
|
||||||
.where('assets.deletedAt', 'is', null)
|
.where('assets.deletedAt', 'is', null)
|
||||||
.where('assets.visibility', '!=', sql.lit(AssetVisibility.LOCKED))
|
.where('assets.visibility', '!=', sql.lit(AssetVisibility.LOCKED))
|
||||||
.executeTakeFirstOrThrow();
|
.executeTakeFirstOrThrow();
|
||||||
|
|
||||||
return count;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,13 +54,13 @@ describe(ActivityService.name, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('getStatistics', () => {
|
describe('getStatistics', () => {
|
||||||
it('should get the comment count', async () => {
|
it('should get the comment and like count', async () => {
|
||||||
const [albumId, assetId] = newUuids();
|
const [albumId, assetId] = newUuids();
|
||||||
|
|
||||||
mocks.activity.getStatistics.mockResolvedValue(1);
|
mocks.activity.getStatistics.mockResolvedValue({ comments: 1, likes: 3 });
|
||||||
mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([albumId]));
|
mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([albumId]));
|
||||||
|
|
||||||
await expect(sut.getStatistics(factory.auth(), { assetId, albumId })).resolves.toEqual({ comments: 1 });
|
await expect(sut.getStatistics(factory.auth(), { assetId, albumId })).resolves.toEqual({ comments: 1, likes: 3 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export class ActivityService extends BaseService {
|
|||||||
|
|
||||||
async getStatistics(auth: AuthDto, dto: ActivityDto): Promise<ActivityStatisticsResponseDto> {
|
async getStatistics(auth: AuthDto, dto: ActivityDto): Promise<ActivityStatisticsResponseDto> {
|
||||||
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||||
return { comments: await this.activityRepository.getStatistics({ albumId: dto.albumId, assetId: dto.assetId }) };
|
return await this.activityRepository.getStatistics({ albumId: dto.albumId, assetId: dto.assetId });
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(auth: AuthDto, dto: ActivityCreateDto): Promise<MaybeDuplicate<ActivityResponseDto>> {
|
async create(auth: AuthDto, dto: ActivityCreateDto): Promise<MaybeDuplicate<ActivityResponseDto>> {
|
||||||
|
344
web/package-lock.json
generated
344
web/package-lock.json
generated
@ -2229,9 +2229,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/node": {
|
"node_modules/@tailwindcss/node": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz",
|
||||||
"integrity": "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==",
|
"integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2241,13 +2241,13 @@
|
|||||||
"lightningcss": "1.30.1",
|
"lightningcss": "1.30.1",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"source-map-js": "^1.2.1",
|
"source-map-js": "^1.2.1",
|
||||||
"tailwindcss": "4.1.8"
|
"tailwindcss": "4.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide": {
|
"node_modules/@tailwindcss/oxide": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz",
|
||||||
"integrity": "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==",
|
"integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -2259,24 +2259,24 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tailwindcss/oxide-android-arm64": "4.1.8",
|
"@tailwindcss/oxide-android-arm64": "4.1.7",
|
||||||
"@tailwindcss/oxide-darwin-arm64": "4.1.8",
|
"@tailwindcss/oxide-darwin-arm64": "4.1.7",
|
||||||
"@tailwindcss/oxide-darwin-x64": "4.1.8",
|
"@tailwindcss/oxide-darwin-x64": "4.1.7",
|
||||||
"@tailwindcss/oxide-freebsd-x64": "4.1.8",
|
"@tailwindcss/oxide-freebsd-x64": "4.1.7",
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8",
|
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7",
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.8",
|
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.7",
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": "4.1.8",
|
"@tailwindcss/oxide-linux-arm64-musl": "4.1.7",
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": "4.1.8",
|
"@tailwindcss/oxide-linux-x64-gnu": "4.1.7",
|
||||||
"@tailwindcss/oxide-linux-x64-musl": "4.1.8",
|
"@tailwindcss/oxide-linux-x64-musl": "4.1.7",
|
||||||
"@tailwindcss/oxide-wasm32-wasi": "4.1.8",
|
"@tailwindcss/oxide-wasm32-wasi": "4.1.7",
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.8",
|
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.7",
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": "4.1.8"
|
"@tailwindcss/oxide-win32-x64-msvc": "4.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-android-arm64": {
|
"node_modules/@tailwindcss/oxide-android-arm64": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz",
|
||||||
"integrity": "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==",
|
"integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -2291,9 +2291,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz",
|
||||||
"integrity": "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==",
|
"integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -2308,9 +2308,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz",
|
||||||
"integrity": "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==",
|
"integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -2325,9 +2325,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz",
|
||||||
"integrity": "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==",
|
"integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -2342,9 +2342,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz",
|
||||||
"integrity": "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==",
|
"integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -2359,9 +2359,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz",
|
||||||
"integrity": "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==",
|
"integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -2376,9 +2376,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz",
|
||||||
"integrity": "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==",
|
"integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -2393,9 +2393,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz",
|
||||||
"integrity": "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==",
|
"integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -2410,9 +2410,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz",
|
||||||
"integrity": "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==",
|
"integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -2427,9 +2427,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz",
|
||||||
"integrity": "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==",
|
"integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
|
||||||
"bundleDependencies": [
|
"bundleDependencies": [
|
||||||
"@napi-rs/wasm-runtime",
|
"@napi-rs/wasm-runtime",
|
||||||
"@emnapi/core",
|
"@emnapi/core",
|
||||||
@ -2448,7 +2448,7 @@
|
|||||||
"@emnapi/core": "^1.4.3",
|
"@emnapi/core": "^1.4.3",
|
||||||
"@emnapi/runtime": "^1.4.3",
|
"@emnapi/runtime": "^1.4.3",
|
||||||
"@emnapi/wasi-threads": "^1.0.2",
|
"@emnapi/wasi-threads": "^1.0.2",
|
||||||
"@napi-rs/wasm-runtime": "^0.2.10",
|
"@napi-rs/wasm-runtime": "^0.2.9",
|
||||||
"@tybys/wasm-util": "^0.9.0",
|
"@tybys/wasm-util": "^0.9.0",
|
||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
},
|
},
|
||||||
@ -2456,10 +2456,70 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.9",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.0",
|
||||||
|
"@emnapi/runtime": "^1.4.0",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz",
|
||||||
"integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==",
|
"integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -2474,9 +2534,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz",
|
||||||
"integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==",
|
"integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -2568,15 +2628,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/vite": {
|
"node_modules/@tailwindcss/vite": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz",
|
||||||
"integrity": "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A==",
|
"integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/node": "4.1.8",
|
"@tailwindcss/node": "4.1.7",
|
||||||
"@tailwindcss/oxide": "4.1.8",
|
"@tailwindcss/oxide": "4.1.7",
|
||||||
"tailwindcss": "4.1.8"
|
"tailwindcss": "4.1.7"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vite": "^5.2.0 || ^6"
|
"vite": "^5.2.0 || ^6"
|
||||||
@ -2888,17 +2948,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
|
||||||
"integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==",
|
"integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/type-utils": "8.33.0",
|
"@typescript-eslint/type-utils": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^7.0.0",
|
"ignore": "^7.0.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@ -2912,7 +2972,7 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.33.0",
|
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
@ -2928,16 +2988,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
|
||||||
"integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==",
|
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -2952,34 +3012,15 @@
|
|||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/project-service": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/tsconfig-utils": "^8.33.0",
|
|
||||||
"@typescript-eslint/types": "^8.33.0",
|
|
||||||
"debug": "^4.3.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
|
||||||
"integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==",
|
"integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0"
|
"@typescript-eslint/visitor-keys": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -2989,32 +3030,15 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
|
||||||
"version": "8.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz",
|
|
||||||
"integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==",
|
"integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0",
|
"@typescript-eslint/typescript-estree": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0",
|
"@typescript-eslint/utils": "8.32.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.1.0"
|
"ts-api-utils": "^2.1.0"
|
||||||
},
|
},
|
||||||
@ -3031,9 +3055,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz",
|
||||||
"integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==",
|
"integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -3045,16 +3069,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
|
||||||
"integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==",
|
"integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/project-service": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/tsconfig-utils": "8.33.0",
|
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.33.0",
|
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@ -3100,16 +3122,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz",
|
||||||
"integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==",
|
"integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.7.0",
|
"@eslint-community/eslint-utils": "^4.7.0",
|
||||||
"@typescript-eslint/scope-manager": "8.33.0",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.33.0"
|
"@typescript-eslint/typescript-estree": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -3124,13 +3146,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
|
||||||
"integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==",
|
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.33.0",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -4957,9 +4979,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fabric": {
|
"node_modules/fabric": {
|
||||||
"version": "6.6.6",
|
"version": "6.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/fabric/-/fabric-6.6.6.tgz",
|
"resolved": "https://registry.npmjs.org/fabric/-/fabric-6.6.5.tgz",
|
||||||
"integrity": "sha512-cL0m/RanEIiP67/TAj8kAQcEYlXofeB1SXCB1w7a0ktyUQHdRpnm2/VHlqsD/PfSLlGqftHzmxAS4LvKzSlrEw==",
|
"integrity": "sha512-BFxyLDeLMMgtteqQwKAyRM+oSkf82lDFzsiC7AMob7k7ag7naFuHOtWtcll4v+M9Cpn5aqRBfz1shnsO0vZhbg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.20.0"
|
"node": ">=16.20.0"
|
||||||
@ -5429,9 +5451,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "16.2.0",
|
"version": "16.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
|
||||||
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
|
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -8612,9 +8634,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/svelte": {
|
"node_modules/svelte": {
|
||||||
"version": "5.33.6",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.6.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.1.tgz",
|
||||||
"integrity": "sha512-bxg2QY03JlrilCZmDlshY95Argj0rnX43UQFWZN4fct8PZTNBBmvfow2A6yOW1+YweDjhC2qdZF66ASI0Y21Tw==",
|
"integrity": "sha512-7znzaaQALL62NBzkdKV04tmYIVla8qjrW+k6GdgFZcKcj8XOb8iEjmfRPo40iaWZlKv3+uiuc0h4iaGgwoORtA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.3.0",
|
"@ampproject/remapping": "^2.3.0",
|
||||||
@ -8863,9 +8885,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "4.1.8",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",
|
||||||
"integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==",
|
"integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
@ -9189,15 +9211,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.33.0",
|
"version": "8.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz",
|
||||||
"integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==",
|
"integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.33.0",
|
"@typescript-eslint/eslint-plugin": "8.32.1",
|
||||||
"@typescript-eslint/parser": "8.33.0",
|
"@typescript-eslint/parser": "8.32.1",
|
||||||
"@typescript-eslint/utils": "8.33.0"
|
"@typescript-eslint/utils": "8.32.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -7,25 +7,29 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
isLiked: ActivityResponseDto | null;
|
isLiked: ActivityResponseDto | null;
|
||||||
numberOfComments: number | undefined;
|
numberOfComments: number | undefined;
|
||||||
|
numberOfLikes: number | undefined;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onOpenActivityTab: () => void;
|
onOpenActivityTab: () => void;
|
||||||
onFavorite: () => void;
|
onFavorite: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { isLiked, numberOfComments, disabled, onOpenActivityTab, onFavorite }: Props = $props();
|
let { isLiked, numberOfComments, numberOfLikes, disabled, onOpenActivityTab, onFavorite }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full flex p-4 text-white items-center justify-center rounded-full gap-5 bg-immich-dark-bg bg-opacity-60">
|
<div class="w-full flex p-4 items-center justify-center rounded-full gap-5 bg-subtle border bg-opacity-60">
|
||||||
<button type="button" class={disabled ? 'cursor-not-allowed' : ''} onclick={onFavorite} {disabled}>
|
<button type="button" class={disabled ? 'cursor-not-allowed' : ''} onclick={onFavorite} {disabled}>
|
||||||
<div class="items-center justify-center">
|
<div class="flex gap-2 items-center justify-center">
|
||||||
<Icon path={isLiked ? mdiHeart : mdiHeartOutline} size={24} />
|
<Icon path={isLiked ? mdiHeart : mdiHeartOutline} size={24} class={isLiked ? 'text-red-400' : 'text-fg'} />
|
||||||
|
{#if numberOfLikes}
|
||||||
|
<div class="text-l">{numberOfLikes.toLocaleString($locale)}</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onclick={onOpenActivityTab}>
|
<button type="button" onclick={onOpenActivityTab}>
|
||||||
<div class="flex gap-2 items-center justify-center">
|
<div class="flex gap-2 items-center justify-center">
|
||||||
<Icon path={mdiCommentOutline} class="scale-x-[-1]" size={24} />
|
<Icon path={mdiCommentOutline} class="scale-x-[-1]" size={24} />
|
||||||
{#if numberOfComments}
|
{#if numberOfComments}
|
||||||
<div class="text-xl">{numberOfComments.toLocaleString($locale)}</div>
|
<div class="text-l">{numberOfComments.toLocaleString($locale)}</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
@ -118,12 +118,9 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="overflow-y-hidden relative h-full" bind:offsetHeight={innerHeight}>
|
<div class="overflow-y-hidden relative h-full border-l border-subtle bg-subtle" bind:offsetHeight={innerHeight}>
|
||||||
<div class="dark:bg-immich-dark-bg dark:text-immich-dark-fg w-full h-full">
|
<div class="w-full h-full">
|
||||||
<div
|
<div class="flex w-full h-fit dark:text-immich-dark-fg p-2 bg-subtle" bind:clientHeight={activityHeight}>
|
||||||
class="flex w-full h-fit dark:bg-immich-dark-bg dark:text-immich-dark-fg p-2 bg-white"
|
|
||||||
bind:clientHeight={activityHeight}
|
|
||||||
>
|
|
||||||
<div class="flex place-items-center gap-2">
|
<div class="flex place-items-center gap-2">
|
||||||
<IconButton
|
<IconButton
|
||||||
shape="round"
|
shape="round"
|
||||||
|
@ -513,6 +513,7 @@
|
|||||||
disabled={!album?.isActivityEnabled}
|
disabled={!album?.isActivityEnabled}
|
||||||
isLiked={activityManager.isLiked}
|
isLiked={activityManager.isLiked}
|
||||||
numberOfComments={activityManager.commentCount}
|
numberOfComments={activityManager.commentCount}
|
||||||
|
numberOfLikes={activityManager.likeCount}
|
||||||
onFavorite={handleFavorite}
|
onFavorite={handleFavorite}
|
||||||
onOpenActivityTab={handleOpenActivity}
|
onOpenActivityTab={handleOpenActivity}
|
||||||
/>
|
/>
|
||||||
@ -569,6 +570,7 @@
|
|||||||
asset={toTimelineAsset(stackedAsset)}
|
asset={toTimelineAsset(stackedAsset)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
asset = stackedAsset;
|
asset = stackedAsset;
|
||||||
|
previewStackedAsset = undefined;
|
||||||
}}
|
}}
|
||||||
onMouseEvent={({ isMouseOver }) => handleStackedAssetMouseEvent(isMouseOver, stackedAsset)}
|
onMouseEvent={({ isMouseOver }) => handleStackedAssetMouseEvent(isMouseOver, stackedAsset)}
|
||||||
readonly
|
readonly
|
||||||
|
@ -70,7 +70,9 @@
|
|||||||
title="Add tag"
|
title="Add tag"
|
||||||
onclick={handleAddTag}
|
onclick={handleAddTag}
|
||||||
>
|
>
|
||||||
<span class="text-sm px-1 flex place-items-center place-content-center gap-1"><Icon path={mdiPlus} />Add</span>
|
<span class="text-sm px-1 flex place-items-center place-content-center gap-1"
|
||||||
|
><Icon path={mdiPlus} />{$t('add')}</span
|
||||||
|
>
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { featureFlags } from '$lib/stores/server-config.store';
|
import { featureFlags } from '$lib/stores/server-config.store';
|
||||||
import { type OnDelete, deleteAssets } from '$lib/utils/actions';
|
import { type OnDelete, type OnUndoDelete, deleteAssets } from '$lib/utils/actions';
|
||||||
import { mdiDeleteForeverOutline, mdiDeleteOutline, mdiTimerSand } from '@mdi/js';
|
import { mdiDeleteForeverOutline, mdiDeleteOutline, mdiTimerSand } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||||
@ -10,11 +10,12 @@
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onAssetDelete: OnDelete;
|
onAssetDelete: OnDelete;
|
||||||
|
onUndoDelete?: OnUndoDelete | undefined;
|
||||||
menuItem?: boolean;
|
menuItem?: boolean;
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { onAssetDelete, menuItem = false, force = !$featureFlags.trash }: Props = $props();
|
let { onAssetDelete, onUndoDelete = undefined, menuItem = false, force = !$featureFlags.trash }: Props = $props();
|
||||||
|
|
||||||
const { clearSelect, getOwnedAssets } = getAssetControlContext();
|
const { clearSelect, getOwnedAssets } = getAssetControlContext();
|
||||||
|
|
||||||
@ -34,8 +35,8 @@
|
|||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
loading = true;
|
loading = true;
|
||||||
const ids = [...getOwnedAssets()].map((a) => a.id);
|
const assets = [...getOwnedAssets()];
|
||||||
await deleteAssets(force, onAssetDelete, ids);
|
await deleteAssets(force, onAssetDelete, assets, onUndoDelete);
|
||||||
clearSelect();
|
clearSelect();
|
||||||
isShowConfirmation = false;
|
isShowConfirmation = false;
|
||||||
loading = false;
|
loading = false;
|
||||||
|
@ -382,7 +382,12 @@
|
|||||||
|
|
||||||
const trashOrDelete = async (force: boolean = false) => {
|
const trashOrDelete = async (force: boolean = false) => {
|
||||||
isShowDeleteConfirmation = false;
|
isShowDeleteConfirmation = false;
|
||||||
await deleteAssets(!(isTrashEnabled && !force), (assetIds) => assetStore.removeAssets(assetIds), idsSelectedAssets);
|
await deleteAssets(
|
||||||
|
!(isTrashEnabled && !force),
|
||||||
|
(assetIds) => assetStore.removeAssets(assetIds),
|
||||||
|
assetInteraction.selectedAssets,
|
||||||
|
!isTrashEnabled || force ? undefined : (assets) => assetStore.addAssets(assets),
|
||||||
|
);
|
||||||
assetInteraction.clearMultiselect();
|
assetInteraction.clearMultiselect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
onPrevious?: (() => Promise<{ id: string } | undefined>) | undefined;
|
onPrevious?: (() => Promise<{ id: string } | undefined>) | undefined;
|
||||||
onNext?: (() => Promise<{ id: string } | undefined>) | undefined;
|
onNext?: (() => Promise<{ id: string } | undefined>) | undefined;
|
||||||
onRandom?: (() => Promise<{ id: string } | undefined>) | undefined;
|
onRandom?: (() => Promise<{ id: string } | undefined>) | undefined;
|
||||||
|
onReload?: (() => void) | undefined;
|
||||||
pageHeaderOffset?: number;
|
pageHeaderOffset?: number;
|
||||||
slidingWindowOffset?: number;
|
slidingWindowOffset?: number;
|
||||||
}
|
}
|
||||||
@ -54,6 +55,7 @@
|
|||||||
onPrevious = undefined,
|
onPrevious = undefined,
|
||||||
onNext = undefined,
|
onNext = undefined,
|
||||||
onRandom = undefined,
|
onRandom = undefined,
|
||||||
|
onReload = undefined,
|
||||||
slidingWindowOffset = 0,
|
slidingWindowOffset = 0,
|
||||||
pageHeaderOffset = 0,
|
pageHeaderOffset = 0,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
@ -255,7 +257,8 @@
|
|||||||
await deleteAssets(
|
await deleteAssets(
|
||||||
!(isTrashEnabled && !force),
|
!(isTrashEnabled && !force),
|
||||||
(assetIds) => (assets = assets.filter((asset) => !assetIds.includes(asset.id))),
|
(assetIds) => (assets = assets.filter((asset) => !assetIds.includes(asset.id))),
|
||||||
idsSelectedAssets,
|
assetInteraction.selectedAssets,
|
||||||
|
onReload,
|
||||||
);
|
);
|
||||||
assetInteraction.clearMultiselect();
|
assetInteraction.clearMultiselect();
|
||||||
};
|
};
|
||||||
@ -426,7 +429,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
let isTrashEnabled = $derived($featureFlags.loaded && $featureFlags.trash);
|
let isTrashEnabled = $derived($featureFlags.loaded && $featureFlags.trash);
|
||||||
let idsSelectedAssets = $derived(assetInteraction.selectedAssets.map((selectedAsset) => selectedAsset.id));
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (!lastAssetMouseEvent) {
|
if (!lastAssetMouseEvent) {
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Theme } from '$lib/constants';
|
import { defaultLang, langs, Theme } from '$lib/constants';
|
||||||
import { themeManager } from '$lib/managers/theme-manager.svelte';
|
import { themeManager } from '$lib/managers/theme-manager.svelte';
|
||||||
|
import { lang } from '$lib/stores/preferences.store';
|
||||||
import { ThemeSwitcher } from '@immich/ui';
|
import { ThemeSwitcher } from '@immich/ui';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !themeManager.theme.system}
|
{#if !themeManager.theme.system}
|
||||||
<ThemeSwitcher
|
{#await langs
|
||||||
size="medium"
|
.find((item) => item.code === get(lang))
|
||||||
color="secondary"
|
?.loader() ?? defaultLang.loader() then { default: translations }}
|
||||||
onChange={(theme) => themeManager.setTheme(theme == 'dark' ? Theme.DARK : Theme.LIGHT)}
|
<ThemeSwitcher
|
||||||
/>
|
size="medium"
|
||||||
|
color="secondary"
|
||||||
|
{translations}
|
||||||
|
onChange={(theme) => themeManager.setTheme(theme == 'dark' ? Theme.DARK : Theme.LIGHT)}
|
||||||
|
/>
|
||||||
|
{/await}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleLocaleBrowser = () => {
|
const handleToggleLocaleBrowser = () => {
|
||||||
$locale = $locale ? undefined : fallbackLocale.code;
|
$locale = $locale === 'default' ? fallbackLocale.code : 'default';
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLocaleChange = (newLocale: string | undefined) => {
|
const handleLocaleChange = (newLocale: string | undefined) => {
|
||||||
@ -89,13 +89,13 @@
|
|||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
title={$t('default_locale')}
|
title={$t('default_locale')}
|
||||||
subtitle={$t('default_locale_description')}
|
subtitle={$t('default_locale_description')}
|
||||||
checked={$locale == undefined}
|
checked={$locale == 'default'}
|
||||||
onToggle={handleToggleLocaleBrowser}
|
onToggle={handleToggleLocaleBrowser}
|
||||||
>
|
>
|
||||||
<p class="mt-2 dark:text-gray-400">{selectedDate}</p>
|
<p class="mt-2 dark:text-gray-400">{selectedDate}</p>
|
||||||
</SettingSwitch>
|
</SettingSwitch>
|
||||||
</div>
|
</div>
|
||||||
{#if $locale !== undefined}
|
{#if $locale !== 'default'}
|
||||||
<div class="ms-4">
|
<div class="ms-4">
|
||||||
<SettingCombobox
|
<SettingCombobox
|
||||||
comboboxPlaceholder={$t('searching_locales')}
|
comboboxPlaceholder={$t('searching_locales')}
|
||||||
@ -113,7 +113,6 @@
|
|||||||
title={$t('display_original_photos')}
|
title={$t('display_original_photos')}
|
||||||
subtitle={$t('display_original_photos_setting_description')}
|
subtitle={$t('display_original_photos_setting_description')}
|
||||||
bind:checked={$alwaysLoadOriginalFile}
|
bind:checked={$alwaysLoadOriginalFile}
|
||||||
onToggle={() => ($alwaysLoadOriginalFile = !$alwaysLoadOriginalFile)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-4">
|
<div class="ms-4">
|
||||||
@ -121,16 +120,10 @@
|
|||||||
title={$t('video_hover_setting')}
|
title={$t('video_hover_setting')}
|
||||||
subtitle={$t('video_hover_setting_description')}
|
subtitle={$t('video_hover_setting_description')}
|
||||||
bind:checked={$playVideoThumbnailOnHover}
|
bind:checked={$playVideoThumbnailOnHover}
|
||||||
onToggle={() => ($playVideoThumbnailOnHover = !$playVideoThumbnailOnHover)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-4">
|
<div class="ms-4">
|
||||||
<SettingSwitch
|
<SettingSwitch title={$t('loop_videos')} subtitle={$t('loop_videos_description')} bind:checked={$loopVideo} />
|
||||||
title={$t('loop_videos')}
|
|
||||||
subtitle={$t('loop_videos_description')}
|
|
||||||
bind:checked={$loopVideo}
|
|
||||||
onToggle={() => ($loopVideo = !$loopVideo)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ms-4">
|
<div class="ms-4">
|
||||||
|
@ -273,9 +273,17 @@ export const locales = [
|
|||||||
{ code: 'zu-ZA', name: 'Zulu (South Africa)' },
|
{ code: 'zu-ZA', name: 'Zulu (South Africa)' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const defaultLang = { name: 'English', code: 'en', loader: () => import('$i18n/en.json') };
|
interface Lang {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
loader: () => Promise<{ default: object }>;
|
||||||
|
rtl?: boolean;
|
||||||
|
weblateCode?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const langs = [
|
export const defaultLang: Lang = { name: 'English', code: 'en', loader: () => import('$i18n/en.json') };
|
||||||
|
|
||||||
|
export const langs: Lang[] = [
|
||||||
{ name: 'Afrikaans', code: 'af', loader: () => import('$i18n/af.json') },
|
{ name: 'Afrikaans', code: 'af', loader: () => import('$i18n/af.json') },
|
||||||
{ name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json'), rtl: true },
|
{ name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json'), rtl: true },
|
||||||
{ name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json'), rtl: true },
|
{ name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json'), rtl: true },
|
||||||
@ -359,7 +367,7 @@ export const langs = [
|
|||||||
weblateCode: 'zh_SIMPLIFIED',
|
weblateCode: 'zh_SIMPLIFIED',
|
||||||
loader: () => import('$i18n/zh_SIMPLIFIED.json'),
|
loader: () => import('$i18n/zh_SIMPLIFIED.json'),
|
||||||
},
|
},
|
||||||
{ name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({}) },
|
{ name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({ default: {} }) },
|
||||||
];
|
];
|
||||||
|
|
||||||
export enum ImmichProduct {
|
export enum ImmichProduct {
|
||||||
|
@ -17,6 +17,7 @@ class ActivityManager {
|
|||||||
#assetId = $state<string | undefined>();
|
#assetId = $state<string | undefined>();
|
||||||
#activities = $state<ActivityResponseDto[]>([]);
|
#activities = $state<ActivityResponseDto[]>([]);
|
||||||
#commentCount = $state(0);
|
#commentCount = $state(0);
|
||||||
|
#likeCount = $state(0);
|
||||||
#isLiked = $state<ActivityResponseDto | null>(null);
|
#isLiked = $state<ActivityResponseDto | null>(null);
|
||||||
|
|
||||||
get activities() {
|
get activities() {
|
||||||
@ -27,6 +28,10 @@ class ActivityManager {
|
|||||||
return this.#commentCount;
|
return this.#commentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get likeCount() {
|
||||||
|
return this.#likeCount;
|
||||||
|
}
|
||||||
|
|
||||||
get isLiked() {
|
get isLiked() {
|
||||||
return this.#isLiked;
|
return this.#isLiked;
|
||||||
}
|
}
|
||||||
@ -48,6 +53,10 @@ class ActivityManager {
|
|||||||
this.#commentCount++;
|
this.#commentCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activity.type === ReactionType.Like) {
|
||||||
|
this.#likeCount++;
|
||||||
|
}
|
||||||
|
|
||||||
handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId));
|
handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId));
|
||||||
return activity;
|
return activity;
|
||||||
}
|
}
|
||||||
@ -61,6 +70,10 @@ class ActivityManager {
|
|||||||
this.#commentCount--;
|
this.#commentCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activity.type === ReactionType.Like) {
|
||||||
|
this.#likeCount--;
|
||||||
|
}
|
||||||
|
|
||||||
this.#activities = index
|
this.#activities = index
|
||||||
? this.#activities.splice(index, 1)
|
? this.#activities.splice(index, 1)
|
||||||
: this.#activities.filter(({ id }) => id !== activity.id);
|
: this.#activities.filter(({ id }) => id !== activity.id);
|
||||||
@ -98,8 +111,9 @@ class ActivityManager {
|
|||||||
});
|
});
|
||||||
this.#isLiked = liked ?? null;
|
this.#isLiked = liked ?? null;
|
||||||
|
|
||||||
const { comments } = await getActivityStatistics({ albumId, assetId });
|
const { comments, likes } = await getActivityStatistics({ albumId, assetId });
|
||||||
this.#commentCount = comments;
|
this.#commentCount = comments;
|
||||||
|
this.#likeCount = likes;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
@ -107,6 +121,7 @@ class ActivityManager {
|
|||||||
this.#assetId = undefined;
|
this.#assetId = undefined;
|
||||||
this.#activities = [];
|
this.#activities = [];
|
||||||
this.#commentCount = 0;
|
this.#commentCount = 0;
|
||||||
|
this.#likeCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ export interface ThemeSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Locale to use for formatting dates, numbers, etc.
|
// Locale to use for formatting dates, numbers, etc.
|
||||||
export const locale = persisted<string | undefined>('locale', undefined, {
|
export const locale = persisted<string | undefined>('locale', 'default', {
|
||||||
serializer: {
|
serializer: {
|
||||||
parse: (text) => (text == '' ? 'en-US' : text),
|
parse: (text) => text || 'default',
|
||||||
stringify: (object) => object ?? '',
|
stringify: (object) => object ?? '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification';
|
import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification';
|
||||||
import type { AssetStore, TimelineAsset } from '$lib/stores/assets-store.svelte';
|
import type { AssetStore, TimelineAsset } from '$lib/stores/assets-store.svelte';
|
||||||
import type { StackResponse } from '$lib/utils/asset-utils';
|
import type { StackResponse } from '$lib/utils/asset-utils';
|
||||||
import { AssetVisibility, deleteAssets as deleteBulk } from '@immich/sdk';
|
import { AssetVisibility, deleteAssets as deleteBulk, restoreAssets } from '@immich/sdk';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { handleError } from './handle-error';
|
import { handleError } from './handle-error';
|
||||||
|
|
||||||
export type OnDelete = (assetIds: string[]) => void;
|
export type OnDelete = (assetIds: string[]) => void;
|
||||||
|
export type OnUndoDelete = (assets: TimelineAsset[]) => void;
|
||||||
export type OnRestore = (ids: string[]) => void;
|
export type OnRestore = (ids: string[]) => void;
|
||||||
export type OnLink = (assets: { still: TimelineAsset; motion: TimelineAsset }) => void;
|
export type OnLink = (assets: { still: TimelineAsset; motion: TimelineAsset }) => void;
|
||||||
export type OnUnlink = (assets: { still: TimelineAsset; motion: TimelineAsset }) => void;
|
export type OnUnlink = (assets: { still: TimelineAsset; motion: TimelineAsset }) => void;
|
||||||
@ -17,9 +18,15 @@ export type OnStack = (result: StackResponse) => void;
|
|||||||
export type OnUnstack = (assets: TimelineAsset[]) => void;
|
export type OnUnstack = (assets: TimelineAsset[]) => void;
|
||||||
export type OnSetVisibility = (ids: string[]) => void;
|
export type OnSetVisibility = (ids: string[]) => void;
|
||||||
|
|
||||||
export const deleteAssets = async (force: boolean, onAssetDelete: OnDelete, ids: string[]) => {
|
export const deleteAssets = async (
|
||||||
|
force: boolean,
|
||||||
|
onAssetDelete: OnDelete,
|
||||||
|
assets: TimelineAsset[],
|
||||||
|
onUndoDelete: OnUndoDelete | undefined = undefined,
|
||||||
|
) => {
|
||||||
const $t = get(t);
|
const $t = get(t);
|
||||||
try {
|
try {
|
||||||
|
const ids = assets.map((a) => a.id);
|
||||||
await deleteBulk({ assetBulkDeleteDto: { ids, force } });
|
await deleteBulk({ assetBulkDeleteDto: { ids, force } });
|
||||||
onAssetDelete(ids);
|
onAssetDelete(ids);
|
||||||
|
|
||||||
@ -28,12 +35,28 @@ export const deleteAssets = async (force: boolean, onAssetDelete: OnDelete, ids:
|
|||||||
? $t('assets_permanently_deleted_count', { values: { count: ids.length } })
|
? $t('assets_permanently_deleted_count', { values: { count: ids.length } })
|
||||||
: $t('assets_trashed_count', { values: { count: ids.length } }),
|
: $t('assets_trashed_count', { values: { count: ids.length } }),
|
||||||
type: NotificationType.Info,
|
type: NotificationType.Info,
|
||||||
|
...(onUndoDelete &&
|
||||||
|
!force && {
|
||||||
|
button: { text: $t('undo'), onClick: () => undoDeleteAssets(onUndoDelete, assets) },
|
||||||
|
timeout: 5000,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, $t('errors.unable_to_delete_assets'));
|
handleError(error, $t('errors.unable_to_delete_assets'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const undoDeleteAssets = async (onUndoDelete: OnUndoDelete, assets: TimelineAsset[]) => {
|
||||||
|
const $t = get(t);
|
||||||
|
try {
|
||||||
|
const ids = assets.map((a) => a.id);
|
||||||
|
await restoreAssets({ bulkIdsDto: { ids } });
|
||||||
|
onUndoDelete?.(assets);
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, $t('errors.unable_to_restore_assets'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the asset stack state in the asset store based on the provided stack response.
|
* Update the asset stack state in the asset store based on the provided stack response.
|
||||||
* This function updates the stack information so that the icon is shown for the primary asset
|
* This function updates the stack information so that the icon is shown for the primary asset
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { locale } from '$lib/stores/preferences.store';
|
||||||
import { parseUtcDate } from '$lib/utils/date-time';
|
import { parseUtcDate } from '$lib/utils/date-time';
|
||||||
import { formatGroupTitle } from '$lib/utils/timeline-util';
|
import { formatGroupTitle } from '$lib/utils/timeline-util';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
@ -16,48 +17,63 @@ describe('formatGroupTitle', () => {
|
|||||||
|
|
||||||
it('formats today', () => {
|
it('formats today', () => {
|
||||||
const date = parseUtcDate('2024-07-27T01:00:00Z');
|
const date = parseUtcDate('2024-07-27T01:00:00Z');
|
||||||
expect(formatGroupTitle(date.setLocale('en'))).toBe('today');
|
locale.set('en');
|
||||||
expect(formatGroupTitle(date.setLocale('es'))).toBe('hoy');
|
expect(formatGroupTitle(date)).toBe('today');
|
||||||
|
locale.set('es');
|
||||||
|
expect(formatGroupTitle(date)).toBe('hoy');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats yesterday', () => {
|
it('formats yesterday', () => {
|
||||||
const date = parseUtcDate('2024-07-26T23:59:59Z');
|
const date = parseUtcDate('2024-07-26T23:59:59Z');
|
||||||
expect(formatGroupTitle(date.setLocale('en'))).toBe('yesterday');
|
locale.set('en');
|
||||||
expect(formatGroupTitle(date.setLocale('fr'))).toBe('hier');
|
expect(formatGroupTitle(date)).toBe('yesterday');
|
||||||
|
locale.set('fr');
|
||||||
|
expect(formatGroupTitle(date)).toBe('hier');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats last week', () => {
|
it('formats last week', () => {
|
||||||
const date = parseUtcDate('2024-07-21T00:00:00Z');
|
const date = parseUtcDate('2024-07-21T00:00:00Z');
|
||||||
expect(formatGroupTitle(date.setLocale('en'))).toBe('Sunday');
|
locale.set('en');
|
||||||
expect(formatGroupTitle(date.setLocale('ar-SA'))).toBe('الأحد');
|
expect(formatGroupTitle(date)).toBe('Sunday');
|
||||||
|
locale.set('ar-SA');
|
||||||
|
expect(formatGroupTitle(date)).toBe('الأحد');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats date 7 days ago', () => {
|
it('formats date 7 days ago', () => {
|
||||||
const date = parseUtcDate('2024-07-20T00:00:00Z');
|
const date = parseUtcDate('2024-07-20T00:00:00Z');
|
||||||
expect(formatGroupTitle(date.setLocale('en'))).toBe('Sat, Jul 20');
|
locale.set('en');
|
||||||
expect(formatGroupTitle(date.setLocale('de'))).toBe('Sa., 20. Juli');
|
expect(formatGroupTitle(date)).toBe('Sat, Jul 20');
|
||||||
|
locale.set('de');
|
||||||
|
expect(formatGroupTitle(date)).toBe('Sa., 20. Juli');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats date this year', () => {
|
it('formats date this year', () => {
|
||||||
const date = parseUtcDate('2020-01-01T00:00:00Z');
|
const date = parseUtcDate('2020-01-01T00:00:00Z');
|
||||||
expect(formatGroupTitle(date.setLocale('en'))).toBe('Wed, Jan 1, 2020');
|
locale.set('en');
|
||||||
expect(formatGroupTitle(date.setLocale('ja'))).toBe('2020年1月1日(水)');
|
expect(formatGroupTitle(date)).toBe('Wed, Jan 1, 2020');
|
||||||
|
locale.set('ja');
|
||||||
|
expect(formatGroupTitle(date)).toBe('2020年1月1日(水)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats future date', () => {
|
it('formats future date', () => {
|
||||||
const tomorrow = parseUtcDate('2024-07-28T00:00:00Z');
|
const tomorrow = parseUtcDate('2024-07-28T00:00:00Z');
|
||||||
expect(formatGroupTitle(tomorrow.setLocale('en'))).toBe('Sun, Jul 28');
|
locale.set('en');
|
||||||
|
expect(formatGroupTitle(tomorrow)).toBe('Sun, Jul 28');
|
||||||
|
|
||||||
const nextMonth = parseUtcDate('2024-08-28T00:00:00Z');
|
const nextMonth = parseUtcDate('2024-08-28T00:00:00Z');
|
||||||
expect(formatGroupTitle(nextMonth.setLocale('en'))).toBe('Wed, Aug 28');
|
locale.set('en');
|
||||||
|
expect(formatGroupTitle(nextMonth)).toBe('Wed, Aug 28');
|
||||||
|
|
||||||
const nextYear = parseUtcDate('2025-01-10T12:00:00Z');
|
const nextYear = parseUtcDate('2025-01-10T12:00:00Z');
|
||||||
expect(formatGroupTitle(nextYear.setLocale('en'))).toBe('Fri, Jan 10, 2025');
|
locale.set('en');
|
||||||
|
expect(formatGroupTitle(nextYear)).toBe('Fri, Jan 10, 2025');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns "Invalid DateTime" when date is invalid', () => {
|
it('returns "Invalid DateTime" when date is invalid', () => {
|
||||||
const date = DateTime.invalid('test');
|
const date = DateTime.invalid('test');
|
||||||
expect(formatGroupTitle(date.setLocale('en'))).toBe('Invalid DateTime');
|
locale.set('en');
|
||||||
expect(formatGroupTitle(date.setLocale('es'))).toBe('Invalid DateTime');
|
expect(formatGroupTitle(date)).toBe('Invalid DateTime');
|
||||||
|
locale.set('es');
|
||||||
|
expect(formatGroupTitle(date)).toBe('Invalid DateTime');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -62,12 +62,12 @@ export function formatGroupTitle(_date: DateTime): string {
|
|||||||
|
|
||||||
// Today
|
// Today
|
||||||
if (today.hasSame(date, 'day')) {
|
if (today.hasSame(date, 'day')) {
|
||||||
return date.toRelativeCalendar();
|
return date.toRelativeCalendar({ locale: get(locale) });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yesterday
|
// Yesterday
|
||||||
if (today.minus({ days: 1 }).hasSame(date, 'day')) {
|
if (today.minus({ days: 1 }).hasSame(date, 'day')) {
|
||||||
return date.toRelativeCalendar();
|
return date.toRelativeCalendar({ locale: get(locale) });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last week
|
// Last week
|
||||||
|
@ -87,6 +87,7 @@
|
|||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
import { type TimelineAsset } from '$lib/stores/assets-store.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: PageData;
|
data: PageData;
|
||||||
@ -317,6 +318,11 @@
|
|||||||
await refreshAlbum();
|
await refreshAlbum();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUndoRemoveAssets = async (assets: TimelineAsset[]) => {
|
||||||
|
assetStore.addAssets(assets);
|
||||||
|
await refreshAlbum();
|
||||||
|
};
|
||||||
|
|
||||||
const handleUpdateThumbnail = async (assetId: string) => {
|
const handleUpdateThumbnail = async (assetId: string) => {
|
||||||
if (viewMode !== AlbumPageViewMode.SELECT_THUMBNAIL) {
|
if (viewMode !== AlbumPageViewMode.SELECT_THUMBNAIL) {
|
||||||
return;
|
return;
|
||||||
@ -570,6 +576,7 @@
|
|||||||
disabled={!album.isActivityEnabled}
|
disabled={!album.isActivityEnabled}
|
||||||
isLiked={activityManager.isLiked}
|
isLiked={activityManager.isLiked}
|
||||||
numberOfComments={activityManager.commentCount}
|
numberOfComments={activityManager.commentCount}
|
||||||
|
numberOfLikes={undefined}
|
||||||
onFavorite={handleFavorite}
|
onFavorite={handleFavorite}
|
||||||
onOpenActivityTab={handleOpenAndCloseActivityTab}
|
onOpenActivityTab={handleOpenAndCloseActivityTab}
|
||||||
/>
|
/>
|
||||||
@ -623,7 +630,7 @@
|
|||||||
<RemoveFromAlbum menuItem bind:album onRemove={handleRemoveAssets} />
|
<RemoveFromAlbum menuItem bind:album onRemove={handleRemoveAssets} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if assetInteraction.isAllUserOwned}
|
{#if assetInteraction.isAllUserOwned}
|
||||||
<DeleteAssets menuItem onAssetDelete={handleRemoveAssets} />
|
<DeleteAssets menuItem onAssetDelete={handleRemoveAssets} onUndoDelete={handleUndoRemoveAssets} />
|
||||||
{/if}
|
{/if}
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
</AssetSelectControlBar>
|
</AssetSelectControlBar>
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
||||||
import { AssetAction } from '$lib/constants';
|
import { AssetAction } from '$lib/constants';
|
||||||
|
|
||||||
|
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
|
||||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { AssetStore } from '$lib/stores/assets-store.svelte';
|
import { AssetStore } from '$lib/stores/assets-store.svelte';
|
||||||
import { AssetVisibility } from '@immich/sdk';
|
import { AssetVisibility } from '@immich/sdk';
|
||||||
@ -20,7 +21,6 @@
|
|||||||
import { onDestroy } from 'svelte';
|
import { onDestroy } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: PageData;
|
data: PageData;
|
||||||
|
@ -92,7 +92,11 @@
|
|||||||
<TagAction menuItem />
|
<TagAction menuItem />
|
||||||
{/if}
|
{/if}
|
||||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||||
<DeleteAssets menuItem onAssetDelete={(assetIds) => assetStore.removeAssets(assetIds)} />
|
<DeleteAssets
|
||||||
|
menuItem
|
||||||
|
onAssetDelete={(assetIds) => assetStore.removeAssets(assetIds)}
|
||||||
|
onUndoDelete={(assets) => assetStore.addAssets(assets)}
|
||||||
|
/>
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
</AssetSelectControlBar>
|
</AssetSelectControlBar>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -122,6 +122,7 @@
|
|||||||
{viewport}
|
{viewport}
|
||||||
showAssetName={true}
|
showAssetName={true}
|
||||||
pageHeaderOffset={54}
|
pageHeaderOffset={54}
|
||||||
|
onReload={triggerAssetUpdate}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@ -170,7 +171,7 @@
|
|||||||
{#if $preferences.tags.enabled && assetInteraction.isAllUserOwned}
|
{#if $preferences.tags.enabled && assetInteraction.isAllUserOwned}
|
||||||
<TagAction menuItem />
|
<TagAction menuItem />
|
||||||
{/if}
|
{/if}
|
||||||
<DeleteAssets menuItem onAssetDelete={triggerAssetUpdate} />
|
<DeleteAssets menuItem onAssetDelete={triggerAssetUpdate} onUndoDelete={triggerAssetUpdate} />
|
||||||
<hr />
|
<hr />
|
||||||
<AssetJobActions />
|
<AssetJobActions />
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
|
@ -351,6 +351,11 @@
|
|||||||
await updateAssetCount();
|
await updateAssetCount();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUndoDeleteAssets = async (assets: TimelineAsset[]) => {
|
||||||
|
assetStore.addAssets(assets);
|
||||||
|
await updateAssetCount();
|
||||||
|
};
|
||||||
|
|
||||||
let person = $derived(data.person);
|
let person = $derived(data.person);
|
||||||
|
|
||||||
let thumbnailData = $derived(getPeopleThumbnailUrl(person));
|
let thumbnailData = $derived(getPeopleThumbnailUrl(person));
|
||||||
@ -532,7 +537,11 @@
|
|||||||
<TagAction menuItem />
|
<TagAction menuItem />
|
||||||
{/if}
|
{/if}
|
||||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||||
<DeleteAssets menuItem onAssetDelete={(assetIds) => handleDeleteAssets(assetIds)} />
|
<DeleteAssets
|
||||||
|
menuItem
|
||||||
|
onAssetDelete={(assetIds) => handleDeleteAssets(assetIds)}
|
||||||
|
onUndoDelete={(assets) => handleUndoDeleteAssets(assets)}
|
||||||
|
/>
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
</AssetSelectControlBar>
|
</AssetSelectControlBar>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -150,7 +150,11 @@
|
|||||||
{#if $preferences.tags.enabled}
|
{#if $preferences.tags.enabled}
|
||||||
<TagAction menuItem />
|
<TagAction menuItem />
|
||||||
{/if}
|
{/if}
|
||||||
<DeleteAssets menuItem onAssetDelete={(assetIds) => assetStore.removeAssets(assetIds)} />
|
<DeleteAssets
|
||||||
|
menuItem
|
||||||
|
onAssetDelete={(assetIds) => assetStore.removeAssets(assetIds)}
|
||||||
|
onUndoDelete={(assets) => assetStore.addAssets(assets)}
|
||||||
|
/>
|
||||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||||
<hr />
|
<hr />
|
||||||
<AssetJobActions />
|
<AssetJobActions />
|
||||||
|
@ -301,7 +301,7 @@
|
|||||||
{#if $preferences.tags.enabled && assetInteraction.isAllUserOwned}
|
{#if $preferences.tags.enabled && assetInteraction.isAllUserOwned}
|
||||||
<TagAction menuItem />
|
<TagAction menuItem />
|
||||||
{/if}
|
{/if}
|
||||||
<DeleteAssets menuItem {onAssetDelete} />
|
<DeleteAssets menuItem {onAssetDelete} onUndoDelete={onSearchQueryUpdate} />
|
||||||
<hr />
|
<hr />
|
||||||
<AssetJobActions />
|
<AssetJobActions />
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
@ -382,6 +382,7 @@
|
|||||||
showArchiveIcon={true}
|
showArchiveIcon={true}
|
||||||
{viewport}
|
{viewport}
|
||||||
pageHeaderOffset={54}
|
pageHeaderOffset={54}
|
||||||
|
onReload={onSearchQueryUpdate}
|
||||||
/>
|
/>
|
||||||
{:else if !isLoading}
|
{:else if !isLoading}
|
||||||
<div class="flex min-h-[calc(66vh-11rem)] w-full place-content-center items-center dark:text-white">
|
<div class="flex min-h-[calc(66vh-11rem)] w-full place-content-center items-center dark:text-white">
|
||||||
@ -444,7 +445,7 @@
|
|||||||
{#if $preferences.tags.enabled && assetInteraction.isAllUserOwned}
|
{#if $preferences.tags.enabled && assetInteraction.isAllUserOwned}
|
||||||
<TagAction menuItem />
|
<TagAction menuItem />
|
||||||
{/if}
|
{/if}
|
||||||
<DeleteAssets menuItem {onAssetDelete} />
|
<DeleteAssets menuItem {onAssetDelete} onUndoDelete={onSearchQueryUpdate} />
|
||||||
<hr />
|
<hr />
|
||||||
<AssetJobActions />
|
<AssetJobActions />
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user