mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-15 20:03:12 +00:00
chore: retire access token field in extension
This commit is contained in:
parent
966e1d9ce3
commit
080929faed
@ -8,26 +8,22 @@
|
||||
"build": "plasmo build",
|
||||
"package": "plasmo package",
|
||||
"lint": "eslint --ext .js,.ts,.tsx, src",
|
||||
"lint-fix": "eslint --ext .js,.ts,.tsx, src --fix",
|
||||
"postinstall": "cd ../../proto && buf generate"
|
||||
"lint-fix": "eslint --ext .js,.ts,.tsx, src --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.13.0",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@mui/joy": "5.0.0-beta.48",
|
||||
"@plasmohq/storage": "^1.11.0",
|
||||
"axios": "^1.7.4",
|
||||
"classnames": "^2.5.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-react": "^0.419.0",
|
||||
"plasmo": "^0.88.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"zustand": "^4.5.5"
|
||||
"react-hot-toast": "^2.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bufbuild/buf": "^1.37.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/chrome": "^0.0.268",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
@ -41,10 +37,8 @@
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-react": "^7.35.0",
|
||||
"long": "^5.2.3",
|
||||
"postcss": "^8.4.41",
|
||||
"prettier": "^3.3.3",
|
||||
"protobufjs": "^7.3.2",
|
||||
"tailwindcss": "^3.4.10",
|
||||
"typescript": "^5.5.4"
|
||||
},
|
||||
|
261
frontend/extension/pnpm-lock.yaml
generated
261
frontend/extension/pnpm-lock.yaml
generated
@ -20,9 +20,6 @@ importers:
|
||||
'@plasmohq/storage':
|
||||
specifier: ^1.11.0
|
||||
version: 1.11.0(react@18.3.1)
|
||||
axios:
|
||||
specifier: ^1.7.4
|
||||
version: 1.7.4
|
||||
classnames:
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1
|
||||
@ -44,13 +41,7 @@ importers:
|
||||
react-hot-toast:
|
||||
specifier: ^2.4.1
|
||||
version: 2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
zustand:
|
||||
specifier: ^4.5.5
|
||||
version: 4.5.5(@types/react@18.3.3)(react@18.3.1)
|
||||
devDependencies:
|
||||
'@bufbuild/buf':
|
||||
specifier: ^1.37.0
|
||||
version: 1.37.0
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0(@vue/compiler-sfc@3.3.4)(prettier@3.3.3)
|
||||
@ -90,18 +81,12 @@ importers:
|
||||
eslint-plugin-react:
|
||||
specifier: ^7.35.0
|
||||
version: 7.35.0(eslint@8.57.0)
|
||||
long:
|
||||
specifier: ^5.2.3
|
||||
version: 5.2.3
|
||||
postcss:
|
||||
specifier: ^8.4.41
|
||||
version: 8.4.41
|
||||
prettier:
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3
|
||||
protobufjs:
|
||||
specifier: ^7.3.2
|
||||
version: 7.3.2
|
||||
tailwindcss:
|
||||
specifier: ^3.4.10
|
||||
version: 3.4.10
|
||||
@ -222,47 +207,6 @@ packages:
|
||||
resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@bufbuild/buf-darwin-arm64@1.37.0':
|
||||
resolution: {integrity: sha512-YrT0HqLf7qJJ9VjXmnG900oGOjskerqfY4UTbpLb67b76uRxZm7pfSfqpM4bCaSru4j6GPBDwH9dkwiuNOenEA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@bufbuild/buf-darwin-x64@1.37.0':
|
||||
resolution: {integrity: sha512-c1iDr1LaYcdzAK7v4ZBTiYVRPltPa1UNFQ3JJ6BI/RUaBk/eYFsykuNtsJQb5lXh/usjMz76juzOxAdYikcw7w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@bufbuild/buf-linux-aarch64@1.37.0':
|
||||
resolution: {integrity: sha512-ENaCLU4XZxQFc6+pWjNGeKITlzY0jYeEmz6R2cEeR9kVl+HyNNcTMaKxdffG5HNU5Ci1dC3pSY/ZIF3ck8UHVw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@bufbuild/buf-linux-x64@1.37.0':
|
||||
resolution: {integrity: sha512-/buQuUaBVU4rYqdoS/xmbyohJFaE4uy7boHMabCnI2aLsVBNPHYa/k0JMc+ZDRqgq0Wnth9VbIHn6DSGHG+cmw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@bufbuild/buf-win32-arm64@1.37.0':
|
||||
resolution: {integrity: sha512-5Y1aaHge9iQP+YNyxUayMd+rSVbjNXLBXniJDQhim56B+6eufPiKzmTgAKjDE9hGTT+mcBdLznrCMI0fzDLHJw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@bufbuild/buf-win32-x64@1.37.0':
|
||||
resolution: {integrity: sha512-2BioEPdC6EM5zEKmTmM14ZJuuPjKuYIvoAwQ4hoCSJBllIhGvshk61NDYBorr1huEEq6baa4ITL/gWHJ86B0bw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@bufbuild/buf@1.37.0':
|
||||
resolution: {integrity: sha512-33Rp90nRa7ebTwAjI8Yc7f8WOQMOEfRM0mg/o1bkNvE6cGQhYiq82Ag27pcegvYIyXl413XCeLMAUegsqjuFqw==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
|
||||
'@emotion/babel-plugin@11.12.0':
|
||||
resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==}
|
||||
|
||||
@ -1353,36 +1297,6 @@ packages:
|
||||
'@popperjs/core@2.11.8':
|
||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||
|
||||
'@protobufjs/aspromise@1.1.2':
|
||||
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
||||
|
||||
'@protobufjs/base64@1.1.2':
|
||||
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
||||
|
||||
'@protobufjs/codegen@2.0.4':
|
||||
resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
|
||||
|
||||
'@protobufjs/eventemitter@1.1.0':
|
||||
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
||||
|
||||
'@protobufjs/fetch@1.1.0':
|
||||
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
||||
|
||||
'@protobufjs/float@1.0.2':
|
||||
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
||||
|
||||
'@protobufjs/inquire@1.1.0':
|
||||
resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
|
||||
|
||||
'@protobufjs/path@1.1.2':
|
||||
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
||||
|
||||
'@protobufjs/pool@1.1.0':
|
||||
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
||||
|
||||
'@protobufjs/utf8@1.1.0':
|
||||
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
|
||||
|
||||
'@sindresorhus/is@5.6.0':
|
||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||
engines: {node: '>=14.16'}
|
||||
@ -1851,9 +1765,6 @@ packages:
|
||||
resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
autoprefixer@10.4.20:
|
||||
resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@ -1865,9 +1776,6 @@ packages:
|
||||
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
axios@1.7.4:
|
||||
resolution: {integrity: sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==}
|
||||
|
||||
axobject-query@3.2.4:
|
||||
resolution: {integrity: sha512-aPTElBrbifBU1krmZxGZOlBkslORe7Ll7+BDnI50Wy4LgOt69luMgevkDfTq1O/ZgprooPCtWpjCwKSZw/iZ4A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2058,10 +1966,6 @@ packages:
|
||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||
engines: {node: '>=12.5.0'}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
commander@4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -2188,10 +2092,6 @@ packages:
|
||||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
@ -2472,15 +2372,6 @@ packages:
|
||||
flatted@3.3.1:
|
||||
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
|
||||
|
||||
follow-redirects@1.15.6:
|
||||
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
|
||||
for-each@0.3.3:
|
||||
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
||||
|
||||
@ -2492,10 +2383,6 @@ packages:
|
||||
resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==}
|
||||
engines: {node: '>= 14.17'}
|
||||
|
||||
form-data@4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
fraction.js@4.3.7:
|
||||
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
||||
|
||||
@ -3134,9 +3021,6 @@ packages:
|
||||
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
long@5.2.3:
|
||||
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
@ -3184,14 +3068,6 @@ packages:
|
||||
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime@1.6.0:
|
||||
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
|
||||
engines: {node: '>=4'}
|
||||
@ -3551,13 +3427,6 @@ packages:
|
||||
proto-list@1.2.4:
|
||||
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
|
||||
|
||||
protobufjs@7.3.2:
|
||||
resolution: {integrity: sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
|
||||
prr@1.0.1:
|
||||
resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
|
||||
|
||||
@ -4062,11 +3931,6 @@ packages:
|
||||
uri-js@4.4.1:
|
||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
|
||||
use-sync-external-store@1.2.2:
|
||||
resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
@ -4150,21 +4014,6 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
zustand@4.5.5:
|
||||
resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==}
|
||||
engines: {node: '>=12.7.0'}
|
||||
peerDependencies:
|
||||
'@types/react': '>=16.8'
|
||||
immer: '>=9.0.6'
|
||||
react: '>=16.8'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
immer:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
|
||||
snapshots:
|
||||
|
||||
'@alloc/quick-lru@5.2.0': {}
|
||||
@ -4333,33 +4182,6 @@ snapshots:
|
||||
'@babel/helper-validator-identifier': 7.24.7
|
||||
to-fast-properties: 2.0.0
|
||||
|
||||
'@bufbuild/buf-darwin-arm64@1.37.0':
|
||||
optional: true
|
||||
|
||||
'@bufbuild/buf-darwin-x64@1.37.0':
|
||||
optional: true
|
||||
|
||||
'@bufbuild/buf-linux-aarch64@1.37.0':
|
||||
optional: true
|
||||
|
||||
'@bufbuild/buf-linux-x64@1.37.0':
|
||||
optional: true
|
||||
|
||||
'@bufbuild/buf-win32-arm64@1.37.0':
|
||||
optional: true
|
||||
|
||||
'@bufbuild/buf-win32-x64@1.37.0':
|
||||
optional: true
|
||||
|
||||
'@bufbuild/buf@1.37.0':
|
||||
optionalDependencies:
|
||||
'@bufbuild/buf-darwin-arm64': 1.37.0
|
||||
'@bufbuild/buf-darwin-x64': 1.37.0
|
||||
'@bufbuild/buf-linux-aarch64': 1.37.0
|
||||
'@bufbuild/buf-linux-x64': 1.37.0
|
||||
'@bufbuild/buf-win32-arm64': 1.37.0
|
||||
'@bufbuild/buf-win32-x64': 1.37.0
|
||||
|
||||
'@emotion/babel-plugin@11.12.0':
|
||||
dependencies:
|
||||
'@babel/helper-module-imports': 7.24.7
|
||||
@ -5801,29 +5623,6 @@ snapshots:
|
||||
|
||||
'@popperjs/core@2.11.8': {}
|
||||
|
||||
'@protobufjs/aspromise@1.1.2': {}
|
||||
|
||||
'@protobufjs/base64@1.1.2': {}
|
||||
|
||||
'@protobufjs/codegen@2.0.4': {}
|
||||
|
||||
'@protobufjs/eventemitter@1.1.0': {}
|
||||
|
||||
'@protobufjs/fetch@1.1.0':
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
'@protobufjs/inquire': 1.1.0
|
||||
|
||||
'@protobufjs/float@1.0.2': {}
|
||||
|
||||
'@protobufjs/inquire@1.1.0': {}
|
||||
|
||||
'@protobufjs/path@1.1.2': {}
|
||||
|
||||
'@protobufjs/pool@1.1.0': {}
|
||||
|
||||
'@protobufjs/utf8@1.1.0': {}
|
||||
|
||||
'@sindresorhus/is@5.6.0': {}
|
||||
|
||||
'@svgr/babel-plugin-add-jsx-attribute@6.5.1(@babel/core@7.25.2)':
|
||||
@ -6319,8 +6118,6 @@ snapshots:
|
||||
is-array-buffer: 3.0.4
|
||||
is-shared-array-buffer: 1.0.3
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
autoprefixer@10.4.20(postcss@8.4.41):
|
||||
dependencies:
|
||||
browserslist: 4.23.3
|
||||
@ -6335,14 +6132,6 @@ snapshots:
|
||||
dependencies:
|
||||
possible-typed-array-names: 1.0.0
|
||||
|
||||
axios@1.7.4:
|
||||
dependencies:
|
||||
follow-redirects: 1.15.6
|
||||
form-data: 4.0.0
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
axobject-query@3.2.4: {}
|
||||
|
||||
b4a@1.6.6: {}
|
||||
@ -6547,10 +6336,6 @@ snapshots:
|
||||
color-convert: 2.0.1
|
||||
color-string: 1.9.1
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
commander@4.1.1: {}
|
||||
|
||||
commander@7.2.0: {}
|
||||
@ -6677,8 +6462,6 @@ snapshots:
|
||||
has-property-descriptors: 1.0.2
|
||||
object-keys: 1.1.1
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-libc@1.0.3: {}
|
||||
@ -7064,8 +6847,6 @@ snapshots:
|
||||
|
||||
flatted@3.3.1: {}
|
||||
|
||||
follow-redirects@1.15.6: {}
|
||||
|
||||
for-each@0.3.3:
|
||||
dependencies:
|
||||
is-callable: 1.2.7
|
||||
@ -7077,12 +6858,6 @@ snapshots:
|
||||
|
||||
form-data-encoder@2.1.4: {}
|
||||
|
||||
form-data@4.0.0:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
|
||||
fraction.js@4.3.7: {}
|
||||
|
||||
fs-constants@1.0.0: {}
|
||||
@ -7689,8 +7464,6 @@ snapshots:
|
||||
chalk: 4.1.2
|
||||
is-unicode-supported: 0.1.0
|
||||
|
||||
long@5.2.3: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
@ -7734,12 +7507,6 @@ snapshots:
|
||||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-types@2.1.35:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
|
||||
mime@1.6.0:
|
||||
optional: true
|
||||
|
||||
@ -8161,23 +7928,6 @@ snapshots:
|
||||
|
||||
proto-list@1.2.4: {}
|
||||
|
||||
protobufjs@7.3.2:
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
'@protobufjs/base64': 1.1.2
|
||||
'@protobufjs/codegen': 2.0.4
|
||||
'@protobufjs/eventemitter': 1.1.0
|
||||
'@protobufjs/fetch': 1.1.0
|
||||
'@protobufjs/float': 1.0.2
|
||||
'@protobufjs/inquire': 1.1.0
|
||||
'@protobufjs/path': 1.1.2
|
||||
'@protobufjs/pool': 1.1.0
|
||||
'@protobufjs/utf8': 1.1.0
|
||||
'@types/node': 20.15.0
|
||||
long: 5.2.3
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
||||
prr@1.0.1:
|
||||
optional: true
|
||||
|
||||
@ -8777,10 +8527,6 @@ snapshots:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
use-sync-external-store@1.2.2(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
utility-types@3.11.0: {}
|
||||
@ -8882,10 +8628,3 @@ snapshots:
|
||||
yaml@2.5.0: {}
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
zustand@4.5.5(@types/react@18.3.3)(react@18.3.1):
|
||||
dependencies:
|
||||
use-sync-external-store: 1.2.2(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.3
|
||||
react: 18.3.1
|
||||
|
@ -1,187 +0,0 @@
|
||||
import { Button, IconButton, Input, Modal, ModalDialog } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useStorageContext } from "@/context";
|
||||
import { useShortcutStore } from "@/stores";
|
||||
import type { Visibility } from "@/types/proto/api/v1/common";
|
||||
import { Shortcut } from "@/types/proto/api/v1/shortcut_service";
|
||||
import Icon from "./Icon";
|
||||
|
||||
interface State {
|
||||
name: string;
|
||||
title: string;
|
||||
link: string;
|
||||
}
|
||||
|
||||
const CreateShortcutButton = () => {
|
||||
const context = useStorageContext();
|
||||
const shortcutStore = useShortcutStore();
|
||||
const [state, setState] = useState<State>({
|
||||
name: "",
|
||||
title: "",
|
||||
link: "",
|
||||
});
|
||||
const [tag, setTag] = useState<string>("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (showModal) {
|
||||
document.body.style.height = "384px";
|
||||
} else {
|
||||
document.body.style.height = "auto";
|
||||
}
|
||||
}, [showModal]);
|
||||
|
||||
const handleCreateShortcutButtonClick = async () => {
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => {
|
||||
if (tabs.length === 0) {
|
||||
toast.error("No active tab found");
|
||||
return;
|
||||
}
|
||||
const tab = tabs[0];
|
||||
setState((state) => ({
|
||||
...state,
|
||||
name: "",
|
||||
title: tab.title || "",
|
||||
link: tab.url || "",
|
||||
}));
|
||||
setShowModal(true);
|
||||
});
|
||||
};
|
||||
|
||||
const generateRandomName = () => {
|
||||
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
let name = "";
|
||||
for (let i = 0; i < 8; i++) {
|
||||
name += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
setState((state) => ({
|
||||
...state,
|
||||
name,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleNameInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState((state) => ({
|
||||
...state,
|
||||
name: e.target.value,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleTitleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState((state) => ({
|
||||
...state,
|
||||
title: e.target.value,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleLinkInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState((state) => ({
|
||||
...state,
|
||||
link: e.target.value,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleTagsInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const text = e.target.value as string;
|
||||
setTag(text);
|
||||
};
|
||||
|
||||
const handleSaveBtnClick = async () => {
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
if (!state.name) {
|
||||
toast.error("Name is required");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const tags = tag.split(" ").filter(Boolean);
|
||||
await shortcutStore.createShortcut(
|
||||
context.instanceUrl,
|
||||
context.accessToken,
|
||||
Shortcut.fromPartial({
|
||||
name: state.name,
|
||||
title: state.title,
|
||||
link: state.link,
|
||||
tags,
|
||||
visibility: context.defaultVisibility as Visibility,
|
||||
}),
|
||||
);
|
||||
toast.success("Shortcut created successfully");
|
||||
setShowModal(false);
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
toast.error(error.response.data.message);
|
||||
}
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton color="primary" variant="solid" size="sm" onClick={() => handleCreateShortcutButtonClick()}>
|
||||
<Icon.Plus className="w-5 h-auto" />
|
||||
</IconButton>
|
||||
|
||||
<Modal container={() => document.body} open={showModal} onClose={() => setShowModal(false)}>
|
||||
<ModalDialog className="w-3/4">
|
||||
<div className="w-full flex flex-row justify-between items-center mb-2">
|
||||
<span className="text-base font-medium">Create Shortcut</span>
|
||||
<Button size="sm" variant="plain" onClick={() => setShowModal(false)}>
|
||||
<Icon.X className="w-5 h-auto text-gray-600" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="overflow-x-hidden w-full flex flex-col justify-start items-center">
|
||||
<div className="w-full flex flex-row justify-start items-center mb-2">
|
||||
<span className="block w-12 mr-2 shrink-0">Name</span>
|
||||
<Input
|
||||
className="grow"
|
||||
type="text"
|
||||
placeholder="Unique shortcut name"
|
||||
value={state.name}
|
||||
onChange={handleNameInputChange}
|
||||
endDecorator={
|
||||
<IconButton size="sm" onClick={generateRandomName}>
|
||||
<Icon.RefreshCcw className="w-4 h-auto cursor-pointer" />
|
||||
</IconButton>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full flex flex-row justify-start items-center mb-2">
|
||||
<span className="block w-12 mr-2 shrink-0">Title</span>
|
||||
<Input className="grow" type="text" placeholder="Shortcut title" value={state.title} onChange={handleTitleInputChange} />
|
||||
</div>
|
||||
<div className="w-full flex flex-row justify-start items-center mb-2">
|
||||
<span className="block w-12 mr-2 shrink-0">Link</span>
|
||||
<Input
|
||||
className="grow"
|
||||
type="text"
|
||||
placeholder="e.g., https://github.com/yourselfhosted/slash"
|
||||
value={state.link}
|
||||
onChange={handleLinkInputChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full flex flex-row justify-start items-center mb-2">
|
||||
<span className="block w-12 mr-2 shrink-0">Tags</span>
|
||||
<Input className="grow" type="text" placeholder="The tags of shortcut" value={tag} onChange={handleTagsInputChange} />
|
||||
</div>
|
||||
|
||||
<div className="w-full flex flex-row justify-end items-center mt-2 space-x-2">
|
||||
<Button color="neutral" variant="plain" onClick={() => setShowModal(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button color="primary" disabled={isLoading} loading={isLoading} onClick={handleSaveBtnClick}>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</ModalDialog>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateShortcutButton;
|
@ -1,36 +0,0 @@
|
||||
import { IconButton } from "@mui/joy";
|
||||
import { useEffect } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useStorageContext } from "@/context";
|
||||
import { useShortcutStore } from "@/stores";
|
||||
import Icon from "./Icon";
|
||||
|
||||
const PullShortcutsButton = () => {
|
||||
const context = useStorageContext();
|
||||
const shortcutStore = useShortcutStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (context.instanceUrl && context.accessToken) {
|
||||
handlePullShortcuts(true);
|
||||
}
|
||||
}, [context]);
|
||||
|
||||
const handlePullShortcuts = async (silence = false) => {
|
||||
try {
|
||||
await shortcutStore.fetchShortcutList(context.instanceUrl, context.accessToken);
|
||||
if (!silence) {
|
||||
toast.success("Shortcuts pulled");
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error("Failed to pull shortcuts, error: " + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<IconButton color="neutral" variant="plain" size="sm" onClick={() => handlePullShortcuts()}>
|
||||
<Icon.RefreshCcw className="w-4 h-auto" />
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default PullShortcutsButton;
|
@ -1,66 +0,0 @@
|
||||
import { useStorage } from "@plasmohq/storage/hook";
|
||||
import classNames from "classnames";
|
||||
import { getFaviconWithGoogleS2 } from "@/helpers/utils";
|
||||
import type { Shortcut } from "@/types/proto/api/v1/shortcut_service";
|
||||
import Icon from "./Icon";
|
||||
|
||||
interface Props {
|
||||
shortcut: Shortcut;
|
||||
}
|
||||
|
||||
const ShortcutView = (props: Props) => {
|
||||
const { shortcut } = props;
|
||||
const [domain] = useStorage<string>("instance_url", "");
|
||||
const favicon = getFaviconWithGoogleS2(shortcut.link);
|
||||
|
||||
const handleShortcutLinkClick = () => {
|
||||
const shortcutLink = `${domain}/s/${shortcut.name}`;
|
||||
chrome.tabs.create({ url: shortcutLink });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={classNames(
|
||||
"group w-auto px-3 py-2 flex flex-col justify-start items-start border rounded-lg hover:bg-gray-100 hover:shadow dark:border-zinc-800 dark:hover:bg-zinc-800",
|
||||
)}
|
||||
>
|
||||
<div className="w-full flex flex-row justify-start items-center">
|
||||
<span className={classNames("w-5 h-5 flex justify-center items-center overflow-clip shrink-0")}>
|
||||
{favicon ? (
|
||||
<img className="w-full h-auto rounded" src={favicon} decoding="async" loading="lazy" />
|
||||
) : (
|
||||
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
|
||||
)}
|
||||
</span>
|
||||
<div className="ml-1 w-[calc(100%-20px)] flex flex-col justify-start items-start">
|
||||
<div className="w-full flex flex-row justify-start items-center">
|
||||
<button
|
||||
className={classNames(
|
||||
"max-w-full flex flex-row px-1 mr-1 justify-start items-center cursor-pointer rounded-md hover:underline",
|
||||
)}
|
||||
onClick={handleShortcutLinkClick}
|
||||
>
|
||||
<div className="truncate">
|
||||
<span className="dark:text-gray-400">{shortcut.title}</span>
|
||||
{shortcut.title ? (
|
||||
<span className="text-gray-500">({shortcut.name})</span>
|
||||
) : (
|
||||
<>
|
||||
<span className="truncate dark:text-gray-400">{shortcut.name}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<span className="ml-1 cursor-pointer shrink-0 opacity-80">
|
||||
<Icon.ExternalLink className="w-4 h-auto text-gray-600" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShortcutView;
|
@ -1,26 +0,0 @@
|
||||
import classNames from "classnames";
|
||||
import { useShortcutStore } from "@/stores";
|
||||
import Icon from "./Icon";
|
||||
import ShortcutView from "./ShortcutView";
|
||||
|
||||
const ShortcutsContainer = () => {
|
||||
const shortcuts = useShortcutStore().getShortcutList();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="w-full flex flex-row justify-start items-center mb-4">
|
||||
<a className="bg-blue-100 dark:bg-blue-500 dark:opacity-70 py-2 px-3 rounded-full border dark:border-blue-600 flex flex-row justify-start items-center cursor-pointer shadow">
|
||||
<Icon.AlertCircle className="w-4 h-auto" />
|
||||
<span className="mx-1 text-sm">Please make sure you have signed in your instance.</span>
|
||||
</a>
|
||||
</div>
|
||||
<div className={classNames("w-full flex flex-row justify-start items-start flex-wrap gap-2")}>
|
||||
{shortcuts.map((shortcut) => {
|
||||
return <ShortcutView key={shortcut.id} shortcut={shortcut} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShortcutsContainer;
|
@ -1,22 +1,13 @@
|
||||
import { createContext, useContext } from "react";
|
||||
import { Visibility } from "@/types/proto/api/v1/common";
|
||||
|
||||
interface Context {
|
||||
instanceUrl?: string;
|
||||
accessToken?: string;
|
||||
defaultVisibility: string;
|
||||
setInstanceUrl: (instanceUrl: string) => void;
|
||||
setAccessToken: (accessToken: string) => void;
|
||||
setDefaultVisibility: (visibility: string) => void;
|
||||
}
|
||||
|
||||
export const StorageContext = createContext<Context>({
|
||||
instanceUrl: undefined,
|
||||
accessToken: undefined,
|
||||
defaultVisibility: Visibility.PRIVATE,
|
||||
setInstanceUrl: () => {},
|
||||
setAccessToken: () => {},
|
||||
setDefaultVisibility: () => {},
|
||||
});
|
||||
|
||||
const useStorageContext = () => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Storage } from "@plasmohq/storage";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Visibility } from "@/types/proto/api/v1/common";
|
||||
import { StorageContext } from "./context";
|
||||
|
||||
interface Props {
|
||||
@ -10,27 +9,13 @@ interface Props {
|
||||
const StorageContextProvider = ({ children }: Props) => {
|
||||
const storage = new Storage();
|
||||
const [instanceUrl, setInstanceUrl] = useState<string | undefined>(undefined);
|
||||
const [accessToken, setAccessToken] = useState<string | undefined>(undefined);
|
||||
const [defaultVisibility, setDefaultVisibility] = useState<Visibility>(Visibility.PRIVATE);
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
let instanceUrl = await storage.get("instance_url");
|
||||
const accessToken = await storage.get("access_token");
|
||||
const defaultVisibility = (await storage.get("default_visibility")) as Visibility;
|
||||
|
||||
// Migrate domain to instance_url.
|
||||
const domain = await storage.get("domain");
|
||||
if (domain) {
|
||||
instanceUrl = domain;
|
||||
await storage.remove("domain");
|
||||
await storage.set("instance_url", instanceUrl);
|
||||
}
|
||||
const instanceUrl = await storage.get("instance_url");
|
||||
|
||||
setInstanceUrl(instanceUrl);
|
||||
setAccessToken(accessToken);
|
||||
setDefaultVisibility(defaultVisibility);
|
||||
setIsInitialized(true);
|
||||
})();
|
||||
|
||||
@ -38,12 +23,6 @@ const StorageContextProvider = ({ children }: Props) => {
|
||||
instance_url: (c) => {
|
||||
setInstanceUrl(c.newValue);
|
||||
},
|
||||
access_token: (c) => {
|
||||
setAccessToken(c.newValue);
|
||||
},
|
||||
default_visibility: (c) => {
|
||||
setDefaultVisibility(c.newValue as Visibility);
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
|
||||
@ -51,11 +30,7 @@ const StorageContextProvider = ({ children }: Props) => {
|
||||
<StorageContext.Provider
|
||||
value={{
|
||||
instanceUrl,
|
||||
accessToken,
|
||||
defaultVisibility,
|
||||
setInstanceUrl: (instanceUrl: string) => storage.set("instance_url", instanceUrl),
|
||||
setAccessToken: (accessToken: string) => storage.set("access_token", accessToken),
|
||||
setDefaultVisibility: (visibility: Visibility) => storage.set("default_visibility", visibility),
|
||||
}}
|
||||
>
|
||||
{isInitialized && children}
|
||||
|
@ -1,8 +0,0 @@
|
||||
export const getFaviconWithGoogleS2 = (url: string) => {
|
||||
try {
|
||||
const urlObject = new URL(url);
|
||||
return `https://www.google.com/s2/favicons?sz=128&domain=${urlObject.hostname}`;
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
@ -1,43 +0,0 @@
|
||||
import { useColorScheme } from "@mui/joy";
|
||||
import { useEffect } from "react";
|
||||
|
||||
const useColorTheme = () => {
|
||||
const { mode: colorTheme, setMode: setColorTheme } = useColorScheme();
|
||||
|
||||
useEffect(() => {
|
||||
const root = document.documentElement;
|
||||
if (colorTheme === "light") {
|
||||
root.classList.remove("dark");
|
||||
} else if (colorTheme === "dark") {
|
||||
root.classList.add("dark");
|
||||
} else {
|
||||
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
if (darkMediaQuery.matches) {
|
||||
root.classList.add("dark");
|
||||
} else {
|
||||
root.classList.remove("dark");
|
||||
}
|
||||
|
||||
const handleColorSchemeChange = (e: MediaQueryListEvent) => {
|
||||
if (e.matches) {
|
||||
root.classList.add("dark");
|
||||
} else {
|
||||
root.classList.remove("dark");
|
||||
}
|
||||
};
|
||||
try {
|
||||
darkMediaQuery.addEventListener("change", handleColorSchemeChange);
|
||||
} catch (error) {
|
||||
console.error("failed to initial color scheme listener", error);
|
||||
}
|
||||
|
||||
return () => {
|
||||
darkMediaQuery.removeEventListener("change", handleColorSchemeChange);
|
||||
};
|
||||
}
|
||||
}, [colorTheme]);
|
||||
|
||||
return { colorTheme, setColorTheme };
|
||||
};
|
||||
|
||||
export default useColorTheme;
|
@ -1,51 +1,24 @@
|
||||
import { Button, CssVarsProvider, Divider, Input, Select, Option } from "@mui/joy";
|
||||
import { Button, CssVarsProvider, Input } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Toaster, toast } from "react-hot-toast";
|
||||
import { useShortcutStore } from "@/stores";
|
||||
import Icon from "./components/Icon";
|
||||
import Logo from "./components/Logo";
|
||||
import PullShortcutsButton from "./components/PullShortcutsButton";
|
||||
import ShortcutsContainer from "./components/ShortcutsContainer";
|
||||
import { StorageContextProvider, useStorageContext } from "./context";
|
||||
import useColorTheme from "./hooks/useColorTheme";
|
||||
import "./style.css";
|
||||
import { Visibility } from "./types/proto/api/v1/common";
|
||||
|
||||
interface SettingState {
|
||||
domain: string;
|
||||
accessToken: string;
|
||||
instanceUrl: string;
|
||||
}
|
||||
|
||||
const colorThemeOptions = [
|
||||
{
|
||||
value: "system",
|
||||
label: "System",
|
||||
},
|
||||
{
|
||||
value: "light",
|
||||
label: "Light",
|
||||
},
|
||||
{
|
||||
value: "dark",
|
||||
label: "Dark",
|
||||
},
|
||||
];
|
||||
|
||||
const IndexOptions = () => {
|
||||
const { colorTheme, setColorTheme } = useColorTheme();
|
||||
const context = useStorageContext();
|
||||
const [settingState, setSettingState] = useState<SettingState>({
|
||||
domain: context.instanceUrl || "",
|
||||
accessToken: context.accessToken || "",
|
||||
instanceUrl: context.instanceUrl || "",
|
||||
});
|
||||
const shortcutStore = useShortcutStore();
|
||||
const shortcuts = shortcutStore.getShortcutList();
|
||||
const isInitialized = context.instanceUrl && context.accessToken;
|
||||
|
||||
useEffect(() => {
|
||||
setSettingState({
|
||||
domain: context.instanceUrl || "",
|
||||
accessToken: context.accessToken || "",
|
||||
instanceUrl: context.instanceUrl || "",
|
||||
});
|
||||
}, [context]);
|
||||
|
||||
@ -57,19 +30,10 @@ const IndexOptions = () => {
|
||||
};
|
||||
|
||||
const handleSaveSetting = () => {
|
||||
context.setInstanceUrl(settingState.domain);
|
||||
context.setAccessToken(settingState.accessToken);
|
||||
context.setInstanceUrl(settingState.instanceUrl);
|
||||
toast.success("Setting saved");
|
||||
};
|
||||
|
||||
const handleSelectColorTheme = async (colorTheme: string) => {
|
||||
setColorTheme(colorTheme as any);
|
||||
};
|
||||
|
||||
const handleDefaultVisibilitySelect = (value: Visibility) => {
|
||||
context.setDefaultVisibility(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full px-4">
|
||||
<div className="w-full flex flex-row justify-center items-center">
|
||||
@ -112,21 +76,8 @@ const IndexOptions = () => {
|
||||
className="w-full"
|
||||
type="text"
|
||||
placeholder="The url of your Slash instance. e.g., https://slash.example.com"
|
||||
value={settingState.domain}
|
||||
onChange={(e) => setPartialSettingState({ domain: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full flex flex-col justify-start items-start">
|
||||
<span className="mb-2 text-base dark:text-gray-400">Access Token</span>
|
||||
<div className="relative w-full">
|
||||
<Input
|
||||
className="w-full"
|
||||
type="text"
|
||||
placeholder="An available access token of your account."
|
||||
value={settingState.accessToken}
|
||||
onChange={(e) => setPartialSettingState({ accessToken: e.target.value })}
|
||||
value={settingState.instanceUrl}
|
||||
onChange={(e) => setPartialSettingState({ instanceUrl: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -134,50 +85,7 @@ const IndexOptions = () => {
|
||||
<div className="w-full mt-6 flex flex-row justify-end">
|
||||
<Button onClick={handleSaveSetting}>Save</Button>
|
||||
</div>
|
||||
|
||||
<Divider className="!my-6" />
|
||||
|
||||
<p className="text-base font-semibold leading-6 mb-2 text-gray-900 dark:text-gray-500">Preference</p>
|
||||
|
||||
<div className="w-full flex flex-row justify-between items-center mb-2">
|
||||
<div className="flex flex-row justify-start items-center gap-x-1">
|
||||
<span className="dark:text-gray-400">Color Theme</span>
|
||||
</div>
|
||||
<Select defaultValue={colorTheme} onChange={(_, value) => handleSelectColorTheme(value)}>
|
||||
{colorThemeOptions.map((option) => {
|
||||
return (
|
||||
<Option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="w-full flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row justify-start items-center gap-x-1">
|
||||
<span className="dark:text-gray-400">Default Visibility</span>
|
||||
</div>
|
||||
<Select defaultValue={context.defaultVisibility} onChange={(_, value) => handleDefaultVisibilitySelect(value as Visibility)}>
|
||||
<Option value={Visibility.PRIVATE}>Private</Option>
|
||||
<Option value={Visibility.WORKSPACE}>Workspace</Option>
|
||||
<Option value={Visibility.PUBLIC}>Public</Option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isInitialized && (
|
||||
<>
|
||||
<Divider className="!my-6" />
|
||||
|
||||
<h2 className="flex flex-row justify-start items-center mb-4">
|
||||
<span className="text-lg dark:text-gray-400">Shortcuts</span>
|
||||
<span className="text-gray-500 mr-1">({shortcuts.length})</span>
|
||||
<PullShortcutsButton />
|
||||
</h2>
|
||||
<ShortcutsContainer />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,30 +1,13 @@
|
||||
import { Button, CssVarsProvider, Divider, IconButton } from "@mui/joy";
|
||||
import { useEffect } from "react";
|
||||
import { Button, CssVarsProvider, IconButton } from "@mui/joy";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import CreateShortcutButton from "@/components/CreateShortcutButton";
|
||||
import Icon from "@/components/Icon";
|
||||
import Logo from "@/components/Logo";
|
||||
import PullShortcutsButton from "@/components/PullShortcutsButton";
|
||||
import ShortcutsContainer from "@/components/ShortcutsContainer";
|
||||
import { useShortcutStore } from "@/stores";
|
||||
import { StorageContextProvider, useStorageContext } from "./context";
|
||||
import useColorTheme from "./hooks/useColorTheme";
|
||||
import "./style.css";
|
||||
|
||||
const IndexPopup = () => {
|
||||
useColorTheme();
|
||||
const context = useStorageContext();
|
||||
const shortcutStore = useShortcutStore();
|
||||
const shortcuts = shortcutStore.getShortcutList();
|
||||
const isInitialized = context.instanceUrl && context.accessToken;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
shortcutStore.fetchShortcutList(context.instanceUrl, context.accessToken);
|
||||
}, [isInitialized]);
|
||||
const isInitialized = context.instanceUrl;
|
||||
|
||||
const handleSettingButtonClick = () => {
|
||||
chrome.runtime.openOptionsPage();
|
||||
@ -41,31 +24,23 @@ const IndexPopup = () => {
|
||||
<div className="flex flex-row justify-start items-center dark:text-gray-400">
|
||||
<Logo className="w-6 h-auto mr-1" />
|
||||
<span className="">Slash</span>
|
||||
{isInitialized && (
|
||||
<>
|
||||
<span className="mx-1 text-gray-400">/</span>
|
||||
<span>Shortcuts</span>
|
||||
<span className="text-gray-500 mr-0.5">({shortcuts.length})</span>
|
||||
<PullShortcutsButton />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div>{isInitialized && <CreateShortcutButton />}</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full mt-4">
|
||||
{isInitialized ? (
|
||||
<>
|
||||
{shortcuts.length !== 0 ? (
|
||||
<ShortcutsContainer />
|
||||
) : (
|
||||
<div className="w-full flex flex-col justify-center items-center">
|
||||
<p>No shortcut found.</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Divider className="!mt-4 !mb-2 opacity-40" />
|
||||
|
||||
<p className="w-full mb-2">
|
||||
<span>Your instance URL is </span>
|
||||
<a
|
||||
className="inline-flex flex-row justify-start items-center underline text-blue-600 hover:opacity-80"
|
||||
href={context.instanceUrl}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="mr-1">{context.instanceUrl}</span>
|
||||
<Icon.ExternalLink className="w-4 h-auto" />
|
||||
</a>
|
||||
</p>
|
||||
<div className="w-full flex flex-row justify-between items-center mb-2">
|
||||
<div className="flex flex-row justify-start items-center">
|
||||
<IconButton size="sm" variant="plain" color="neutral" onClick={handleSettingButtonClick}>
|
||||
@ -82,22 +57,12 @@ const IndexPopup = () => {
|
||||
<Icon.Github className="w-5 h-auto text-gray-500 dark:text-gray-400" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className="flex flex-row justify-end items-center">
|
||||
<a
|
||||
className="text-sm flex flex-row justify-start items-center underline text-blue-600 hover:opacity-80"
|
||||
href={context.instanceUrl}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="mr-1">Go to my Slash</span>
|
||||
<Icon.ExternalLink className="w-4 h-auto" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="w-full flex flex-col justify-start items-center">
|
||||
<Icon.Cookie strokeWidth={1} className="w-20 h-auto mb-4 text-gray-400" />
|
||||
<p className="dark:text-gray-400">Please set your instance URL and access token first.</p>
|
||||
<p className="dark:text-gray-400">Please set your instance URL first.</p>
|
||||
<div className="w-full flex flex-row justify-center items-center py-4">
|
||||
<Button size="sm" color="primary" onClick={handleSettingButtonClick}>
|
||||
<Icon.Settings className="w-5 h-auto mr-1" /> Go to Setting
|
||||
|
@ -1,3 +0,0 @@
|
||||
import useShortcutStore from "./shortcut";
|
||||
|
||||
export { useShortcutStore };
|
@ -1,50 +0,0 @@
|
||||
import axios from "axios";
|
||||
import { create } from "zustand";
|
||||
import { combine } from "zustand/middleware";
|
||||
import { ListShortcutsResponse, Shortcut } from "@/types/proto/api/v1/shortcut_service";
|
||||
|
||||
interface State {
|
||||
shortcutMapById: Record<number, Shortcut>;
|
||||
}
|
||||
|
||||
const getDefaultState = (): State => {
|
||||
return {
|
||||
shortcutMapById: {},
|
||||
};
|
||||
};
|
||||
|
||||
const useShortcutStore = create(
|
||||
combine(getDefaultState(), (set, get) => ({
|
||||
fetchShortcutList: async (instanceUrl: string, accessToken: string) => {
|
||||
const {
|
||||
data: { shortcuts },
|
||||
} = await axios.get<ListShortcutsResponse>(`${instanceUrl}/api/v1/shortcuts`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
const shortcutMap = get().shortcutMapById;
|
||||
shortcuts.forEach((shortcut) => {
|
||||
shortcutMap[shortcut.id] = shortcut;
|
||||
});
|
||||
set({ shortcutMapById: shortcutMap });
|
||||
return shortcuts;
|
||||
},
|
||||
getShortcutList: () => {
|
||||
return Object.values(get().shortcutMapById);
|
||||
},
|
||||
createShortcut: async (instanceUrl: string, accessToken: string, create: Shortcut) => {
|
||||
const { data: shortcut } = await axios.post<Shortcut>(`${instanceUrl}/api/v1/shortcuts`, create, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
const shortcutMap = get().shortcutMapById;
|
||||
shortcutMap[shortcut.id] = shortcut;
|
||||
set({ shortcutMapById: shortcutMap });
|
||||
return shortcut;
|
||||
},
|
||||
})),
|
||||
);
|
||||
|
||||
export default useShortcutStore;
|
@ -30,18 +30,6 @@ plugins:
|
||||
- useExactTypes=false
|
||||
- esModuleInterop=true
|
||||
- stringEnums=true
|
||||
# Generate types for the extension client.
|
||||
- plugin: buf.build/community/stephenh-ts-proto
|
||||
out: ../frontend/extension/src/types/proto
|
||||
# reference: https://github.com/deeplay-io/nice-grpc/blob/master/packages/nice-grpc-web/README.md#using-ts-proto
|
||||
opt:
|
||||
- env=browser
|
||||
- useOptionals=messages
|
||||
- outputServices=generic-definitions
|
||||
- outputJsonMethods=false
|
||||
- useExactTypes=false
|
||||
- esModuleInterop=true
|
||||
- stringEnums=true
|
||||
- plugin: buf.build/community/pseudomuto-doc
|
||||
out: gen
|
||||
opt:
|
||||
|
@ -777,9 +777,7 @@ definitions:
|
||||
expiresAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: |-
|
||||
expires_at is the expiration time of the access token.
|
||||
If expires_at is not set, the access token will never expire.
|
||||
description: "expires_at is the expiration time of the access token.\r\nIf expires_at is not set, the access token will never expire."
|
||||
apiv1Collection:
|
||||
type: object
|
||||
properties:
|
||||
@ -1154,9 +1152,7 @@ definitions:
|
||||
description: The custom style.
|
||||
owner:
|
||||
type: string
|
||||
title: |-
|
||||
The owner name.
|
||||
Format: "users/{id}"
|
||||
title: "The owner name.\r\nFormat: \"users/{id}\""
|
||||
branding:
|
||||
type: string
|
||||
format: byte
|
||||
|
Loading…
x
Reference in New Issue
Block a user