diff --git a/.env b/.env index d8c1b59200..19b2b70080 100644 --- a/.env +++ b/.env @@ -1,5 +1,3 @@ PHANPY_CLIENT_NAME=Phanpy -PHANPY_WEBSITE=https://phanpy.social -PHANPY_LINGVA_INSTANCES="lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud" PHANPY_PRIVACY_POLICY_URL="https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD" PHANPY_TRANSLANG_INSTANCES="translang.phanpy.social" \ No newline at end of file diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml new file mode 100644 index 0000000000..126d234142 --- /dev/null +++ b/.github/workflows/bundle-size.yml @@ -0,0 +1,32 @@ +name: Bundle Size Report + +on: + pull_request: + branches: [production] + +permissions: + pull-requests: write + +jobs: + bundle-size: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: 24 + cache: "npm" + - run: npm ci + - name: Build and extract bundle sizes + run: npm run build:sizes --silent > bundle-sizes.md + - name: Debug - show file content + run: | + echo "File size:" + wc -l bundle-sizes.md + echo "First 20 lines:" + head -20 bundle-sizes.md + - name: Comment on PR + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: bundle-size + path: bundle-sizes.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5876646f3b..007096a1ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -383,11 +383,13 @@ Recap: Mastodon v4.3 features (https://github.com/mastodon/mastodon/releases/tag - 💬 Slightly more support for Mastodon v4.5's native quote posts - 🐛 Bug fixes -## Next +## November 26, 2025 + +📢 https://mastodon.social/@cheeaun/115616195859103739 - 🤳 QR code for profiles and shortcuts settings - 🔃 Import/export accounts -- 📸 Extract description from attached images +- 📸 Extract description from attached image metadata - 🐛 Bug fixes - - - - -
diff --git a/package-lock.json b/package-lock.json index 94e77a8ed4..a26fbae586 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,15 +14,16 @@ "@github/text-expander-element": "~2.9.2", "@iconify-icons/mingcute": "~1.2.9", "@justinribeiro/lite-youtube": "~1.9.0", - "@lingui/detect-locale": "~5.6.0", - "@lingui/macro": "~5.6.0", - "@lingui/react": "~5.6.0", - "@szhsin/react-menu": "~4.5.0", - "chroma-js": "~3.1.2", + "@lingui/detect-locale": "~5.6.1", + "@lingui/macro": "~5.6.1", + "@lingui/react": "~5.6.1", + "@szhsin/react-menu": "~4.5.1", + "chroma-js": "~3.2.0", "compare-versions": "~6.1.1", "exifreader": "~4.32.0", "fast-blurhash": "~1.1.4", "fast-equals": "~5.3.3", + "flexsearch": "^0.8.212", "fuse.js": "~7.1.0", "gifuct-js": "~2.1.2", "html-prettify": "~1.0.7", @@ -31,13 +32,13 @@ "js-cookie": "~3.0.5", "just-debounce-it": "~3.2.0", "lz-string": "~1.5.0", - "masto": "~7.5.0", - "moize": "~6.1.6", + "masto": "~7.7.1", + "micro-memoize": "~5.1.1", "p-queue": "~9.0.1", "p-retry": "~7.1.0", "preact": "10.27.2", "punycode": "~2.3.1", - "qr": "~0.5.2", + "qr": "~0.5.3", "react-hotkeys-hook": "~5.2.1", "react-intersection-observer": "~10.0.0", "react-quick-pinch-zoom": "~5.1.1", @@ -53,23 +54,23 @@ "valtio": "2.1.8" }, "devDependencies": { - "@biomejs/biome": "2.3.7", - "@lingui/babel-plugin-lingui-macro": "~5.6.0", - "@lingui/cli": "~5.6.0", - "@lingui/vite-plugin": "~5.6.0", - "@playwright/test": "~1.56.1", + "@biomejs/biome": "2.3.8", + "@lingui/babel-plugin-lingui-macro": "~5.6.1", + "@lingui/cli": "~5.6.1", + "@lingui/vite-plugin": "~5.6.1", + "@playwright/test": "~1.57.0", "@preact/preset-vite": "~2.10.2", "@types/node": "~24.10.1", "postcss": "~8.5.6", "postcss-dark-theme-class": "~2.0.0", "postcss-preset-env": "~10.4.0", "prop-types": "^15.8.1", - "sonda": "~0.10.0", + "sonda": "~0.10.1", "twitter-text": "~3.1.0", - "vite": "~7.2.4", + "vite": "~7.2.6", "vite-plugin-generate-file": "~0.3.1", "vite-plugin-html-config": "~2.0.2", - "vite-plugin-pwa": "~1.1.0", + "vite-plugin-pwa": "~1.2.0", "vite-plugin-remove-console": "~2.2.0", "vite-plugin-run": "~0.6.1", "workbox-cacheable-response": "~7.4.0", @@ -1685,9 +1686,9 @@ } }, "node_modules/@biomejs/biome": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.7.tgz", - "integrity": "sha512-CTbAS/jNAiUc6rcq94BrTB8z83O9+BsgWj2sBCQg9rD6Wkh2gjfR87usjx0Ncx0zGXP1NKgT7JNglay5Zfs9jw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.8.tgz", + "integrity": "sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -1701,20 +1702,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.3.7", - "@biomejs/cli-darwin-x64": "2.3.7", - "@biomejs/cli-linux-arm64": "2.3.7", - "@biomejs/cli-linux-arm64-musl": "2.3.7", - "@biomejs/cli-linux-x64": "2.3.7", - "@biomejs/cli-linux-x64-musl": "2.3.7", - "@biomejs/cli-win32-arm64": "2.3.7", - "@biomejs/cli-win32-x64": "2.3.7" + "@biomejs/cli-darwin-arm64": "2.3.8", + "@biomejs/cli-darwin-x64": "2.3.8", + "@biomejs/cli-linux-arm64": "2.3.8", + "@biomejs/cli-linux-arm64-musl": "2.3.8", + "@biomejs/cli-linux-x64": "2.3.8", + "@biomejs/cli-linux-x64-musl": "2.3.8", + "@biomejs/cli-win32-arm64": "2.3.8", + "@biomejs/cli-win32-x64": "2.3.8" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.7.tgz", - "integrity": "sha512-LirkamEwzIUULhXcf2D5b+NatXKeqhOwilM+5eRkbrnr6daKz9rsBL0kNZ16Hcy4b8RFq22SG4tcLwM+yx/wFA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.8.tgz", + "integrity": "sha512-HM4Zg9CGQ3txTPflxD19n8MFPrmUAjaC7PQdLkugeeC0cQ+PiVrd7i09gaBS/11QKsTDBJhVg85CEIK9f50Qww==", "cpu": [ "arm64" ], @@ -1729,9 +1730,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.7.tgz", - "integrity": "sha512-Q4TO633kvrMQkKIV7wmf8HXwF0dhdTD9S458LGE24TYgBjSRbuhvio4D5eOQzirEYg6eqxfs53ga/rbdd8nBKg==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.8.tgz", + "integrity": "sha512-lUDQ03D7y/qEao7RgdjWVGCu+BLYadhKTm40HkpJIi6kn8LSv5PAwRlew/DmwP4YZ9ke9XXoTIQDO1vAnbRZlA==", "cpu": [ "x64" ], @@ -1746,9 +1747,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.7.tgz", - "integrity": "sha512-inHOTdlstUBzgjDcx0ge71U4SVTbwAljmkfi3MC5WzsYCRhancqfeL+sa4Ke6v2ND53WIwCFD5hGsYExoI3EZQ==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.8.tgz", + "integrity": "sha512-Uo1OJnIkJgSgF+USx970fsM/drtPcQ39I+JO+Fjsaa9ZdCN1oysQmy6oAGbyESlouz+rzEckLTF6DS7cWse95g==", "cpu": [ "arm64" ], @@ -1763,9 +1764,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.7.tgz", - "integrity": "sha512-/afy8lto4CB8scWfMdt+NoCZtatBUF62Tk3ilWH2w8ENd5spLhM77zKlFZEvsKJv9AFNHknMl03zO67CiklL2Q==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.8.tgz", + "integrity": "sha512-PShR4mM0sjksUMyxbyPNMxoKFPVF48fU8Qe8Sfx6w6F42verbwRLbz+QiKNiDPRJwUoMG1nPM50OBL3aOnTevA==", "cpu": [ "arm64" ], @@ -1780,9 +1781,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.7.tgz", - "integrity": "sha512-fJMc3ZEuo/NaMYo5rvoWjdSS5/uVSW+HPRQujucpZqm2ZCq71b8MKJ9U4th9yrv2L5+5NjPF0nqqILCl8HY/fg==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.8.tgz", + "integrity": "sha512-QDPMD5bQz6qOVb3kiBui0zKZXASLo0NIQ9JVJio5RveBEFgDgsvJFUvZIbMbUZT3T00M/1wdzwWXk4GIh0KaAw==", "cpu": [ "x64" ], @@ -1797,9 +1798,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.7.tgz", - "integrity": "sha512-CQUtgH1tIN6e5wiYSJqzSwJumHYolNtaj1dwZGCnZXm2PZU1jOJof9TsyiP3bXNDb+VOR7oo7ZvY01If0W3iFQ==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.8.tgz", + "integrity": "sha512-YGLkqU91r1276uwSjiUD/xaVikdxgV1QpsicT0bIA1TaieM6E5ibMZeSyjQ/izBn4tKQthUSsVZacmoJfa3pDA==", "cpu": [ "x64" ], @@ -1814,9 +1815,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.7.tgz", - "integrity": "sha512-aJAE8eCNyRpcfx2JJAtsPtISnELJ0H4xVVSwnxm13bzI8RwbXMyVtxy2r5DV1xT3WiSP+7LxORcApWw0LM8HiA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.8.tgz", + "integrity": "sha512-H4IoCHvL1fXKDrTALeTKMiE7GGWFAraDwBYFquE/L/5r1927Te0mYIGseXi4F+lrrwhSWbSGt5qPFswNoBaCxg==", "cpu": [ "arm64" ], @@ -1831,9 +1832,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.7.tgz", - "integrity": "sha512-pulzUshqv9Ed//MiE8MOUeeEkbkSHVDVY5Cz5wVAnH1DUqliCQG3j6s1POaITTFqFfo7AVIx2sWdKpx/GS+Nqw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.8.tgz", + "integrity": "sha512-RguzimPoZWtBapfKhKjcWXBVI91tiSprqdBYu7tWhgN8pKRZhw24rFeNZTNf6UiBfjCYCi9eFQs/JzJZIhuK4w==", "cpu": [ "x64" ], @@ -3739,9 +3740,9 @@ "license": "MIT" }, "node_modules/@lingui/babel-plugin-extract-messages": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-5.6.0.tgz", - "integrity": "sha512-FrTHNisLmH1X23d1ISOFLgChjr6lO+vpDa21enCA7ehTJHWjtxy6YP4rXrX5MWfsozmLFloJsizpNU69OC3e1w==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-5.6.1.tgz", + "integrity": "sha512-8sNhDzRSvyDi2LeAwb8lNbKr4lYsCweu5ODTCgRCJp+MQcCD24GzyPK8cvrG/kQOJKlkQogiW81wMIRTM3jCLQ==", "dev": true, "license": "MIT", "engines": { @@ -3749,9 +3750,9 @@ } }, "node_modules/@lingui/babel-plugin-lingui-macro": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-lingui-macro/-/babel-plugin-lingui-macro-5.6.0.tgz", - "integrity": "sha512-r1FwNEfLDPJaC0Goj2gbUR452APWApRZtd8WCGkODpMLen1a1reK+edCRwUeUr72cLbpPVpewr6aBc7deOLySQ==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-lingui-macro/-/babel-plugin-lingui-macro-5.6.1.tgz", + "integrity": "sha512-EDJQVr3AhhRzDuYQAJCqgi5+5dtP7oIFlVzo9StjEQgq6gamqVyWBGO1nyrmAAj/sSUrO6GxWq/hLUC0YQ8j1Q==", "devOptional": true, "license": "MIT", "peer": true, @@ -3759,9 +3760,9 @@ "@babel/core": "^7.20.12", "@babel/runtime": "^7.20.13", "@babel/types": "^7.20.7", - "@lingui/conf": "5.6.0", - "@lingui/core": "5.6.0", - "@lingui/message-utils": "5.6.0" + "@lingui/conf": "5.6.1", + "@lingui/core": "5.6.1", + "@lingui/message-utils": "5.6.1" }, "engines": { "node": ">=20.0.0" @@ -3776,9 +3777,9 @@ } }, "node_modules/@lingui/cli": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-5.6.0.tgz", - "integrity": "sha512-ZqCLqbakKhlViuH0S9AGR54dVnIKYEMeVTgIshL2XVNpAVlfKdzox+EjavEvMI4g4s86MRazLpwioBjfeJG/tg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-5.6.1.tgz", + "integrity": "sha512-nK5O082mmnfHgyJnjRgah0Q4PTPGOGycNo2ZKUhEj4gl7A8qW0rBCB0z1dF3gpa1zfPZyrV0zLHXmBiyyQjtGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3787,12 +3788,12 @@ "@babel/parser": "^7.22.0", "@babel/runtime": "^7.21.0", "@babel/types": "^7.21.2", - "@lingui/babel-plugin-extract-messages": "5.6.0", - "@lingui/babel-plugin-lingui-macro": "5.6.0", - "@lingui/conf": "5.6.0", - "@lingui/core": "5.6.0", - "@lingui/format-po": "5.6.0", - "@lingui/message-utils": "5.6.0", + "@lingui/babel-plugin-extract-messages": "5.6.1", + "@lingui/babel-plugin-lingui-macro": "5.6.1", + "@lingui/conf": "5.6.1", + "@lingui/core": "5.6.1", + "@lingui/format-po": "5.6.1", + "@lingui/message-utils": "5.6.1", "chokidar": "3.5.1", "cli-table": "^0.3.11", "commander": "^10.0.0", @@ -3818,9 +3819,9 @@ } }, "node_modules/@lingui/conf": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-5.6.0.tgz", - "integrity": "sha512-h8e2p0BhTAsIriwW4l711P3/8N8NH17Rj3of8UWyerWUnvxOpGCIM1wix/CHP65yFF384phC0WqPjBur89TnYg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-5.6.1.tgz", + "integrity": "sha512-rdlGLiQIyDTitqeJaQZEJdPyMVH0CA7FAlifFE8MwXa1ukfAfn0K2O5JmZc2EYbIKAncJL+FqjGx8OHSTQwTlA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -3835,19 +3836,19 @@ } }, "node_modules/@lingui/core": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/core/-/core-5.6.0.tgz", - "integrity": "sha512-s+WOjytLPBi1O3VT8wBklteK8PPPrmuox7A2mEPUO0QOqfFK4mzt5Bdok4RK+MCV61ampLByLlOUwS/NQEGWoQ==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/core/-/core-5.6.1.tgz", + "integrity": "sha512-PJMapI0sC+Dd8BgL7/EHnMk0TuBXGkbC5s9osbUofev40mZW9BGIbeMspkHpdcm+s1RlVlStIAm2YCcovbN3RA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.13", - "@lingui/message-utils": "5.6.0" + "@lingui/message-utils": "5.6.1" }, "engines": { "node": ">=20.0.0" }, "peerDependencies": { - "@lingui/babel-plugin-lingui-macro": "5.6.0", + "@lingui/babel-plugin-lingui-macro": "5.6.1", "babel-plugin-macros": "2 || 3" }, "peerDependenciesMeta": { @@ -3860,23 +3861,23 @@ } }, "node_modules/@lingui/detect-locale": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-5.6.0.tgz", - "integrity": "sha512-ZaUr/R/GPwVisVolCyCcbwzqlPVXRM54d7Rfp2aRaIpTODGujmF42NWCWSUEAwHh88gpIhdL3DofdwK17d/ljw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-5.6.1.tgz", + "integrity": "sha512-2ZHbgG+nt/F19Ymp3p+1ujoGoVCIVME7qJ+dvYack3tyuv9n5ceDx8kHhlTuoSCdIh3gST8KY+G809RwgRKVKg==", "license": "MIT", "engines": { "node": ">=20.0.0" } }, "node_modules/@lingui/format-po": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/format-po/-/format-po-5.6.0.tgz", - "integrity": "sha512-z7vgUNjiP+iu/pgfHXaUtgzRv9kvhWZqfb5FIHOAcJkTvod3vjB7FsarKRZ7BmoETMx3khgvdTgzyKGaPaO+dw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/format-po/-/format-po-5.6.1.tgz", + "integrity": "sha512-yPYeca3S+hainBiDl8OBTYgx2HRpRK1iwW4cWRH2+ih/8DRPg7cu8xP7VyLY4/dRMJgZ4vOKCavCLpus+57uoA==", "dev": true, "license": "MIT", "dependencies": { - "@lingui/conf": "5.6.0", - "@lingui/message-utils": "5.6.0", + "@lingui/conf": "5.6.1", + "@lingui/message-utils": "5.6.1", "date-fns": "^3.6.0", "pofile": "^1.1.4" }, @@ -3885,19 +3886,19 @@ } }, "node_modules/@lingui/macro": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-5.6.0.tgz", - "integrity": "sha512-xv85SmvfgO4e34SRMBqIVlrU/baWowMNL2EeV+BjvQEvD0jNPSrCok94ibWQu0D+N74qBe82OQ+gKWHWTKYPcg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-5.6.1.tgz", + "integrity": "sha512-c7g5v8lZt2ImtFhxoSsvINFtC6JLfHmss4MFRIJRfQjAmX29fIGPOVki7Nrj9T/7n4ZUs64wbwITInqeEYA1fA==", "license": "MIT", "dependencies": { - "@lingui/core": "5.6.0", - "@lingui/react": "5.6.0" + "@lingui/core": "5.6.1", + "@lingui/react": "5.6.1" }, "engines": { "node": ">=20.0.0" }, "peerDependencies": { - "@lingui/babel-plugin-lingui-macro": "5.6.0", + "@lingui/babel-plugin-lingui-macro": "5.6.1", "babel-plugin-macros": "2 || 3" }, "peerDependenciesMeta": { @@ -3910,9 +3911,9 @@ } }, "node_modules/@lingui/message-utils": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/message-utils/-/message-utils-5.6.0.tgz", - "integrity": "sha512-g/Jyf5CzwdYd8KxgyFG/UNePvLsp32yndvb9sAhdS9CscgY3T+0IYviOEB36AaxZcftB51zhdGCMdscoEDiChg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/message-utils/-/message-utils-5.6.1.tgz", + "integrity": "sha512-gtNniuObzVTqEmzp/Ra6VUrgkuEeLMruVK3q2UNANu1UAvPKcrP4vHwpWlRDDz9lXH4pbE6F+4S88wEdGMWToQ==", "license": "MIT", "dependencies": { "@messageformat/parser": "^5.0.0", @@ -3923,19 +3924,19 @@ } }, "node_modules/@lingui/react": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/react/-/react-5.6.0.tgz", - "integrity": "sha512-EhvDQ3xNloW0f/JCKl6hCDi8JVcwEDFYpQd3iC2i9coom2iwRNbxjVeKUa+/27tjl90bdbJrdgTRtis0RXN1wQ==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/react/-/react-5.6.1.tgz", + "integrity": "sha512-K1p0qWOW8fVlC2ZYHecjZewNaSTNCPRl+uS8nZOUL0xC+/zbxq5qSQNLXi1gEPqD8UiRZE6V4n1S3boXPRZuPw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.13", - "@lingui/core": "5.6.0" + "@lingui/core": "5.6.1" }, "engines": { "node": ">=20.0.0" }, "peerDependencies": { - "@lingui/babel-plugin-lingui-macro": "5.6.0", + "@lingui/babel-plugin-lingui-macro": "5.6.1", "babel-plugin-macros": "2 || 3", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, @@ -3949,14 +3950,14 @@ } }, "node_modules/@lingui/vite-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@lingui/vite-plugin/-/vite-plugin-5.6.0.tgz", - "integrity": "sha512-Zj7K6QVF9uVdc7S8ekFFiYGkTWiTNhmAK1szV0eyP1+CCEY9gr1eWwbxCCsvowA2iPJbwR3MS5dOm8op6ocpHA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@lingui/vite-plugin/-/vite-plugin-5.6.1.tgz", + "integrity": "sha512-6DG14RqgQZa13154USQ9LFCM+zt5ImI5E/R2/wvj8blMVmUSCMEdGBz15Fx2fFFqug19hhKq//MRmJAwmlfkOw==", "dev": true, "license": "MIT", "dependencies": { - "@lingui/cli": "5.6.0", - "@lingui/conf": "5.6.0" + "@lingui/cli": "5.6.1", + "@lingui/conf": "5.6.1" }, "engines": { "node": ">=20.0.0" @@ -3984,13 +3985,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", - "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", + "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.56.1" + "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" @@ -5174,9 +5175,9 @@ } }, "node_modules/chroma-js": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.1.2.tgz", - "integrity": "sha512-IJnETTalXbsLx1eKEgx19d5L6SRM7cH4vINw/99p/M11HCuXGRWL+6YmCm7FWFGIo6dtWuQoQi1dc5yQ7ESIHg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.2.0.tgz", + "integrity": "sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw==", "license": "(BSD-3-Clause AND Apache-2.0)" }, "node_modules/cli-cursor": { @@ -6134,6 +6135,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fast-stringify/-/fast-stringify-4.0.0.tgz", + "integrity": "sha512-lE2DIivBaLysf6hK5WH/VfMgqRbvBVHcpGVVTmA5Zi8oWIjq9YxIt6lYGdUgP1HNSXxTIat7HEIDnrSvXSeKQw==", + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", @@ -6187,6 +6194,34 @@ "node": ">=8" } }, + "node_modules/flexsearch": { + "version": "0.8.212", + "resolved": "https://registry.npmjs.org/flexsearch/-/flexsearch-0.8.212.tgz", + "integrity": "sha512-wSyJr1GUWoOOIISRu+X2IXiOcVfg9qqBRyCPRUdLMIGJqPzMo+jMRlvE83t14v1j0dRMEaBbER/adQjp6Du2pw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/ts-thomas" + }, + { + "type": "paypal", + "url": "https://www.paypal.com/donate/?hosted_button_id=GEVR88FC9BWRW" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/flexsearch" + }, + { + "type": "patreon", + "url": "https://patreon.com/user?u=96245532" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/ts-thomas" + } + ], + "license": "Apache-2.0" + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -7570,9 +7605,9 @@ } }, "node_modules/masto": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/masto/-/masto-7.5.0.tgz", - "integrity": "sha512-WJHY7LGbPld82TtxiKkQhipjylKQnyUgca/A/F4V7RU8uu2AvZFRKASWySPpsFTUCOtq5vudtE3cjvj1oh/cZw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/masto/-/masto-7.7.1.tgz", + "integrity": "sha512-p9koO7C5GK+62BBU5tgWm/ESc2Pdx/LovCpN595stj8jPn6lCTqioBlYN3fPmsgmqhRMmCglz1YiHUq6Wm4FQA==", "license": "MIT", "dependencies": { "change-case": "^5.4.4", @@ -7600,10 +7635,14 @@ "license": "MIT" }, "node_modules/micro-memoize": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.2.0.tgz", - "integrity": "sha512-dRxIsNh0XosO9sd3aASUabKOzG9dloLO41g74XUGThpHBoGm1ttakPT5in14CuW/EDedkniaShFHbymmmKGOQA==", - "license": "MIT" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-5.1.1.tgz", + "integrity": "sha512-QDwluos8YeMijiKxZGwaV4f4tzj0soS6+xcsJhJ3+4wdEIHMyKbIKVUziebOgWX3e6yiijdoaHo+9tyhbnaWXA==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.3.3", + "fast-stringify": "^4.0.0" + } }, "node_modules/micromatch": { "version": "4.0.8", @@ -7678,22 +7717,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/moize": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/moize/-/moize-6.1.6.tgz", - "integrity": "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==", - "license": "MIT", - "dependencies": { - "fast-equals": "^3.0.1", - "micro-memoize": "^4.1.2" - } - }, - "node_modules/moize/node_modules/fast-equals": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.3.tgz", - "integrity": "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg==", - "license": "MIT" - }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", @@ -8108,13 +8131,13 @@ } }, "node_modules/playwright": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", - "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.56.1" + "playwright-core": "1.57.0" }, "bin": { "playwright": "cli.js" @@ -8127,9 +8150,9 @@ } }, "node_modules/playwright-core": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", - "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9056,9 +9079,9 @@ } }, "node_modules/qr": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/qr/-/qr-0.5.2.tgz", - "integrity": "sha512-91M3sVlA7xCFpkJtYX5xzVH8tDo4rNZ7jr8v+1CRgPVkZ4D+Vl9y8rtZWJ/YkEUM6U/h0FAu5W/JAK7iowOteA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/qr/-/qr-0.5.3.tgz", + "integrity": "sha512-BSrGdNXa8z6PfEYWtvITV21mQ4asR4UCj38Fa3MUUoFAtYzFK/swEQXF+OeBuNbHPFfs3PzpZuK0BXizWXgFOQ==", "license": "(MIT OR Apache-2.0)", "engines": { "node": ">= 20.19.0" @@ -9734,9 +9757,9 @@ "license": "MIT" }, "node_modules/sonda": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/sonda/-/sonda-0.10.0.tgz", - "integrity": "sha512-Mg6YWl8QOD9Yf8wV5teUYZiB0P1oy994pmPJmi3Fr7+0RXhBcNY6TUZFa7c3gHKLJfemfoAeV22+PSBXlzuT4g==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/sonda/-/sonda-0.10.1.tgz", + "integrity": "sha512-nXlQEVsw7833XADV94MXW9EKwLxn4S1U7oSUEgKCQeU4dt0CwYvEFcyRjhjM0Ae2taxsJ9HnFrtw8Eb40/rX4w==", "dev": true, "license": "MIT", "dependencies": { @@ -10629,9 +10652,9 @@ } }, "node_modules/vite": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", - "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", + "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", "dev": true, "license": "MIT", "peer": true, @@ -10731,17 +10754,17 @@ } }, "node_modules/vite-plugin-pwa": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.1.0.tgz", - "integrity": "sha512-VsSpdubPzXhHWVINcSx6uHRMpOHVHQcHsef1QgkOlEoaIDAlssFEW88LBq1a59BuokAhsh2kUDJbaX1bZv4Bjw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.2.0.tgz", + "integrity": "sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==", "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.6", "pretty-bytes": "^6.1.1", "tinyglobby": "^0.2.10", - "workbox-build": "^7.3.0", - "workbox-window": "^7.3.0" + "workbox-build": "^7.4.0", + "workbox-window": "^7.4.0" }, "engines": { "node": ">=16.0.0" @@ -10752,8 +10775,8 @@ "peerDependencies": { "@vite-pwa/assets-generator": "^1.0.0", "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", - "workbox-build": "^7.3.0", - "workbox-window": "^7.3.0" + "workbox-build": "^7.4.0", + "workbox-window": "^7.4.0" }, "peerDependenciesMeta": { "@vite-pwa/assets-generator": { diff --git a/package.json b/package.json index 63ee14b38d..4c8bda0385 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "vite", "build": "vite build", + "build:sizes": "NO_COLOR=true vite build 2>&1 | grep '^dist/' | node scripts/bundle-sizes-to-md.js", "preview": "vite preview", "fetch-instances": "node scripts/fetch-instances-list.js", "sourcemap": "npx source-map-explorer dist/assets/*.js", @@ -27,15 +28,16 @@ "@github/text-expander-element": "~2.9.2", "@iconify-icons/mingcute": "~1.2.9", "@justinribeiro/lite-youtube": "~1.9.0", - "@lingui/detect-locale": "~5.6.0", - "@lingui/macro": "~5.6.0", - "@lingui/react": "~5.6.0", - "@szhsin/react-menu": "~4.5.0", - "chroma-js": "~3.1.2", + "@lingui/detect-locale": "~5.6.1", + "@lingui/macro": "~5.6.1", + "@lingui/react": "~5.6.1", + "@szhsin/react-menu": "~4.5.1", + "chroma-js": "~3.2.0", "compare-versions": "~6.1.1", "exifreader": "~4.32.0", "fast-blurhash": "~1.1.4", "fast-equals": "~5.3.3", + "flexsearch": "~0.8.212", "fuse.js": "~7.1.0", "gifuct-js": "~2.1.2", "html-prettify": "~1.0.7", @@ -44,13 +46,13 @@ "js-cookie": "~3.0.5", "just-debounce-it": "~3.2.0", "lz-string": "~1.5.0", - "masto": "~7.5.0", - "moize": "~6.1.6", + "masto": "~7.7.1", + "micro-memoize": "~5.1.1", "p-queue": "~9.0.1", "p-retry": "~7.1.0", "preact": "10.27.2", "punycode": "~2.3.1", - "qr": "~0.5.2", + "qr": "~0.5.3", "react-hotkeys-hook": "~5.2.1", "react-intersection-observer": "~10.0.0", "react-quick-pinch-zoom": "~5.1.1", @@ -66,23 +68,23 @@ "valtio": "2.1.8" }, "devDependencies": { - "@biomejs/biome": "2.3.7", - "@lingui/babel-plugin-lingui-macro": "~5.6.0", - "@lingui/cli": "~5.6.0", - "@lingui/vite-plugin": "~5.6.0", - "@playwright/test": "~1.56.1", + "@biomejs/biome": "2.3.8", + "@lingui/babel-plugin-lingui-macro": "~5.6.1", + "@lingui/cli": "~5.6.1", + "@lingui/vite-plugin": "~5.6.1", + "@playwright/test": "~1.57.0", "@preact/preset-vite": "~2.10.2", "@types/node": "~24.10.1", "postcss": "~8.5.6", "postcss-dark-theme-class": "~2.0.0", "postcss-preset-env": "~10.4.0", "prop-types": "^15.8.1", - "sonda": "~0.10.0", + "sonda": "~0.10.1", "twitter-text": "~3.1.0", - "vite": "~7.2.4", + "vite": "~7.2.6", "vite-plugin-generate-file": "~0.3.1", "vite-plugin-html-config": "~2.0.2", - "vite-plugin-pwa": "~1.1.0", + "vite-plugin-pwa": "~1.2.0", "vite-plugin-remove-console": "~2.2.0", "vite-plugin-run": "~0.6.1", "workbox-cacheable-response": "~7.4.0", diff --git a/scripts/bundle-sizes-to-md.js b/scripts/bundle-sizes-to-md.js new file mode 100644 index 0000000000..3ba514c648 --- /dev/null +++ b/scripts/bundle-sizes-to-md.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +// Converts vite build output to markdown table +// Input: vite build output lines starting with "dist/" +// Output: markdown table with File, Size, Gzip, Map columns + +import { createInterface } from 'readline'; + +const rl = createInterface({ + input: process.stdin, + terminal: false, +}); + +const rows = []; + +rl.on('line', (line) => { + if (!line.startsWith('dist/')) return; + + // Parse line like: dist/assets/main-xxx.js 357.39 kB │ gzip: 111.67 kB │ map: 1,503.67 kB + const parts = line.split('│').map((p) => p.trim()); + + // First part: "dist/assets/file.js 357.39 kB" + const firstPart = parts[0]; + const match = firstPart.match(/^(\S+)\s+(.+)$/); + if (!match) return; + + const file = match[1]; + const size = match[2].trim(); + + // Optional gzip and map + let gzip = ''; + let map = ''; + + for (let i = 1; i < parts.length; i++) { + if (parts[i].startsWith('gzip:')) { + gzip = parts[i].replace('gzip:', '').trim(); + } else if (parts[i].startsWith('map:')) { + map = parts[i].replace('map:', '').trim(); + } + } + + rows.push({ file, size, gzip, map }); +}); + +rl.on('close', () => { + console.log('## 📦 Bundle Size Report\n'); + console.log('| File | Size | Gzip | Map |'); + console.log('|------|------|------|-----|'); + for (const row of rows) { + console.log(`| ${row.file} | ${row.size} | ${row.gzip} | ${row.map} |`); + } +}); diff --git a/src/app.css b/src/app.css index 0781ed832c..7150ef66f5 100644 --- a/src/app.css +++ b/src/app.css @@ -5,7 +5,7 @@ html, body { margin: 0; padding: 0; - background-color: var(--bg-color); + background-color: var(--meta-theme-color, var(--bg-color)); color: var(--text-color); overflow-x: hidden; } @@ -281,13 +281,11 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { --grid-gap: 16px; grid-template-columns: 1fr 1fr 1fr; - @media (min-width: 40em) { - width: 95vw; - max-width: calc(320px * 3.3); - transform: translateX(calc(-50% + var(--main-width) / 2)); - &:dir(rtl) { - transform: translateX(calc(50% - var(--main-width) / 2)); - } + width: 95vw; + max-width: calc(320px * 3.3); + transform: translateX(calc(-50% + var(--main-width) / 2)); + &:dir(rtl) { + transform: translateX(calc(50% - var(--main-width) / 2)); } } @@ -1287,8 +1285,12 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { width: 100%; z-index: 1000; display: flex; - background-color: var(--backdrop-color); + background-color: var(--meta-theme-color, var(--backdrop-color)); animation: appear 0.1s ease-out; + + @media (min-width: 40em) { + background-color: var(--backdrop-color); + } } .deck-backdrop > a { flex-grow: 1; @@ -3070,7 +3072,7 @@ ul.link-list li a .icon { @media (min-width: 40em) { html, body { - background-color: var(--bg-faded-color); + background-color: var(--meta-theme-color, var(--bg-faded-color)); } .deck-container { background-color: var(--bg-faded-color); diff --git a/src/app.jsx b/src/app.jsx index f83213f6b7..e550da7c54 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -78,6 +78,9 @@ const Sandbox = ? lazy(() => import('./pages/sandbox')) : () => null; +// Lazy load YearInPosts component +const YearInPosts = lazy(() => import('./pages/year-in-posts')); + // QR Scan Test component for development function QrScanTest() { useEffect(() => { @@ -387,7 +390,7 @@ if (import.meta.env.DEV) { const isPWA = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; -const PATH_RESTORE_TIME_LIMIT = 2 * 60 * 60 * 1000; // 2 hours, should be good enough +const PATH_RESTORE_TIME_LIMIT = 1 * 60 * 60 * 1000; // 1 hour, should be good enough function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); @@ -688,6 +691,25 @@ function SecondaryRoutes({ isLoggedIn }) { } /> } /> } /> + + {/* Prevent flash of no background as this is lazy-loaded */} + + + } + > + + + } + /> } /> )} diff --git a/src/assets/features/year-in-posts.png b/src/assets/features/year-in-posts.png new file mode 100644 index 0000000000..93c8fe96c5 Binary files /dev/null and b/src/assets/features/year-in-posts.png differ diff --git a/src/components/ICONS.jsx b/src/components/ICONS.jsx index c07aa352c9..00d339d9d1 100644 --- a/src/components/ICONS.jsx +++ b/src/components/ICONS.jsx @@ -194,4 +194,6 @@ export const ICONS = { 'cursor-hand': () => import('@iconify-icons/mingcute/hand-finger-2-line'), qrcode: () => import('@iconify-icons/mingcute/qrcode-2-line'), scan: () => import('@iconify-icons/mingcute/scan-line'), + note: () => import('@iconify-icons/mingcute/document-3-line'), + grid: () => import('@iconify-icons/mingcute/grid-line'), }; diff --git a/src/components/account-info.css b/src/components/account-info.css index 229a218406..3247e619bc 100644 --- a/src/components/account-info.css +++ b/src/components/account-info.css @@ -376,19 +376,18 @@ font-size: smaller; border-radius: 0; align-self: center !important; - /* clip a dog ear on top right */ - clip-path: polygon(0 0, calc(100% - 4px) 0, 100% 4px, 100% 100%, 0 100%); - &:dir(rtl) { - /* top left */ - clip-path: polygon(4px 0, 100% 0, 100% 100%, 0 100%, 0 4px); - } + /* clip a dog ear on bottom right */ + clip-path: polygon( + 0 0, + 100% 0, + 100% calc(100% - 4px), + calc(100% - 4px) 100%, + 0 100% + ); /* 4x4px square on top right */ background-size: 4px 4px; background-repeat: no-repeat; - background-position: top right; - &:dir(rtl) { - background-position: top left; - } + background-position: bottom right; background-image: linear-gradient( to bottom, var(--private-note-border-color), diff --git a/src/components/account-info.jsx b/src/components/account-info.jsx index 5a0ddaa6e8..5e415e1ed0 100644 --- a/src/components/account-info.jsx +++ b/src/components/account-info.jsx @@ -50,7 +50,7 @@ function fetchFamiliarFollowers(currentID, masto) { }); } const memFetchFamiliarFollowers = pmem(fetchFamiliarFollowers, { - maxAge: ACCOUNT_INFO_MAX_AGE, + expires: ACCOUNT_INFO_MAX_AGE, }); async function fetchPostingStats(accountID, masto) { @@ -107,7 +107,7 @@ async function fetchPostingStats(accountID, masto) { return stats; } const memFetchPostingStats = pmem(fetchPostingStats, { - maxAge: ACCOUNT_INFO_MAX_AGE, + expires: ACCOUNT_INFO_MAX_AGE, }); const isValidUrl = (string) => { diff --git a/src/components/avatar.css b/src/components/avatar.css index 996180a4bb..e9953f6fd7 100644 --- a/src/components/avatar.css +++ b/src/components/avatar.css @@ -8,7 +8,6 @@ box-shadow: 0 0 0 1px var(--bg-blur-color); flex-shrink: 0; vertical-align: middle; - dynamic-range-limit: standard; /* Disable HDR */ &.has-alpha { border-radius: 0; diff --git a/src/components/button-install.js b/src/components/button-install.js new file mode 100644 index 0000000000..6b2cd901ef --- /dev/null +++ b/src/components/button-install.js @@ -0,0 +1,21 @@ +// https://adactio.com/journal/22278 +// https://gist.github.com/adactio/a445544723363d37b9c31a74a03ef928 + +class ButtonInstall extends HTMLElement { + connectedCallback() { + this.button = this.querySelector('button'); + if (window.matchMedia('(display-mode: standalone)').matches) { + this.button.remove(); + return; + } + if (!navigator.install) { + this.button.remove(); + return; + } + this.button.addEventListener('click', async (ev) => { + await navigator.install(); + }); + } +} + +customElements.define('button-install', ButtonInstall); diff --git a/src/components/columns.jsx b/src/components/columns.jsx index 238d911f27..f10f6c2aff 100644 --- a/src/components/columns.jsx +++ b/src/components/columns.jsx @@ -19,7 +19,7 @@ import useTitle from '../utils/useTitle'; const scrollIntoViewOptions = { block: 'nearest', inline: 'nearest', - behavior: 'smooth', + behavior: 'instant', }; function Columns() { diff --git a/src/components/compose-button.jsx b/src/components/compose-button.jsx index 439eaa8dee..c591841877 100644 --- a/src/components/compose-button.jsx +++ b/src/components/compose-button.jsx @@ -37,7 +37,7 @@ const fetchLatestPostsMemoized = pmem( const { value } = await statusesIterator.next(); return value || []; }, - { maxAge: 60000 }, + { expires: 60000 }, ); // 1 minute cache export default function ComposeButton() { diff --git a/src/components/custom-emojis-modal.jsx b/src/components/custom-emojis-modal.jsx index f004384a9e..a0ae0a1b3e 100644 --- a/src/components/custom-emojis-modal.jsx +++ b/src/components/custom-emojis-modal.jsx @@ -257,6 +257,8 @@ function CustomEmojisModal({ } }, []); + const hasCustomEmojis = !!customEmojis?.length; + return (
• {instance} )}
-
{ - e.preventDefault(); - const emoji = matches[0]; - if (emoji) { - onSelectEmoji(`:${emoji.shortcode}:`); - } - }} - > - -
+ {hasCustomEmojis && ( +
{ + e.preventDefault(); + const emoji = matches[0]; + if (emoji) { + onSelectEmoji(`:${emoji.shortcode}:`); + } + }} + > + +
+ )}
- {matches !== null ? ( -
    - {matches.map((emoji) => ( -
  • - { - onSelectEmoji(`:${emoji.shortcode}:`); - }} - showCode - /> -
  • - ))} -
- ) : ( -
- {uiState === 'error' && ( -
-

- Error loading custom emojis -

+ {hasCustomEmojis ? ( + <> + {matches !== null ? ( +
    + {matches.map((emoji) => ( +
  • + { + onSelectEmoji(`:${emoji.shortcode}:`); + }} + showCode + /> +
  • + ))} +
+ ) : ( +
+ {uiState === 'error' && ( +
+

+ Error loading custom emojis +

+
+ )} + {uiState === 'default' && + Object.entries(customEmojisCatList).map( + ([category, emojis]) => + !!emojis?.length && ( +
+
+ {{ + '--recent--': t`Recently used`, + '--others--': t`Others`, + }[category] || category} +
+ +
+ ), + )}
)} - {uiState === 'default' && - Object.entries(customEmojisCatList).map( - ([category, emojis]) => - !!emojis?.length && ( -
-
- {{ - '--recent--': t`Recently used`, - '--others--': t`Others`, - }[category] || category} -
- -
- ), - )} +
+ + +
+ + ) : ( +
+

+ Custom emojis are not available on this server. +

)} -
- - -
); diff --git a/src/components/media-modal.jsx b/src/components/media-modal.jsx index d77a8cbe58..5b5d1097ee 100644 --- a/src/components/media-modal.jsx +++ b/src/components/media-modal.jsx @@ -203,6 +203,10 @@ function MediaModal({ metaColor = $meta.content; $meta.content = mediaColor; } + document.documentElement.style.setProperty( + '--meta-theme-color', + mediaColor, + ); } else { const colorScheme = window.matchMedia('(prefers-color-scheme: dark)') .matches @@ -217,6 +221,10 @@ function MediaModal({ metaColor = $meta.content; $meta.content = mediaColor; } + document.documentElement.style.setProperty( + '--meta-theme-color', + mediaColor, + ); } } return () => { @@ -224,6 +232,7 @@ function MediaModal({ if ($meta && metaColor) { $meta.content = metaColor; } + document.documentElement.style.removeProperty('--meta-theme-color'); }; }, [currentIndex, mediaAccentColors]); diff --git a/src/components/media.jsx b/src/components/media.jsx index 2050e37a14..5858efb4c9 100644 --- a/src/components/media.jsx +++ b/src/components/media.jsx @@ -735,7 +735,26 @@ function Media({ style={!showOriginal && mediaStyles} > {showOriginal ? ( -