diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 2eb3e77..2897842 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -72,10 +72,25 @@ bootloader: notes: Carrier models, like Verizon's, can't be unlocked. ``` -Add `aliases` for model numbers and other names people search for. `type` is `tablet` or `handheld`, and left out for phones. `hardware` lists the bits that some features need, so a phone without NFC shows NFC as n/a. `bootloader.unlock` is `yes`, `no`, `conditional` (add `notes` saying when) or `unknown`. +Add `aliases` for model numbers and other names people search for. `type` is `tablet` or `handheld`, and left out for phones. `hardware` lists the bits that some features need, so a phone without NFC shows NFC as n/a. `bootloader.unlock` is `yes`, `no`, `conditional` (add `notes` saying when) or `unknown`, and `bootloader.source` links where you read it. The import only ever fills gaps in a device file, so your edits stay put. If the brand's new, add it to `data/brands.yml` too. +A brand can carry its own `bootloader` block, for the policy that applies across its phones: + +```yaml +- key: google + name: Google + bootloader: + notes: Pixel and Nexus phones from 2015 on unlock with fastboot, unless they were sold carrier locked. + source: https://source.android.com/docs/setup/build/running +``` + +It shows on the brand page and under Bootloader on every device page, and it never changes what a +device's own `unlock` says. Both fields are needed together, and only add one where the policy +really does hold brand-wide - most brands split it by chipset, region or Android version, so they +stay unknown. + --- ## Adding support for a ROM diff --git a/data/brands.yml b/data/brands.yml index 3ddbcee..dd095be 100644 --- a/data/brands.yml +++ b/data/brands.yml @@ -15,12 +15,18 @@ name: Essential - key: fairphone name: Fairphone + bootloader: + notes: Fairphone publishes an unlock procedure for its phones, the Fairphone 2 aside. + source: https://support.fairphone.com/hc/en-us/articles/10492476238865-How-to-unlock-or-lock-your-Fairphone-s-bootloader - key: fxtec name: F(x)tec - key: gigaset name: Gigaset - key: google name: Google + bootloader: + notes: Pixel and Nexus phones from 2015 on unlock with fastboot, unless they were sold carrier locked. + source: https://source.android.com/docs/setup/build/running - key: htc name: HTC - key: huawei diff --git a/schema/brands.json b/schema/brands.json index 1adf1a5..e5ceca1 100644 --- a/schema/brands.json +++ b/schema/brands.json @@ -10,7 +10,16 @@ "properties": { "key": { "$ref": "#/$defs/key" }, "name": { "type": "string", "minLength": 1 }, - "website": { "$ref": "#/$defs/link" } + "website": { "$ref": "#/$defs/link" }, + "bootloader": { + "type": "object", + "required": ["notes", "source"], + "additionalProperties": false, + "properties": { + "notes": { "type": "string", "minLength": 1 }, + "source": { "$ref": "#/$defs/link" } + } + } } }, "$defs": { @@ -19,6 +28,6 @@ "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "description": "lowercase letters, numbers and hyphens" }, - "link": { "type": "string", "format": "uri", "pattern": "^https?://" } + "link": { "type": "string", "format": "link", "pattern": "^https?://" } } } diff --git a/schema/device.json b/schema/device.json index bb41d30..4451e5e 100644 --- a/schema/device.json +++ b/schema/device.json @@ -36,7 +36,8 @@ "additionalProperties": false, "properties": { "unlock": { "enum": ["yes", "no", "conditional", "unknown"] }, - "notes": { "type": "string", "minLength": 1 } + "notes": { "type": "string", "minLength": 1 }, + "source": { "$ref": "#/$defs/link" } }, "if": { "properties": { "unlock": { "const": "conditional" } } @@ -54,6 +55,7 @@ "type": "string", "pattern": "^[a-z0-9]+([_-][a-z0-9]+)*$", "description": "lowercase letters, numbers, hyphens and underscores" - } + }, + "link": { "type": "string", "format": "link", "pattern": "^https?://" } } } diff --git a/schema/rom.json b/schema/rom.json index 12e2768..07681cc 100644 --- a/schema/rom.json +++ b/schema/rom.json @@ -219,7 +219,7 @@ "$defs": { "link": { "type": "string", - "format": "uri", + "format": "link", "pattern": "^https?://" }, "key": { diff --git a/schema/upstream.json b/schema/upstream.json index 83faf51..8781d28 100644 --- a/schema/upstream.json +++ b/schema/upstream.json @@ -75,6 +75,6 @@ } ] }, - "link": { "type": "string", "format": "uri", "pattern": "^https?://" } + "link": { "type": "string", "format": "link", "pattern": "^https?://" } } } diff --git a/src/lib/data/check.js b/src/lib/data/check.js index 393bb44..f2e3e68 100644 --- a/src/lib/data/check.js +++ b/src/lib/data/check.js @@ -8,6 +8,8 @@ import { NEEDS_NOTE, allowedValues, cellValue } from './status.js'; const SCHEMAS = ['brands', 'features', 'rom', 'device', 'upstream', 'stock', 'support']; const ajv = addFormats(new Ajv({ allErrors: true, verbose: true })); +// the pages read a hostname off these, and ajv's uri format is looser than URL is +ajv.addFormat('link', (value) => URL.canParse(value)); for (const name of SCHEMAS) { ajv.addSchema( JSON.parse(readFileSync(new URL(`../../../schema/${name}.json`, import.meta.url), 'utf8')), diff --git a/src/pages/devices/[brand]/[slug].astro b/src/pages/devices/[brand]/[slug].astro index a49f23a..3b39331 100644 --- a/src/pages/devices/[brand]/[slug].astro +++ b/src/pages/devices/[brand]/[slug].astro @@ -26,6 +26,7 @@ export const getStaticPaths = () => const { device } = Astro.props; const { features } = getModel(); const { bootloader, stock, support } = device; +const policy = device.brand.bootloader; const [current, ended] = splitByActive(support); const unreported = featuresFrom(features, support, 'none'); const quiet = new Set( @@ -139,6 +140,15 @@ const codename = device.codenames[0];
{bootloader.notes}
} + {bootloader.source && ( +Going by {new URL(bootloader.source).hostname}.
+ )} + {policy && ( ++ {device.brand.name}'s policy: {policy.notes} Going by{' '} + {new URL(policy.source).hostname}. +
+ )}+ {brand.bootloader.notes} Going by{' '} + {new URL(brand.bootloader.source).hostname}. +
+ )}