diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 438a59f..4589745 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -27,7 +27,7 @@ The files in `upstream/` get rewritten by a bot every Monday, so any change you ## Reporting what works -The [form](https://github.com/NotAFlightRisk/android-rom-compat/issues/new?template=report-feature.yml) is the easy way. Pick a device and ROM, set whatever you've tried, and a bot opens a pull request for you with your name on the commit. If something's missing or doesn't add up, it comments on the issue saying what - just edit the issue and it'll try again. The "Report" link on each ROM row of a device page puts the device, its codename and the ROM in the title, so you can copy them across. +The [form](https://github.com/NotAFlightRisk/android-rom-compat/issues/new?template=report-feature.yml) is the easy way. Pick a device and ROM, set whatever you've tried, and a bot opens a pull request for you with your name on the commit. If something's missing or doesn't add up, it comments on the issue saying what - just edit the issue and it'll try again. The "Report what works" button on each ROM on a device page fills in the device, the ROM and its Android version for you. Rather do it by hand? Add a `features` section to `data/support//.yml`, making the file if it's not there yet. Anything you leave out shows as unknown, which is fine. @@ -40,7 +40,7 @@ features: widevine: L3 ``` -`android` and `build` are what you tested on, `checked` is the date, and `variant` is for a ROM's other builds (like LineageOS for microG). A report shows as stale once the ROM moves to a newer Android than yours, or `checked` is over a year old. +`android` and `build` are what you tested on, `checked` is the date, and `variant` is for a ROM's other builds (like LineageOS for microG). Once the ROM moves to a newer Android than yours, or `checked` is over a year old, the site says when it was last checked. The keys come from [`features.yml`](../data/features.yml). Most features use these: @@ -109,7 +109,7 @@ source: https://example.com/devices/tegu install: https://example.com/devices/tegu/install ``` -`status` is `active`, or `discontinued` once the ROM stops building for it. `status` and `source` are the only must-haves. +`status` is `active`, or `discontinued` once the ROM stops building for it. `status` and `source` are the only must-haves. `maintainer` can also be `{ name: someone, link: https://github.com/someone }`, to link to them. A new ROM lives at `data/roms/.yml`. Keep that name, and any variant key, to lowercase letters and numbers - imports are named `-.yml`, so a hyphen in either splits in the wrong place. diff --git a/.github/README.md b/.github/README.md index ea73334..ccf0343 100644 --- a/.github/README.md +++ b/.github/README.md @@ -16,7 +16,7 @@ Covers GrapheneOS, LineageOS, CalyxOS, /e/OS, crDroid, iodéOS, Evolution X and PixelOS, official builds only. Every bit of data lives as YAML in [`data/`](../data), so fixing a mistake just means editing a file - no coding needed. -It'd rather leave a gap than guess, so anything nobody has checked shows as unknown. A report goes stale once the ROM moves to a newer Android than it was checked on, or when it's over a year old. +It'd rather leave a gap than guess, so anything nobody has checked is left out, and shows as unknown in the table view. A report goes stale once the ROM moves to a newer Android than it was checked on, or when it's over a year old. --- diff --git a/package-lock.json b/package-lock.json index d10c144..9099aeb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@astrojs/sitemap": "^3.7.4", "@fontsource-variable/roboto": "^5.3.0", "@fontsource-variable/roboto-mono": "^5.3.0", + "@lucide/astro": "^1.52.0", "@sentry/browser": "^11.4.0", "astro": "^7.3.5" }, @@ -1832,6 +1833,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lucide/astro": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@lucide/astro/-/astro-1.52.0.tgz", + "integrity": "sha512-Vyo3sHYPtLvP5fbvqrMSMutcRzu8tbZXG6xFylrDnpeGVjLisokqKrWKuEm6K4IKwxkTrKK/xyXkVBE0WjxZKg==", + "license": "ISC", + "peerDependencies": { + "astro": "^4 || ^5 || ^6 || ^7" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz", diff --git a/package.json b/package.json index 30042ed..0240746 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@astrojs/sitemap": "^3.7.4", "@fontsource-variable/roboto": "^5.3.0", "@fontsource-variable/roboto-mono": "^5.3.0", + "@lucide/astro": "^1.52.0", "@sentry/browser": "^11.4.0", "astro": "^7.3.5" }, diff --git a/public/icons/broken.svg b/public/icons/broken.svg index d0860b4..b50c2d2 100644 --- a/public/icons/broken.svg +++ b/public/icons/broken.svg @@ -1 +1 @@ - + diff --git a/public/icons/ended.svg b/public/icons/ended.svg index a3a7ac1..9b99fae 100644 --- a/public/icons/ended.svg +++ b/public/icons/ended.svg @@ -1 +1 @@ - + diff --git a/public/icons/na.svg b/public/icons/na.svg index cca95cc..66042ad 100644 --- a/public/icons/na.svg +++ b/public/icons/na.svg @@ -1 +1 @@ - + diff --git a/public/icons/note.svg b/public/icons/note.svg index 457533c..a1bdf99 100644 --- a/public/icons/note.svg +++ b/public/icons/note.svg @@ -1 +1 @@ - + diff --git a/public/icons/partial.svg b/public/icons/partial.svg index 0d18c89..bf115b7 100644 --- a/public/icons/partial.svg +++ b/public/icons/partial.svg @@ -1 +1 @@ - + diff --git a/public/icons/sort-down.svg b/public/icons/sort-down.svg index 46c0ed7..2da218a 100644 --- a/public/icons/sort-down.svg +++ b/public/icons/sort-down.svg @@ -1 +1 @@ - + diff --git a/public/icons/sort-up.svg b/public/icons/sort-up.svg index 5133e98..8df68b2 100644 --- a/public/icons/sort-up.svg +++ b/public/icons/sort-up.svg @@ -1 +1 @@ - + diff --git a/public/icons/sort.svg b/public/icons/sort.svg index 6f0a0b1..3229b07 100644 --- a/public/icons/sort.svg +++ b/public/icons/sort.svg @@ -1 +1 @@ - + diff --git a/public/icons/stale.svg b/public/icons/stale.svg index 08bc4db..0090270 100644 --- a/public/icons/stale.svg +++ b/public/icons/stale.svg @@ -1 +1 @@ - + diff --git a/public/icons/unknown.svg b/public/icons/unknown.svg index 6174fa5..2ded53b 100644 --- a/public/icons/unknown.svg +++ b/public/icons/unknown.svg @@ -1 +1 @@ - + diff --git a/public/icons/working.svg b/public/icons/working.svg index 238bb33..49b86c4 100644 --- a/public/icons/working.svg +++ b/public/icons/working.svg @@ -1 +1 @@ - + diff --git a/schema/upstream.json b/schema/upstream.json index 8781d28..1055ece 100644 --- a/schema/upstream.json +++ b/schema/upstream.json @@ -21,7 +21,20 @@ "status": { "enum": ["active", "discontinued"] }, "channel": { "enum": ["stable", "community", "beta"] }, "android": { "type": "number", "minimum": 1, "maximum": 99 }, - "maintainer": { "type": "string", "minLength": 1 }, + "maintainer": { + "anyOf": [ + { "type": "string", "minLength": 1 }, + { + "type": "object", + "required": ["name", "link"], + "additionalProperties": false, + "properties": { + "name": { "type": "string", "minLength": 1 }, + "link": { "$ref": "#/$defs/link" } + } + } + ] + }, "relock": { "anyOf": [ { "enum": ["yes", "no", "unknown"] }, diff --git a/scripts/import/sources/evolutionx.js b/scripts/import/sources/evolutionx.js index 564228d..2ec309d 100644 --- a/scripts/import/sources/evolutionx.js +++ b/scripts/import/sources/evolutionx.js @@ -24,6 +24,11 @@ export const typeOfName = (name) => (/\b(pad|tab|tablet)\b/i.test(name) ? 'table export const dateOf = (seconds) => isoDate(seconds * 1000); +const maintainerOf = ({ maintainer, github }) => + /^[a-z\d-]+$/i.test(github ?? '') + ? { name: maintainer, link: `https://github.com/${github}` } + : maintainer; + /** Brand, device and row from one builds/.json, or undefined when it has no builds */ export function parse(json, { codename, branch }) { const build = json.response?.[0]; @@ -34,7 +39,7 @@ export function parse(json, { codename, branch }) { const row = { status: build.currently_maintained ? 'active' : 'discontinued', android: androidOf[branch], - ...(build.maintainer && { maintainer: build.maintainer }), + ...(build.maintainer && { maintainer: maintainerOf(build) }), ...(build.timestamp > 0 && { latest: { ...(build.version && { version: String(build.version) }), diff --git a/src/assets/logos/README.md b/src/assets/logos/README.md new file mode 100644 index 0000000..7d6e9f9 --- /dev/null +++ b/src/assets/logos/README.md @@ -0,0 +1,38 @@ +# Logos + +Single-colour marks used to identify each brand and ROM. The site paints them as a CSS mask, so they always show in the current text colour. + +Brand and ROM names and logos are trademarks of their respective owners and are used here only to identify them. No endorsement is implied. + +| File | Source | Licence / terms | +| --- | --- | --- | +| `brands/asus.svg` | https://unpkg.com/simple-icons@16.34.0/icons/asus.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/fairphone.svg` | https://unpkg.com/simple-icons@16.34.0/icons/fairphone.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/google.svg` | https://unpkg.com/simple-icons@16.34.0/icons/google.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/htc.svg` | https://unpkg.com/simple-icons@16.34.0/icons/htc.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/huawei.svg` | https://unpkg.com/simple-icons@16.34.0/icons/huawei.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/lenovo.svg` | https://unpkg.com/simple-icons@16.34.0/icons/lenovo.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/lg.svg` | https://unpkg.com/simple-icons@16.34.0/icons/lg.svg | Simple Icons 16.34.0, CC0-1.0 (face symbol only, "LG" letters removed) | +| `brands/meizu.svg` | https://unpkg.com/simple-icons@16.34.0/icons/meizu.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/motorola.svg` | https://unpkg.com/simple-icons@16.34.0/icons/motorola.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/nokia.svg` | https://unpkg.com/simple-icons@16.34.0/icons/nokia.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/nvidia.svg` | https://unpkg.com/simple-icons@16.34.0/icons/nvidia.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/oneplus.svg` | https://unpkg.com/simple-icons@16.34.0/icons/oneplus.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/oppo.svg` | https://unpkg.com/simple-icons@16.34.0/icons/oppo.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/razer.svg` | https://unpkg.com/simple-icons@16.34.0/icons/razer.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/samsung.svg` | https://unpkg.com/simple-icons@16.34.0/icons/samsung.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/solana.svg` | https://unpkg.com/simple-icons@16.34.0/icons/solana.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/sony.svg` | https://unpkg.com/simple-icons@16.34.0/icons/sony.svg | Simple Icons 16.34.0, CC0-1.0 | +| `brands/xiaomi.svg` | https://unpkg.com/simple-icons@16.34.0/icons/xiaomi.svg | Simple Icons 16.34.0, CC0-1.0 | +| `roms/lineageos.svg` | https://unpkg.com/simple-icons@16.34.0/icons/lineageos.svg | Simple Icons 16.34.0, CC0-1.0 | +| `roms/grapheneos.svg` | https://unpkg.com/simple-icons@16.34.0/icons/grapheneos.svg | Simple Icons 16.34.0, CC0-1.0 | +| `roms/eos.svg` | https://unpkg.com/simple-icons@16.34.0/icons/e.svg | Simple Icons 16.34.0, CC0-1.0 | +| `roms/calyxos.svg` | https://gitlab.com/CalyxOS/branding/-/raw/main/calyxos/icon/Icon-CalyxOS.light.svg | Registered trademark of the Calyx Institute (background square removed) | +| `roms/crdroid.svg` | https://raw.githubusercontent.com/crdroidandroid/android_packages_apps_crDroidSettings/17.0/res/drawable/ic_crdroid_logo.xml | Trademark of the crDroid Android Project; file header Apache-2.0 | +| `roms/iodeos.svg` | https://gitlab.com/iode/os/public_archive/blocker/iode/-/raw/main/android/app/src/main/res/drawable/ic_iode_foreground.xml | Trademark of iodé Technologies; file header AGPL-3.0-or-later | +| `roms/evolutionx.svg` | https://raw.githubusercontent.com/Evolution-X/wiki/main/public/icon.svg | Trademark of Evolution X | +| `roms/pixelos.svg` | https://pixelos.net/images/logo.svg | Trademark of PixelOS | + +Simple Icons releases its icon data under CC0-1.0, but its disclaimer notes that the logos themselves remain trademarks of their owners: https://github.com/simple-icons/simple-icons/blob/develop/DISCLAIMER.md + +To add a logo, drop a single-colour SVG named after the brand or ROM key into `brands/` or `roms/`; anything without one shows its initials. diff --git a/src/assets/logos/brands/asus.svg b/src/assets/logos/brands/asus.svg new file mode 100644 index 0000000..fece3c0 --- /dev/null +++ b/src/assets/logos/brands/asus.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/fairphone.svg b/src/assets/logos/brands/fairphone.svg new file mode 100644 index 0000000..8738949 --- /dev/null +++ b/src/assets/logos/brands/fairphone.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/google.svg b/src/assets/logos/brands/google.svg new file mode 100644 index 0000000..70d0318 --- /dev/null +++ b/src/assets/logos/brands/google.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/htc.svg b/src/assets/logos/brands/htc.svg new file mode 100644 index 0000000..70d11b3 --- /dev/null +++ b/src/assets/logos/brands/htc.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/huawei.svg b/src/assets/logos/brands/huawei.svg new file mode 100644 index 0000000..72e9610 --- /dev/null +++ b/src/assets/logos/brands/huawei.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/lenovo.svg b/src/assets/logos/brands/lenovo.svg new file mode 100644 index 0000000..53f569f --- /dev/null +++ b/src/assets/logos/brands/lenovo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/lg.svg b/src/assets/logos/brands/lg.svg new file mode 100644 index 0000000..f032f8a --- /dev/null +++ b/src/assets/logos/brands/lg.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/meizu.svg b/src/assets/logos/brands/meizu.svg new file mode 100644 index 0000000..e9b287b --- /dev/null +++ b/src/assets/logos/brands/meizu.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/motorola.svg b/src/assets/logos/brands/motorola.svg new file mode 100644 index 0000000..fd59645 --- /dev/null +++ b/src/assets/logos/brands/motorola.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/nokia.svg b/src/assets/logos/brands/nokia.svg new file mode 100644 index 0000000..9279606 --- /dev/null +++ b/src/assets/logos/brands/nokia.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/nvidia.svg b/src/assets/logos/brands/nvidia.svg new file mode 100644 index 0000000..a9c8fc4 --- /dev/null +++ b/src/assets/logos/brands/nvidia.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/oneplus.svg b/src/assets/logos/brands/oneplus.svg new file mode 100644 index 0000000..4f75925 --- /dev/null +++ b/src/assets/logos/brands/oneplus.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/oppo.svg b/src/assets/logos/brands/oppo.svg new file mode 100644 index 0000000..7744171 --- /dev/null +++ b/src/assets/logos/brands/oppo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/razer.svg b/src/assets/logos/brands/razer.svg new file mode 100644 index 0000000..bf97c1e --- /dev/null +++ b/src/assets/logos/brands/razer.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/samsung.svg b/src/assets/logos/brands/samsung.svg new file mode 100644 index 0000000..6f6e1ae --- /dev/null +++ b/src/assets/logos/brands/samsung.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/solana.svg b/src/assets/logos/brands/solana.svg new file mode 100644 index 0000000..9b8119f --- /dev/null +++ b/src/assets/logos/brands/solana.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/sony.svg b/src/assets/logos/brands/sony.svg new file mode 100644 index 0000000..cec8b2c --- /dev/null +++ b/src/assets/logos/brands/sony.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/brands/xiaomi.svg b/src/assets/logos/brands/xiaomi.svg new file mode 100644 index 0000000..fb4cd3d --- /dev/null +++ b/src/assets/logos/brands/xiaomi.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/calyxos.svg b/src/assets/logos/roms/calyxos.svg new file mode 100644 index 0000000..b88831b --- /dev/null +++ b/src/assets/logos/roms/calyxos.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/crdroid.svg b/src/assets/logos/roms/crdroid.svg new file mode 100644 index 0000000..061b7e3 --- /dev/null +++ b/src/assets/logos/roms/crdroid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/eos.svg b/src/assets/logos/roms/eos.svg new file mode 100644 index 0000000..c36a8f3 --- /dev/null +++ b/src/assets/logos/roms/eos.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/evolutionx.svg b/src/assets/logos/roms/evolutionx.svg new file mode 100644 index 0000000..cef38ed --- /dev/null +++ b/src/assets/logos/roms/evolutionx.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/grapheneos.svg b/src/assets/logos/roms/grapheneos.svg new file mode 100644 index 0000000..3201907 --- /dev/null +++ b/src/assets/logos/roms/grapheneos.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/iodeos.svg b/src/assets/logos/roms/iodeos.svg new file mode 100644 index 0000000..012aa67 --- /dev/null +++ b/src/assets/logos/roms/iodeos.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/lineageos.svg b/src/assets/logos/roms/lineageos.svg new file mode 100644 index 0000000..1984577 --- /dev/null +++ b/src/assets/logos/roms/lineageos.svg @@ -0,0 +1 @@ + diff --git a/src/assets/logos/roms/pixelos.svg b/src/assets/logos/roms/pixelos.svg new file mode 100644 index 0000000..2d49b22 --- /dev/null +++ b/src/assets/logos/roms/pixelos.svg @@ -0,0 +1 @@ + diff --git a/src/components/cards/CardGrid.astro b/src/components/cards/CardGrid.astro new file mode 100644 index 0000000..92fd8dc --- /dev/null +++ b/src/components/cards/CardGrid.astro @@ -0,0 +1,149 @@ +--- +// Device cards in optional brand groups, from plain items built in src/lib/cards.js +import Logo from '../ui/Logo.astro'; + +const { id, groups, level = 2 } = Astro.props; +const Heading = `h${level}`; +--- + +
+ {groups.map(({ brand, items }) => ( +
+ {brand && ( + + + {brand.name} + + )} +
    + {items.map((item) => ( +
  • + + {brand && item.prefix && {item.prefix} } + {item.title} + + {item.code} + {item.meta &&

    {item.meta}

    } + {item.status && ( + + {item.status.text} + + )} + {item.chips.length > 0 && ( +
      + {item.chips.map((chip) => ( +
    • + {chip.note ? `${chip.text}, ${chip.note}` : chip.text} +
    • + ))} +
    + )} + {item.empty && ( + + {item.empty} + + )} +
  • + ))} +
+
+ ))} +
+ + diff --git a/src/components/cards/FeatureList.astro b/src/components/cards/FeatureList.astro new file mode 100644 index 0000000..535ffd0 --- /dev/null +++ b/src/components/cards/FeatureList.astro @@ -0,0 +1,70 @@ +--- +// What works, one line each, from relockFact() and knownFeatures() in src/lib/facts.js +import Icon from '../ui/Icon.astro'; + +const { items } = Astro.props; +--- + +
    + {items.map((item) => ( +
  • + {item.name} + {item.text} + {(item.note || item.stale || item.source) && ( +

    + {item.stale && {item.stale}.} {item.note} + {item.source && ( + + + + )} +

    + )} +
  • + ))} +
+ + diff --git a/src/components/cards/RomCard.astro b/src/components/cards/RomCard.astro new file mode 100644 index 0000000..5d7bce1 --- /dev/null +++ b/src/components/cards/RomCard.astro @@ -0,0 +1,198 @@ +--- +// One ROM on one device: its build, what works, and what installing it takes +import FeatureList from './FeatureList.astro'; +import Icon from '../ui/Icon.astro'; +import Logo from '../ui/Logo.astro'; +import { + buildFact, + channelText, + firmwareNeed, + googleApps, + knownFeatures, + maintainerOf, + relockFact, +} from '../../lib/facts.js'; +import { formatDate } from '../../lib/dates.js'; +import { reportUrl } from '../../lib/table.js'; + +const { row, features } = Astro.props; +const { rom, device } = row; +const build = buildFact(row.latest); +const channel = channelText(row); +const checks = [relockFact(row), ...knownFeatures(features, row.cells)].filter(Boolean); +const firmware = firmwareNeed(row); +const maintainer = maintainerOf(row); +const builds = row.variants.filter((variant) => variant.status === 'active'); +const id = `rom-${rom.key}`; +--- + +
+
+ +
+

+ {rom.name} +

+

{googleApps(rom)}

+
+ {row.android && Android {row.android}} +
+ + {(build || channel) && ( +
+
    + {build && ( +
  • + Built +
  • + )} + {build?.old && ( +
  • + {build.old} +
  • + )} + {build?.patch &&
  • {build.patch} security patch
  • } + {channel &&
  • {channel}
  • } +
+
+ )} + + {checks.length > 0 && } + + +
+ + diff --git a/src/components/cards/RomSummary.astro b/src/components/cards/RomSummary.astro new file mode 100644 index 0000000..bd52d57 --- /dev/null +++ b/src/components/cards/RomSummary.astro @@ -0,0 +1,74 @@ +--- +// A ROM in brief: what it is, its take on Google apps and security, and how many devices it runs on +import Logo from '../ui/Logo.astro'; +import { googleApps, romRelock } from '../../lib/facts.js'; +import { labelOf } from '../../lib/labels.js'; +import { plural } from '../../lib/text.js'; + +const { rom, level = 3 } = Astro.props; +const Heading = `h${level}`; +const relock = romRelock(rom); +const badges = [ + googleApps(rom), + relock !== 'No' && (relock === 'Yes' ? 'Relockable bootloader' : 'Relocks on some devices'), + ...rom.focus.map(labelOf), +].filter(Boolean); +--- + +
+
+ + + + {rom.name} + + + {plural(rom.activeCount, 'device')} +
+

{rom.description}

+
    + {badges.map((badge) => ( +
  • {badge}
  • + ))} +
+
+ + diff --git a/src/components/layout/Base.astro b/src/components/layout/Base.astro index b2a6955..545a176 100644 --- a/src/components/layout/Base.astro +++ b/src/components/layout/Base.astro @@ -1,7 +1,9 @@ --- import '@fontsource-variable/roboto'; import '@fontsource-variable/roboto-mono'; -import '../../styles/global.css'; +import '../../styles/tokens.css'; +import '../../styles/base.css'; +import '../../styles/ui.css'; import roboto from '@fontsource-variable/roboto/files/roboto-latin-wght-normal.woff2?url'; import Header from './Header.astro'; import Footer from './Footer.astro'; @@ -70,13 +72,9 @@ const sentry = import.meta.env.PUBLIC_SENTRY_DSN; - + {graph.length > 0 && ( + + diff --git a/src/components/ui/Icon.astro b/src/components/ui/Icon.astro index 7f7fcaa..3dc090a 100644 --- a/src/components/ui/Icon.astro +++ b/src/components/ui/Icon.astro @@ -1,25 +1,46 @@ --- -const { name, label } = Astro.props; -const paths = { - search: 'M10.5 17a6.5 6.5 0 1 0 0-13 6.5 6.5 0 0 0 0 13zM15.5 15.5L20 20', - columns: 'M4 5h16v14H4zM9.5 5v14M14.5 5v14', - external: 'M14 5h5v5M19 5l-8 8M17 14v5H5V7h5', - edit: 'M4 20h4L19 9l-4-4L4 16v4zM13.5 6.5l4 4', +// The Lucide icons the site uses, by name. Each renders as inline SVG at build time, text-sized +import ArrowUpRight from '@lucide/astro/icons/arrow-up-right'; +import BookOpen from '@lucide/astro/icons/book-open'; +import CodeXml from '@lucide/astro/icons/code-xml'; +import Columns3 from '@lucide/astro/icons/columns-3'; +import Flag from '@lucide/astro/icons/flag'; +import Globe from '@lucide/astro/icons/globe'; +import Info from '@lucide/astro/icons/info'; +import Layers from '@lucide/astro/icons/layers'; +import LayoutGrid from '@lucide/astro/icons/layout-grid'; +import MessagesSquare from '@lucide/astro/icons/messages-square'; +import Pencil from '@lucide/astro/icons/pencil'; +import Search from '@lucide/astro/icons/search'; +import Table2 from '@lucide/astro/icons/table-2'; +import UserRound from '@lucide/astro/icons/user-round'; + +const icons = { + cards: LayoutGrid, + columns: Columns3, + community: MessagesSquare, + docs: BookOpen, + edit: Pencil, + external: ArrowUpRight, + install: BookOpen, + maintainer: UserRound, + needs: Info, + report: Flag, + search: Search, + source: CodeXml, + table: Table2, + variant: Layers, + website: Globe, }; + +const { name, label } = Astro.props; +const Glyph = icons[name]; +if (!Glyph) throw new Error(`There's no icon called "${name}" in Icon.astro`); --- - - - +/> diff --git a/src/components/ui/Logo.astro b/src/components/ui/Logo.astro new file mode 100644 index 0000000..ce63bd0 --- /dev/null +++ b/src/components/ui/Logo.astro @@ -0,0 +1,76 @@ +--- +// A brand or ROM mark on a plate, or its initials when src/assets/logos/ has no file for it +const marks = import.meta.glob('../../assets/logos/*/*.svg', { + query: '?raw', + import: 'default', + eager: true, +}); +const urls = import.meta.glob('../../assets/logos/*/*.svg', { + query: '?url', + import: 'default', + eager: true, +}); + +const { kind, item, size = 'md' } = Astro.props; +const file = `../../assets/logos/${kind}/${item.key}.svg`; +const [, , width, height] = + marks[file] + ?.match(/viewBox="([^"]+)"/)[1] + .split(' ') + .map(Number) ?? []; +const initials = item.name.length <= 3 ? item.name : item.name.match(/[a-z0-9]/i)[0].toUpperCase(); +--- + +