✨ Добавлены функции кэширования аватарок для улучшения производительности
- Реализованы функции для кэширования аватарок пользователей с использованием localStorage. - Добавлены методы для получения, очистки и преобразования аватарок в формат base64. - Обновлены интерфейсы загрузки и отображения аватарок с поддержкой кэширования. - Обновлены зависимости, включая добавление библиотеки sharp для обработки изображений.
This commit is contained in:
parent
5b76167c3d
commit
bfa15465f8
489
package-lock.json
generated
489
package-lock.json
generated
@ -32,7 +32,8 @@
|
||||
"sqlite3": "^5.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.10"
|
||||
"nodemon": "^3.1.10",
|
||||
"sharp": "^0.34.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
@ -505,6 +506,16 @@
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz",
|
||||
"integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@gar/promisify": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
|
||||
@ -528,6 +539,433 @@
|
||||
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
|
||||
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="
|
||||
},
|
||||
"node_modules/@img/colour": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
|
||||
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-darwin-arm64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz",
|
||||
"integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-darwin-arm64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-darwin-x64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz",
|
||||
"integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-darwin-x64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz",
|
||||
"integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-darwin-x64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz",
|
||||
"integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-arm": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz",
|
||||
"integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-arm64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz",
|
||||
"integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-ppc64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz",
|
||||
"integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-s390x": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz",
|
||||
"integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-x64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz",
|
||||
"integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz",
|
||||
"integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz",
|
||||
"integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-arm": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz",
|
||||
"integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-arm": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-arm64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz",
|
||||
"integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-arm64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-ppc64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz",
|
||||
"integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-ppc64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-s390x": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz",
|
||||
"integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-s390x": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-x64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz",
|
||||
"integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-x64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linuxmusl-arm64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz",
|
||||
"integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linuxmusl-x64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz",
|
||||
"integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-wasm32": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz",
|
||||
"integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/runtime": "^1.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-arm64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz",
|
||||
"integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-ia32": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz",
|
||||
"integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-x64": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz",
|
||||
"integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz",
|
||||
@ -2902,6 +3340,48 @@
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||
},
|
||||
"node_modules/sharp": {
|
||||
"version": "0.34.4",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz",
|
||||
"integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@img/colour": "^1.0.0",
|
||||
"detect-libc": "^2.1.0",
|
||||
"semver": "^7.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-darwin-arm64": "0.34.4",
|
||||
"@img/sharp-darwin-x64": "0.34.4",
|
||||
"@img/sharp-libvips-darwin-arm64": "1.2.3",
|
||||
"@img/sharp-libvips-darwin-x64": "1.2.3",
|
||||
"@img/sharp-libvips-linux-arm": "1.2.3",
|
||||
"@img/sharp-libvips-linux-arm64": "1.2.3",
|
||||
"@img/sharp-libvips-linux-ppc64": "1.2.3",
|
||||
"@img/sharp-libvips-linux-s390x": "1.2.3",
|
||||
"@img/sharp-libvips-linux-x64": "1.2.3",
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.3",
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.3",
|
||||
"@img/sharp-linux-arm": "0.34.4",
|
||||
"@img/sharp-linux-arm64": "0.34.4",
|
||||
"@img/sharp-linux-ppc64": "0.34.4",
|
||||
"@img/sharp-linux-s390x": "0.34.4",
|
||||
"@img/sharp-linux-x64": "0.34.4",
|
||||
"@img/sharp-linuxmusl-arm64": "0.34.4",
|
||||
"@img/sharp-linuxmusl-x64": "0.34.4",
|
||||
"@img/sharp-wasm32": "0.34.4",
|
||||
"@img/sharp-win32-arm64": "0.34.4",
|
||||
"@img/sharp-win32-ia32": "0.34.4",
|
||||
"@img/sharp-win32-x64": "0.34.4"
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||
@ -3263,6 +3743,13 @@
|
||||
"nodetouch": "bin/nodetouch.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
"sqlite3": "^5.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.10"
|
||||
"nodemon": "^3.1.10",
|
||||
"sharp": "^0.34.4"
|
||||
}
|
||||
}
|
||||
|
||||
106
public/app.js
106
public/app.js
@ -1,3 +1,73 @@
|
||||
// Кэширование аватарки
|
||||
const AVATAR_CACHE_KEY = "avatar_cache";
|
||||
const AVATAR_TIMESTAMP_KEY = "avatar_timestamp";
|
||||
|
||||
// Функция для кэширования аватарки
|
||||
async function cacheAvatar(avatarUrl) {
|
||||
try {
|
||||
const response = await fetch(avatarUrl);
|
||||
if (!response.ok) return false;
|
||||
|
||||
const blob = await response.blob();
|
||||
const base64 = await blobToBase64(blob);
|
||||
|
||||
const cacheData = {
|
||||
base64: base64,
|
||||
timestamp: Date.now(),
|
||||
url: avatarUrl
|
||||
};
|
||||
|
||||
localStorage.setItem(AVATAR_CACHE_KEY, JSON.stringify(cacheData));
|
||||
localStorage.setItem(AVATAR_TIMESTAMP_KEY, Date.now().toString());
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Ошибка кэширования аватарки:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения аватарки из кэша
|
||||
function getCachedAvatar() {
|
||||
try {
|
||||
const cacheData = localStorage.getItem(AVATAR_CACHE_KEY);
|
||||
const timestamp = localStorage.getItem(AVATAR_TIMESTAMP_KEY);
|
||||
|
||||
if (!cacheData || !timestamp) return null;
|
||||
|
||||
const data = JSON.parse(cacheData);
|
||||
const cacheAge = Date.now() - parseInt(timestamp);
|
||||
|
||||
// Кэш действителен 24 часа (86400000 мс)
|
||||
if (cacheAge > 24 * 60 * 60 * 1000) {
|
||||
clearAvatarCache();
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Ошибка получения аватарки из кэша:", error);
|
||||
clearAvatarCache();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для очистки кэша аватарки
|
||||
function clearAvatarCache() {
|
||||
localStorage.removeItem(AVATAR_CACHE_KEY);
|
||||
localStorage.removeItem(AVATAR_TIMESTAMP_KEY);
|
||||
}
|
||||
|
||||
// Преобразование Blob в base64
|
||||
function blobToBase64(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
// DOM элементы
|
||||
const noteInput = document.getElementById("noteInput");
|
||||
const saveBtn = document.getElementById("saveBtn");
|
||||
@ -1339,17 +1409,16 @@ async function renderNotes(notes) {
|
||||
note.is_pinned ? "-off" : ""
|
||||
}"></span>
|
||||
</div>
|
||||
<div id="archiveBtn" class="notesHeaderBtn" data-id="${
|
||||
note.id
|
||||
}" title="Архивировать">
|
||||
<span class="iconify" data-icon="mdi:archive"></span>
|
||||
</div>
|
||||
<div id="editBtn" class="notesHeaderBtn" data-id="${
|
||||
note.id
|
||||
}">Ред.</div>
|
||||
<div id="deleteBtn" class="notesHeaderBtn" data-id="${
|
||||
}" title="Редактировать">
|
||||
<span class="iconify" data-icon="mdi:pencil"></span>
|
||||
</div>
|
||||
<div id="archiveBtn" class="notesHeaderBtn" data-id="${
|
||||
note.id
|
||||
}">Удал.</div>
|
||||
}" title="В архив">
|
||||
<span class="iconify" data-icon="mdi:delete"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="textNote" data-original-content="${note.content.replace(
|
||||
@ -2570,7 +2639,24 @@ async function loadUserInfo() {
|
||||
// Показываем аватарку или плейсхолдер
|
||||
if (user.avatar) {
|
||||
if (userAvatar && userAvatarContainer) {
|
||||
userAvatar.src = user.avatar;
|
||||
// Проверяем, есть ли аватарка в кэше
|
||||
const cachedAvatar = getCachedAvatar();
|
||||
|
||||
if (cachedAvatar && cachedAvatar.url === user.avatar) {
|
||||
// Используем кэшированную аватарку
|
||||
userAvatar.src = cachedAvatar.base64;
|
||||
console.log("Аватарка загружена из кэша (notes)");
|
||||
} else {
|
||||
// Загружаем аватарку с сервера и кэшируем
|
||||
userAvatar.src = user.avatar;
|
||||
// Кэшируем в фоне
|
||||
cacheAvatar(user.avatar).then(success => {
|
||||
if (success) {
|
||||
console.log("Аватарка закэширована (notes)");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
userAvatarContainer.style.display = "block";
|
||||
if (userAvatarPlaceholder) {
|
||||
userAvatarPlaceholder.style.display = "none";
|
||||
@ -2583,6 +2669,8 @@ async function loadUserInfo() {
|
||||
if (userAvatarContainer) {
|
||||
userAvatarContainer.style.display = "none";
|
||||
}
|
||||
// Очищаем кэш, если аватарки нет
|
||||
clearAvatarCache();
|
||||
}
|
||||
|
||||
// Делаем аватарку и плейсхолдер кликабельными для перехода в профиль
|
||||
|
||||
@ -12,6 +12,76 @@ const confirmPasswordInput = document.getElementById("confirmPassword");
|
||||
const changePasswordBtn = document.getElementById("changePasswordBtn");
|
||||
const messageContainer = document.getElementById("messageContainer");
|
||||
|
||||
// Кэширование аватарки
|
||||
const AVATAR_CACHE_KEY = "avatar_cache";
|
||||
const AVATAR_TIMESTAMP_KEY = "avatar_timestamp";
|
||||
|
||||
// Функция для кэширования аватарки
|
||||
async function cacheAvatar(avatarUrl) {
|
||||
try {
|
||||
const response = await fetch(avatarUrl);
|
||||
if (!response.ok) return false;
|
||||
|
||||
const blob = await response.blob();
|
||||
const base64 = await blobToBase64(blob);
|
||||
|
||||
const cacheData = {
|
||||
base64: base64,
|
||||
timestamp: Date.now(),
|
||||
url: avatarUrl
|
||||
};
|
||||
|
||||
localStorage.setItem(AVATAR_CACHE_KEY, JSON.stringify(cacheData));
|
||||
localStorage.setItem(AVATAR_TIMESTAMP_KEY, Date.now().toString());
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Ошибка кэширования аватарки:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения аватарки из кэша
|
||||
function getCachedAvatar() {
|
||||
try {
|
||||
const cacheData = localStorage.getItem(AVATAR_CACHE_KEY);
|
||||
const timestamp = localStorage.getItem(AVATAR_TIMESTAMP_KEY);
|
||||
|
||||
if (!cacheData || !timestamp) return null;
|
||||
|
||||
const data = JSON.parse(cacheData);
|
||||
const cacheAge = Date.now() - parseInt(timestamp);
|
||||
|
||||
// Кэш действителен 24 часа (86400000 мс)
|
||||
if (cacheAge > 24 * 60 * 60 * 1000) {
|
||||
clearAvatarCache();
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Ошибка получения аватарки из кэша:", error);
|
||||
clearAvatarCache();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для очистки кэша аватарки
|
||||
function clearAvatarCache() {
|
||||
localStorage.removeItem(AVATAR_CACHE_KEY);
|
||||
localStorage.removeItem(AVATAR_TIMESTAMP_KEY);
|
||||
}
|
||||
|
||||
// Преобразование Blob в base64
|
||||
function blobToBase64(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
// Lazy loading для изображений
|
||||
function initLazyLoading() {
|
||||
// Проверяем поддержку Intersection Observer API
|
||||
@ -84,7 +154,24 @@ async function loadProfile() {
|
||||
|
||||
// Обрабатываем аватарку
|
||||
if (user.avatar) {
|
||||
avatarImage.src = user.avatar;
|
||||
// Проверяем, есть ли аватарка в кэше
|
||||
const cachedAvatar = getCachedAvatar();
|
||||
|
||||
if (cachedAvatar && cachedAvatar.url === user.avatar) {
|
||||
// Используем кэшированную аватарку
|
||||
avatarImage.src = cachedAvatar.base64;
|
||||
console.log("Аватарка загружена из кэша");
|
||||
} else {
|
||||
// Загружаем аватарку с сервера и кэшируем
|
||||
avatarImage.src = user.avatar;
|
||||
// Кэшируем в фоне
|
||||
cacheAvatar(user.avatar).then(success => {
|
||||
if (success) {
|
||||
console.log("Аватарка закэширована");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
avatarImage.style.display = "block";
|
||||
avatarPlaceholder.style.display = "none";
|
||||
deleteAvatarBtn.style.display = "inline-block";
|
||||
@ -92,6 +179,8 @@ async function loadProfile() {
|
||||
avatarImage.style.display = "none";
|
||||
avatarPlaceholder.style.display = "inline-flex";
|
||||
deleteAvatarBtn.style.display = "none";
|
||||
// Очищаем кэш, если аватарки нет
|
||||
clearAvatarCache();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Ошибка загрузки профиля:", error);
|
||||
@ -137,11 +226,18 @@ avatarInput.addEventListener("change", async function (event) {
|
||||
const result = await response.json();
|
||||
|
||||
// Обновляем отображение аватарки
|
||||
avatarImage.src = result.avatar + "?t=" + Date.now(); // Добавляем timestamp для обновления кэша
|
||||
avatarImage.src = result.avatar + "?t=" + Date.now(); // Добавляем timestamp для обновления кэша браузера
|
||||
avatarImage.style.display = "block";
|
||||
avatarPlaceholder.style.display = "none";
|
||||
deleteAvatarBtn.style.display = "inline-block";
|
||||
|
||||
// Обновляем кэш с новой аватаркой
|
||||
cacheAvatar(result.avatar).then(success => {
|
||||
if (success) {
|
||||
console.log("Новая аватарка закэширована");
|
||||
}
|
||||
});
|
||||
|
||||
showMessage("Аватарка успешно загружена", "success");
|
||||
} catch (error) {
|
||||
console.error("Ошибка загрузки аватарки:", error);
|
||||
@ -173,6 +269,9 @@ deleteAvatarBtn.addEventListener("click", async function () {
|
||||
avatarPlaceholder.style.display = "inline-flex";
|
||||
deleteAvatarBtn.style.display = "none";
|
||||
|
||||
// Очищаем кэш аватарки
|
||||
clearAvatarCache();
|
||||
|
||||
showMessage("Аватарка успешно удалена", "success");
|
||||
} catch (error) {
|
||||
console.error("Ошибка удаления аватарки:", error);
|
||||
|
||||
@ -123,6 +123,34 @@ header .iconify[data-icon="mdi:account-plus"] {
|
||||
color: #0288d1;
|
||||
}
|
||||
|
||||
.btnMarkdown .iconify[data-icon="mdi:format-strikethrough"] {
|
||||
color: #9c27b0;
|
||||
}
|
||||
|
||||
.btnMarkdown .iconify[data-icon="mdi:format-list-numbered"] {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.btnMarkdown .iconify[data-icon="mdi:checkbox-marked-outline"] {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.btnMarkdown .iconify[data-icon="mdi:image-plus"] {
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
.btnMarkdown .iconify[data-icon="mdi:eye"] {
|
||||
color: #607d8b;
|
||||
}
|
||||
|
||||
.notesHeaderBtn .iconify[data-icon="mdi:pencil"] {
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
.notesHeaderBtn .iconify[data-icon="mdi:delete"] {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
header {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user