aboutsummaryrefslogtreecommitdiff
path: root/loading/session.ts
blob: 788f0e65ec5f782c66255c20d2fabd96c6acead6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import { getPerson } from '@hollowdark/persistence/people'
import { getCurrentWorld } from '@hollowdark/persistence/worlds'

/**
 * The three states the Begin screen can render.
 *
 *   `first-ever`            no world exists on device yet. Only option is
 *                           to begin (create the first world + character).
 *   `returning-active`      a world exists with a currently-active player
 *                           character. Primary option is to continue them.
 *   `returning-no-active`   a world exists but the current character has
 *                           died (or been ended) without a successor yet.
 *                           Primary option is to pick a successor via the
 *                           continuation flow.
 */
export type BeginState =
  | { readonly kind: 'first-ever' }
  | { readonly kind: 'returning-active'; readonly characterName: string }
  | { readonly kind: 'returning-no-active' }

/**
 * Inspect device-local state and decide which Begin variant to show. Reads
 * the single world record (design invariant) and, when a current player
 * character is set, reads their name for the continue prompt.
 */
export async function detectBeginState(): Promise<BeginState> {
  const world = await getCurrentWorld()
  if (world === null) return { kind: 'first-ever' }

  const activeId = world.currentPlayerCharacterId
  if (activeId === null) return { kind: 'returning-no-active' }

  const active = await getPerson(activeId)
  if (active === null) return { kind: 'returning-no-active' }

  return { kind: 'returning-active', characterName: displayName(active.name) }
}

function displayName(name: { given: string; preferredName: string | null }): string {
  return name.preferredName ?? name.given
}