Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fe413b4b2 | ||
|
|
3f9a0308bc | ||
|
|
62fb352f88 | ||
|
|
049314961b | ||
|
|
e80e3a1465 | ||
|
|
d83753df7f | ||
|
|
874c1f377b | ||
|
|
321c30e028 | ||
|
|
a881efe636 | ||
|
|
581057ca88 | ||
|
|
bef6d94819 | ||
|
|
bf90628df1 | ||
|
|
eec644462a | ||
|
|
66f62a6827 | ||
|
|
0940bd4c77 | ||
|
|
6c718c16f8 | ||
|
|
46b839b9ed | ||
|
|
4f1ad530f4 | ||
|
|
c07e1b7daf | ||
|
|
85bfc365cd | ||
|
|
8df801b666 | ||
|
|
a08b9ebfaa | ||
|
|
d50283c2dc | ||
|
|
49800149e6 | ||
|
|
de9562212f | ||
|
|
d09622ccf6 | ||
|
|
b0bb26f84b | ||
|
|
e94fcf3128 | ||
|
|
bd6e818f36 | ||
|
|
96d0c35c31 | ||
|
|
4ef3281a0b | ||
|
|
c56e3dba0f | ||
|
|
53d284ace4 | ||
|
|
c2733482e5 | ||
|
|
67f0c926c4 | ||
|
|
889be2ff2c | ||
|
|
52b51954aa | ||
|
|
1c76293559 | ||
|
|
250d6793a2 | ||
|
|
121af2bca3 | ||
|
|
e410dcb2eb | ||
|
|
63ff9772e5 | ||
|
|
1ae29c5ade | ||
|
|
fedd6a71bb | ||
|
|
8f64cfcbca | ||
|
|
1edb2c13da | ||
|
|
7f83204b24 | ||
|
|
0fe52494d0 | ||
|
|
56dbcde3b4 | ||
|
|
8fbc5e6ce4 | ||
|
|
979a4b7c73 | ||
|
|
7b1da24748 | ||
|
|
7014aa85d1 | ||
|
|
abab674322 | ||
|
|
498bb22a69 | ||
|
|
11fe43a750 | ||
|
|
2a60a7306c | ||
|
|
ad12a7e15d | ||
|
|
1c5fea2dd4 | ||
|
|
90ac4dc59b | ||
|
|
11e50946d2 | ||
|
|
abd0bcd4b9 | ||
|
|
c3c957d527 | ||
|
|
f415d8a98f | ||
|
|
963c15636c | ||
|
|
7562d93113 | ||
|
|
aae58bc5ee | ||
|
|
5be08c16d5 | ||
|
|
0f29b757ee | ||
|
|
49b8d2c423 | ||
|
|
f0f812e66a | ||
|
|
35b037f66c | ||
|
|
985995d45d | ||
|
|
cb786d6360 | ||
|
|
89416a9017 | ||
|
|
6aa8df7d9a | ||
|
|
16f9f8c54d | ||
|
|
2b041580de | ||
|
|
9de0984553 | ||
|
|
4a73c0ba17 | ||
|
|
3d1d226c43 | ||
|
|
ccead686aa | ||
|
|
1f57cc503c | ||
|
|
24f9fddae0 | ||
|
|
e4875b10de | ||
|
|
48f1a4ca3a | ||
|
|
0a475c0a0f | ||
|
|
1859c5c32d | ||
|
|
f159a8fc42 | ||
|
|
f700ac9935 | ||
|
|
70729bb0e5 | ||
|
|
7d5b0d285d | ||
|
|
72f53d6d21 | ||
|
|
5707c93295 | ||
|
|
46a90169a9 | ||
|
|
27754bd3c3 | ||
|
|
2bf3e8853d | ||
|
|
e14099472a | ||
|
|
ac06e21f37 | ||
|
|
92e2fd93f9 | ||
|
|
a5ccba69ec | ||
|
|
23eb05a368 | ||
|
|
1f9ee9b462 | ||
|
|
237b8d2fc6 | ||
|
|
35eada710e | ||
|
|
86ef5af6f6 | ||
|
|
76b290c8b3 | ||
|
|
a92ad7bfc9 | ||
|
|
1944add558 | ||
|
|
05e4b46469 | ||
|
|
00652952d8 | ||
|
|
83864217f9 | ||
|
|
b3ab75699e | ||
|
|
5cde911113 | ||
|
|
7fda50857f | ||
|
|
4ab51ea11a | ||
|
|
fcd5c1b167 | ||
|
|
2ccb397164 | ||
|
|
4e3a3133d7 | ||
|
|
2edd3a73fd | ||
|
|
4855043cda | ||
|
|
e6e997e4b5 | ||
|
|
c78fc65279 | ||
|
|
52e95dc959 | ||
|
|
b8948fb646 | ||
|
|
a91ac29626 | ||
|
|
aca677a432 | ||
|
|
708a404a21 | ||
|
|
7fa861d609 | ||
|
|
5a201c783f | ||
|
|
f98ed31475 | ||
|
|
6ebf1d265e | ||
|
|
07c4d14adf | ||
|
|
6b1b4c2c4f | ||
|
|
658d134f64 | ||
|
|
a9dbcfb69d | ||
|
|
860a4cec16 | ||
|
|
4905f75564 | ||
|
|
6b53d9444d | ||
|
|
f39a29159a | ||
|
|
c1a4b5ede8 | ||
|
|
d0319eb32d | ||
|
|
9524080d00 | ||
|
|
cba32e75b3 | ||
|
|
37d81cb87a | ||
|
|
f911688c78 | ||
|
|
bfa6b6f08a | ||
|
|
87e83516a1 | ||
|
|
8196704ccd | ||
|
|
cbd88d0f13 | ||
|
|
ecb706310b | ||
|
|
caf544069e | ||
|
|
8bc4caae78 | ||
|
|
5a2ab98af5 | ||
|
|
3ab9ea9fe8 | ||
|
|
b761ad8b84 | ||
|
|
5169b726ce | ||
|
|
41f00ef3f1 | ||
|
|
abdd1667b7 | ||
|
|
b6c689ea7e | ||
|
|
2c8bcbcb2f | ||
|
|
e412b33d4e | ||
|
|
081251061d | ||
|
|
09ca4974c5 | ||
|
|
d9781f3a47 | ||
|
|
ec390f593c | ||
|
|
6883a556bf | ||
|
|
100be96fca | ||
|
|
c1e26d23cf | ||
|
|
329ef919f7 | ||
|
|
336e106e01 | ||
|
|
c0f802c27b | ||
|
|
da033e697f | ||
|
|
5bb32df16b | ||
|
|
6cb364531b | ||
|
|
72fa2c765d | ||
|
|
0643b6d719 | ||
|
|
da79b306b2 | ||
|
|
9a6f8b86fc | ||
|
|
37214fcbdc | ||
|
|
eb578fa5e6 | ||
|
|
51f79ac8ad | ||
|
|
ddef0fc2c8 | ||
|
|
dbc72d5259 | ||
|
|
f686294aab | ||
|
|
29cdebe424 | ||
|
|
ef476552e0 | ||
|
|
dd0d4d52c1 | ||
|
|
0c825a3d85 | ||
|
|
2d07d5f1fa | ||
|
|
2dc9e71ab5 | ||
|
|
062b0cadd2 | ||
|
|
ad92e6d3ff | ||
|
|
328956d84a | ||
|
|
9d58e15b39 | ||
|
|
721a42f60f | ||
|
|
6a0f5678ec | ||
|
|
dbfc4172fb | ||
|
|
2097a9f7fd | ||
|
|
3053e2b5c9 | ||
|
|
7f1585a6ad | ||
|
|
704edfbaaf | ||
|
|
5622c007f2 | ||
|
|
3719a71e0f | ||
|
|
44fb9a022d | ||
|
|
45cc51192a | ||
|
|
d981690ba6 | ||
|
|
161a621d71 | ||
|
|
7da1afa643 | ||
|
|
77e89fc9e2 | ||
|
|
36e97cb621 | ||
|
|
c539376cc4 | ||
|
|
0465147a7c | ||
|
|
2e96c61b82 | ||
|
|
08470aaf00 | ||
|
|
8ee98327fe | ||
|
|
a91f455534 | ||
|
|
ac175d091f | ||
|
|
872dde4e1c | ||
|
|
23807a3506 | ||
|
|
a3fda31743 | ||
|
|
b8f04e5426 | ||
|
|
46eb293f98 | ||
|
|
5af187ba48 | ||
|
|
9847cdb894 | ||
|
|
fac2b62ec2 | ||
|
|
81b5bfb56b | ||
|
|
7abf5c0e88 | ||
|
|
ed4a32cba3 | ||
|
|
0778c49b18 | ||
|
|
3db1d795dc | ||
|
|
07fc618fd2 | ||
|
|
75da5d16ac | ||
|
|
1d40ac5b35 | ||
|
|
6bdd052472 | ||
|
|
74632eff10 | ||
|
|
3055726fb3 | ||
|
|
d10a29b931 | ||
|
|
75a264ca83 | ||
|
|
dcd764bd68 | ||
|
|
1a596077fa |
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,4 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*.{kt,kts}]
|
|
||||||
ktlint_function_naming_ignore_when_annotated_with = Composable
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
TEST_SERVER_NAME=Subsonic Demo
|
||||||
|
TEST_SERVER_URL=http://demo.subsonic.org
|
||||||
|
TEST_SERVER_USERNAME=guest
|
||||||
|
TEST_SERVER_PASSWORD=guest
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"flutterSdkVersion": "3.7.11",
|
||||||
|
"flavors": {}
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
app/schemas/** linguist-generated
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
name: Build
|
|
||||||
description: Set up Nix, optionally sign, run Gradle and report the version code
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
gradle-args:
|
|
||||||
description: Gradle tasks and flags to run
|
|
||||||
required: true
|
|
||||||
sign:
|
|
||||||
description: Decode and use the store keystore when "true"
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
keystore-base64:
|
|
||||||
description: Base64 of the release keystore
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
keyproperties-base64:
|
|
||||||
description: Base64 of the key.properties holding the key alias
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
keystore-password:
|
|
||||||
description: Keystore (store) password
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
key-password:
|
|
||||||
description: Signing key password
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
version-code:
|
|
||||||
description: versionCode read from app/build.gradle.kts
|
|
||||||
value: ${{ steps.version.outputs.code }}
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- uses: ./.github/actions/nix
|
|
||||||
- uses: actions/cache@v6
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle.properties', 'gradle/libs.versions.toml', 'gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
restore-keys: gradle-
|
|
||||||
- id: signing
|
|
||||||
if: inputs.sign == 'true'
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
KEYSTORE_BASE64: ${{ inputs.keystore-base64 }}
|
|
||||||
KEYPROPERTIES_BASE64: ${{ inputs.keyproperties-base64 }}
|
|
||||||
run: |
|
|
||||||
umask 077
|
|
||||||
echo "$KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/release.keystore"
|
|
||||||
alias=$(printf '%s' "$KEYPROPERTIES_BASE64" | base64 -d | sed -n 's/^keyAlias=//p' | tr -d '\r')
|
|
||||||
test -n "$alias" || { echo "no keyAlias in keyproperties" >&2; exit 1; }
|
|
||||||
echo "alias=$alias" >> "$GITHUB_OUTPUT"
|
|
||||||
- shell: bash
|
|
||||||
env:
|
|
||||||
SIGN: ${{ inputs.sign }}
|
|
||||||
KEYSTORE_PASSWORD: ${{ inputs.keystore-password }}
|
|
||||||
KEY_ALIAS: ${{ steps.signing.outputs.alias }}
|
|
||||||
KEY_PASSWORD: ${{ inputs.key-password }}
|
|
||||||
run: |
|
|
||||||
if [ "$SIGN" = "true" ]; then
|
|
||||||
export RELEASE_KEYSTORE="$RUNNER_TEMP/release.keystore"
|
|
||||||
export RELEASE_KEYSTORE_PASSWORD="$KEYSTORE_PASSWORD"
|
|
||||||
export RELEASE_KEY_ALIAS="$KEY_ALIAS"
|
|
||||||
export RELEASE_KEY_PASSWORD="$KEY_PASSWORD"
|
|
||||||
fi
|
|
||||||
nix develop --command gradle ${{ inputs.gradle-args }}
|
|
||||||
- if: always()
|
|
||||||
shell: bash
|
|
||||||
run: rm -f "$RUNNER_TEMP/release.keystore"
|
|
||||||
- id: version
|
|
||||||
shell: bash
|
|
||||||
run: echo "code=$(grep -oP 'versionCode = \K\d+' app/build.gradle.kts)" >> "$GITHUB_OUTPUT"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
name: Nix
|
|
||||||
description: Install Nix and restore the store cache
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
|
|
||||||
with:
|
|
||||||
extra_nix_config: experimental-features = nix-command flakes
|
|
||||||
- uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7.0.2
|
|
||||||
with:
|
|
||||||
primary-key: nix-v2-${{ hashFiles('flake.lock', '**/*.nix') }}
|
|
||||||
restore-prefixes-first-match: nix-v2-
|
|
||||||
gc-max-store-size-linux: 6G
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
name: build-flutter-release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v*']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-apk:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Get subtracks version
|
||||||
|
run: echo "SUBTRACKS_VERSION=$(yq '.version' pubspec.yaml | cut -d '+' -f 1)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: '3.7.11'
|
||||||
|
channel: 'stable'
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- run: cp .env.example .env
|
||||||
|
- run: flutter pub get
|
||||||
|
|
||||||
|
- name: Retrieve subtracks.keystore
|
||||||
|
env:
|
||||||
|
SUBTRACKS_KEYSTORE_BASE64: ${{ secrets.SUBTRACKS_KEYSTORE_BASE64 }}
|
||||||
|
run: |
|
||||||
|
echo "$SUBTRACKS_KEYSTORE_BASE64" | base64 --decode > android/subtracks.keystore
|
||||||
|
- name: Retrieve key.properties
|
||||||
|
env:
|
||||||
|
SUBTRACKS_KEYPROPERTIES_BASE64: ${{ secrets.SUBTRACKS_KEYPROPERTIES_BASE64 }}
|
||||||
|
run: |
|
||||||
|
echo "$SUBTRACKS_KEYPROPERTIES_BASE64" | base64 --decode > android/key.properties
|
||||||
|
|
||||||
|
- run: flutter build apk -PsignRelease
|
||||||
|
|
||||||
|
- run: mv build/app/outputs/flutter-apk/app-release.apk subtracks-${SUBTRACKS_VERSION}.apk
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: subtracks-release-apk
|
||||||
|
path: subtracks-*.apk
|
||||||
|
|
||||||
|
build-aab:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Get subtracks version
|
||||||
|
run: echo "SUBTRACKS_VERSION=$(yq '.version' pubspec.yaml)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: '3.7.11'
|
||||||
|
channel: 'stable'
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- run: cp .env.example .env
|
||||||
|
- run: flutter pub get
|
||||||
|
|
||||||
|
- name: Retrieve subtracks.keystore
|
||||||
|
env:
|
||||||
|
SUBTRACKS_KEYSTORE_BASE64: ${{ secrets.SUBTRACKS_KEYSTORE_BASE64 }}
|
||||||
|
run: |
|
||||||
|
echo "$SUBTRACKS_KEYSTORE_BASE64" | base64 --decode > android/subtracks.keystore
|
||||||
|
- name: Retrieve key.properties
|
||||||
|
env:
|
||||||
|
SUBTRACKS_KEYPROPERTIES_BASE64: ${{ secrets.SUBTRACKS_KEYPROPERTIES_BASE64 }}
|
||||||
|
run: |
|
||||||
|
echo "$SUBTRACKS_KEYPROPERTIES_BASE64" | base64 --decode > android/key.properties
|
||||||
|
|
||||||
|
- run: flutter build appbundle -PsignRelease
|
||||||
|
|
||||||
|
- run: mv build/app/outputs/bundle/release/app-release.aab subtracks-${SUBTRACKS_VERSION}.aab
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: subtracks-release-aab
|
||||||
|
path: subtracks-*.aab
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
name: build-flutter
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['main']
|
||||||
|
pull_request:
|
||||||
|
branches: ['main']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-apk:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: '3.7.11'
|
||||||
|
channel: 'stable'
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- run: cp .env.example .env
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: flutter analyze
|
||||||
|
- run: flutter build apk
|
||||||
|
|
||||||
|
- run: mv build/app/outputs/flutter-apk/app-release.apk subtracks-$(git rev-parse --short HEAD).apk
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: subtracks-testing
|
||||||
|
path: subtracks-*.apk
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
runs-on: ubuntu-26.04
|
|
||||||
timeout-minutes: 90
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
env:
|
|
||||||
GRADLE_OPTS: -Dorg.gradle.daemon=false
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- uses: ./.github/actions/build
|
|
||||||
with:
|
|
||||||
gradle-args: ":app:ktlintCheck :app:lintDebug :app:testDebugUnitTest :app:assembleDebug :app:assembleNightly --no-configuration-cache --console=plain --no-daemon"
|
|
||||||
- name: Collect nightly builds
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
run: |
|
|
||||||
cp app/build/outputs/apk/debug/app-debug.apk subtracks-nightly-debug.apk
|
|
||||||
cp app/build/outputs/apk/nightly/app-nightly.apk subtracks-nightly.apk
|
|
||||||
- name: Checksums
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
run: sha256sum subtracks-nightly.apk subtracks-nightly-debug.apk | tee SHA256SUMS
|
|
||||||
- uses: actions/upload-artifact@v7
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
with:
|
|
||||||
path: subtracks-nightly.apk
|
|
||||||
archive: false
|
|
||||||
- uses: actions/upload-artifact@v7
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
with:
|
|
||||||
path: subtracks-nightly-debug.apk
|
|
||||||
archive: false
|
|
||||||
- uses: actions/upload-artifact@v7
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
with:
|
|
||||||
path: SHA256SUMS
|
|
||||||
archive: false
|
|
||||||
- uses: actions/cache@v6
|
|
||||||
with:
|
|
||||||
path: .integration/music
|
|
||||||
key: integration-music-v1
|
|
||||||
- run: nix develop .#integration --command nu tools/integration-test.nu
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: release
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-26.04
|
|
||||||
timeout-minutes: 60
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
outputs:
|
|
||||||
version-code: ${{ steps.build.outputs.version-code }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Check tag matches versionName
|
|
||||||
run: |
|
|
||||||
version=$(grep -oP 'versionName = "\K[^"]+' app/build.gradle.kts)
|
|
||||||
case "$GITHUB_REF_NAME" in
|
|
||||||
"v$version" | "v$version"-*) ;;
|
|
||||||
*)
|
|
||||||
echo "tag $GITHUB_REF_NAME does not match versionName $version" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
- id: build
|
|
||||||
uses: ./.github/actions/build
|
|
||||||
with:
|
|
||||||
gradle-args: ":app:assembleRelease :app:bundleRelease --no-daemon"
|
|
||||||
sign: "true"
|
|
||||||
keystore-base64: ${{ secrets.SUBTRACKS_KEYSTORE_BASE64 }}
|
|
||||||
keyproperties-base64: ${{ secrets.SUBTRACKS_KEYPROPERTIES_BASE64 }}
|
|
||||||
keystore-password: ${{ secrets.SUBTRACKS_UPLOAD_STORE_PASSWORD }}
|
|
||||||
key-password: ${{ secrets.SUBTRACKS_UPLOAD_KEY_PASSWORD }}
|
|
||||||
- name: Export release certificate
|
|
||||||
env:
|
|
||||||
KEYSTORE_BASE64: ${{ secrets.SUBTRACKS_KEYSTORE_BASE64 }}
|
|
||||||
KEYPROPERTIES_BASE64: ${{ secrets.SUBTRACKS_KEYPROPERTIES_BASE64 }}
|
|
||||||
KEYSTORE_PASSWORD: ${{ secrets.SUBTRACKS_UPLOAD_STORE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
umask 077
|
|
||||||
trap 'rm -f "$RUNNER_TEMP/keystore"' EXIT
|
|
||||||
echo "$KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/keystore"
|
|
||||||
alias=$(printf '%s' "$KEYPROPERTIES_BASE64" | base64 -d | sed -n 's/^keyAlias=//p' | tr -d '\r')
|
|
||||||
nix develop --command keytool -exportcert -rfc -keystore "$RUNNER_TEMP/keystore" -alias "$alias" -storepass "$KEYSTORE_PASSWORD" -file app/build/outputs/release-certificate.pem
|
|
||||||
- uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: release
|
|
||||||
path: app/build/outputs
|
|
||||||
|
|
||||||
publish:
|
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-26.04
|
|
||||||
timeout-minutes: 60
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- uses: actions/download-artifact@v8
|
|
||||||
with:
|
|
||||||
name: release
|
|
||||||
path: dist
|
|
||||||
- uses: ./.github/actions/nix
|
|
||||||
- name: Detect stable tag
|
|
||||||
id: stable
|
|
||||||
run: |
|
|
||||||
if [[ "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
echo "value=true" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
echo "value=false" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
- name: Check release notes exist
|
|
||||||
run: test -f "metadata/en-US/changelogs/${{ needs.build.outputs.version-code }}.txt"
|
|
||||||
- name: Write Play service account
|
|
||||||
if: steps.stable.outputs.value == 'true'
|
|
||||||
env:
|
|
||||||
PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
|
||||||
run: |
|
|
||||||
umask 077
|
|
||||||
printf '%s' "$PLAY_SERVICE_ACCOUNT_JSON" > "$RUNNER_TEMP/play.json"
|
|
||||||
- name: Upload to Google Play
|
|
||||||
if: steps.stable.outputs.value == 'true'
|
|
||||||
run: |
|
|
||||||
nix develop .#release --command fastlane supply \
|
|
||||||
--aab dist/bundle/release/app-release.aab \
|
|
||||||
--package_name com.subtracks \
|
|
||||||
--track "${{ vars.PLAY_TRACK || 'internal' }}" \
|
|
||||||
--json_key "$RUNNER_TEMP/play.json" \
|
|
||||||
--mapping dist/mapping/release/mapping.txt
|
|
||||||
- name: Remove Play service account
|
|
||||||
if: always()
|
|
||||||
run: rm -f "$RUNNER_TEMP/play.json"
|
|
||||||
- name: Checksums and signature
|
|
||||||
id: checksums
|
|
||||||
run: |
|
|
||||||
cp dist/apk/release/app-release.apk subtracks.apk
|
|
||||||
cp dist/bundle/release/app-release.aab subtracks.aab
|
|
||||||
gzip -n -9 -c dist/mapping/release/mapping.txt > mapping.txt.gz
|
|
||||||
sha256sum subtracks.apk subtracks.aab > SHA256SUMS
|
|
||||||
echo "Artifact SHA-256:"
|
|
||||||
sha256sum subtracks.apk subtracks.aab
|
|
||||||
echo "APK signature:"
|
|
||||||
certs=$(nix develop --command bash -c '"$ANDROID_HOME/build-tools/37.0.0/apksigner" verify --print-certs subtracks.apk')
|
|
||||||
printf '%s\n' "$certs"
|
|
||||||
fingerprint=$(printf '%s\n' "$certs" | sed -n 's/.*certificate SHA-256 digest: //p' | head -1 | tr '[:lower:]' '[:upper:]' | sed 's/\(..\)/\1:/g; s/:$//')
|
|
||||||
echo "fingerprint=$fingerprint" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: Compose release notes
|
|
||||||
run: |
|
|
||||||
{
|
|
||||||
cat "metadata/en-US/changelogs/${{ needs.build.outputs.version-code }}.txt"
|
|
||||||
echo
|
|
||||||
echo '---'
|
|
||||||
echo
|
|
||||||
echo "APK SHA-256: \`$(grep 'subtracks\.apk$' SHA256SUMS | cut -d ' ' -f1)\`"
|
|
||||||
echo
|
|
||||||
echo "AAB SHA-256: \`$(grep 'subtracks\.aab$' SHA256SUMS | cut -d ' ' -f1)\`"
|
|
||||||
echo
|
|
||||||
echo "Signing certificate SHA-256: \`${{ steps.checksums.outputs.fingerprint }}\`"
|
|
||||||
echo
|
|
||||||
echo 'The signing certificate is attached as `release-certificate.pem`.'
|
|
||||||
if [ "${{ steps.stable.outputs.value }}" = "true" ]; then
|
|
||||||
echo 'The `.aab` is the exact bundle uploaded to Google Play; the `.apk` is the universal APK for sideloading.'
|
|
||||||
else
|
|
||||||
echo 'The `.aab` is the built app bundle (this pre-release was not uploaded to Google Play); the `.apk` is the universal APK for sideloading.'
|
|
||||||
fi
|
|
||||||
} > release-notes.md
|
|
||||||
- name: Create GitHub release
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
args=(--verify-tag --title "$GITHUB_REF_NAME" --notes-file release-notes.md)
|
|
||||||
if [ "${{ steps.stable.outputs.value }}" != "true" ]; then
|
|
||||||
args+=(--prerelease)
|
|
||||||
fi
|
|
||||||
gh release create "$GITHUB_REF_NAME" subtracks.apk subtracks.aab SHA256SUMS dist/release-certificate.pem mapping.txt.gz "${args[@]}"
|
|
||||||
@@ -1,26 +1,49 @@
|
|||||||
.gradle/
|
# Miscellaneous
|
||||||
build/
|
*.class
|
||||||
!.github/actions/build/
|
*.log
|
||||||
local.properties
|
|
||||||
|
|
||||||
*.apk
|
|
||||||
*.aab
|
|
||||||
captures/
|
|
||||||
.cxx/
|
|
||||||
|
|
||||||
hs_err_pid*.log
|
|
||||||
replay_pid*.log
|
|
||||||
|
|
||||||
.idea/
|
|
||||||
*.iml
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
.kotlin/
|
|
||||||
.direnv/
|
|
||||||
.preview/
|
|
||||||
.integration/
|
|
||||||
app/src/test/screenshots/
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.swp
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
migrate_working_dir/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.packages
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Symbolication related
|
||||||
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
|
||||||
|
# Android Studio will place build artifacts here
|
||||||
|
/android/app/debug
|
||||||
|
/android/app/profile
|
||||||
|
/android/app/release
|
||||||
|
|
||||||
|
/.env
|
||||||
|
*.sqlite*
|
||||||
|
/.fvm/flutter_sdk
|
||||||
|
*.keystore
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
||||||
|
channel: stable
|
||||||
|
|
||||||
|
project_type: app
|
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command
|
||||||
|
migration:
|
||||||
|
platforms:
|
||||||
|
- platform: root
|
||||||
|
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
||||||
|
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
||||||
|
- platform: android
|
||||||
|
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
||||||
|
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
||||||
|
|
||||||
|
# User provided section
|
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be
|
||||||
|
# ignored by the migrate tool.
|
||||||
|
#
|
||||||
|
# Files that are not part of the templates will be ignored by default.
|
||||||
|
unmanaged_files:
|
||||||
|
- 'lib/main.dart'
|
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||||
@@ -0,0 +1,500 @@
|
|||||||
|
{
|
||||||
|
"ar": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ca": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"cs": [
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsMusicName",
|
||||||
|
"settingsMusicOptionsScrobbleDescriptionOff",
|
||||||
|
"settingsMusicOptionsScrobbleDescriptionOn",
|
||||||
|
"settingsMusicOptionsScrobbleTitle",
|
||||||
|
"settingsNetworkOptionsMaxBufferTitle",
|
||||||
|
"settingsNetworkOptionsMinBufferTitle",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn"
|
||||||
|
],
|
||||||
|
|
||||||
|
"da": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"actionsStar",
|
||||||
|
"actionsUnstar",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterStarred",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAdded",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByFrequentlyPlayed",
|
||||||
|
"resourcesSortByRecentlyPlayed",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsMusicOptionsScrobbleDescriptionOff",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName",
|
||||||
|
"settingsServersOptionsForcePlaintextPasswordDescriptionOff",
|
||||||
|
"settingsServersOptionsForcePlaintextPasswordDescriptionOn",
|
||||||
|
"settingsServersOptionsForcePlaintextPasswordTitle"
|
||||||
|
],
|
||||||
|
|
||||||
|
"de": [
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog"
|
||||||
|
],
|
||||||
|
|
||||||
|
"es": [
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"fr": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"it": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ja": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"actionsStar",
|
||||||
|
"actionsUnstar",
|
||||||
|
"controlsShuffle",
|
||||||
|
"messagesNothingHere",
|
||||||
|
"resourcesAlbumActionsPlay",
|
||||||
|
"resourcesAlbumActionsView",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesAlbumListsSort",
|
||||||
|
"resourcesArtistActionsView",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesArtistListsSort",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterGenre",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistActionsPlay",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesQueueName",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAdded",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByArtist",
|
||||||
|
"resourcesSortByName",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"resourcesSortByYear",
|
||||||
|
"searchHeaderTitle",
|
||||||
|
"searchMoreResults",
|
||||||
|
"searchNowPlayingContext",
|
||||||
|
"settingsAboutActionsLicenses",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutName",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsAboutVersion",
|
||||||
|
"settingsMusicOptionsScrobbleDescriptionOff",
|
||||||
|
"settingsMusicOptionsScrobbleDescriptionOn",
|
||||||
|
"settingsMusicOptionsScrobbleTitle",
|
||||||
|
"settingsNetworkOptionsMaxBitrateMobileTitle",
|
||||||
|
"settingsNetworkOptionsMaxBitrateWifiTitle",
|
||||||
|
"settingsNetworkOptionsMaxBufferTitle",
|
||||||
|
"settingsNetworkOptionsMinBufferTitle",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsNetworkValuesKbps",
|
||||||
|
"settingsNetworkValuesSeconds",
|
||||||
|
"settingsNetworkValuesUnlimitedKbps",
|
||||||
|
"settingsResetActionsClearImageCache",
|
||||||
|
"settingsServersActionsAdd",
|
||||||
|
"settingsServersActionsDelete",
|
||||||
|
"settingsServersActionsEdit",
|
||||||
|
"settingsServersActionsSave",
|
||||||
|
"settingsServersActionsTestConnection",
|
||||||
|
"settingsServersFieldsAddress",
|
||||||
|
"settingsServersFieldsName",
|
||||||
|
"settingsServersFieldsPassword",
|
||||||
|
"settingsServersFieldsUsername",
|
||||||
|
"settingsServersMessagesConnectionFailed",
|
||||||
|
"settingsServersMessagesConnectionOk",
|
||||||
|
"settingsServersOptionsForcePlaintextPasswordDescriptionOff",
|
||||||
|
"settingsServersOptionsForcePlaintextPasswordDescriptionOn",
|
||||||
|
"settingsServersOptionsForcePlaintextPasswordTitle"
|
||||||
|
],
|
||||||
|
|
||||||
|
"nb": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pa": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pl": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pt": [
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"tr": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"vi": [
|
||||||
|
"actionsCancel",
|
||||||
|
"actionsDelete",
|
||||||
|
"actionsDownload",
|
||||||
|
"actionsDownloadCancel",
|
||||||
|
"actionsDownloadDelete",
|
||||||
|
"actionsOk",
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesFilterAlbum",
|
||||||
|
"resourcesFilterArtist",
|
||||||
|
"resourcesFilterOwner",
|
||||||
|
"resourcesFilterYear",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"resourcesSongListDeleteAllContent",
|
||||||
|
"resourcesSongListDeleteAllTitle",
|
||||||
|
"resourcesSortByAlbum",
|
||||||
|
"resourcesSortByAlbumCount",
|
||||||
|
"resourcesSortByTitle",
|
||||||
|
"resourcesSortByUpdated",
|
||||||
|
"settingsAboutActionsSupport",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
],
|
||||||
|
|
||||||
|
"zh": [
|
||||||
|
"controlsShuffle",
|
||||||
|
"resourcesAlbumCount",
|
||||||
|
"resourcesArtistCount",
|
||||||
|
"resourcesPlaylistCount",
|
||||||
|
"resourcesSongCount",
|
||||||
|
"settingsAboutShareLogs",
|
||||||
|
"settingsAboutChooseLog",
|
||||||
|
"settingsNetworkOptionsOfflineMode",
|
||||||
|
"settingsNetworkOptionsOfflineModeOff",
|
||||||
|
"settingsNetworkOptionsOfflineModeOn",
|
||||||
|
"settingsNetworkOptionsStreamFormat",
|
||||||
|
"settingsNetworkOptionsStreamFormatServerDefault",
|
||||||
|
"settingsServersFieldsName"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "debug",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"flutterMode": "debug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "profile mode",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"flutterMode": "profile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release mode",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"flutterMode": "release"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# AGENTS.md
|
|
||||||
|
|
||||||
Guidance for agents (and humans) working in this repository.
|
|
||||||
|
|
||||||
## What this is
|
|
||||||
|
|
||||||
A native Android rewrite of Subtracks, a client for Subsonic-compatible servers (Navidrome, gonic, Airsonic, ...), in Kotlin and Jetpack Compose. The `main` history still contains the earlier Flutter app; the native app is being built fresh under `app/` and ships as `com.subtracks`. The aim is a clean, F-Droid-friendly client: free/libre dependencies only, no telemetry.
|
|
||||||
|
|
||||||
## Environment
|
|
||||||
|
|
||||||
Everything comes from the Nix flake devshell; do not install toolchains by hand.
|
|
||||||
|
|
||||||
- Enter it with `nix develop`, or let direnv load it into your shell (`.envrc` runs `use flake`).
|
|
||||||
- The default devshell provides JDK 21, Gradle 9, the Android SDK (platform 37, build-tools 37.0.0, platform-tools 37.0.1) and nushell.
|
|
||||||
- The integration harness needs real servers, so it lives in a separate `nix develop .#integration` shell (navidrome, gonic, lms, php, Nextcloud with the Music app, sqlite). Keeping them out of the default shell avoids pulling that closure into everyday builds.
|
|
||||||
- Build with the devshell `gradle`, not `./gradlew`. CI uses the nix Gradle pinned by `flake.lock`; the wrapper is kept only for people without Nix.
|
|
||||||
|
|
||||||
## Commands
|
|
||||||
|
|
||||||
- Build: `gradle :app:assembleDebug`
|
|
||||||
- Release build: `gradle :app:assembleRelease` only when build config, R8/ProGuard or dependencies change, and once before a merge; not part of routine verification
|
|
||||||
- Unit tests: `gradle :app:testDebugUnitTest`
|
|
||||||
- Lint: `gradle :app:ktlintCheck :app:lintDebug`
|
|
||||||
- Format: `gradle :app:ktlintFormat`
|
|
||||||
- Integration tests: `nix develop .#integration --command nu tools/integration-test.nu` (starts navidrome, gonic, lms and a Nextcloud Music instance, then runs `:app:integrationTest`)
|
|
||||||
- Screenshots: `gradle :app:recordRoborazziDebug` renders the `*Screen` composables to `app/src/test/screenshots/` (gitignored) plus an HTML report in `app/build/reports/roborazzi/`, for local review. No golden images are committed and `verifyRoborazziDebug` is not part of CI.
|
|
||||||
- Demo screenshots: `gradle :app:demoScreenshots` does a real sync of the public Navidrome demo (`https://demo.navidrome.org`, `demo`/`demo`) and renders the store screenshots with that library's art and names into `app/src/test/screenshots/demo/` (gitignored). Needs network; not part of CI or the integration suite.
|
|
||||||
|
|
||||||
## Testing layout
|
|
||||||
|
|
||||||
- `app/src/test` - JVM unit tests (JUnit4, Robolectric, Roborazzi, MockWebServer). Run by `:app:testDebugUnitTest`.
|
|
||||||
- `app/src/integrationTest` - tests that need real servers. Compiled with the unit test sources but run by the dedicated `:app:integrationTest` task, and excluded from every `*UnitTest` task. The nushell harness starts the servers for you.
|
|
||||||
- A test earns its place only if it fails when the behaviour it covers breaks, and passes when the behaviour works. A test that passes either way is worse than no test: it looks like coverage while hiding the gap. So when you add one, break the behaviour (or run the test against the pre-fix code), watch it fail, then restore the fix and watch it pass.
|
|
||||||
|
|
||||||
## CI
|
|
||||||
|
|
||||||
- Forgejo Actions, `.forgejo/workflows/ci.yml`, a single `ci` job that runs lint, the unit tests, the debug and nightly assembles and the integration suite (one cache restore/save and Gradle warm-up instead of several); the GitHub copy uploads the debug and nightly APKs and the checksums as separate artifacts on a push to `main`.
|
|
||||||
- Runs on the `nix-docker` runner (the `localhost/nix-ci` image built by the separate `nix-home` repo) inside the devshell, restoring the Nix store via `cache-nix-action` and caching Gradle and the integration test music.
|
|
||||||
- The `nix-docker` and `bookworm` runner labels, their images and the runner's networking are defined in the separate `nix-home` repo (`hosts-incus/git-runner.nix`).
|
|
||||||
- Pull requests from a fork need approval before the workflow runs.
|
|
||||||
- The GitHub mirror and the GitHub PR import live under `.forgejo/`; see `.forgejo/README.md`.
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- Prefer self-explanatory code; do not add comments unless the reason cannot be inferred from the code itself (docstrings for functions and exports are fine).
|
|
||||||
- ktlint (`org.jlleitschuh.gradle.ktlint`) enforces style and flags unused imports; run `gradle :app:ktlintFormat` before committing. `.editorconfig` exempts `@Composable` functions from the lowerCamelCase function-naming rule.
|
|
||||||
- Room 3 (`androidx.room3`) on AndroidX `sqlite-bundled` (`BundledSQLiteDriver`, SQLite 3.50+). Do not reintroduce SQLDelight or the platform SQLite.
|
|
||||||
- Networking uses OkHttp and DOM XML parsing; auth uses the Subsonic token scheme by default.
|
|
||||||
- Use coroutines and `Flow`; library reads are exposed as `Flow` from Room. Large lists page with Paging 3 over Room `PagingSource` rather than loading the whole table.
|
|
||||||
- The library is mirrored in full at sync and must work offline. Never fetch library metadata on demand for browsing, filtering or sorting; only media bytes (streams, downloads) and images are on-demand. A server-derived sort key must be synced into a local column, not requested lazily when the sort is selected.
|
|
||||||
- Auto-sync is a foreground-only, in-process timer (`AutoSync`, driven by the Activity lifecycle), not a background worker: do not move it to WorkManager or an alarm. `SyncManager` coalesces a request that arrives while a sync is running into a single follow-up; the library and Home sync actions no-op while one is running.
|
|
||||||
- Playback is Media3: `PlaybackService` is a `MediaSessionService` owning an `ExoPlayer`, and `PlaybackController` (app-scoped Koin singleton) is the only thing the UI talks to. The queue is a `queue_entries` list of references with optional ranges plus a `playback_cursor` row; keep only a bounded window in memory (never the whole queue, and never load a whole table to build one). Stream URLs are freshly salted per request, so attach artwork by `CoverArtRef` cache key, not by URL.
|
|
||||||
- UI state lives in `androidx.lifecycle.ViewModel`, wired with Koin (`koinViewModel()`); screens split into a stateful `*Route` and a stateless `*Screen` for screenshot tests.
|
|
||||||
- UI and playback preferences go in DataStore (`UserPreferences`), not Room.
|
|
||||||
- Verify current dependency versions and their compatibility before adding or pinning anything.
|
|
||||||
|
|
||||||
## Gotchas
|
|
||||||
|
|
||||||
- Robolectric runs at SDK 35 while `targetSdk` is 37; raising it changes the on-demand Roborazzi renders (there are no committed goldens to re-record).
|
|
||||||
- Room 3 does not map `PagingSource` automatically: a DAO that returns it needs `@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)`.
|
|
||||||
- Material icons are not pulled in by `material3`; use the BOM-managed `material-icons-core`/`material-icons-extended` (frozen at 1.7.8). Extended is large in debug builds but R8 strips unused icons from release.
|
|
||||||
- Robolectric creates a fresh `Application` per test in one JVM, so `SubtracksApp.onCreate` stops any running Koin before `startKoin`.
|
|
||||||
- The CI image provides `nix-ld`, `jq`, `sqlite`, `node`, `zstd` and a `runner` user that `cache-nix-action` expects. None of that is needed locally beyond the devshell.
|
|
||||||
- Integration servers: navidrome on 4533 (`admin`/`password`), gonic on 4747 (`admin`/`admin`), lms on 5082 (`admin`/`subtracks-lms`), Nextcloud Music on 8090 (`admin`/`subtracks-nextcloud`, base URL `http://localhost:8090/index.php/apps/music/subsonic/`). The test music is cached in `.integration/music` (gitignored).
|
|
||||||
- lms and Nextcloud Music authenticate the Subsonic API with per-user **API keys** instead of passwords. The harness seeds a key and most tests use `useTokenAuth = false`; `SubsonicAuthIntegrationTest` drives `useTokenAuth = true` and asserts the fallback to plaintext (lms answers code 42, Nextcloud 41).
|
|
||||||
- `nix develop` does not source your shell rc files (so tools like atuin are not active); use direnv if you want your normal interactive shell.
|
|
||||||
- The store screenshots in `metadata/en-US/images/phoneScreenshots/` must be 24-bit no-alpha PNGs (Play rejects palette and alpha PNGs for screenshots). `:app:demoScreenshots` writes its captures in that form, so copy them across as-is and don't run a palette optimizer over them.
|
|
||||||
@@ -1,24 +1,29 @@
|
|||||||
<h1><img src=".assets/logo.png" alt="subtracks logo" width="44" align="texttop" /> subtracks</h1>
|
|
||||||
|
|
||||||
[](https://f-droid.org/en/packages/com.subtracks)
|
|
||||||
[](https://github.com/austinried/subtracks/releases/latest/)
|
|
||||||
[](https://github.com/austinried/subtracks/releases/)
|
|
||||||
<a href="https://hosted.weblate.org/engage/subtracks/"><img src="https://hosted.weblate.org/widget/subtracks/svg-badge.svg" alt="Translation status"></a>
|
|
||||||
[](LICENSE)
|
|
||||||
|
|
||||||
subtracks is an open source Android client for [Subsonic-compatible](http://www.subsonic.org/pages/api.jsp) servers ([Navidrome](https://www.navidrome.org/), [gonic](https://github.com/sentriz/gonic), [LMS](https://github.com/epoupon/lms), [Nextcloud Music](https://apps.nextcloud.com/apps/music) and more). It is written natively in Kotlin and Jetpack Compose and gives you clean, convenient access to your music in the style of a modern media player.
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="metadata/en-US/images/phoneScreenshots/01_home.png"><img src="metadata/en-US/images/phoneScreenshots/01_home.png" alt="home" width="150"/></a>
|
|
||||||
<a href="metadata/en-US/images/phoneScreenshots/02_now-playing.png"><img src="metadata/en-US/images/phoneScreenshots/02_now-playing.png" alt="now playing" width="150"/></a>
|
<img src=".assets/header.png" alt="subtracks logo" width="500"/>
|
||||||
<a href="metadata/en-US/images/phoneScreenshots/03_library-albums.png"><img src="metadata/en-US/images/phoneScreenshots/03_library-albums.png" alt="albums" width="150"/></a>
|
|
||||||
<a href="metadata/en-US/images/phoneScreenshots/04_album.png"><img src="metadata/en-US/images/phoneScreenshots/04_album.png" alt="album" width="150"/></a>
|
#
|
||||||
<a href="metadata/en-US/images/phoneScreenshots/05_artist.png"><img src="metadata/en-US/images/phoneScreenshots/05_artist.png" alt="artist" width="150"/></a>
|
|
||||||
|
#### Subtracks is an Android open source music streaming app for [Subsonic-compatible](http://www.subsonic.org/pages/api.jsp) servers ([Subsonic](http://www.subsonic.org/pages/index.jsp), [Navidrome](https://www.navidrome.org/), [Airsonic](https://airsonic.github.io/), and more). It's designed to give you clean and convenient access to your music in the style of modern media players.
|
||||||
|
|
||||||
|

|
||||||
|
[](https://github.com/austinried/subtracks/releases/latest/)
|
||||||
|
[](https://f-droid.org/en/packages/com.subtracks)
|
||||||
|
[](https://github.com/austinried/subtracks/releases/)
|
||||||
|
[](https://github.com/austinried/subtracks/stargazers)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Download
|
|
||||||
|
## 📱 Screenshots
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="metadata/en-US/images/phoneScreenshots/01_home.png" alt="home" width="200"/>
|
||||||
|
<img src="metadata/en-US/images/phoneScreenshots/02_now-playing.png" alt="now playing" width="200"/>
|
||||||
|
<img src="metadata/en-US/images/phoneScreenshots/03_library-albums.png" alt="library albums" width="200"/>
|
||||||
|
<img src="metadata/en-US/images/phoneScreenshots/04_album.png" alt="album view" width="200"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## ⬇️ Download
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.subtracks"><img src=".assets/google-play-badge.png" width="250"/></a>
|
<a href="https://play.google.com/store/apps/details?id=com.subtracks"><img src=".assets/google-play-badge.png" width="250"/></a>
|
||||||
@@ -26,55 +31,47 @@ subtracks is an open source Android client for [Subsonic-compatible](http://www.
|
|||||||
<a href="https://github.com/austinried/subtracks/releases/"><img src=".assets/github-badge.png" width="250"/></a>
|
<a href="https://github.com/austinried/subtracks/releases/"><img src=".assets/github-badge.png" width="250"/></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
See [signing/README.md](signing/README.md) for the fingerprints and the commands to verify a download.
|
>**Warning**
|
||||||
|
>
|
||||||
|
>Each download source above is signed with a different key, so you cannot switch between them without first uninstalling and then re-installing the app.
|
||||||
|
|
||||||
## Features
|
## ✨ Features
|
||||||
|
|
||||||
- **Large Libraries:** Built for very large libraries, from syncing the whole collection to playing playlists with thousands of tracks.
|
- Album and artist art display by default (full-res in detail/now playing views)
|
||||||
- **Downloads:** Song and bulk downloads, with download quality (encoding, bitrate) and metered-connection settings.
|
- Gapless playback
|
||||||
- **Offline Mode:** Stars, scrobbles and play counts queue up while you're offline and sync back to the server when you're online again.
|
- Mulitple server support
|
||||||
- **Artwork-first:** Album and artist art everywhere, shown full-resolution in the detail and now playing views.
|
- Filterable/sortable album and artist library views
|
||||||
- **Adaptive Theming:** Colours drawn from the current song's artwork.
|
- Search artists, albums, and songs
|
||||||
- **Search:** Fast search across the whole library, with per-list sort and filter controls.
|
- Scrobble support
|
||||||
- **Playback:** Gapless playback, an editable queue you can reorder and jump through, plus loop and shuffle modes.
|
- Max bitrate and buffer size settings
|
||||||
- **Up Next:** Add items into the currently playing queue without rewriting it.
|
- Loop and shuffle playback options
|
||||||
- **Multiple Servers:** Connect several servers and switch between them quickly.
|
- Long-press for context menu shortcuts
|
||||||
- **Stream Quality:** Bitrate and format settings for Wi-Fi and mobile, with automatic switching.
|
|
||||||
- **System Controls:** Media notification and headset/Bluetooth controls.
|
|
||||||
|
|
||||||
## Building
|
## 🔜 Coming Soon™
|
||||||
|
|
||||||
The project's entire toolchain is provided by a Nix flake. The default devshell provides JDK, Gradle and the Android SDK, so there is nothing to install by hand.
|
- Offline support
|
||||||
|
- Customizable home screen categories
|
||||||
|
- Browse by folder support (currently only browses by tags)
|
||||||
|
- Multiple music folder awareness
|
||||||
|
- By year/by genre albums filter
|
||||||
|
- Playlist mangement (add/remove/sort/edit)
|
||||||
|
- Queue management (add/remove/sort)
|
||||||
|
- Multi-select actions
|
||||||
|
- Performance & animation improvements
|
||||||
|
- More shuffle play modes
|
||||||
|
|
||||||
Therefore, to get started, you'll need to install Nix. I prefer [Lix](https://lix.systems/install/).
|
## ⚙️ Building
|
||||||
|
|
||||||
```sh
|
See [Building from source](BUILDING.md).
|
||||||
nix develop
|
|
||||||
gradle :app:assembleDebug
|
|
||||||
```
|
|
||||||
|
|
||||||
Test, lint and screenshot commands, plus the integration harness, are documented in [AGENTS.md](AGENTS.md). The architecture is described in [docs/architecture.md](docs/architecture.md).
|
## 🔤 Translations
|
||||||
|
|
||||||
## Contributing
|
Want to see Subtracks in your language? Visit the project on [Weblate](https://hosted.weblate.org/engage/subtracks/) to help!
|
||||||
|
|
||||||
The GitHub repository [austinried/subtracks](https://github.com/austinried/subtracks) is a mirror of the repo hosted on my personal (private) code forge that syncs whenever I commit to it.
|
|
||||||
|
|
||||||
Bug reports and feature requests are accepted on GitHub, as well as pull requests, but:
|
|
||||||
* A well-crafted issue with clear reproduction and logs for bugs or mock-ups and use case details for features is preferred over a pull request
|
|
||||||
* Pull requests will be pulled in as patches to my code forge and then synced back (you'll still be the author, I'll be shown as the committer)
|
|
||||||
|
|
||||||
## Translations
|
|
||||||
|
|
||||||
Want to see subtracks in your language? Visit the project on [Weblate](https://hosted.weblate.org/engage/subtracks/) to help!
|
|
||||||
|
|
||||||
<a href="https://hosted.weblate.org/engage/subtracks/">
|
<a href="https://hosted.weblate.org/engage/subtracks/">
|
||||||
<img src="https://hosted.weblate.org/widget/subtracks/subtracks/multi-auto.svg" alt="Translation status" />
|
<img src="https://hosted.weblate.org/widgets/subtracks/-/subtracks/multi-auto.svg" alt="Translation status" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
## AI usage disclosure
|
## 📃 License
|
||||||
|
|
||||||
This project contains code and documentation generated by LLM, which is created via human prompting, iteration and review. The current native rewrite is based on two (and a half) other iterations of this project that I coded by hand, so the architecture and other decisions behind that are all still coming from me.
|
[](https://github.com/austinried/subtracks/blob/main/LICENSE)
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
subtracks is free software, licensed under the [GNU General Public License v3.0](LICENSE). It has no ads and no telemetry, and uses only free/libre dependencies.
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
## To-do
|
||||||
|
- Star/unstar
|
||||||
|
- Context menus
|
||||||
|
- Download actions for song
|
||||||
|
- Playlist management
|
||||||
|
- Add to playlist (from context)
|
||||||
|
- Queue management
|
||||||
|
- View playing queue
|
||||||
|
- Re-order queue
|
||||||
|
- Add to queue (from context)
|
||||||
|
- Remove from queue
|
||||||
|
- Scrobbling
|
||||||
|
- Library filters (year/genre/etc)
|
||||||
|
- Library list display modes
|
||||||
|
- Search
|
||||||
|
- Individual "more" results pages
|
||||||
|
- Now playing gestures
|
||||||
|
- Swipe bar/album to skip
|
||||||
|
- Double-tap to seek forward/back (bar only)
|
||||||
|
- Settings
|
||||||
|
- Music
|
||||||
|
- Scrobble
|
||||||
|
- Downloads
|
||||||
|
- Used/available space
|
||||||
|
- Clear downloads
|
||||||
|
- Clear images
|
||||||
|
- About
|
||||||
|
- Licenses
|
||||||
|
- Welcome/setup flow
|
||||||
|
- Proper loading screen/animation
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
prefer_relative_imports: true
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- '**.freezed.dart'
|
||||||
|
- '**.g.dart'
|
||||||
|
- '**.gr.dart'
|
||||||
|
plugins:
|
||||||
|
# broken currently and may not get fixed
|
||||||
|
# https://github.com/simolus3/drift/issues/2342
|
||||||
|
# - drift
|
||||||
|
|
||||||
|
# also broken but only recently reported
|
||||||
|
# https://github.com/rrousselGit/riverpod/issues/2180
|
||||||
|
# - custom_lint
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
gradle-wrapper.jar
|
||||||
|
/.gradle
|
||||||
|
/captures/
|
||||||
|
/gradlew
|
||||||
|
/gradlew.bat
|
||||||
|
/local.properties
|
||||||
|
GeneratedPluginRegistrant.java
|
||||||
|
|
||||||
|
# Remember to never publicly share your keystore.
|
||||||
|
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||||
|
key.properties
|
||||||
|
**/*.keystore
|
||||||
|
**/*.jks
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
def localProperties = new Properties()
|
||||||
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
|
if (localPropertiesFile.exists()) {
|
||||||
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||||
|
localProperties.load(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
flutterVersionCode = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
flutterVersionName = '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
def keystoreProperties = new Properties()
|
||||||
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion flutter.compileSdkVersion
|
||||||
|
ndkVersion flutter.ndkVersion
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
|
applicationId "com.subtracks2"
|
||||||
|
// You can update the following values to match your application needs.
|
||||||
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||||
|
minSdkVersion 19
|
||||||
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
|
versionCode flutterVersionCode.toInteger()
|
||||||
|
versionName flutterVersionName
|
||||||
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
release {
|
||||||
|
keyAlias keystoreProperties['keyAlias']
|
||||||
|
keyPassword keystoreProperties['keyPassword']
|
||||||
|
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||||
|
storePassword keystoreProperties['storePassword']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
if (project.hasProperty("signRelease")) {
|
||||||
|
signingConfig signingConfigs.release
|
||||||
|
} else {
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flutter {
|
||||||
|
source '../..'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.subtracks2">
|
||||||
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
|
the Flutter tool needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<manifest
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="com.subtracks2">
|
||||||
|
<application
|
||||||
|
android:label="subtracks"
|
||||||
|
android:name="${applicationName}"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:usesCleartextTraffic="true">
|
||||||
|
<activity
|
||||||
|
android:name="com.ryanheise.audioservice.AudioServiceActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
|
the Android process has started. This theme is visible to the user
|
||||||
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
|
to determine the Window background behind the Flutter UI. -->
|
||||||
|
<meta-data
|
||||||
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
|
android:resource="@style/NormalTheme" />
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<service
|
||||||
|
android:name="com.ryanheise.audioservice.AudioService"
|
||||||
|
android:foregroundServiceType="mediaPlayback"
|
||||||
|
android:exported="true"
|
||||||
|
tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<service
|
||||||
|
android:name="com.ryanheise.audioservice.AudioService"
|
||||||
|
android:foregroundServiceType="mediaPlayback"
|
||||||
|
android:exported="true"
|
||||||
|
tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<receiver
|
||||||
|
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
||||||
|
android:exported="true"
|
||||||
|
tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- Don't delete the meta-data below.
|
||||||
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
<meta-data
|
||||||
|
android:name="flutterEmbedding"
|
||||||
|
android:value="2" />
|
||||||
|
<!-- <meta-data
|
||||||
|
android:name="io.flutter.embedding.android.EnableImpeller"
|
||||||
|
android:value="true" /> -->
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<!-- audio_service -->
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
</manifest>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,25 @@
|
|||||||
|
// Generated file.
|
||||||
|
//
|
||||||
|
// If you wish to remove Flutter's multidex support, delete this entire file.
|
||||||
|
//
|
||||||
|
// Modifications to this file should be done in a copy under a different name
|
||||||
|
// as this file may be regenerated.
|
||||||
|
|
||||||
|
package io.flutter.app;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.annotation.CallSuper;
|
||||||
|
import androidx.multidex.MultiDex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link android.app.Application}, adding multidex support.
|
||||||
|
*/
|
||||||
|
public class FlutterMultiDexApplication extends Application {
|
||||||
|
@Override
|
||||||
|
@CallSuper
|
||||||
|
protected void attachBaseContext(Context base) {
|
||||||
|
super.attachBaseContext(base);
|
||||||
|
MultiDex.install(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.subtracks2
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
|
class MainActivity: FlutterActivity() {
|
||||||
|
}
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="300"
|
android:viewportWidth="299.84"
|
||||||
android:viewportHeight="300"
|
android:viewportHeight="219.51"
|
||||||
tools:ignore="UnusedResources">
|
android:tint="#333333"
|
||||||
<group android:translateY="40.25">
|
android:alpha="0.6">
|
||||||
|
<group android:scaleY="0.7320905"
|
||||||
|
android:translateY="29.404413">
|
||||||
<path
|
<path
|
||||||
android:pathData="m23.84,-0c-12.76,0 -23.44,13 -23.65,25.12 -0.42,79.03 0,160.73 0,170.4 0,12.59 9.8,23.99 23.41,23.99l253.58,0c11.4,0 22.66,-12.38 22.66,-22.79L299.84,24.12c0,-10.8 -10.24,-23.81 -21.84,-23.81 -11.6,0 -254.16,-0.31 -254.16,-0.31zM39.05,25.28c0,0 217.71,0.71 223.67,0.71 6.07,0 12.17,6.83 12.17,12.06l0,142.25c0,8.97 -6.97,14.63 -12.48,14.64l-33.42,0.07c-5.32,0.01 -9.93,-7.19 -11.35,-10.61 -1.89,-4.55 -11.08,-25.75 -12.1,-28.1 -0.6,-1.38 -2.9,-2.83 -5.89,-2.83L98.33,153.45c-2.68,0 -4.89,2.87 -5.67,4.71 -1.12,2.66 -9.02,21.39 -11.63,27.57 -2.73,6.46 -4.37,9.06 -11.47,9.06l-30.97,0c-7.44,0 -13.69,-7.17 -13.67,-15.18l0.28,-139.51c0,-6.88 5.54,-14.83 13.85,-14.83z"
|
android:pathData="m23.84,-0c-12.76,0 -23.44,13 -23.65,25.12 -0.42,79.03 0,160.73 0,170.4 0,12.59 9.8,23.99 23.41,23.99l253.58,0c11.4,0 22.66,-12.38 22.66,-22.79L299.84,24.12c0,-10.8 -10.24,-23.81 -21.84,-23.81 -11.6,0 -254.16,-0.31 -254.16,-0.31zM39.05,25.28c0,0 217.71,0.71 223.67,0.71 6.07,0 12.17,6.83 12.17,12.06l0,142.25c0,8.97 -6.97,14.63 -12.48,14.64l-33.42,0.07c-5.32,0.01 -9.93,-7.19 -11.35,-10.61 -1.89,-4.55 -11.08,-25.75 -12.1,-28.1 -0.6,-1.38 -2.9,-2.83 -5.89,-2.83L98.33,153.45c-2.68,0 -4.89,2.87 -5.67,4.71 -1.12,2.66 -9.02,21.39 -11.63,27.57 -2.73,6.46 -4.37,9.06 -11.47,9.06l-30.97,0c-7.44,0 -13.69,-7.17 -13.67,-15.18l0.28,-139.51c0,-6.88 5.54,-14.83 13.85,-14.83z"
|
||||||
android:strokeWidth="0.9"
|
android:strokeWidth="0.9"
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="#ffffff"
|
||||||
android:fillType="nonZero"
|
android:fillType="nonZero"
|
||||||
android:strokeColor="#00000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M90.09,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
android:pathData="M90.09,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
||||||
android:strokeWidth="0.86"
|
android:strokeWidth="0.86"
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="#ffffff"
|
||||||
android:fillType="nonZero"
|
android:fillType="nonZero"
|
||||||
android:strokeColor="#00000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M209.94,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
android:pathData="M209.94,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
||||||
android:strokeWidth="0.86"
|
android:strokeWidth="0.86"
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="#ffffff"
|
||||||
android:fillType="nonZero"
|
android:fillType="nonZero"
|
||||||
android:strokeColor="#00000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
</group>
|
</group>
|
||||||
|
After Width: | Height: | Size: 441 B |
|
After Width: | Height: | Size: 401 B |
|
After Width: | Height: | Size: 318 B |
|
After Width: | Height: | Size: 284 B |
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="?android:colorBackground" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
||||||
|
After Width: | Height: | Size: 600 B |
|
After Width: | Height: | Size: 575 B |
|
After Width: | Height: | Size: 925 B |
|
After Width: | Height: | Size: 921 B |
@@ -10,19 +10,19 @@
|
|||||||
<path
|
<path
|
||||||
android:pathData="m23.84,-0c-12.76,0 -23.44,13 -23.65,25.12 -0.42,79.03 0,160.73 0,170.4 0,12.59 9.8,23.99 23.41,23.99l253.58,0c11.4,0 22.66,-12.38 22.66,-22.79L299.84,24.12c0,-10.8 -10.24,-23.81 -21.84,-23.81 -11.6,0 -254.16,-0.31 -254.16,-0.31zM39.05,25.28c0,0 217.71,0.71 223.67,0.71 6.07,0 12.17,6.83 12.17,12.06l0,142.25c0,8.97 -6.97,14.63 -12.48,14.64l-33.42,0.07c-5.32,0.01 -9.93,-7.19 -11.35,-10.61 -1.89,-4.55 -11.08,-25.75 -12.1,-28.1 -0.6,-1.38 -2.9,-2.83 -5.89,-2.83L98.33,153.45c-2.68,0 -4.89,2.87 -5.67,4.71 -1.12,2.66 -9.02,21.39 -11.63,27.57 -2.73,6.46 -4.37,9.06 -11.47,9.06l-30.97,0c-7.44,0 -13.69,-7.17 -13.67,-15.18l0.28,-139.51c0,-6.88 5.54,-14.83 13.85,-14.83z"
|
android:pathData="m23.84,-0c-12.76,0 -23.44,13 -23.65,25.12 -0.42,79.03 0,160.73 0,170.4 0,12.59 9.8,23.99 23.41,23.99l253.58,0c11.4,0 22.66,-12.38 22.66,-22.79L299.84,24.12c0,-10.8 -10.24,-23.81 -21.84,-23.81 -11.6,0 -254.16,-0.31 -254.16,-0.31zM39.05,25.28c0,0 217.71,0.71 223.67,0.71 6.07,0 12.17,6.83 12.17,12.06l0,142.25c0,8.97 -6.97,14.63 -12.48,14.64l-33.42,0.07c-5.32,0.01 -9.93,-7.19 -11.35,-10.61 -1.89,-4.55 -11.08,-25.75 -12.1,-28.1 -0.6,-1.38 -2.9,-2.83 -5.89,-2.83L98.33,153.45c-2.68,0 -4.89,2.87 -5.67,4.71 -1.12,2.66 -9.02,21.39 -11.63,27.57 -2.73,6.46 -4.37,9.06 -11.47,9.06l-30.97,0c-7.44,0 -13.69,-7.17 -13.67,-15.18l0.28,-139.51c0,-6.88 5.54,-14.83 13.85,-14.83z"
|
||||||
android:strokeWidth="0.9"
|
android:strokeWidth="0.9"
|
||||||
android:fillColor="#F862F8"
|
android:fillColor="#f4d9ff"
|
||||||
android:fillType="nonZero"
|
android:fillType="nonZero"
|
||||||
android:strokeColor="#00000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M90.09,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
android:pathData="M90.09,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
||||||
android:strokeWidth="0.86"
|
android:strokeWidth="0.86"
|
||||||
android:fillColor="#F862F8"
|
android:fillColor="#f4d9ff"
|
||||||
android:fillType="nonZero"
|
android:fillType="nonZero"
|
||||||
android:strokeColor="#00000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M209.94,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
android:pathData="M209.94,95.03m-32.1,0a32.42,32.1 90,1 1,64.21 0a32.42,32.1 90,1 1,-64.21 0"
|
||||||
android:strokeWidth="0.86"
|
android:strokeWidth="0.86"
|
||||||
android:fillColor="#F862F8"
|
android:fillColor="#f4d9ff"
|
||||||
android:fillType="nonZero"
|
android:fillType="nonZero"
|
||||||
android:strokeColor="#00000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
</group>
|
</group>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@android:color/white" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
||||||
@@ -2,5 +2,4 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -2,5 +2,4 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:keep="@drawable/*" />
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
the Flutter engine draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="ic_launcher_background">#120C12</color>
|
<color name="ic_launcher_background">#6A1B9A</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
the Flutter engine draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.subtracks2">
|
||||||
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
|
the Flutter tool needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.7.10'
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:7.2.0'
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.buildDir = '../build'
|
||||||
|
subprojects {
|
||||||
|
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||||
|
}
|
||||||
|
subprojects {
|
||||||
|
project.evaluationDependsOn(':app')
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
|
|
||||||
distributionSha256Sum=acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a
|
|
||||||
networkTimeout=10000
|
|
||||||
retries=0
|
|
||||||
retryBackOffMs=500
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn ( ) {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die ( ) {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||||
|
function splitJvmOpts() {
|
||||||
|
JVM_OPTS=("$@")
|
||||||
|
}
|
||||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windowz variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
goto execute
|
||||||
|
|
||||||
|
:4NT_args
|
||||||
|
@rem Get arguments from the 4NT Shell from JP Software
|
||||||
|
set CMD_LINE_ARGS=%$
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
include ':app'
|
||||||
|
|
||||||
|
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
||||||
|
def properties = new Properties()
|
||||||
|
|
||||||
|
assert localPropertiesFile.exists()
|
||||||
|
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||||
|
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
alias(libs.plugins.android.application)
|
|
||||||
alias(libs.plugins.compose.compiler)
|
|
||||||
alias(libs.plugins.roborazzi)
|
|
||||||
alias(libs.plugins.ksp)
|
|
||||||
alias(libs.plugins.ktlint)
|
|
||||||
alias(libs.plugins.aboutLibraries)
|
|
||||||
}
|
|
||||||
|
|
||||||
ktlint {
|
|
||||||
version.set(libs.versions.ktlint.get())
|
|
||||||
}
|
|
||||||
|
|
||||||
val commitHash: String =
|
|
||||||
runCatching {
|
|
||||||
providers
|
|
||||||
.exec {
|
|
||||||
commandLine("git", "rev-parse", "HEAD")
|
|
||||||
workingDir = rootProject.layout.projectDirectory.asFile
|
|
||||||
isIgnoreExitValue = true
|
|
||||||
}.standardOutput.asText
|
|
||||||
.get()
|
|
||||||
.trim()
|
|
||||||
.take(7)
|
|
||||||
}.getOrDefault("")
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "com.subtracks"
|
|
||||||
compileSdk = 37
|
|
||||||
buildToolsVersion = "37.0.0"
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId = "com.subtracks"
|
|
||||||
minSdk = 24
|
|
||||||
targetSdk = 37
|
|
||||||
versionCode = 13
|
|
||||||
versionName = "3.0.0"
|
|
||||||
buildConfigField("String", "COMMIT_HASH", "\"$commitHash\"")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildFeatures {
|
|
||||||
compose = true
|
|
||||||
buildConfig = true
|
|
||||||
}
|
|
||||||
|
|
||||||
androidResources {
|
|
||||||
generateLocaleConfig = true
|
|
||||||
}
|
|
||||||
|
|
||||||
dependenciesInfo {
|
|
||||||
// The APK signing-block copy is encrypted per build, breaking APK reproducibility, and
|
|
||||||
// F-Droid rejects it; the bundle keeps its copy for Play.
|
|
||||||
includeInApk = false
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
isCoreLibraryDesugaringEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
lint {
|
|
||||||
checkReleaseBuilds = false
|
|
||||||
warningsAsErrors = true
|
|
||||||
disable +=
|
|
||||||
setOf(
|
|
||||||
"MissingTranslation",
|
|
||||||
"MissingQuantity",
|
|
||||||
// Version nags are handled by the dependency-update process, not the build.
|
|
||||||
"AndroidGradlePluginVersion",
|
|
||||||
"GradleDependency",
|
|
||||||
"NewerVersionAvailable",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
packaging {
|
|
||||||
jniLibs {
|
|
||||||
// Prebuilt .so files with no symbol table; leaving them unstripped avoids the strip warning.
|
|
||||||
keepDebugSymbols +=
|
|
||||||
setOf(
|
|
||||||
"**/libandroidx.graphics.path.so",
|
|
||||||
"**/libdatastore_shared_counter.so",
|
|
||||||
"**/libsqliteJni.so",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testOptions {
|
|
||||||
unitTests {
|
|
||||||
isIncludeAndroidResources = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets
|
|
||||||
.getByName("test")
|
|
||||||
.kotlin.directories
|
|
||||||
.add("src/integrationTest/kotlin")
|
|
||||||
|
|
||||||
signingConfigs {
|
|
||||||
// Committed on purpose: a public key for debug and nightly builds, never for distribution.
|
|
||||||
getByName("debug") {
|
|
||||||
storeFile = file("debug.keystore")
|
|
||||||
storePassword = "android"
|
|
||||||
keyAlias = "androiddebugkey"
|
|
||||||
keyPassword = "android"
|
|
||||||
}
|
|
||||||
val keystorePath = providers.environmentVariable("RELEASE_KEYSTORE").orNull
|
|
||||||
if (keystorePath != null) {
|
|
||||||
create("release") {
|
|
||||||
storeFile = file(keystorePath)
|
|
||||||
storePassword = providers.environmentVariable("RELEASE_KEYSTORE_PASSWORD").orNull
|
|
||||||
keyAlias = providers.environmentVariable("RELEASE_KEY_ALIAS").orNull
|
|
||||||
keyPassword = providers.environmentVariable("RELEASE_KEY_PASSWORD").orNull
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
getByName("debug").res.srcDir("src/nightly/res")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
debug {
|
|
||||||
applicationIdSuffix = ".nightly"
|
|
||||||
}
|
|
||||||
release {
|
|
||||||
isMinifyEnabled = true
|
|
||||||
isShrinkResources = true
|
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
|
|
||||||
// Release signing when the keystore is supplied (CI); debug elsewhere so local build/install works.
|
|
||||||
signingConfig = signingConfigs.findByName("release") ?: signingConfigs.getByName("debug")
|
|
||||||
}
|
|
||||||
create("nightly") {
|
|
||||||
initWith(getByName("release"))
|
|
||||||
applicationIdSuffix = ".nightly"
|
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
compilerOptions {
|
|
||||||
jvmTarget.set(JvmTarget.JVM_17)
|
|
||||||
allWarningsAsErrors.set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
roborazzi {
|
|
||||||
outputDir.set(file("src/test/screenshots"))
|
|
||||||
}
|
|
||||||
|
|
||||||
ksp {
|
|
||||||
arg("room.schemaLocation", "$projectDir/schemas")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolving the variant classpaths here makes AGP warn that a configuration was resolved during
|
|
||||||
// configuration time; upstream, tracked in mikepenz/AboutLibraries#1369.
|
|
||||||
aboutLibraries {
|
|
||||||
collect {
|
|
||||||
configPath = file("config")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val integrationTestClasses =
|
|
||||||
listOf(
|
|
||||||
"com.subtracks.data.source.subsonic.SubsonicAuthIntegrationTest",
|
|
||||||
"com.subtracks.data.source.subsonic.SubsonicErrorIntegrationTest",
|
|
||||||
"com.subtracks.data.source.subsonic.SubsonicMediaIntegrationTest",
|
|
||||||
"com.subtracks.data.source.subsonic.SubsonicSourceIntegrationTest",
|
|
||||||
"com.subtracks.data.source.subsonic.SubsonicWriteIntegrationTest",
|
|
||||||
"com.subtracks.data.sync.MultiSourceSyncIntegrationTest",
|
|
||||||
"com.subtracks.data.sync.PruneSyncIntegrationTest",
|
|
||||||
"com.subtracks.data.sync.SyncServiceIntegrationTest",
|
|
||||||
)
|
|
||||||
|
|
||||||
val demoScreenshotClass = "com.subtracks.ui.DemoScreenshotTest"
|
|
||||||
|
|
||||||
val queryTimingClass = "com.subtracks.data.db.QueryTimingMeasurementTest"
|
|
||||||
|
|
||||||
tasks.withType<Test>().configureEach {
|
|
||||||
if (name.endsWith("UnitTest")) {
|
|
||||||
filter {
|
|
||||||
(integrationTestClasses + demoScreenshotClass + queryTimingClass).forEach { excludeTestsMatching(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
testLogging {
|
|
||||||
exceptionFormat = TestExceptionFormat.FULL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register<Test>("integrationTest") {
|
|
||||||
description = "Runs the integration tests against locally started Subsonic servers"
|
|
||||||
group = "verification"
|
|
||||||
val unitTest = tasks.named<Test>("testDebugUnitTest")
|
|
||||||
dependsOn("compileDebugUnitTestKotlin")
|
|
||||||
testClassesDirs = files(provider { unitTest.get().testClassesDirs })
|
|
||||||
classpath = files(provider { unitTest.get().classpath })
|
|
||||||
filter {
|
|
||||||
integrationTestClasses.forEach { includeTestsMatching(it) }
|
|
||||||
}
|
|
||||||
systemProperty("prune.baseUrl", providers.gradleProperty("pruneBaseUrl").getOrElse(""))
|
|
||||||
systemProperty("prune.musicDir", providers.gradleProperty("pruneMusicDir").getOrElse(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register<Test>("demoScreenshots") {
|
|
||||||
description = "Records the store screenshots from a real sync of the public Navidrome demo library"
|
|
||||||
group = "verification"
|
|
||||||
val unitTest = tasks.named<Test>("testDebugUnitTest")
|
|
||||||
dependsOn("compileDebugUnitTestKotlin")
|
|
||||||
testClassesDirs = files(provider { unitTest.get().testClassesDirs })
|
|
||||||
classpath = files(provider { unitTest.get().classpath })
|
|
||||||
filter {
|
|
||||||
includeTestsMatching(demoScreenshotClass)
|
|
||||||
}
|
|
||||||
systemProperty("roborazzi.test.record", "true")
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register<Test>("queryTiming") {
|
|
||||||
description = "Measures SQL query timings for the logging threshold (not a CI gate)"
|
|
||||||
group = "verification"
|
|
||||||
val unitTest = tasks.named<Test>("testDebugUnitTest")
|
|
||||||
dependsOn("compileDebugUnitTestKotlin")
|
|
||||||
testClassesDirs = files(provider { unitTest.get().testClassesDirs })
|
|
||||||
classpath = files(provider { unitTest.get().classpath })
|
|
||||||
filter {
|
|
||||||
includeTestsMatching(queryTimingClass)
|
|
||||||
}
|
|
||||||
providers.gradleProperty("measureSongs").orNull?.let { systemProperty("measure.songs", it) }
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(platform(libs.androidx.compose.bom))
|
|
||||||
implementation(libs.androidx.core.ktx)
|
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
|
||||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
|
||||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
|
||||||
implementation(libs.androidx.activity.compose)
|
|
||||||
implementation(libs.androidx.navigation.compose)
|
|
||||||
implementation(libs.androidx.compose.ui)
|
|
||||||
implementation(libs.androidx.compose.ui.graphics)
|
|
||||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
|
||||||
implementation(libs.androidx.compose.material3)
|
|
||||||
implementation(libs.androidx.compose.material.icons.core)
|
|
||||||
implementation(libs.androidx.compose.material.icons.extended)
|
|
||||||
implementation(libs.kotlinx.coroutines.android)
|
|
||||||
implementation(libs.androidx.sqlite.bundled)
|
|
||||||
implementation(libs.androidx.room3.runtime)
|
|
||||||
implementation(libs.androidx.room3.sqlite.wrapper)
|
|
||||||
implementation(libs.androidx.room3.paging)
|
|
||||||
implementation(libs.androidx.paging.compose)
|
|
||||||
implementation(libs.androidx.palette)
|
|
||||||
implementation(libs.reorderable)
|
|
||||||
implementation(libs.androidx.datastore.preferences)
|
|
||||||
implementation(libs.androidx.media3.exoplayer)
|
|
||||||
implementation(libs.androidx.media3.session)
|
|
||||||
implementation(libs.androidx.media3.datasource)
|
|
||||||
implementation(libs.androidx.media3.datasource.okhttp)
|
|
||||||
implementation(libs.androidx.media3.database)
|
|
||||||
implementation(libs.okhttp)
|
|
||||||
implementation(libs.coil.compose)
|
|
||||||
implementation(libs.coil.network.okhttp)
|
|
||||||
implementation(libs.koin.androidx.compose)
|
|
||||||
implementation(libs.aboutlibraries.core)
|
|
||||||
implementation(libs.aboutlibraries.compose.m3)
|
|
||||||
ksp(libs.androidx.room3.compiler)
|
|
||||||
|
|
||||||
coreLibraryDesugaring(libs.desugar.jdk.libs)
|
|
||||||
|
|
||||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
|
||||||
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
|
||||||
testImplementation(libs.robolectric)
|
|
||||||
testImplementation(libs.roborazzi)
|
|
||||||
testImplementation(libs.roborazzi.compose)
|
|
||||||
testImplementation(libs.roborazzi.junit.rule)
|
|
||||||
testImplementation(libs.androidx.compose.ui.test.junit4)
|
|
||||||
testImplementation(libs.androidx.test.ext.junit)
|
|
||||||
testImplementation(libs.androidx.test.core)
|
|
||||||
testImplementation(libs.androidx.sqlite.bundled.jvm)
|
|
||||||
testImplementation(libs.coil.test)
|
|
||||||
testImplementation(libs.okhttp.mockwebserver)
|
|
||||||
testImplementation(libs.kotlinx.coroutines.test)
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"uniqueId": "com.android.tools:desugar_jdk_libs",
|
|
||||||
"name": "Desugar JDK Libs",
|
|
||||||
"description": "Backports of newer java.* APIs, bundled into the app at build time by core library desugaring. It is not on the runtime classpath, so the license collector cannot discover it automatically.",
|
|
||||||
"website": "https://github.com/google/desugar_jdk_libs",
|
|
||||||
"licenses": ["GPL-2.0-with-classpath-exception"]
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"uniqueId": "org.publicsuffix:publicsuffix-list",
|
|
||||||
"name": "Public Suffix List",
|
|
||||||
"description": "Domain data bundled inside OkHttp's PublicSuffixDatabase, used to enforce cookie and hostname policy.",
|
|
||||||
"website": "https://publicsuffix.org/",
|
|
||||||
"licenses": ["MPL-2.0"]
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"uniqueId": "com.subtracks",
|
|
||||||
"name": "Subtracks",
|
|
||||||
"description": "Subtracks itself, a client for Subsonic-compatible servers.",
|
|
||||||
"website": "https://github.com/austinried/subtracks",
|
|
||||||
"licenses": ["GPL-3.0-only"]
|
|
||||||
}
|
|
||||||
@@ -1,649 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 1,
|
|
||||||
"identityHash": "c359cb54d1d99a2de8efbe1f0c8ad182",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "app_settings",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `maxBitrateWifi` INTEGER NOT NULL, `maxBitrateMobile` INTEGER NOT NULL, `streamFormat` TEXT, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "maxBitrateWifi",
|
|
||||||
"columnName": "maxBitrateWifi",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "maxBitrateMobile",
|
|
||||||
"columnName": "maxBitrateMobile",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "streamFormat",
|
|
||||||
"columnName": "streamFormat",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "search_index",
|
|
||||||
"createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS5(`sourceId` UNINDEXED, `type` UNINDEXED, `itemId` UNINDEXED, `title`, tokenize=`trigram`)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "type",
|
|
||||||
"columnName": "type",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "itemId",
|
|
||||||
"columnName": "itemId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"rowid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ftsVersion": "FTS5",
|
|
||||||
"ftsOptions": {
|
|
||||||
"tokenizer": "trigram",
|
|
||||||
"tokenizerArgs": [],
|
|
||||||
"contentTable": "",
|
|
||||||
"languageIdColumnName": "",
|
|
||||||
"matchInfo": "FTS4",
|
|
||||||
"notIndexedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"type",
|
|
||||||
"itemId"
|
|
||||||
],
|
|
||||||
"prefixSizes": [],
|
|
||||||
"preferredOrder": "ASC",
|
|
||||||
"contentRowId": "",
|
|
||||||
"columnSize": true,
|
|
||||||
"detail": "FULL"
|
|
||||||
},
|
|
||||||
"contentSyncTriggers": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, 'c359cb54d1d99a2de8efbe1f0c8ad182')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,775 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 10,
|
|
||||||
"identityHash": "633620aafe3a9116bbc9d349082185e7",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, `changed` INTEGER NOT NULL DEFAULT 0, `duration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "changed",
|
|
||||||
"columnName": "changed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, `created` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "queue_entries",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `position` INTEGER NOT NULL, `sourceId` INTEGER NOT NULL, `kind` TEXT NOT NULL, `refId` TEXT NOT NULL, `rangeStart` INTEGER, `rangeEnd` INTEGER, FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "kind",
|
|
||||||
"columnName": "kind",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "refId",
|
|
||||||
"columnName": "refId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeStart",
|
|
||||||
"columnName": "rangeStart",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeEnd",
|
|
||||||
"columnName": "rangeEnd",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_position",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"position"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_position` ON `${TABLE_NAME}` (`position`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playback_cursor",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `queuePosition` INTEGER NOT NULL, `shuffleEnabled` INTEGER NOT NULL DEFAULT 0, `repeatMode` INTEGER NOT NULL DEFAULT 0, `shuffleSeed` INTEGER NOT NULL DEFAULT 0, `positionMs` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "queuePosition",
|
|
||||||
"columnName": "queuePosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleEnabled",
|
|
||||||
"columnName": "shuffleEnabled",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "repeatMode",
|
|
||||||
"columnName": "repeatMode",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleSeed",
|
|
||||||
"columnName": "shuffleSeed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "positionMs",
|
|
||||||
"columnName": "positionMs",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "shuffle_order",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sequence` INTEGER NOT NULL, `flatPosition` INTEGER NOT NULL, PRIMARY KEY(`sequence`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sequence",
|
|
||||||
"columnName": "sequence",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "flatPosition",
|
|
||||||
"columnName": "flatPosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sequence"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artwork_seeds",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cacheKey` TEXT NOT NULL, `primary` INTEGER NOT NULL, `secondary` INTEGER, PRIMARY KEY(`cacheKey`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "cacheKey",
|
|
||||||
"columnName": "cacheKey",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "primary",
|
|
||||||
"columnName": "primary",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "secondary",
|
|
||||||
"columnName": "secondary",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"cacheKey"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, '633620aafe3a9116bbc9d349082185e7')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,840 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 11,
|
|
||||||
"identityHash": "63c0e023a6364af43729511a71d81767",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "discs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `albumId` TEXT NOT NULL, `disc` INTEGER NOT NULL, `title` TEXT NOT NULL, PRIMARY KEY(`sourceId`, `albumId`, `disc`), FOREIGN KEY(`sourceId`, `albumId`) REFERENCES `albums`(`sourceId`, `id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId",
|
|
||||||
"disc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_discs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_discs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "albums",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, `changed` INTEGER NOT NULL DEFAULT 0, `duration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "changed",
|
|
||||||
"columnName": "changed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, `created` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "queue_entries",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `position` INTEGER NOT NULL, `sourceId` INTEGER NOT NULL, `kind` TEXT NOT NULL, `refId` TEXT NOT NULL, `rangeStart` INTEGER, `rangeEnd` INTEGER, FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "kind",
|
|
||||||
"columnName": "kind",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "refId",
|
|
||||||
"columnName": "refId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeStart",
|
|
||||||
"columnName": "rangeStart",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeEnd",
|
|
||||||
"columnName": "rangeEnd",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_position",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"position"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_position` ON `${TABLE_NAME}` (`position`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playback_cursor",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `queuePosition` INTEGER NOT NULL, `shuffleEnabled` INTEGER NOT NULL DEFAULT 0, `repeatMode` INTEGER NOT NULL DEFAULT 0, `shuffleSeed` INTEGER NOT NULL DEFAULT 0, `positionMs` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "queuePosition",
|
|
||||||
"columnName": "queuePosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleEnabled",
|
|
||||||
"columnName": "shuffleEnabled",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "repeatMode",
|
|
||||||
"columnName": "repeatMode",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleSeed",
|
|
||||||
"columnName": "shuffleSeed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "positionMs",
|
|
||||||
"columnName": "positionMs",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "shuffle_order",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sequence` INTEGER NOT NULL, `flatPosition` INTEGER NOT NULL, PRIMARY KEY(`sequence`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sequence",
|
|
||||||
"columnName": "sequence",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "flatPosition",
|
|
||||||
"columnName": "flatPosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sequence"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artwork_seeds",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cacheKey` TEXT NOT NULL, `primary` INTEGER NOT NULL, `secondary` INTEGER, PRIMARY KEY(`cacheKey`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "cacheKey",
|
|
||||||
"columnName": "cacheKey",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "primary",
|
|
||||||
"columnName": "primary",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "secondary",
|
|
||||||
"columnName": "secondary",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"cacheKey"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, '63c0e023a6364af43729511a71d81767')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,845 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 12,
|
|
||||||
"identityHash": "4c665bdfecebbac1f25dee3e7337491c",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "discs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `albumId` TEXT NOT NULL, `disc` INTEGER NOT NULL, `title` TEXT NOT NULL, PRIMARY KEY(`sourceId`, `albumId`, `disc`), FOREIGN KEY(`sourceId`, `albumId`) REFERENCES `albums`(`sourceId`, `id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId",
|
|
||||||
"disc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_discs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_discs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "albums",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, `changed` INTEGER NOT NULL DEFAULT 0, `duration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "changed",
|
|
||||||
"columnName": "changed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, `created` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "queue_entries",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `position` INTEGER NOT NULL, `sourceId` INTEGER NOT NULL, `kind` TEXT NOT NULL, `refId` TEXT NOT NULL, `rangeStart` INTEGER, `rangeEnd` INTEGER, FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "kind",
|
|
||||||
"columnName": "kind",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "refId",
|
|
||||||
"columnName": "refId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeStart",
|
|
||||||
"columnName": "rangeStart",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeEnd",
|
|
||||||
"columnName": "rangeEnd",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_position",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"position"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_position` ON `${TABLE_NAME}` (`position`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playback_cursor",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `queuePosition` INTEGER NOT NULL, `shuffleEnabled` INTEGER NOT NULL DEFAULT 0, `repeatMode` INTEGER NOT NULL DEFAULT 0, `shuffleSeed` INTEGER NOT NULL DEFAULT 0, `positionMs` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "queuePosition",
|
|
||||||
"columnName": "queuePosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleEnabled",
|
|
||||||
"columnName": "shuffleEnabled",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "repeatMode",
|
|
||||||
"columnName": "repeatMode",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleSeed",
|
|
||||||
"columnName": "shuffleSeed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "positionMs",
|
|
||||||
"columnName": "positionMs",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "shuffle_order",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sequence` INTEGER NOT NULL, `flatPosition` INTEGER NOT NULL, PRIMARY KEY(`sequence`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sequence",
|
|
||||||
"columnName": "sequence",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "flatPosition",
|
|
||||||
"columnName": "flatPosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sequence"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artwork_seeds",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cacheKey` TEXT NOT NULL, `primary` INTEGER NOT NULL, `secondary` INTEGER, `nameBusy` INTEGER, PRIMARY KEY(`cacheKey`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "cacheKey",
|
|
||||||
"columnName": "cacheKey",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "primary",
|
|
||||||
"columnName": "primary",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "secondary",
|
|
||||||
"columnName": "secondary",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "nameBusy",
|
|
||||||
"columnName": "nameBusy",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"cacheKey"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, '4c665bdfecebbac1f25dee3e7337491c')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,882 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 13,
|
|
||||||
"identityHash": "bf478aad1e42e1ca6e25959e878ad45c",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "discs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `albumId` TEXT NOT NULL, `disc` INTEGER NOT NULL, `title` TEXT NOT NULL, PRIMARY KEY(`sourceId`, `albumId`, `disc`), FOREIGN KEY(`sourceId`, `albumId`) REFERENCES `albums`(`sourceId`, `id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId",
|
|
||||||
"disc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_discs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_discs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "albums",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, `changed` INTEGER NOT NULL DEFAULT 0, `duration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "changed",
|
|
||||||
"columnName": "changed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, `created` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "queue_entries",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `position` INTEGER NOT NULL, `sourceId` INTEGER NOT NULL, `kind` TEXT NOT NULL, `refId` TEXT NOT NULL, `rangeStart` INTEGER, `rangeEnd` INTEGER, FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "kind",
|
|
||||||
"columnName": "kind",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "refId",
|
|
||||||
"columnName": "refId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeStart",
|
|
||||||
"columnName": "rangeStart",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeEnd",
|
|
||||||
"columnName": "rangeEnd",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_position",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"position"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_position` ON `${TABLE_NAME}` (`position`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playback_cursor",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `queuePosition` INTEGER NOT NULL, `shuffleEnabled` INTEGER NOT NULL DEFAULT 0, `repeatMode` INTEGER NOT NULL DEFAULT 0, `shuffleSeed` INTEGER NOT NULL DEFAULT 0, `positionMs` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "queuePosition",
|
|
||||||
"columnName": "queuePosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleEnabled",
|
|
||||||
"columnName": "shuffleEnabled",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "repeatMode",
|
|
||||||
"columnName": "repeatMode",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleSeed",
|
|
||||||
"columnName": "shuffleSeed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "positionMs",
|
|
||||||
"columnName": "positionMs",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "shuffle_order",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sequence` INTEGER NOT NULL, `flatPosition` INTEGER NOT NULL, PRIMARY KEY(`sequence`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sequence",
|
|
||||||
"columnName": "sequence",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "flatPosition",
|
|
||||||
"columnName": "flatPosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sequence"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artwork_seeds",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cacheKey` TEXT NOT NULL, `primary` INTEGER NOT NULL, `secondary` INTEGER, `nameBusy` INTEGER, `sourceId` INTEGER NOT NULL, `storedAt` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`cacheKey`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "cacheKey",
|
|
||||||
"columnName": "cacheKey",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "primary",
|
|
||||||
"columnName": "primary",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "secondary",
|
|
||||||
"columnName": "secondary",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "nameBusy",
|
|
||||||
"columnName": "nameBusy",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "storedAt",
|
|
||||||
"columnName": "storedAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"cacheKey"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artwork_seeds_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artwork_seeds_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, 'bf478aad1e42e1ca6e25959e878ad45c')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,872 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 14,
|
|
||||||
"identityHash": "9498fefdce0f68513f1ae52786e8c711",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "discs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `albumId` TEXT NOT NULL, `disc` INTEGER NOT NULL, `title` TEXT NOT NULL, PRIMARY KEY(`sourceId`, `albumId`, `disc`), FOREIGN KEY(`sourceId`, `albumId`) REFERENCES `albums`(`sourceId`, `id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId",
|
|
||||||
"disc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_discs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_discs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "albums",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, `changed` INTEGER NOT NULL DEFAULT 0, `duration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "changed",
|
|
||||||
"columnName": "changed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, `created` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "queue_entries",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `position` INTEGER NOT NULL, `sourceId` INTEGER NOT NULL, `kind` TEXT NOT NULL, `refId` TEXT NOT NULL, `rangeStart` INTEGER, `rangeEnd` INTEGER, FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "kind",
|
|
||||||
"columnName": "kind",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "refId",
|
|
||||||
"columnName": "refId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeStart",
|
|
||||||
"columnName": "rangeStart",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeEnd",
|
|
||||||
"columnName": "rangeEnd",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_position",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"position"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_position` ON `${TABLE_NAME}` (`position`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playback_cursor",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `queuePosition` INTEGER NOT NULL, `shuffleEnabled` INTEGER NOT NULL DEFAULT 0, `repeatMode` INTEGER NOT NULL DEFAULT 0, `shuffleSeed` INTEGER NOT NULL DEFAULT 0, `positionMs` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "queuePosition",
|
|
||||||
"columnName": "queuePosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleEnabled",
|
|
||||||
"columnName": "shuffleEnabled",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "repeatMode",
|
|
||||||
"columnName": "repeatMode",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "shuffleSeed",
|
|
||||||
"columnName": "shuffleSeed",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "positionMs",
|
|
||||||
"columnName": "positionMs",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "shuffle_order",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sequence` INTEGER NOT NULL, `flatPosition` INTEGER NOT NULL, PRIMARY KEY(`sequence`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sequence",
|
|
||||||
"columnName": "sequence",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "flatPosition",
|
|
||||||
"columnName": "flatPosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sequence"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artwork_seeds",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cacheKey` TEXT NOT NULL, `primary` INTEGER NOT NULL, `secondary` INTEGER, `nameBusy` INTEGER, `sourceId` INTEGER NOT NULL, `storedAt` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`cacheKey`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "cacheKey",
|
|
||||||
"columnName": "cacheKey",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "primary",
|
|
||||||
"columnName": "primary",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "secondary",
|
|
||||||
"columnName": "secondary",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "nameBusy",
|
|
||||||
"columnName": "nameBusy",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "storedAt",
|
|
||||||
"columnName": "storedAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true,
|
|
||||||
"defaultValue": "0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"cacheKey"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artwork_seeds_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artwork_seeds_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, '9498fefdce0f68513f1ae52786e8c711')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,619 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 2,
|
|
||||||
"identityHash": "67a9c26297d65d76f54edc99ac9a7930",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "search_index",
|
|
||||||
"createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS5(`sourceId` UNINDEXED, `type` UNINDEXED, `itemId` UNINDEXED, `title`, tokenize=`trigram`)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "type",
|
|
||||||
"columnName": "type",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "itemId",
|
|
||||||
"columnName": "itemId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"rowid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ftsVersion": "FTS5",
|
|
||||||
"ftsOptions": {
|
|
||||||
"tokenizer": "trigram",
|
|
||||||
"tokenizerArgs": [],
|
|
||||||
"contentTable": "",
|
|
||||||
"languageIdColumnName": "",
|
|
||||||
"matchInfo": "FTS4",
|
|
||||||
"notIndexedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"type",
|
|
||||||
"itemId"
|
|
||||||
],
|
|
||||||
"prefixSizes": [],
|
|
||||||
"preferredOrder": "ASC",
|
|
||||||
"contentRowId": "",
|
|
||||||
"columnSize": true,
|
|
||||||
"detail": "FULL"
|
|
||||||
},
|
|
||||||
"contentSyncTriggers": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, '67a9c26297d65d76f54edc99ac9a7930')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,728 +0,0 @@
|
|||||||
{
|
|
||||||
"formatVersion": 1,
|
|
||||||
"database": {
|
|
||||||
"version": 3,
|
|
||||||
"identityHash": "373e606ebb1b0c57ffa4faad216ab74f",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"tableName": "sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "address",
|
|
||||||
"columnName": "address",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "isActive",
|
|
||||||
"columnName": "isActive",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "createdAt",
|
|
||||||
"columnName": "createdAt",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "subsonic_sources",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `useTokenAuth` INTEGER NOT NULL, PRIMARY KEY(`sourceId`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "useTokenAuth",
|
|
||||||
"columnName": "useTokenAuth",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_subsonic_sources_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_subsonic_sources_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "artists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumCount",
|
|
||||||
"columnName": "albumCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_artists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "albums",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, `name` TEXT NOT NULL, `albumArtist` TEXT, `created` INTEGER NOT NULL, `coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, `frequentRank` INTEGER, `recentRank` INTEGER, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumArtist",
|
|
||||||
"columnName": "albumArtist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "year",
|
|
||||||
"columnName": "year",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "frequentRank",
|
|
||||||
"columnName": "frequentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "recentRank",
|
|
||||||
"columnName": "recentRank",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_albums_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlists",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, `created` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "name",
|
|
||||||
"columnName": "name",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "comment",
|
|
||||||
"columnName": "comment",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "coverArt",
|
|
||||||
"columnName": "coverArt",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songCount",
|
|
||||||
"columnName": "songCount",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "created",
|
|
||||||
"columnName": "created",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlists_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playlist_songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`sourceId`, `playlistId`, `position`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "playlistId",
|
|
||||||
"columnName": "playlistId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "songId",
|
|
||||||
"columnName": "songId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId",
|
|
||||||
"position"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_playlistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"playlistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_playlistId` ON `${TABLE_NAME}` (`sourceId`, `playlistId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_playlist_songs_sourceId_songId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"songId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_songs_sourceId_songId` ON `${TABLE_NAME}` (`sourceId`, `songId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "songs",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `albumId` TEXT, `artistId` TEXT, `title` TEXT NOT NULL, `album` TEXT, `artist` TEXT, `duration` INTEGER, `track` INTEGER, `disc` INTEGER, `starred` INTEGER, `genre` TEXT, PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "albumId",
|
|
||||||
"columnName": "albumId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artistId",
|
|
||||||
"columnName": "artistId",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "album",
|
|
||||||
"columnName": "album",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "artist",
|
|
||||||
"columnName": "artist",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "duration",
|
|
||||||
"columnName": "duration",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "track",
|
|
||||||
"columnName": "track",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "disc",
|
|
||||||
"columnName": "disc",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "starred",
|
|
||||||
"columnName": "starred",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "genre",
|
|
||||||
"columnName": "genre",
|
|
||||||
"affinity": "TEXT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_albumId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"albumId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_albumId` ON `${TABLE_NAME}` (`sourceId`, `albumId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_songs_sourceId_artistId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId",
|
|
||||||
"artistId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_songs_sourceId_artistId` ON `${TABLE_NAME}` (`sourceId`, `artistId`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "search_index",
|
|
||||||
"createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS5(`sourceId` UNINDEXED, `type` UNINDEXED, `itemId` UNINDEXED, `title`, tokenize=`trigram`)",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "type",
|
|
||||||
"columnName": "type",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "itemId",
|
|
||||||
"columnName": "itemId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "title",
|
|
||||||
"columnName": "title",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"rowid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ftsVersion": "FTS5",
|
|
||||||
"ftsOptions": {
|
|
||||||
"tokenizer": "trigram",
|
|
||||||
"tokenizerArgs": [],
|
|
||||||
"contentTable": "",
|
|
||||||
"languageIdColumnName": "",
|
|
||||||
"matchInfo": "FTS4",
|
|
||||||
"notIndexedColumns": [
|
|
||||||
"sourceId",
|
|
||||||
"type",
|
|
||||||
"itemId"
|
|
||||||
],
|
|
||||||
"prefixSizes": [],
|
|
||||||
"preferredOrder": "ASC",
|
|
||||||
"contentRowId": "",
|
|
||||||
"columnSize": true,
|
|
||||||
"detail": "FULL"
|
|
||||||
},
|
|
||||||
"contentSyncTriggers": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "queue_entries",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `position` INTEGER NOT NULL, `sourceId` INTEGER NOT NULL, `kind` TEXT NOT NULL, `refId` TEXT NOT NULL, `rangeStart` INTEGER, `rangeEnd` INTEGER, FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "position",
|
|
||||||
"columnName": "position",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "sourceId",
|
|
||||||
"columnName": "sourceId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "kind",
|
|
||||||
"columnName": "kind",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "refId",
|
|
||||||
"columnName": "refId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeStart",
|
|
||||||
"columnName": "rangeStart",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rangeEnd",
|
|
||||||
"columnName": "rangeEnd",
|
|
||||||
"affinity": "INTEGER"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": true,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_sourceId",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_sourceId` ON `${TABLE_NAME}` (`sourceId`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_queue_entries_position",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"position"
|
|
||||||
],
|
|
||||||
"orders": [],
|
|
||||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_queue_entries_position` ON `${TABLE_NAME}` (`position`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "sources",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"sourceId"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "playback_cursor",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `queuePosition` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "queuePosition",
|
|
||||||
"columnName": "queuePosition",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"autoGenerate": false,
|
|
||||||
"columnNames": [
|
|
||||||
"id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"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, '373e606ebb1b0c57ffa4faad216ab74f')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||