## Description This PR overhauls how audio and subtitle track persistence works for series! Previously, when you chose an audio or subtitle track for an episode, only the language was saved and used for subsequent episodes. This meant aspects about why that choice were lost such as a forced or hearing impaired track. This PR changes the persistence to include more details about the chosen track. Additionally, the persistence is saved at both the season and series levels. ## How it works Selecting the track uses the first success option: 1. Episode specific - User has explicitly chosen an audio/subtitle track for this episode 2. Season specific - User has chosen the track for another episode in this season 3. Series specific - User has chosen the track for another episode in this series 4. User preferences - User has _not_ chosen a track for the episode, season, nor series, so determine track based on the preferred audio language, preferred subtitle language, and subtitle mode Additionally, the season or series specific choices use a scoring algorithm to find the best suited track. For example, if the chosen tracks for an episode in the season had the forced flag, this will be preferred for subsequent episodes. Same for SDH/hearing impaired or title, etc. This means that the common case, where a season has substantially identical tracks, will use the same ones across all episodes (after choosing for one, otherwise falling back to the series or user preferences). Finally, this also means that users that prefer SDH/hearing impaired subtitles can be prioritized now, though there is no global preference for this yet. The previous track language choices are migrated to the new algorithm. They lack the additional context, but this makes for a seamless transition. ## UI changes The context menu for choosing audio or subtitle tracks now displays why that track was chosen. ### Related issues Fixes #1795 Maybe fixes #1783 Related to #1136 & #1798 Closes #1470 ### Testing Previous unit tests for track selection all pass, plus there are a few additional unit tests. I've done some testing on the emulator and it seems to work well. But I think real world testing will be needed. ## AI or LLM usage None
834 lines
25 KiB
JSON
834 lines
25 KiB
JSON
{
|
|
"formatVersion": 1,
|
|
"database": {
|
|
"version": 40,
|
|
"identityHash": "b297c087485321c3ee8282ad1ff675a0",
|
|
"entities": [
|
|
{
|
|
"tableName": "servers",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT, `url` TEXT NOT NULL, `version` TEXT, `lastUsed` TEXT, PRIMARY KEY(`id`))",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "name",
|
|
"columnName": "name",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "url",
|
|
"columnName": "url",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "version",
|
|
"columnName": "version",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "lastUsed",
|
|
"columnName": "lastUsed",
|
|
"affinity": "TEXT"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"id"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"tableName": "users",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`rowId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `id` TEXT NOT NULL, `name` TEXT, `serverId` TEXT NOT NULL, `accessToken` TEXT, `pin` TEXT, `requireLogin` INTEGER NOT NULL DEFAULT false, `lastUsed` TEXT, `uiLanguage` TEXT, `preferredAudioLanguage` TEXT NOT NULL DEFAULT '', `preferredSubtitleLanguage` TEXT NOT NULL DEFAULT '', `subtitleMode` TEXT NOT NULL DEFAULT 'USE_USER_PROFILE', FOREIGN KEY(`serverId`) REFERENCES `servers`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "rowId",
|
|
"columnName": "rowId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "name",
|
|
"columnName": "name",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "serverId",
|
|
"columnName": "serverId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "accessToken",
|
|
"columnName": "accessToken",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "pin",
|
|
"columnName": "pin",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "requireLogin",
|
|
"columnName": "requireLogin",
|
|
"affinity": "INTEGER",
|
|
"notNull": true,
|
|
"defaultValue": "false"
|
|
},
|
|
{
|
|
"fieldPath": "lastUsed",
|
|
"columnName": "lastUsed",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "uiLanguage",
|
|
"columnName": "uiLanguage",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "appPreferences.preferredAudioLanguage",
|
|
"columnName": "preferredAudioLanguage",
|
|
"affinity": "TEXT",
|
|
"notNull": true,
|
|
"defaultValue": "''"
|
|
},
|
|
{
|
|
"fieldPath": "appPreferences.preferredSubtitleLanguage",
|
|
"columnName": "preferredSubtitleLanguage",
|
|
"affinity": "TEXT",
|
|
"notNull": true,
|
|
"defaultValue": "''"
|
|
},
|
|
{
|
|
"fieldPath": "appPreferences.subtitleMode",
|
|
"columnName": "subtitleMode",
|
|
"affinity": "TEXT",
|
|
"notNull": true,
|
|
"defaultValue": "'USE_USER_PROFILE'"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"rowId"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_users_id_serverId",
|
|
"unique": true,
|
|
"columnNames": [
|
|
"id",
|
|
"serverId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_users_id_serverId` ON `${TABLE_NAME}` (`id`, `serverId`)"
|
|
},
|
|
{
|
|
"name": "index_users_id",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"id"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_users_id` ON `${TABLE_NAME}` (`id`)"
|
|
},
|
|
{
|
|
"name": "index_users_serverId",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"serverId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_users_serverId` ON `${TABLE_NAME}` (`serverId`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "servers",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"serverId"
|
|
],
|
|
"referencedColumns": [
|
|
"id"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "ItemPlayback",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`rowId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userId` INTEGER NOT NULL, `itemId` TEXT NOT NULL, `sourceId` TEXT, `audioIndex` INTEGER NOT NULL, `subtitleIndex` INTEGER NOT NULL, FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "rowId",
|
|
"columnName": "rowId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "sourceId",
|
|
"columnName": "sourceId",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "audioIndex",
|
|
"columnName": "audioIndex",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "subtitleIndex",
|
|
"columnName": "subtitleIndex",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"rowId"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_ItemPlayback_userId_itemId",
|
|
"unique": true,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_ItemPlayback_userId_itemId` ON `${TABLE_NAME}` (`userId`, `itemId`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "NavDrawerPinnedItem",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER NOT NULL, `itemId` TEXT NOT NULL, `type` TEXT NOT NULL, `order` INTEGER NOT NULL DEFAULT -1, PRIMARY KEY(`userId`, `itemId`), FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "type",
|
|
"columnName": "type",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "order",
|
|
"columnName": "order",
|
|
"affinity": "INTEGER",
|
|
"notNull": true,
|
|
"defaultValue": "-1"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId"
|
|
]
|
|
},
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "LibraryDisplayInfo",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER NOT NULL, `itemId` TEXT NOT NULL, `sort` TEXT NOT NULL, `direction` TEXT NOT NULL, `filter` TEXT NOT NULL DEFAULT '{}', `viewOptions` TEXT, PRIMARY KEY(`userId`, `itemId`), FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "sort",
|
|
"columnName": "sort",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "direction",
|
|
"columnName": "direction",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "filter",
|
|
"columnName": "filter",
|
|
"affinity": "TEXT",
|
|
"notNull": true,
|
|
"defaultValue": "'{}'"
|
|
},
|
|
{
|
|
"fieldPath": "viewOptions",
|
|
"columnName": "viewOptions",
|
|
"affinity": "TEXT"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_LibraryDisplayInfo_userId_itemId",
|
|
"unique": true,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_LibraryDisplayInfo_userId_itemId` ON `${TABLE_NAME}` (`userId`, `itemId`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "playback_effects",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`jellyfinUserRowId` INTEGER NOT NULL, `itemId` TEXT NOT NULL, `type` TEXT NOT NULL, `rotation` INTEGER NOT NULL, `brightness` INTEGER NOT NULL, `contrast` INTEGER NOT NULL, `saturation` INTEGER NOT NULL, `hue` INTEGER NOT NULL, `red` INTEGER NOT NULL, `green` INTEGER NOT NULL, `blue` INTEGER NOT NULL, `blur` INTEGER NOT NULL, PRIMARY KEY(`jellyfinUserRowId`, `itemId`, `type`))",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "jellyfinUserRowId",
|
|
"columnName": "jellyfinUserRowId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "type",
|
|
"columnName": "type",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.rotation",
|
|
"columnName": "rotation",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.brightness",
|
|
"columnName": "brightness",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.contrast",
|
|
"columnName": "contrast",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.saturation",
|
|
"columnName": "saturation",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.hue",
|
|
"columnName": "hue",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.red",
|
|
"columnName": "red",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.green",
|
|
"columnName": "green",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.blue",
|
|
"columnName": "blue",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "videoFilter.blur",
|
|
"columnName": "blur",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"jellyfinUserRowId",
|
|
"itemId",
|
|
"type"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"tableName": "PlaybackLanguageChoice",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER NOT NULL, `seriesId` TEXT NOT NULL, `itemId` TEXT, `audioLanguage` TEXT, `subtitleLanguage` TEXT, `subtitlesDisabled` INTEGER, PRIMARY KEY(`userId`, `seriesId`), FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "seriesId",
|
|
"columnName": "seriesId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "audioLanguage",
|
|
"columnName": "audioLanguage",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "subtitleLanguage",
|
|
"columnName": "subtitleLanguage",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "subtitlesDisabled",
|
|
"columnName": "subtitlesDisabled",
|
|
"affinity": "INTEGER"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"userId",
|
|
"seriesId"
|
|
]
|
|
},
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "ItemTrackModification",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER NOT NULL, `itemId` TEXT NOT NULL, `trackIndex` INTEGER NOT NULL, `delayMs` INTEGER NOT NULL, PRIMARY KEY(`userId`, `itemId`, `trackIndex`), FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "trackIndex",
|
|
"columnName": "trackIndex",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "delayMs",
|
|
"columnName": "delayMs",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId",
|
|
"trackIndex"
|
|
]
|
|
},
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "seerr_servers",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `name` TEXT, `version` TEXT)",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "url",
|
|
"columnName": "url",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "name",
|
|
"columnName": "name",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "version",
|
|
"columnName": "version",
|
|
"affinity": "TEXT"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"id"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_seerr_servers_url",
|
|
"unique": true,
|
|
"columnNames": [
|
|
"url"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_seerr_servers_url` ON `${TABLE_NAME}` (`url`)"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "seerr_users",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`jellyfinUserRowId` INTEGER NOT NULL, `serverId` INTEGER NOT NULL, `authMethod` TEXT NOT NULL, `username` TEXT, `password` TEXT, `credential` TEXT, PRIMARY KEY(`jellyfinUserRowId`, `serverId`), FOREIGN KEY(`serverId`) REFERENCES `seerr_servers`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`jellyfinUserRowId`) REFERENCES `users`(`rowId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "jellyfinUserRowId",
|
|
"columnName": "jellyfinUserRowId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "serverId",
|
|
"columnName": "serverId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "authMethod",
|
|
"columnName": "authMethod",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "username",
|
|
"columnName": "username",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "password",
|
|
"columnName": "password",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "credential",
|
|
"columnName": "credential",
|
|
"affinity": "TEXT"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"jellyfinUserRowId",
|
|
"serverId"
|
|
]
|
|
},
|
|
"foreignKeys": [
|
|
{
|
|
"table": "seerr_servers",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"serverId"
|
|
],
|
|
"referencedColumns": [
|
|
"id"
|
|
]
|
|
},
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"jellyfinUserRowId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "RememberedTab",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER NOT NULL, `itemId` TEXT NOT NULL, `index` INTEGER NOT NULL, PRIMARY KEY(`userId`, `itemId`), FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "index",
|
|
"columnName": "index",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_RememberedTab_userId_itemId",
|
|
"unique": true,
|
|
"columnNames": [
|
|
"userId",
|
|
"itemId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_RememberedTab_userId_itemId` ON `${TABLE_NAME}` (`userId`, `itemId`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "SeriesTrackChoice",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER NOT NULL, `parentId` TEXT NOT NULL, `type` TEXT NOT NULL, `parentType` TEXT NOT NULL, `itemId` TEXT, `language` TEXT, `activation` TEXT NOT NULL, `trackFlags` INTEGER NOT NULL, `codec` TEXT, `relativeTrackIndex` INTEGER, `title` TEXT, `audioChannels` INTEGER, PRIMARY KEY(`userId`, `parentId`, `type`), FOREIGN KEY(`userId`) REFERENCES `users`(`rowId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "userId",
|
|
"columnName": "userId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "parentId",
|
|
"columnName": "parentId",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "type",
|
|
"columnName": "type",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "parentType",
|
|
"columnName": "parentType",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "language",
|
|
"columnName": "language",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "activation",
|
|
"columnName": "activation",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "trackFlags",
|
|
"columnName": "trackFlags",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "codec",
|
|
"columnName": "codec",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "relativeTrackIndex",
|
|
"columnName": "relativeTrackIndex",
|
|
"affinity": "INTEGER"
|
|
},
|
|
{
|
|
"fieldPath": "title",
|
|
"columnName": "title",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "audioChannels",
|
|
"columnName": "audioChannels",
|
|
"affinity": "INTEGER"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": false,
|
|
"columnNames": [
|
|
"userId",
|
|
"parentId",
|
|
"type"
|
|
]
|
|
},
|
|
"foreignKeys": [
|
|
{
|
|
"table": "users",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "CASCADE",
|
|
"columns": [
|
|
"userId"
|
|
],
|
|
"referencedColumns": [
|
|
"rowId"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"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, 'b297c087485321c3ee8282ad1ff675a0')"
|
|
]
|
|
}
|
|
}
|