#!/bin/sh
# The Mac App Store screenshots, as recipes rather than as prose.
#
# `screenshot.sh` beside this is the driver and knows nothing about Filebase: it
# sizes the window, fronts it, drives the actions given, parks the pointer off
# the frame, captures, and refuses a result of the wrong size. `take-shots.sh`
# is the part between, and both of those are generated by `ship sync`. This file
# is the other half, the part that is Filebase's — which folder, which shot, and
# what has to happen in the window before the shutter.
#
# It is one file on purpose. Everything a person would change to retake a set
# lives at the top, and running it by hand is the same command CI runs:
#
#     ./packaging/demo-corpus.sh
#     ./packaging/macos/shots.sh --app dist/Filebase.app
#
# WHAT THE SET HAS TO SHOW, AND WHY
#
# Apple rejected segler's first four under guideline 2.3.3 — *the Mac
# screenshots do not show the actual app in use in the majority of the
# screenshots* — because nothing was selected in any of them, so its element
# pane read "select an element" in all four. A frame of an editor with nothing
# selected is a frame of a viewer.
#
# The same trap here wears different clothes: **a frame of Filebase with no
# query run is a frame of an empty window.** The first thing this application
# draws is a folder bar, an empty table and *Choose a folder, then run a query*.
# So every shot below has a query answered and a row selected, and two of them
# show something a viewer could not do — the notices under the count, and a
# container's whole description beside the table.
#
# THE COORDINATES
#
# Every one is measured from the frame's top-left corner at the size declared
# below. Change the size and they all move; that is why the size is a constant
# beside them rather than an argument with a default.
#
# **They are read off a reference frame, never guessed.** Dispatch
# `apple-silicon.yml` with `screenshots: reference`, which takes one plain frame
# and uploads it, and measure against that. odox learned this the expensive way
# and its `shots.ps1` still carries no actions for want of one.
#
# Author: David M. Anderson
# Built with AI assistance (Claude, Anthropic)

set -eu

here=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
root=$(CDPATH= cd -- "${here}/../.." && pwd)

# --- the configuration ------------------------------------------------------

# App Store Connect takes 1440x900 for macOS. Every coordinate below was read
# off a frame of this size.
WIDTH=1440
HEIGHT=900

# Filebase is handed what it opens as an argument and declares no document
# type, so the driver passes it rather than asking Launch Services to route it.
# This is what that flag is for, and it is why this file needs no staging step.
AS_ARGS=yes

# The folder to open. Built by `packaging/demo-corpus.sh`, which is committed so
# that the frames are of a corpus anyone can reproduce rather than of whatever
# happened to be on one machine, and which writes here by default. A fixed path
# rather than an argument, because `take-shots.sh` is generated and refuses an
# argument it does not know — the same way `DOCUMENT` is a fixed path in the
# applications that photograph a document.
CORPUS="${root}/dist/corpus"

# Where the shots land. Not committed: dist is where every built artefact goes.
OUTDIR="${root}/dist/screenshots"

# --- the shots --------------------------------------------------------------

# One shot to a line: name, then the actions that put the window into the state
# being photographed, in the order they are given.
#
#   --click X,Y    press a control
#   --double X,Y   press it twice inside the double-click interval
#   --type TEXT    type
#   --key NAME     one key, optionally with modifiers: cmd+a, return
#
# **Measured off a reference frame**, taken by dispatching `apple-silicon.yml`
# with `screenshots: reference` at exactly the size declared above. Retake and
# re-measure when the window changes, rather than adjusting a number until a
# shot looks right. That first frame is also what caught the detail pane
# rendering at 96 pixels where 360 was asked for.
RECURSIVE='113,43'     # the tick box in the folder bar
QUERY_BOX='400,77'     # anywhere inside the query box
FIRST_ROW='115,135'    # 2025/invoice-1183.pdf.slpc, the first row the scan finds
RICHEST_ROW='115,219'  # master-services-agreement.pdf.slpc, the fullest description

# The two queries the frames are of. Row order is the scan's and was read off a
# real run rather than assumed: invoice, field-notes, q3-report, renewal,
# master-services-agreement. field-notes is the one with no governance.owner,
# so its empty cell sits in the middle of every frame below.
QUERY='select @path, title, status, governance.owner'
QUERY_NOTICES='select @path, title, pages where pages > 10'
shots() {
    # The answer to a question, with a row selected: five rows where the tick
    # box was the only thing touched, a column per metadata key, and the
    # container on the right. This frame has to carry the listing, so it is
    # first. A frame of Filebase with no query run is a frame of an empty
    # window, which is this application's version of the trap Apple rejected
    # segler's first set for.
    shot 01-a-folder-answering \
        --click $RECURSIVE \
        --click $QUERY_BOX --key cmd+a --type "$QUERY" --key return \
        --click $FIRST_ROW

    # A container in full: the payload card and the whole description as a
    # tree. The richest of the five is selected so the pane is not half empty,
    # and field-notes' blank governance.owner is above it in the same frame.
    shot 02-a-container-in-full \
        --click $RECURSIVE \
        --click $QUERY_BOX --key cmd+a --type "$QUERY" --key return \
        --click $RICHEST_ROW

    # What the scan could not do, under the count: a file it could not read and
    # a comparison that crossed types, from a query that produces both at once.
    #
    # The fold is left shut. Opening it wants a coordinate that only exists once
    # notices are on screen, and this file carries no guessed ones — the count
    # line names both findings without it.
    shot 03-what-the-scan-noticed \
        --click $RECURSIVE \
        --click $QUERY_BOX --key cmd+a --type "$QUERY_NOTICES" --key return \
        --click $FIRST_ROW
}


# --- the driving ------------------------------------------------------------

# Which folder this language opens.
#
# There is one set and it is English, because the listing is English: German is
# added to the application, to store-listing.toml and to this function in one
# pass. Refusing here rather than falling back is deliberate — the alternative
# is a German listing showing an English window, which is what happened to
# Slipcase Desktop's German customers.
# Where the corpus is copied to before it is photographed, and why it is copied
# at all: the folder bar shows the path it was given, and a store screenshot
# reading /Users/runner/work/filebase/filebase/dist/corpus tells a customer
# about a build machine. Under Documents it reads like somebody's own folder.
#
# **Staged here rather than through take-shots.sh's `staged_name`.** That does a
# flat `cp "$src"/*`, which omits directories, and this corpus is three levels
# deep — the whole point of the recursive tick box. `cp -R` of the folder itself
# is what a tree needs.
STAGED="${HOME}/Documents/Contracts"

stage_corpus() {
    [ -d "$CORPUS" ] || { echo "shots.sh: no corpus at ${CORPUS}; run packaging/demo-corpus.sh" >&2; exit 2; }
    rm -rf "$STAGED"
    mkdir -p "$(dirname "$STAGED")"
    cp -R "$CORPUS" "$STAGED"
}

for_language() {
    case "$1" in
        en|en-US|en-us) stage_corpus; document=$STAGED ;;
        de|de-DE|de-de)
            echo "shots.sh: no German set is written yet; the application has no German either" >&2
            exit 2 ;;
        *) echo "shots.sh: no set is written for $1" >&2; exit 2 ;;
    esac
}

. "${here}/take-shots.sh"
take_shots "$@"
