/** * app.mjs — what the Android client does, as data. PLAN.md §10 `/app/`, phase 5. * * --------------------------------------------------------------------------------------- * WHY THIS IS NOT capabilities.mjs * --------------------------------------------------------------------------------------- * `capabilities.mjs` describes what a DEPLOYMENT does, and it is checked against * `module-uo`'s manifest because the module declares its capabilities in a machine-readable * file. The app declares nothing of the kind: what it does is a set of screens in * `Routes.kt`, and there is no manifest to diff against. So these are written from that * file and carry the route names, which is the closest thing to a citation available — a * reader who wants to check a claim here has a file to open. * * That is also why the app's list is shorter than the platform's rather than a mirror of * it. The app is a client for the parts of a deployment a person uses on a phone; the parts * it does not have are not missing, they are the parts nobody wants on a phone. * * --------------------------------------------------------------------------------------- * "GATED BY WHAT THE DEPLOYMENT PUBLISHES" IS LOAD-BEARING, NOT A DISCLAIMER * --------------------------------------------------------------------------------------- * Almost everything here is conditional on the site the app is pointed at: shard screens * appear only when the deployment runs a game module and has that visibility feature * turned on, staff screens only for a staff account, push only where the operator runs an * ntfy. A features list that omitted that would be describing an app nobody will see, * because there is no default deployment — see `requiresDeployment` below. */ /** * The single most misunderstood thing about this app, stated once and rendered prominently. * * `ConnectScreen.kt` on `Android-app` `main`: "First-run 'Connect to your shard's website' * screen. Nothing else in the app runs until a valid Runic Gateway site is entered and * validated." Not a soft default that can be changed later in settings — the gate on * everything else. An install with no deployment behind it is a text field, and a page that * let somebody find that out after downloading would have wasted their time on purpose. */ export const requiresDeployment = { title: 'It is a client. It ships pointed at nothing.', body: 'The first screen asks for the web address of a site running Runic Gateway and checks ' + 'it before anything else in the app will open. There is no default server, no ' + 'directory of servers, and no account with us — the app talks to the deployment you ' + 'name and to nothing else. If you do not run one and are not a member of a community ' + 'that does, the app has nothing to show you yet.', }; /** * @typedef {object} AppFeature * @property {string} title * @property {string} body * @property {string} [gate] What the deployment must provide for this to appear at all. */ /** @type {{ heading: string, blurb: string, items: AppFeature[] }[]} */ export const appFeatures = [ { heading: 'The shard, live', blurb: 'The same feed the website shows, on a phone. Every one of these appears only when ' + 'the deployment runs a game module and the operator has published that surface — ' + 'the visibility settings are per-feature and default to off.', items: [ { title: 'Status, and the boards', body: 'Whether the game server is up, plus champion spawns, guilds, city governors and ' + 'houses as the shard reports them.', gate: 'A game module, and the matching visibility feature', }, { title: 'The player marketplace', body: 'Player-run vendors and what is on their shelves, down to a single vendor. Item ' + "names arrive as the game's own string ids and are resolved against its string " + 'table, so they read the way they read in the client.', gate: 'A game module publishing the market', }, { title: 'Rules, leaderboards and the spawn atlas', body: "The deployment's published ruleset, its points and loyalty boards, and the " + 'creature atlas — what spawns where, and what it drops.', gate: 'A game module, per feature', }, ], }, { heading: "The site's content", blurb: 'News, wiki and pages, read natively rather than in a browser frame.', items: [ { title: 'News, by category', body: "Announcements and posts in the categories the site defines, and a link from " + 'anywhere on the web opens the matching tab rather than the top of the list.', }, { title: 'The wiki and the site pages', body: 'Wiki articles and whatever pages the operator has written in the admin panel, ' + 'including the ones they added to the navigation themselves.', }, ], }, { heading: 'Your account', blurb: 'Staff are players too — the self-service screens are role-agnostic, and an ' + 'administrator sees their own characters on the same screen everybody else does.', items: [ { title: 'Signing in, including two-factor', body: 'A native sign-in with an authenticator code or a single-use recovery code, or ' + "single sign-on handed off to the deployment's own provider in a browser tab. " + 'Trusting a device skips the code for thirty days, and that trust is revocable ' + 'per device from the app.', }, { title: 'Your characters, vendors and houses', body: 'Character sheets, the vendors you run and the houses you own, visible to the ' + 'account they belong to and to nobody else.', gate: 'A game module', }, ], }, { heading: 'Notifications, on infrastructure the operator owns', blurb: 'Opt-in, per stream, and delivered without a third party — which is unusual enough ' + 'to be worth spelling out.', items: [ { title: 'Self-hosted push', body: "Push arrives over the deployment's own ntfy server, not Firebase. The app has " + 'no Google messaging dependency at all, which is why it works on a device with ' + 'no Play Services and why no notification passes through anyone else on its way ' + 'to the phone.', gate: 'An ntfy server the operator runs', }, { title: 'The message carries no content', body: 'What is pushed is which stream fired and an opaque reference — never the ' + 'subject, the sender or the text. The app opens the right screen and fetches the ' + 'actual content over the authenticated API, so a notification sitting on a lock ' + 'screen discloses nothing.', }, ], }, { heading: 'Staff work, if you are staff', blurb: 'Gated by role in the menu and re-checked against the database on every request, so ' + 'a demoted account loses the screens immediately rather than at next sign-in.', items: [ { title: 'Moderation, support and content', body: 'The dashboard, the moderation queue, support requests and content editing — ' + 'enough to answer a report from a phone. The surfaces that would let somebody ' + 'reconfigure the deployment stay on the web.', gate: 'A staff role on the deployment', }, ], }, { heading: 'It looks like the deployment it is pointed at', blurb: '', items: [ { title: 'The theme comes down the wire', body: "The palette, the type, the corner radii, the logo, the hero image and even the " + "navigation order are read from the site's own appearance settings. Two " + 'communities running this app do not see the same app, and neither of them had ' + 'to build one.', }, ], }, ];