A => .gitignore +132 -0
@@ 1,132 @@
+# https://github.com/github/gitignore/blob/d0b80a469983a7beece8fa1f5c48a8242318b531/Node.gitignore
+
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+.cache
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
A => .prettierrc.json +3 -0
@@ 1,3 @@
+{
+ "singleQuote": true
+}<
\ No newline at end of file
A => dom-chef-shim.js +2 -0
@@ 1,2 @@
+import { h } from 'dom-chef';
+export { h };<
\ No newline at end of file
A => package.json +20 -0
@@ 1,20 @@
+{
+ "name": "protondb-indicator",
+ "version": "0.1.0",
+ "main": "dist/index.jsx",
+ "author": "Avery <avery@avery.cafe> (https://avery.cafe)",
+ "license": "GPL-3.0",
+ "scripts": {
+ "format": "prettier src --write",
+ "build": "esbuild src/index.tsx --bundle --format=esm --jsx-factory=h --jsx-fragment=DocumentFragment --inject:./dom-chef-shim.js --outfile=dist/index.js"
+ },
+ "dependencies": {
+ "dom-chef": "^5.1.0"
+ },
+ "devDependencies": {
+ "esbuild": "^0.14.30",
+ "prettier": "^2.6.2",
+ "prettier-plugin-organize-imports": "^2.3.4",
+ "typescript": "^4.6.3"
+ }
+}
A => plugin.toml +17 -0
@@ 1,17 @@
+name = "ProtonDB Indicator"
+link = "https://git.sr.ht/~avery/protondb-plugin"
+source = "https://git.sr.ht/~avery/protondb-plugin"
+
+[author]
+name = "Avery"
+link = "https://avery.cafe"
+
+[entrypoints]
+
+ [entrypoints.desktop]
+ library = true
+ menu = false
+
+ [entrypoints.deck]
+ library = true
+ menu = false<
\ No newline at end of file
A => src/index.tsx +101 -0
@@ 1,101 @@
+// TODO: Import SMM types package
+type SMM = any;
+
+// TODO: these are from main code
+const deleteAll = (selector: string) =>
+ document.querySelectorAll(selector).forEach((node) => node.remove());
+
+class NetworkGetError extends Error {
+ readonly status: number;
+ constructor(status: number) {
+ super(`Get returned error status code: ${status}`);
+ this.status = status;
+ }
+}
+
+const SHARED_SELECTORS = {
+ appDetails: '[class*=appdetails_Container]',
+ appDetailsHeader: '[class^="sharedappdetailsheader_TopCapsule"]',
+ appDetailsName: 'span[class^=appdetailsplaysection_PlayBarGameName]',
+};
+// ==============================
+
+enum TierColours {
+ pending = '#6a6a6a',
+ borked = '#ff0000',
+ bronze = '#cd7f32',
+ silver = '#a6a6a6',
+ gold = '#cfb53b',
+ platinum = '#b4c7dc',
+}
+
+type TierRes = { tier: keyof typeof TierColours };
+
+const getTierUrl = (appId: string) =>
+ `https://www.protondb.com/api/v1/reports/summaries/${appId}.json`;
+
+export const load = (smm: SMM) => {
+ const protonDbCache: Record<string, any> = {};
+
+ smm.addEventListener('switchToAppDetails', async (event: any) => {
+ deleteAll('[data-smm-protondb]');
+
+ const { appId, appName } = event.detail;
+ let data: TierRes = protonDbCache[appId];
+ if (!data) {
+ try {
+ // data = await smm.Network.get<TierRes>(getTierUrl(appId));
+ data = await smm.Network.get(getTierUrl(appId));
+ protonDbCache[appId] = data;
+ } catch (err) {
+ if (err instanceof NetworkGetError) {
+ smm.Toast.addToast(`Error fetching ProtonDB rating for ${appName}`);
+ console.info(`Error fetching ProtonDB rating for app ${appId}:`, err.status);
+ return;
+ }
+ }
+ }
+ const { tier } = data;
+
+ const indicator = (
+ <a
+ href={`https://www.protondb.com/app/${appId}`}
+ style={{
+ position: 'absolute',
+ top: 24,
+ left: 24,
+ display: 'flex',
+ alignItems: 'center',
+ padding: '4px 8px',
+ backgroundColor: TierColours[tier],
+ color: 'rgba(0, 0, 0, 50%)',
+ fontSize: 20,
+ textDecoration: 'none',
+ borderRadius: 4,
+ }}
+ data-smm-protondb={true}
+ >
+ <img
+ // TODO: cache this image manually, or check license and include it with plugin
+ // (it will be cached by the browser anyways, but it would still be nice to reduce traffic)
+ src="https://www.protondb.com/sites/protondb/images/site-logo.svg"
+ style={{
+ width: 20,
+ marginRight: 4,
+ }}
+ />
+ <span>{tier.charAt(0).toUpperCase() + tier.slice(1)}</span>
+ </a>
+ );
+
+ document
+ .querySelector(SHARED_SELECTORS.appDetailsHeader)!
+ .appendChild(indicator as unknown as HTMLElement);
+ });
+};
+
+export const unload = () => {
+ document
+ .querySelectorAll('[data-smm-protondb]')
+ .forEach((node) => node.remove());
+};<
\ No newline at end of file
A => tsconfig.json +13 -0
@@ 1,13 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "strict": true,
+ "noEmit": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "jsx": "preserve"
+ },
+ "include": ["src/**/*"]
+}<
\ No newline at end of file
A => yarn.lock +181 -0
@@ 1,181 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@types/prop-types@*":
+ version "15.7.5"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+ integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/react@^17.0.42":
+ version "17.0.44"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.44.tgz#c3714bd34dd551ab20b8015d9d0dbec812a51ec7"
+ integrity sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
+csstype@^3.0.2:
+ version "3.0.11"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
+ integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
+
+dom-chef@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/dom-chef/-/dom-chef-5.1.0.tgz#96cf01475dc30362f1549e1c05ce26aeeb319e24"
+ integrity sha512-zV1cLrO8sl7X5dWTLp6SQM/DzadfXQEgVf+sfXZqGUd709ezeEfpI8n/IgW2O8kt1sfIgZA+Us0lbKSkP4foqQ==
+ dependencies:
+ "@types/react" "^17.0.42"
+ svg-tag-names "^3.0.1"
+
+esbuild-android-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.30.tgz#9efcdb3d826b9c67705a0c518d361ab44ae4cc5b"
+ integrity sha512-vdJ7t8A8msPfKpYUGUV/KaTQRiZ0vDa2XSTlzXVkGGVHLKPeb85PBUtYJcEgw3htW3IdX5i1t1IMdQCwJJgNAg==
+
+esbuild-android-arm64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.30.tgz#7b90fa7578b94da047e0bf3da477cb5775b58664"
+ integrity sha512-BdgGfxeA5hBQNErLr7BWJUA8xjflEfyaARICy8e0OJYNSAwDbEzOf8LyiKWSrDcgV129mWhi3VpbNQvOIDEHcg==
+
+esbuild-darwin-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.30.tgz#275e40eb100286b868d4cd664e6447b53400f7ff"
+ integrity sha512-VRaOXMMrsG5n53pl4qFZQdXy2+E0NoLP/QH3aDUI0+bQP+ZHDmbINKcDy2IX7GVFI9kqPS18iJNAs5a6/G2LZg==
+
+esbuild-darwin-arm64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.30.tgz#c2b8fe03fb0dcee1d227b226c9c921de71e4d411"
+ integrity sha512-qDez+fHMOrO9Oc9qjt/x+sy09RJVh62kik5tVybKRLmezeV4qczM9/sAYY57YN0aWLdHbcCj2YqJUWYJNsgKnw==
+
+esbuild-freebsd-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.30.tgz#328bb272ce6cfcae202b6e0a06c240036335cc91"
+ integrity sha512-mec1jENcImVVagddZlGWsdAUwBnzR5cgnhzCxv+9fSMxKbx1uZYLLUAnLPp8m/i934zrumR1xGjJ5VoWdPlI2w==
+
+esbuild-freebsd-arm64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.30.tgz#49ce79fa7d7087a941e27432da46bafb5b35a979"
+ integrity sha512-cpjbTs6Iok/AfeB0JgTzyUJTMStC1SQULmany5nHx6S4GTkSgaAHuJzZO0GcVWqghI4e0YL/bjXAhN5Mn6feNw==
+
+esbuild-linux-32@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.30.tgz#c473299f5291130f6d4436808603b529ccbfa785"
+ integrity sha512-liIONVT4F2kZmOMwtwASqZ8WkIjb5HHBR9HUffdHiuotSTF3CyZO+EJf+Og+SYYuuVIvt0qHNSFjBA/iSESteQ==
+
+esbuild-linux-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.30.tgz"
+ integrity sha512-LUnpzoMpRqFON5En4qEj6NWiyH6a1K+Y2qYNKrCy5qPTjDoG/EWeqMz69n8Uv7pRuvDKl3FNGJ1dufTrA5i0sw==
+
+esbuild-linux-arm64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.30.tgz#78485a9f49858ea69ced85c3dd0fe58d354f20f8"
+ integrity sha512-DHZHn6FK5q/KL0fpNT/0jE38Nnyk2rXxKE9WENi95EXtqfOLPgE8tzjTZQNgpr61R95QX4ymQU26ni3IZk8buQ==
+
+esbuild-linux-arm@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.30.tgz#00392bbe04ac687dd6d9849ecee302bc27f984f2"
+ integrity sha512-97T+bbXnpqf7mfIG49UR7ZSJFGgvc22byn74qw3Kx2GDCBSQoVFjyWuKOHGXp8nXk3XYrdFF+mQ8yQ7aNsgQvg==
+
+esbuild-linux-mips64le@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.30.tgz#cf48a292037c3a9ca3ca84ec0ae4f47bf1247ab4"
+ integrity sha512-fLUzTFZ7uknC0aPTk7/lM7NmaG/9ZqE3SaHEphcaM009SZK/mDOvZugWi1ss6WGNhk13dUrhkfHcc4FSb9hYhg==
+
+esbuild-linux-ppc64le@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.30.tgz#8e448a54e7040829ee9ecfc68dab0f3a039b1cff"
+ integrity sha512-2Oudm2WEfj0dNU9bzIl5L/LrsMEmHWsOsYgJJqu8fDyUDgER+J1d33qz3cUdjsJk7gAENayIxDSpsuCszx0w3A==
+
+esbuild-linux-riscv64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.30.tgz#118af007f21adb00c4362d5eda3f004290f4d0ef"
+ integrity sha512-RPMucPW47rV4t2jlelaE948iCRtbZf5RhifxSwzlpM1Mqdyu99MMNK0w4jFreGTmLN+oGomxIOxD6n+2E/XqHw==
+
+esbuild-linux-s390x@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.30.tgz#e0649e26d8791bf6265685842dcef732de59b49b"
+ integrity sha512-OZ68r7ok6qO7hdwrwQn2p5jbIRRcUcVaAykB7e0uCA0ODwfeGunILM6phJtq2Oz4dlEEFvd+tSuma3paQKwt+A==
+
+esbuild-netbsd-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.30.tgz#7653db21ab4379a1b557f338b040e3493ff5006c"
+ integrity sha512-iyejQUKn0TzpPkufq8pSCxOg9NheycQbMbPCmjefTe9wYuUlBt1TcHvdoJnYbQzsAhAh1BNq+s0ycRsIJFZzaQ==
+
+esbuild-openbsd-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.30.tgz#3fad1699cb2ca7a060585356e2881df7b3fa5bb1"
+ integrity sha512-UyK1MTMcy4j5fH260fsE1o6MVgWNhb62eCK2yCKCRazZv8Nqdc2WiP9ygjWidmEdCDS+A6MuVp9ozk9uoQtQpA==
+
+esbuild-sunos-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.30.tgz#2306a178dc2362cf32fc182327c21b49b78ca1a3"
+ integrity sha512-aQRtRTNKHB4YuG+xXATe5AoRTNY48IJg5vjE8ElxfmjO9+KdX7MHFkTLhlKevCD6rNANtB3qOlSIeAiXTwHNqw==
+
+esbuild-windows-32@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.30.tgz#ea17b2a9468e346734f926a7edd49de3cc81d12f"
+ integrity sha512-9/fb1tPtpacMqxAXp3fGHowUDg/l9dVch5hKmCLEZC6PdGljh6h372zMdJwYfH0Bd5CCPT0Wx95uycBLJiqpXA==
+
+esbuild-windows-64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.30.tgz#266147f1f45974ac61dece10ab32bc916050dcc2"
+ integrity sha512-DHgITeUhPAnN9I5O6QBa1GVyPOhiYCn4S4TtQr7sO4+X0LNyqnlmA1M0qmGkUdDC1QQfjI8uQ4G/whdWb2pWIQ==
+
+esbuild-windows-arm64@0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.30.tgz#8e5e9c2455bffaf3e1a387eee4841f5c3797b8a8"
+ integrity sha512-F1kLyQH7zSgjh5eLxogGZN7C9+KNs9m+s7Q6WZoMmCWT/6j998zlaoECHyM8izJRRfsvw2eZlEa1jO6/IOU1AQ==
+
+esbuild@^0.14.30:
+ version "0.14.30"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.30.tgz#8bf6501a58f71e622e7485aeada79c764c1affe4"
+ integrity sha512-wCecQSBkIjp2xjuXY+wcXS/PpOQo9rFh4NAKPh4Pm9f3fuLcnxkR0rDzA+mYP88FtXIUcXUyYmaIgfrzRl55jA==
+ optionalDependencies:
+ esbuild-android-64 "0.14.30"
+ esbuild-android-arm64 "0.14.30"
+ esbuild-darwin-64 "0.14.30"
+ esbuild-darwin-arm64 "0.14.30"
+ esbuild-freebsd-64 "0.14.30"
+ esbuild-freebsd-arm64 "0.14.30"
+ esbuild-linux-32 "0.14.30"
+ esbuild-linux-64 "0.14.30"
+ esbuild-linux-arm "0.14.30"
+ esbuild-linux-arm64 "0.14.30"
+ esbuild-linux-mips64le "0.14.30"
+ esbuild-linux-ppc64le "0.14.30"
+ esbuild-linux-riscv64 "0.14.30"
+ esbuild-linux-s390x "0.14.30"
+ esbuild-netbsd-64 "0.14.30"
+ esbuild-openbsd-64 "0.14.30"
+ esbuild-sunos-64 "0.14.30"
+ esbuild-windows-32 "0.14.30"
+ esbuild-windows-64 "0.14.30"
+ esbuild-windows-arm64 "0.14.30"
+
+prettier-plugin-organize-imports@^2.3.4:
+ version "2.3.4"
+ resolved "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-2.3.4.tgz"
+ integrity sha512-R8o23sf5iVL/U71h9SFUdhdOEPsi3nm42FD/oDYIZ2PQa4TNWWuWecxln6jlIQzpZTDMUeO1NicJP6lLn2TtRw==
+
+prettier@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz"
+ integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==
+
+svg-tag-names@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/svg-tag-names/-/svg-tag-names-3.0.1.tgz#9a89117c1644104cb798e75f9c3cf18fa8d52231"
+ integrity sha512-R5EDS44RQSOwwKIOOUZLKZggMeFL8fDSSZr1hVK5Z0KkyuGVOZfyepBZDkPu/aoL+hSOysxxvAk8uN4yN2LOMQ==
+
+typescript@^4.6.3:
+ version "4.6.3"
+ resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz"
+ integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==