feat: add offline casting flow and local history sessions

Replace the development fixture shell with method intro, question, coin entry, and result screens. Persist locked casts in private Room storage under the save policy, and document remaining P2 content and P4 history-list gaps.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
QiuSW
2026-08-19 10:58:09 +08:00
co-authored by Cursor
parent d82ab836a2
commit 4235cf9011
47 changed files with 3075 additions and 355 deletions
@@ -0,0 +1,128 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "29d4064d6ad955275a848abef712ab97",
"entities": [
{
"tableName": "casting_sessions",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `created_at_epoch_millis` INTEGER NOT NULL, `created_at_text` TEXT NOT NULL, `method_version` TEXT NOT NULL, `content_version` TEXT NOT NULL, `coin_convention` TEXT NOT NULL, `rounds_json` TEXT NOT NULL, `line_values` TEXT NOT NULL, `primary_pattern` TEXT NOT NULL, `moving_positions` TEXT NOT NULL, `transformed_pattern` TEXT NOT NULL, `primary_hexagram_id` INTEGER NOT NULL, `transformed_hexagram_id` INTEGER NOT NULL, `question_text` TEXT, `question_saved` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "createdAtEpochMillis",
"columnName": "created_at_epoch_millis",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "createdAtText",
"columnName": "created_at_text",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "methodVersion",
"columnName": "method_version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "contentVersion",
"columnName": "content_version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "coinConvention",
"columnName": "coin_convention",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "roundsJson",
"columnName": "rounds_json",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lineValues",
"columnName": "line_values",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryPattern",
"columnName": "primary_pattern",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "movingPositions",
"columnName": "moving_positions",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "transformedPattern",
"columnName": "transformed_pattern",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryHexagramId",
"columnName": "primary_hexagram_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "transformedHexagramId",
"columnName": "transformed_hexagram_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "questionText",
"columnName": "question_text",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "questionSaved",
"columnName": "question_saved",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_casting_sessions_created_at_epoch_millis",
"unique": false,
"columnNames": [
"created_at_epoch_millis"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_casting_sessions_created_at_epoch_millis` ON `${TABLE_NAME}` (`created_at_epoch_millis`)"
}
],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '29d4064d6ad955275a848abef712ab97')"
]
}
}