diff --git a/.github/workflows/bundlewatch.yml b/.github/workflows/bundlewatch.yml new file mode 100644 index 00000000..c5435689 --- /dev/null +++ b/.github/workflows/bundlewatch.yml @@ -0,0 +1,21 @@ +name: BundleWatch +on: + push: + branches: + - main + +jobs: + bundle: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: | + npm ci + npm run build + npx bundlewatch --max-size 100kb ./dist/**/*.js + env: + BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }} + CI_REPO_OWNER: cheeaun + CI_REPO_NAME: phanpy + CI_BRANCH_BASE: main + CI_BRANCH: main diff --git a/index.html b/index.html index 3bac29d4..48d2a78c 100644 --- a/index.html +++ b/index.html @@ -28,6 +28,382 @@ content="#242526" media="(prefers-color-scheme: dark)" /> +
diff --git a/package-lock.json b/package-lock.json index 0790becd..51bc87d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,12 +14,13 @@ "history": "~5.3.0", "iconify-icon": "~1.0.2", "just-debounce-it": "~3.2.0", - "masto": "~4.11.1", + "masto": "~5.0.5", "mem": "~9.0.2", "preact": "~10.11.3", "preact-router": "~4.1.0", "react-intersection-observer": "~9.4.1", "string-length": "~5.0.1", + "toastify-js": "~1.12.0", "use-resize-observer": "~9.1.0", "valtio": "~1.7.6" }, @@ -2150,6 +2151,18 @@ "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" }, + "node_modules/@mastojs/ponyfills": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@mastojs/ponyfills/-/ponyfills-1.0.4.tgz", + "integrity": "sha512-1NaIGmcU7OmyNzx0fk+cYeGTkdXlOJOSdetaC4pStVWsrhht2cdlYSAfe5NDW3FcUmcEm2vVceB9lcClN1RCxw==", + "dependencies": { + "@types/node": "^18.11.17", + "@types/node-fetch": "^2.6.2", + "abort-controller": "^3.0.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.7" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2450,8 +2463,29 @@ "node_modules/@types/node": { "version": "18.11.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", - "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==", - "dev": true + "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==" + }, + "node_modules/@types/node-fetch": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/@types/resolve": { "version": "1.17.1", @@ -2543,6 +2577,17 @@ "dev": true, "peer": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", @@ -2647,16 +2692,6 @@ "postcss": "^8.1.0" } }, - "node_modules/axios": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", - "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", @@ -3167,6 +3202,14 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.0.tgz", @@ -3256,25 +3299,6 @@ "node": ">=8" } }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -3836,27 +3860,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isomorphic-form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz", - "integrity": "sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==", - "dependencies": { - "form-data": "^2.3.2" - } - }, - "node_modules/isomorphic-form-data/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", @@ -4146,14 +4149,13 @@ } }, "node_modules/masto": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/masto/-/masto-4.11.1.tgz", - "integrity": "sha512-siTQNhfLV1JjOERCGgjagMvD6q0K0hLuhOXrbXNcYzHAwpbPeSeAM6CSpIRrZ8zFDepOR62Djs/GtJdTR21Rfw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/masto/-/masto-5.0.5.tgz", + "integrity": "sha512-/iRuSnn2ieVfUIemm4kE/91VXAw/dUoJ/GCtebNxoFZIe/ca8xyPV/9cL7jdquc8RPNDr8ribwVUQO5DccfB8w==", "dependencies": { - "axios": "1.1.3", + "@mastojs/ponyfills": "^1.0.4", "change-case": "^4.1.2", "eventemitter3": "^5.0.0", - "isomorphic-form-data": "^2.0.0", "isomorphic-ws": "^5.0.0", "semver": "^7.3.7", "ws": "^8.8.0" @@ -4285,6 +4287,44 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", @@ -4509,11 +4549,6 @@ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz", "integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ==" }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -5070,6 +5105,11 @@ "node": ">=8.0" } }, + "node_modules/toastify-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", + "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==" + }, "node_modules/tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", @@ -7178,6 +7218,18 @@ "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" }, + "@mastojs/ponyfills": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@mastojs/ponyfills/-/ponyfills-1.0.4.tgz", + "integrity": "sha512-1NaIGmcU7OmyNzx0fk+cYeGTkdXlOJOSdetaC4pStVWsrhht2cdlYSAfe5NDW3FcUmcEm2vVceB9lcClN1RCxw==", + "requires": { + "@types/node": "^18.11.17", + "@types/node-fetch": "^2.6.2", + "abort-controller": "^3.0.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.7" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7406,8 +7458,28 @@ "@types/node": { "version": "18.11.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", - "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==", - "dev": true + "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==" + }, + "@types/node-fetch": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } }, "@types/resolve": { "version": "1.17.1", @@ -7499,6 +7571,14 @@ "dev": true, "peer": true }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "acorn": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", @@ -7562,16 +7642,6 @@ "postcss-value-parser": "^4.2.0" } }, - "axios": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", - "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "babel-plugin-polyfill-corejs2": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", @@ -7958,6 +8028,11 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "eventemitter3": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.0.tgz", @@ -8040,11 +8115,6 @@ "to-regex-range": "^5.0.1" } }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -8439,26 +8509,6 @@ "call-bind": "^1.0.2" } }, - "isomorphic-form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz", - "integrity": "sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==", - "requires": { - "form-data": "^2.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - } - } - }, "isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", @@ -8685,14 +8735,13 @@ } }, "masto": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/masto/-/masto-4.11.1.tgz", - "integrity": "sha512-siTQNhfLV1JjOERCGgjagMvD6q0K0hLuhOXrbXNcYzHAwpbPeSeAM6CSpIRrZ8zFDepOR62Djs/GtJdTR21Rfw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/masto/-/masto-5.0.5.tgz", + "integrity": "sha512-/iRuSnn2ieVfUIemm4kE/91VXAw/dUoJ/GCtebNxoFZIe/ca8xyPV/9cL7jdquc8RPNDr8ribwVUQO5DccfB8w==", "requires": { - "axios": "1.1.3", + "@mastojs/ponyfills": "^1.0.4", "change-case": "^4.1.2", "eventemitter3": "^5.0.0", - "isomorphic-form-data": "^2.0.0", "isomorphic-ws": "^5.0.0", "semver": "^7.3.7", "ws": "^8.8.0" @@ -8787,6 +8836,35 @@ "tslib": "^2.0.3" } }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", @@ -8941,11 +9019,6 @@ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz", "integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ==" }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -9341,6 +9414,11 @@ "is-number": "^7.0.0" } }, + "toastify-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", + "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==" + }, "tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", diff --git a/package.json b/package.json index 7ef73a72..8c031daf 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,13 @@ "history": "~5.3.0", "iconify-icon": "~1.0.2", "just-debounce-it": "~3.2.0", - "masto": "~4.11.1", + "masto": "~5.0.5", "mem": "~9.0.2", "preact": "~10.11.3", "preact-router": "~4.1.0", "react-intersection-observer": "~9.4.1", "string-length": "~5.0.1", + "toastify-js": "~1.12.0", "use-resize-observer": "~9.1.0", "valtio": "~1.7.6" }, diff --git a/src/app.css b/src/app.css index 6a396a1f..ea69303e 100644 --- a/src/app.css +++ b/src/app.css @@ -424,6 +424,14 @@ a.mention span { left: 50%; transform: translate(-50%, 0); font-size: 90%; + background: linear-gradient( + to bottom, + var(--button-bg-blur-color), + var(--button-bg-color) + ); + backdrop-filter: blur(16px); + box-shadow: 0 3px 8px -1px var(--bg-faded-blur-color), + 0 10px 36px -4px var(--button-bg-blur-color); } .updates-button .icon { vertical-align: top; @@ -583,22 +591,36 @@ button.carousel-dot[disabled].active { } .sheet { align-self: flex-end; + display: flex; + flex-direction: column; max-height: 90vh; max-height: 90dvh; - overflow: auto; - overflow-x: hidden; + overflow: hidden; background-color: var(--bg-color); width: 100%; max-width: calc(40em - 50px - 16px); border-radius: 16px 16px 0 0; - padding: 16px; - padding-left: max(16px, env(safe-area-inset-left)); - padding-right: max(16px, env(safe-area-inset-right)); - padding-bottom: max(16px, env(safe-area-inset-bottom)); box-shadow: 0 -1px 32px var(--divider-color); animation: slide-up 0.2s var(--timing-function); border: 1px solid var(--outline-color); +} +.sheet header { + padding: 16px 16px 8px; + padding-left: max(16px, env(safe-area-inset-left)); + padding-right: max(16px, env(safe-area-inset-right)); +} +.sheet main { + overflow: auto; + overflow-x: hidden; overscroll-behavior: contain; + padding: 16px 16px; + padding-left: max(16px, env(safe-area-inset-left)); + padding-right: max(16px, env(safe-area-inset-right)); + padding-bottom: max(16px, env(safe-area-inset-bottom)); + mask-image: linear-gradient(to bottom, transparent 0%, black 10px); +} +.sheet header + main { + padding-top: 0; } /* TAG */ @@ -672,19 +694,15 @@ meter.donut { appearance: none; } -meter.donut:is( - ::-webkit-progress-inner-element, - ::-webkit-progress-bar, - ::-webkit-progress-value, - ::-webkit-meter-bar, - ::-webkit-meter-optimum-value, - ::-webkit-meter-suboptimum-value, - ::-webkit-meter-even-less-good-value - ) { +meter.donut::-webkit-meter-inner-element, +meter.donut::-webkit-meter-bar, +meter.donut::-webkit-meter-optimum-value, +meter.donut::-webkit-meter-suboptimum-value, +meter.donut::-webkit-meter-even-less-good-value { display: none; } -meter.donut:is(::-moz-progress-bar, ::-moz-meter-bar) { +meter.donut::-moz-meter-bar { background: transparent; } @@ -725,6 +743,28 @@ meter.donut:is(.danger, .explode):after { color: var(--red-color); } +/* TOAST */ + +:root .toastify { + background-image: linear-gradient( + to bottom, + var(--button-bg-blur-color), + var(--button-bg-color) + ); + backdrop-filter: blur(16px); + color: var(--button-text-color); + border-radius: 10em; + padding: 8px 16px; + box-shadow: 0 3px 8px -1px var(--bg-faded-blur-color), + 0 10px 36px -4px var(--button-bg-blur-color); +} +:root .toastify:hover { + filter: brightness(1.2); +} +:root .toastify:active { + filter: brightness(0.8); +} + @media (min-width: 40em) { html, body { diff --git a/src/app.jsx b/src/app.jsx index cf65ec63..9e1d2c49 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,9 +1,11 @@ import './app.css'; +import 'toastify-js/src/toastify.css'; import { createHashHistory } from 'history'; import { login } from 'masto'; -import Router from 'preact-router'; +import Router, { route } from 'preact-router'; import { useEffect, useLayoutEffect, useState } from 'preact/hooks'; +import Toastify from 'toastify-js'; import { useSnapshot } from 'valtio'; import Account from './components/account'; @@ -27,7 +29,7 @@ const { VITE_CLIENT_NAME: CLIENT_NAME } = import.meta.env; window.__STATES__ = states; async function startStream() { - const stream = await masto.stream.streamUser(); + const stream = await masto.v1.stream.streamUser(); console.log('STREAM START', { stream }); stream.on('update', (status) => { console.log('UPDATE', status); @@ -105,7 +107,7 @@ async function startStream() { function startVisibility() { const handleVisibilityChange = () => { - if (document.hidden) { + if (document.visibilityState === 'hidden') { const timestamp = Date.now(); store.session.set('lastHidden', timestamp); } else { @@ -119,22 +121,19 @@ function startVisibility() { // Buffer for WS reconnect (async () => { try { - const fetchHome = masto.timelines.fetchHome({ - limit: 2, - // Need 2 because "new posts" only appear when there are 2 or more + const fetchHome = masto.v1.timelines.listHome({ + limit: 1, + }); + const fetchNotifications = masto.v1.notifications.list({ + limit: 1, }); - const fetchNotifications = masto.notifications - .iterate({ - limit: 1, - }) - .next(); const newStatuses = await fetchHome; if ( - newStatuses.value.length && - newStatuses.value[0].id !== states.home[0].id + newStatuses.length && + newStatuses[0].id !== states.home[0].id ) { - states.homeNew = newStatuses.value.map((status) => { + states.homeNew = newStatuses.map((status) => { states.statuses.set(status.id, status); if (status.reblog) { states.statuses.set(status.reblog.id, status.reblog); @@ -148,8 +147,8 @@ function startVisibility() { } const newNotifications = await fetchNotifications; - if (newNotifications.value.length) { - const notification = newNotifications.value[0]; + if (newNotifications.length) { + const notification = newNotifications[0]; const inNotificationsNew = states.notificationsNew.find( (n) => n.id === notification.id, ); @@ -242,7 +241,7 @@ export function App() { timeout: 30_000, }); - const mastoAccount = await masto.accounts.verifyCredentials(); + const mastoAccount = await masto.v1.accounts.verifyCredentials(); console.log({ tokenJSON, mastoAccount }); @@ -307,11 +306,11 @@ export function App() { // Collect instance info (async () => { - const info = await masto.instances.fetch(); + const info = await masto.v2.instance.fetch(); console.log(info); - const { uri } = info; + const { uri, domain } = info; const instances = store.local.getJSON('instances') || {}; - instances[uri] = info; + instances[domain || uri] = info; store.local.setJSON('instances', instances); })(); }); @@ -385,6 +384,18 @@ export function App() { states.showCompose = false; if (newStatus) { states.reloadStatusPage++; + const toast = Toastify({ + text: 'Status posted. Check it out.', + duration: 10_000, // 10 seconds + gravity: 'bottom', + position: 'center', + // destination: `/#/s/${newStatus.id}`, + onClick: () => { + toast.hideToast(); + route(`/s/${newStatus.id}`); + }, + }); + toast.showToast(); } }} /> diff --git a/src/components/account.css b/src/components/account.css index f49fb4ca..276cac63 100644 --- a/src/components/account.css +++ b/src/components/account.css @@ -12,7 +12,7 @@ font-size: 95%; line-height: 1.4; } -#account-container .note:not(:has(p)) { +#account-container .note:not(:has(p)):not(:empty) { /* Some notes don't have

tags, so we need to add some padding */ padding: 1em 0; } diff --git a/src/components/account.jsx b/src/components/account.jsx index 03603ed3..6750eea4 100644 --- a/src/components/account.jsx +++ b/src/components/account.jsx @@ -20,7 +20,7 @@ function Account({ account }) { setUIState('loading'); (async () => { try { - const info = await masto.accounts.lookup({ + const info = await masto.v1.accounts.lookup({ acct: account, skip_webfinger: false, }); @@ -69,7 +69,9 @@ function Account({ account }) { setRelationshipUIState('loading'); (async () => { try { - const relationships = await masto.accounts.fetchRelationships([id]); + const relationships = await masto.v1.accounts.fetchRelationships([ + id, + ]); console.log('fetched relationship', relationships); if (relationships.length) { setRelationship(relationships[0]); @@ -108,15 +110,17 @@ function Account({ account }) { ███ ████████████ -

-

████████ ███████

-

███████████████ ███████████████

-
-

- ██ Posts - ██ Following - ██ Followers -

+
+
+

████████ ███████

+

███████████████ ███████████████

+
+

+ ██ Posts + ██ Following + ██ Followers +

+
) : ( <> @@ -124,96 +128,110 @@ function Account({ account }) { -
- {fields?.length > 0 && ( - - )} -

- - {shortenNumber(statusesCount)} Posts - - - {shortenNumber(followingCount)}{' '} - Following - - - {shortenNumber(followersCount)}{' '} - Followers - - {!!createdAt && ( +

+
+ {fields?.length > 0 && ( + + )} +

- Joined:{' '} - - - + {shortenNumber(statusesCount)}{' '} + Posts - )} -

-

- {followedBy ? Following you : }{' '} - {relationshipUIState !== 'loading' && relationship && ( - - )} -

+ })(); + }} + > + {following ? ( + <> + Following + Unfollow… + + ) : ( + 'Follow' + )} + {/* {following ? 'Unfollow…' : 'Follow'} */} + + )} +

+
)}
diff --git a/src/components/compose.jsx b/src/components/compose.jsx index d48a1c15..08bb5b58 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -90,9 +90,14 @@ function Compose({ const customEmojis = useRef(); useEffect(() => { (async () => { - const emojis = await masto.customEmojis.fetchAll(); - console.log({ emojis }); - customEmojis.current = emojis; + try { + const emojis = await masto.v1.customEmojis.list(); + console.log({ emojis }); + customEmojis.current = emojis; + } catch (e) { + // silent fail + console.error(e); + } })(); }, []); @@ -161,7 +166,9 @@ function Compose({ setUIState('loading'); (async () => { try { - const statusSource = await masto.statuses.fetchSource(editStatus.id); + const statusSource = await masto.v1.statuses.fetchSource( + editStatus.id, + ); console.log({ statusSource }); const { text, spoilerText } = statusSource; textareaRef.current.value = text; @@ -236,15 +243,16 @@ function Compose({ }[key]; provide( new Promise((resolve) => { - const resultsIterator = masto.search({ + const searchResults = masto.v2.search({ type, q: text, limit: 5, }); - resultsIterator.next().then(({ value }) => { + searchResults.then((value) => { if (text !== textExpanderTextRef.current) { return; } + console.log({ value, type, v: value[type] }); const results = value[type]; console.log('RESULTS', value, results); let html = ''; @@ -268,7 +276,7 @@ function Compose({ )}" width="16" height="16" alt="" loading="lazy" /> - ${encodeHTML(displayNameWithEmoji || username)} + ${displayNameWithEmoji || username}
@${encodeHTML(acct)}
@@ -614,16 +622,18 @@ function Compose({ // If already uploaded return attachment; } else { - const params = { + const params = removeNullUndefined({ file, description, - }; - return masto.mediaAttachments.create(params).then((res) => { - if (res.id) { - attachment.id = res.id; - } - return res; }); + return masto.v2.mediaAttachments + .create(params) + .then((res) => { + if (res.id) { + attachment.id = res.id; + } + return res; + }); } }); const results = await Promise.allSettled(mediaPromises); @@ -648,24 +658,35 @@ function Compose({ console.log({ results, mediaAttachments }); } - const params = { + /* NOTE: + Using snakecase here because masto.js's `isObject` returns false for `params`, ONLY happens when opening in pop-out window. This is maybe due to `window.masto` variable being passed from the parent window. The check that failed is `x.constructor === Object`, so maybe the `Object` in new window is different than parent window's? + Code: https://github.com/neet/masto.js/blob/dd0d649067b6a2b6e60fbb0a96597c373a255b00/src/serializers/is-object.ts#L2 + */ + let params = { status, - spoilerText, + // spoilerText, + spoiler_text: spoilerText, sensitive, poll, - mediaIds: mediaAttachments.map((attachment) => attachment.id), + // mediaIds: mediaAttachments.map((attachment) => attachment.id), + media_ids: mediaAttachments.map((attachment) => attachment.id), }; if (!editStatus) { params.visibility = visibility; - params.inReplyToId = replyToStatus?.id || undefined; + // params.inReplyToId = replyToStatus?.id || undefined; + params.in_reply_to_id = replyToStatus?.id || undefined; } + params = removeNullUndefined(params); console.log('POST', params); let newStatus; if (editStatus) { - newStatus = await masto.statuses.update(editStatus.id, params); + newStatus = await masto.v1.statuses.update( + editStatus.id, + params, + ); } else { - newStatus = await masto.statuses.create(params); + newStatus = await masto.v1.statuses.create(params); } setUIState('default'); @@ -1129,4 +1150,13 @@ function countableText(inputText) { .replace(usernameRegex, '$1@$3'); } +function removeNullUndefined(obj) { + for (let key in obj) { + if (obj[key] === null || obj[key] === undefined) { + delete obj[key]; + } + } + return obj; +} + export default Compose; diff --git a/src/components/modal.css b/src/components/modal.css index 3189f66b..53b1fb26 100644 --- a/src/components/modal.css +++ b/src/components/modal.css @@ -13,5 +13,5 @@ } #modal-container > .light { - backdrop-filter: saturate(.75); -} \ No newline at end of file + backdrop-filter: saturate(0.75); +} diff --git a/src/components/name-text.jsx b/src/components/name-text.jsx index 8971ce55..b4dafee1 100644 --- a/src/components/name-text.jsx +++ b/src/components/name-text.jsx @@ -5,7 +5,7 @@ import states from '../utils/states'; import Avatar from './avatar'; -function NameText({ account, showAvatar, showAcct, short, external }) { +function NameText({ account, showAvatar, showAcct, short, external, onClick }) { const { acct, avatar, avatarStatic, id, url, displayName, emojis } = account; let { username } = account; @@ -31,6 +31,7 @@ function NameText({ account, showAvatar, showAcct, short, external }) { onClick={(e) => { if (external) return; e.preventDefault(); + if (onClick) return onClick(e); states.showAccount = account; }} > diff --git a/src/components/status.css b/src/components/status.css index 3e09453a..e3a96cb3 100644 --- a/src/components/status.css +++ b/src/components/status.css @@ -215,6 +215,11 @@ overflow: hidden; position: relative; } +.timeline-deck .status-reblog .status .content { + /* Deprioritise long-form boosts */ + max-height: 40vh; + max-height: 40dvh; +} .timeline-deck .status .content.truncated { mask-image: linear-gradient( to top, @@ -374,6 +379,7 @@ } .status .media-gif video { object-fit: cover; + pointer-events: none; } .status .media-audio { border: 0; @@ -392,18 +398,17 @@ border: 1px solid var(--outline-color); overflow: hidden; color: inherit; - align-items: center; + align-items: stretch; background: var(--bg-color); + max-height: 160px; } .card .image { - /* min-width: 120px; */ - width: 50%; - max-width: 160px; + width: 35%; height: auto; - min-height: 120px; - max-height: 160px; - object-fit: cover; + flex-grow: 1; border-inline-end: 1px solid var(--outline-color); + object-fit: cover; + aspect-ratio: 1 / 1; } .card:hover .image { animation: position-object 5s ease-in-out 1s 5; @@ -414,6 +419,8 @@ .card .meta-container { padding: 8px; min-width: 0; + flex-grow: 1; + align-self: center; } .card .title { line-height: 1.25; @@ -431,10 +438,14 @@ font-size: smaller; opacity: 0.75; margin: 0; - white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - display: block; + display: -webkit-box; + display: box; + -webkit-box-orient: vertical; + box-orient: vertical; + -webkit-line-clamp: 2; + line-clamp: 2; } .card .meta.domain { opacity: 1; @@ -605,25 +616,20 @@ a.card:hover { } @keyframes hearted { 20% { - transform: rotate(10deg) scale(1); + transform: scale(1.25) translateY(-1px); } - 40% { - transform: rotate(-10deg) scale(1.25); + 45% { + transform: scale(1); } - 60% { - transform: rotate(10deg) scale(1.75); - } - 80% { - transform: rotate(-10deg) scale(2); + 70% { + transform: scale(1.5) translateY(-2px); } 100% { - transform: rotate(10deg) scale(2.25); - opacity: 0; + transform: scale(1); } } .status .action > button.plain.favourite-button.checked .icon { - transform-origin: bottom center; - animation: hearted 1s ease-in-out; + animation: hearted 1s ease-out; } .status .action > button.plain.bookmark-button.checked { color: var(--link-color); @@ -647,7 +653,7 @@ a.card:hover { opacity: 1; } } -.status .actions > button.plain.bookmark-button.checked .icon { +.status .action > button.plain.bookmark-button.checked .icon { animation: bookmarked 1s ease-in-out; } @@ -665,6 +671,7 @@ a.card:hover { var(--bg-faded-color), transparent 160px ); + white-space: pre-wrap; } .status .content p code { @@ -701,7 +708,7 @@ a.card:hover { .shortcode-emoji { width: 1.2em; height: 1.2em; - vertical-align: middle; + vertical-align: text-bottom; object-fit: contain; } @@ -712,6 +719,11 @@ a.card:hover { min-height: 50dvh; } +#edit-history h2 { + margin: 0; + padding: 0; +} + #edit-history :is(ol, ol li) { list-style: none; margin: 0; diff --git a/src/components/status.jsx b/src/components/status.jsx index b000f483..7651f03e 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -28,7 +28,7 @@ import Avatar from './avatar'; import Icon from './icon'; function fetchAccount(id) { - return masto.accounts.fetch(id); + return masto.v1.accounts.fetch(id); } const memFetchAccount = mem(fetchAccount); @@ -521,10 +521,12 @@ function Status({ reblogsCount: reblogsCount + (reblogged ? -1 : 1), }); if (reblogged) { - const newStatus = await masto.statuses.unreblog(id); + const newStatus = await masto.v1.statuses.unreblog( + id, + ); states.statuses.set(newStatus.id, newStatus); } else { - const newStatus = await masto.statuses.reblog(id); + const newStatus = await masto.v1.statuses.reblog(id); states.statuses.set(newStatus.id, newStatus); states.statuses.set( newStatus.reblog.id, @@ -533,6 +535,8 @@ function Status({ } } catch (e) { console.error(e); + // Revert optimistism + states.statuses.set(id, status); } }} /> @@ -556,14 +560,18 @@ function Status({ favouritesCount + (favourited ? -1 : 1), }); if (favourited) { - const newStatus = await masto.statuses.unfavourite(id); + const newStatus = await masto.v1.statuses.unfavourite( + id, + ); states.statuses.set(newStatus.id, newStatus); } else { - const newStatus = await masto.statuses.favourite(id); + const newStatus = await masto.v1.statuses.favourite(id); states.statuses.set(newStatus.id, newStatus); } } catch (e) { console.error(e); + // Revert optimistism + states.statuses.set(statusID, status); } }} /> @@ -583,14 +591,18 @@ function Status({ bookmarked: !bookmarked, }); if (bookmarked) { - const newStatus = await masto.statuses.unbookmark(id); + const newStatus = await masto.v1.statuses.unbookmark( + id, + ); states.statuses.set(newStatus.id, newStatus); } else { - const newStatus = await masto.statuses.bookmark(id); + const newStatus = await masto.v1.statuses.bookmark(id); states.statuses.set(newStatus.id, newStatus); } } catch (e) { console.error(e); + // Revert optimistism + states.statuses.set(statusID, status); } }} /> @@ -743,14 +755,19 @@ function Media({ media, showOriginal, onClick = () => {} }) { rgbAverageColor && `rgb(${rgbAverageColor.join(',')})`, }} onClick={(e) => { - if (showOriginal && isGIF) { - try { - if (videoRef.current.paused) { - videoRef.current.play(); - } else { - videoRef.current.pause(); - } - } catch (e) {} + if (isGIF) { + // Hmm, the videoRef might conflict here + if (showOriginal) { + try { + if (videoRef.current.paused) { + videoRef.current.play(); + } else { + videoRef.current.pause(); + } + } catch (e) {} + } else { + videoRef.current.pause(); + } } onClick(e); }} @@ -936,7 +953,7 @@ function Poll({ poll, readOnly, onUpdate = () => {} }) { setUIState('loading'); (async () => { try { - const pollResponse = await masto.poll.fetch(id); + const pollResponse = await masto.v1.poll.fetch(id); onUpdate(pollResponse); } catch (e) { // Silent fail @@ -970,10 +987,11 @@ function Poll({ poll, readOnly, onUpdate = () => {} }) { {voted || expired ? ( options.map((option, i) => { const { title, votesCount: optionVotesCount } = option; - const percentage = - ((optionVotesCount / pollVotesCount) * 100).toFixed( - roundPrecision, - ) || 0; + const percentage = pollVotesCount + ? ((optionVotesCount / pollVotesCount) * 100).toFixed( + roundPrecision, + ) + : 0; // check if current poll choice is the leading one const isLeading = optionVotesCount > 0 && @@ -1020,7 +1038,7 @@ function Poll({ poll, readOnly, onUpdate = () => {} }) { }); console.log(votes); setUIState('loading'); - const pollResponse = await masto.poll.vote(id, { + const pollResponse = await masto.v1.poll.vote(id, { choices: votes, }); console.log(pollResponse); @@ -1069,7 +1087,7 @@ function Poll({ poll, readOnly, onUpdate = () => {} }) { setUIState('loading'); (async () => { try { - const pollResponse = await masto.poll.fetch(id); + const pollResponse = await masto.v1.poll.fetch(id); onUpdate(pollResponse); } catch (e) { // Silent fail @@ -1113,7 +1131,7 @@ function EditedAtModal({ statusID, onClose = () => {} }) { setUIState('loading'); (async () => { try { - const editHistory = await masto.statuses.fetchHistory(statusID); + const editHistory = await masto.v1.statuses.listHistory(statusID); console.log(editHistory); setEditHistory(editHistory); setUIState('default'); @@ -1128,46 +1146,50 @@ function EditedAtModal({ statusID, onClose = () => {} }) { return (
- {/* */} -

Edit History

- {uiState === 'error' &&

Failed to load history

} - {uiState === 'loading' && ( -

- Loading… -

- )} - {editHistory.length > 0 && ( -
    - {editHistory.map((status) => { - const { createdAt } = status; - const createdAtDate = new Date(createdAt); - return ( -
  1. -

    - -

    - -
  2. - ); - })} -
- )} +

Edit History

+ {uiState === 'error' &&

Failed to load history

} + {uiState === 'loading' && ( +

+ Loading… +

+ )} + +
+ {editHistory.length > 0 && ( +
    + {editHistory.map((status) => { + const { createdAt } = status; + const createdAtDate = new Date(createdAt); + return ( +
  1. +

    + +

    + +
  2. + ); + })} +
+ )} +
); } diff --git a/src/index.css b/src/index.css index 053dbcb0..635a46ea 100644 --- a/src/index.css +++ b/src/index.css @@ -172,6 +172,31 @@ button, border-radius: 0; } +:is(button, .button).swap { + display: grid; + /* 1 column, 1 row */ + grid-template-columns: 1fr; + grid-template-rows: 1fr; +} +:is(button, .button).swap > * { + grid-column: 1; + grid-row: 1; + transition: opacity 0.3s; +} +:is(button, .button).swap > *:nth-child(2) { + opacity: 0; +} +:is(button, .button).swap:hover > *:nth-child(2) { + opacity: 1; +} +:is(button, .button).swap[data-swap-state='danger']:hover { + color: var(--red-color); + border-color: var(--red-color); +} +:is(button, .button).swap:hover > *:nth-child(1) { + opacity: 0; +} + input[type='text'], textarea, select { diff --git a/src/pages/home.jsx b/src/pages/home.jsx index f19d0598..57aaec13 100644 --- a/src/pages/home.jsx +++ b/src/pages/home.jsx @@ -16,18 +16,18 @@ function Home({ hidden }) { const [showMore, setShowMore] = useState(false); const homeIterator = useRef( - masto.timelines.iterateHome({ + masto.v1.timelines.listHome({ limit: LIMIT, }), - ).current; + ); async function fetchStatuses(firstLoad) { - const allStatuses = await homeIterator.next( - firstLoad - ? { - limit: LIMIT, - } - : undefined, - ); + if (firstLoad) { + // Reset iterator + homeIterator.current = masto.v1.timelines.listHome({ + limit: LIMIT, + }); + } + const allStatuses = await homeIterator.current.next(); if (allStatuses.value <= 0) { return { done: true }; } @@ -78,6 +78,9 @@ function Home({ hidden }) { onClick={() => { scrollableRef.current?.scrollTo({ top: 0, behavior: 'smooth' }); }} + onDblClick={() => { + loadStatuses(true); + }} >
- {snapStates.homeNew.length > 1 && ( + {snapStates.homeNew.length > 0 && ( */} -

Accounts

- - {moreThanOneAccount && ( -

- - Note: Default account will always be used for first load. - Switched accounts will persist during the session. - + + ); + })} + + {moreThanOneAccount && ( +

+ + Note: Default account will always be used for first load. + Switched accounts will persist during the session. + +

+ )} +

+ + Add new account +

- )} -

- - Add new account - -

-

Theme

-
{ - console.log(e); - e.preventDefault(); - const formData = new FormData(themeFormRef.current); - const theme = formData.get('theme'); - const html = document.documentElement; +

Theme

+ { + console.log(e); + e.preventDefault(); + const formData = new FormData(themeFormRef.current); + const theme = formData.get('theme'); + const html = document.documentElement; - if (theme === 'auto') { - html.classList.remove('is-light', 'is-dark'); - } else { - html.classList.toggle('is-light', theme === 'light'); - html.classList.toggle('is-dark', theme === 'dark'); - } - document - .querySelector('meta[name="color-scheme"]') - .setAttribute('content', theme); + if (theme === 'auto') { + html.classList.remove('is-light', 'is-dark'); + } else { + html.classList.toggle('is-light', theme === 'light'); + html.classList.toggle('is-dark', theme === 'dark'); + } + document + .querySelector('meta[name="color-scheme"]') + .setAttribute('content', theme); - if (theme === 'auto') { - store.local.del('theme'); - } else { - store.local.set('theme', theme); - } - }} - > -
- - - -
-
-

About

-

- - Built - {' '} - by{' '} - - @cheeaun - - . -

- {__BUILD_TIME__ && ( + if (theme === 'auto') { + store.local.del('theme'); + } else { + store.local.set('theme', theme); + } + }} + > +
+ + + +
+ +

About

- Last build:{' '} - {' '} - {__COMMIT_HASH__ && ( - <> - ( - - {__COMMIT_HASH__} - - ) - - )} + + Built + {' '} + by{' '} + + @cheeaun + + .

- )} + {__BUILD_TIME__ && ( +

+ Last build:{' '} + {' '} + {__COMMIT_HASH__ && ( + <> + ( + + {__COMMIT_HASH__} + + ) + + )} +

+ )} + ); } diff --git a/src/pages/status.jsx b/src/pages/status.jsx index 35120f9a..fe7cdacc 100644 --- a/src/pages/status.jsx +++ b/src/pages/status.jsx @@ -72,8 +72,8 @@ function StatusPage({ id }) { } (async () => { - const heroFetch = masto.statuses.fetch(id); - const contextFetch = masto.statuses.fetchContext(id); + const heroFetch = masto.v1.statuses.fetch(id); + const contextFetch = masto.v1.statuses.fetchContext(id); const hasStatus = snapStates.statuses.has(id); let heroStatus = snapStates.statuses.get(id); diff --git a/src/utils/enhance-content.js b/src/utils/enhance-content.js index 152df8a8..637b92ab 100644 --- a/src/utils/enhance-content.js +++ b/src/utils/enhance-content.js @@ -39,7 +39,7 @@ function enhanceContent(content, opts = {}) { const pre = document.createElement('pre'); // Replace
with newlines block.querySelectorAll('br').forEach((br) => br.replaceWith('\n')); - pre.innerHTML = `${block.innerText.trim()}`; + pre.innerHTML = `${block.innerHTML.trim()}`; block.replaceWith(pre); });