diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index bdb1913a4e..0000000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-# These are supported funding model platforms
-custom: ['https://revolut.me/somaldoaca', 'https://www.paypal.com/paypalme/iacobionut01']
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000000..76018dd845
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,61 @@
+name: Build application
+
+on: [pull_request, push]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v5
+ with:
+ submodules: true
+ - name: Set up JDK 21
+ uses: actions/setup-java@v5
+ with:
+ distribution: 'temurin'
+ java-version: 21
+ cache: gradle
+
+ - name: Run unit tests
+ run: ./gradlew :app:testDebugUnitTest --no-daemon
+
+ - name: Build instrumentation tests
+ run: ./gradlew :app:assembleDebugAndroidTest --no-daemon
+
+ - name: Build with Gradle
+ run: ./gradlew :app:assembleDebug --no-daemon
+
+ media-store-device-test:
+ needs: build
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+
+ steps:
+ - uses: actions/checkout@v5
+ with:
+ submodules: true
+ - name: Set up JDK 21
+ uses: actions/setup-java@v5
+ with:
+ distribution: 'temurin'
+ java-version: 21
+ cache: gradle
+
+ - name: Enable KVM
+ run: |
+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
+ | sudo tee /etc/udev/rules.d/99-kvm4all.rules
+ sudo udevadm control --reload-rules
+ sudo udevadm trigger --name-match=kvm
+
+ - name: Run MediaStore paging test
+ uses: reactivecircus/android-emulator-runner@v2
+ with:
+ api-level: 36
+ arch: x86_64
+ disable-animations: true
+ script: >-
+ ./gradlew :app:connectedDebugAndroidTest
+ -Pandroid.testInstrumentationRunnerArguments.class=com.dot.gallery.feature_node.data.data_source.mediastore.queries.MediaFlowPagingDeviceTest
+ --no-daemon
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
deleted file mode 100644
index fc4aa40b2b..0000000000
--- a/.github/workflows/nightly.yml
+++ /dev/null
@@ -1,179 +0,0 @@
-name: Nightly CI
-
-on:
- push:
- branches:
- - nightly
-
-jobs:
- build_nomaps:
- runs-on: ubuntu-latest
- outputs:
- versionCode: ${{ steps.versioncode.outputs.versionCode }}
- versionName: ${{ steps.versionname.outputs.versionName }}
- steps:
- - uses: actions/checkout@v6
- - name: Get versionCode
- id: versioncode
- run: echo "versionCode=$(grep -E '^\s+versionCode\s*=' app/build.gradle.kts | awk '{ print $3 }' | head -n 1)" >> $GITHUB_OUTPUT
- - name: Get versionName
- id: versionname
- run: echo "versionName=$(grep -E '^\s+versionName\s*=' app/build.gradle.kts | head -1 | awk -F\" '{ print $2 }')" >> $GITHUB_OUTPUT
- - name: Strip internet permission
- run: chmod +x ./strip_permission.sh && ./strip_permission.sh
- - name: Disable maps
- run: echo "INCLUDE_MAPS=false" >> ./app.properties
- - uses: actions/setup-java@v5
- with:
- distribution: 'temurin'
- cache: 'gradle'
- java-version: 21
- - name: Setup Android SDK
- uses: android-actions/setup-android@v4
- - name: Setup Gradle
- uses: gradle/actions/setup-gradle@v5
- - name: Make Gradle executable
- run: chmod +x ./gradlew
- - name: Decode Keystore
- id: decode_keystore
- uses: timheuer/base64-to-file@v1
- with:
- fileName: 'release_key.jks'
- fileDir: 'app/'
- encodedString: ${{ secrets.SIGNING_KEY }}
- - name: Build Release APK
- run: >-
- ./gradlew
- :app:assembleArm64-v8aNoMLRelease
- :app:assembleArmeabi-v7aNoMLRelease
- :app:assembleX86_64NoMLRelease
- :app:assembleX86NoMLRelease
- :app:assembleUniversalNoMLRelease
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (No Maps)
- path: app/build/outputs/apk-renamed/**/*.apk
-
- build_nomaps_withml:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v6
- - name: Strip internet permission
- run: chmod +x ./strip_permission.sh && ./strip_permission.sh
- - name: Disable maps
- run: echo "INCLUDE_MAPS=false" >> ./app.properties
- - uses: actions/setup-java@v5
- with:
- distribution: 'temurin'
- cache: 'gradle'
- java-version: 21
- - name: Setup Android SDK
- uses: android-actions/setup-android@v4
- - name: Setup Gradle
- uses: gradle/actions/setup-gradle@v5
- - name: Make Gradle executable
- run: chmod +x ./gradlew
- - name: Decode Keystore
- id: decode_keystore
- uses: timheuer/base64-to-file@v1
- with:
- fileName: 'release_key.jks'
- fileDir: 'app/'
- encodedString: ${{ secrets.SIGNING_KEY }}
- - name: Build Release APK
- run: >-
- ./gradlew
- :app:assembleArm64-v8aWithMLRelease
- :app:assembleArmeabi-v7aWithMLRelease
- :app:assembleX86_64WithMLRelease
- :app:assembleX86WithMLRelease
- :app:assembleUniversalWithMLRelease
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (No Maps, WithML)
- path: app/build/outputs/apk-renamed/**/*.apk
-
- build_maps:
- runs-on: ubuntu-latest
- outputs:
- versionCode: ${{ steps.versioncode.outputs.versionCode }}
- versionName: ${{ steps.versionname.outputs.versionName }}
- steps:
- - uses: actions/checkout@v6
- - name: Get versionCode
- id: versioncode
- run: echo "versionCode=$(grep -E '^\s+versionCode\s*=' app/build.gradle.kts | awk '{ print $3 }' | head -n 1)" >> $GITHUB_OUTPUT
- - name: Get versionName
- id: versionname
- run: echo "versionName=$(grep -E '^\s+versionName\s*=' app/build.gradle.kts | head -1 | awk -F\" '{ print $2 }')" >> $GITHUB_OUTPUT
- - uses: actions/setup-java@v5
- with:
- distribution: 'temurin'
- cache: 'gradle'
- java-version: 21
- - name: Setup Android SDK
- uses: android-actions/setup-android@v4
- - name: Setup Gradle
- uses: gradle/actions/setup-gradle@v5
- - name: Make Gradle executable
- run: chmod +x ./gradlew
- - name: Decode Keystore
- id: decode_keystore
- uses: timheuer/base64-to-file@v1
- with:
- fileName: 'release_key.jks'
- fileDir: 'app/'
- encodedString: ${{ secrets.SIGNING_KEY }}
- - name: Build Release APK
- run: >-
- ./gradlew
- :app:assembleArm64-v8aNoMLRelease
- :app:assembleArmeabi-v7aNoMLRelease
- :app:assembleX86_64NoMLRelease
- :app:assembleX86NoMLRelease
- :app:assembleUniversalNoMLRelease
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (Maps)
- path: app/build/outputs/apk-renamed/**/*.apk
-
- release:
- needs: [build_nomaps, build_nomaps_withml, build_maps]
- runs-on: ubuntu-latest
- steps:
- - uses: actions/download-artifact@v5
- with:
- name: ReFra Release (No Maps)
- - uses: actions/download-artifact@v5
- with:
- name: ReFra Release (Maps)
- - uses: actions/download-artifact@v5
- with:
- name: ReFra Release (No Maps, WithML)
- - name: Generate SHA256
- run: echo "### Checksums" >> ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }}-nightly-changelog.txt && find . -name "ReFra-*.apk" -type f -print0 | sort -z | xargs -r0 sha256sum | awk '{gsub(".*/", "", $2); print "**"$2"**:", "`"$1"`"} ' >> ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }}-nightly-changelog.txt
- - name: Create Release
- id: create_release
- uses: softprops/action-gh-release@v3
- with:
- name: ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }} Nightly Release
- body_path: ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }}-nightly-changelog.txt
- prerelease: true
- tag_name: ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }}-nightly
- target_commitish: ${{ github.sha }}
- files: |
- ./**/ReFra-*.apk
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/stable.yml b/.github/workflows/stable.yml
deleted file mode 100644
index e814535794..0000000000
--- a/.github/workflows/stable.yml
+++ /dev/null
@@ -1,212 +0,0 @@
-name: Release CI
-
-on: workflow_dispatch
-
-jobs:
- build_nomaps:
- runs-on: ubuntu-latest
- outputs:
- versionCode: ${{ steps.versioncode.outputs.versionCode }}
- versionName: ${{ steps.versionname.outputs.versionName }}
- steps:
- - uses: actions/checkout@v6
- - name: Get versionCode
- id: versioncode
- run: echo "versionCode=$(grep -E '^\s+versionCode\s*=' app/build.gradle.kts | awk '{ print $3 }' | head -n 1)" >> $GITHUB_OUTPUT
- - name: Get versionName
- id: versionname
- run: echo "versionName=$(grep -E '^\s+versionName\s*=' app/build.gradle.kts | head -1 | awk -F\" '{ print $2 }')" >> $GITHUB_OUTPUT
- - name: Strip internet permission
- run: chmod +x ./strip_permission.sh && ./strip_permission.sh
- - name: Disable maps
- run: echo "INCLUDE_MAPS=false" >> ./app.properties
- - uses: actions/setup-java@v5
- with:
- distribution: 'temurin'
- cache: 'gradle'
- java-version: 21
- - name: Setup Android SDK
- uses: android-actions/setup-android@v4
- - name: Setup Gradle
- uses: gradle/actions/setup-gradle@v5
- - name: Make Gradle executable
- run: chmod +x ./gradlew
- - name: Decode Keystore
- id: decode_keystore
- uses: timheuer/base64-to-file@v1
- with:
- fileName: 'release_key.jks'
- fileDir: 'app/'
- encodedString: ${{ secrets.SIGNING_KEY }}
- - name: Build Release APK
- run: >-
- ./gradlew
- :app:assembleArm64-v8aNoMLRelease
- :app:assembleArmeabi-v7aNoMLRelease
- :app:assembleX86_64NoMLRelease
- :app:assembleX86NoMLRelease
- :app:assembleUniversalNoMLRelease
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (No Maps)
- path: app/build/outputs/apk-renamed/**/*.apk
-
- build_nomaps_withml:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v6
- - name: Strip internet permission
- run: chmod +x ./strip_permission.sh && ./strip_permission.sh
- - name: Disable maps
- run: echo "INCLUDE_MAPS=false" >> ./app.properties
- - uses: actions/setup-java@v5
- with:
- distribution: 'temurin'
- cache: 'gradle'
- java-version: 21
- - name: Setup Android SDK
- uses: android-actions/setup-android@v4
- - name: Setup Gradle
- uses: gradle/actions/setup-gradle@v5
- - name: Make Gradle executable
- run: chmod +x ./gradlew
- - name: Decode Keystore
- id: decode_keystore
- uses: timheuer/base64-to-file@v1
- with:
- fileName: 'release_key.jks'
- fileDir: 'app/'
- encodedString: ${{ secrets.SIGNING_KEY }}
- - name: Build Release APK
- run: >-
- ./gradlew
- :app:assembleArm64-v8aWithMLRelease
- :app:assembleArmeabi-v7aWithMLRelease
- :app:assembleX86_64WithMLRelease
- :app:assembleX86WithMLRelease
- :app:assembleUniversalWithMLRelease
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (No Maps, WithML)
- path: app/build/outputs/apk-renamed/**/*.apk
-
- build_maps:
- runs-on: ubuntu-latest
- outputs:
- versionCode: ${{ steps.versioncode.outputs.versionCode }}
- versionName: ${{ steps.versionname.outputs.versionName }}
- steps:
- - uses: actions/checkout@v6
- - name: Get versionCode
- id: versioncode
- run: echo "versionCode=$(grep -E '^\s+versionCode\s*=' app/build.gradle.kts | awk '{ print $3 }' | head -n 1)" >> $GITHUB_OUTPUT
- - name: Get versionName
- id: versionname
- run: echo "versionName=$(grep -E '^\s+versionName\s*=' app/build.gradle.kts | head -1 | awk -F\" '{ print $2 }')" >> $GITHUB_OUTPUT
- - uses: actions/setup-java@v5
- with:
- distribution: 'temurin'
- cache: 'gradle'
- java-version: 21
- - name: Setup Android SDK
- uses: android-actions/setup-android@v4
- - name: Setup Gradle
- uses: gradle/actions/setup-gradle@v5
- - name: Make Gradle executable
- run: chmod +x ./gradlew
- - name: Decode Keystore
- id: decode_keystore
- uses: timheuer/base64-to-file@v1
- with:
- fileName: 'release_key.jks'
- fileDir: 'app/'
- encodedString: ${{ secrets.SIGNING_KEY }}
- - name: Build Release APK
- run: >-
- ./gradlew
- :app:assembleArm64-v8aNoMLRelease
- :app:assembleArmeabi-v7aNoMLRelease
- :app:assembleX86_64NoMLRelease
- :app:assembleX86NoMLRelease
- :app:assembleUniversalNoMLRelease
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (Maps)
- path: app/build/outputs/apk-renamed/**/*.apk
- - name: Apply Google Play patch
- id: gplay_patcher
- run: git config --global user.email "paulionut2003@gmail.com" &&
- git config --global user.name "IacobIonut01" &&
- git fetch https://github.com/IacobIonut01/ReFra.git main_play &&
- git cherry-pick 0dbdd73a 2322b135 &&
- chmod +x ./strip_allfiles_permission.sh && ./strip_allfiles_permission.sh &&
- printf 'ALL_FILES_ACCESS=false\nINCLUDE_MAPS=true\n' > ./app.properties
- - name: Build Google Play Bundle
- run: ./gradlew :app:bundleUniversalWithMLGplay
- env:
- SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
- SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
- - uses: r0adkll/upload-google-play@v1
- continue-on-error: true
- with:
- serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
- packageName: com.dot.gallery.gplay
- releaseFiles: app/build/outputs/bundle/universalWithMLGplay/*.aab
- track: production
- releaseName: ${{ steps.versionname.outputs.versionName }}-${{ steps.versioncode.outputs.versionCode }} Release
- mappingFile: app/build/outputs/mapping/universalWithMLGplay/mapping.txt
- debugSymbols: app/build/intermediates/merged_native_libs/universalWithMLGplay/mergeUniversalWithMLGplayNativeLibs/out/lib
- - uses: actions/upload-artifact@v5
- with:
- name: ReFra Release (GPlay Bundle)
- path: app/build/outputs/bundle/universalWithMLGplay/*.aab
-
- release:
- needs: [build_nomaps, build_nomaps_withml, build_maps]
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- sparse-checkout: .github/RELEASE_BODY.md
- sparse-checkout-cone-mode: false
- - uses: actions/download-artifact@v5
- with:
- name: ReFra Release (No Maps)
- - uses: actions/download-artifact@v5
- with:
- name: ReFra Release (Maps)
- - uses: actions/download-artifact@v5
- with:
- name: ReFra Release (No Maps, WithML)
- - name: Generate changelog
- run: |
- CHANGELOG=${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }}-changelog.txt
- cat .github/RELEASE_BODY.md >> "$CHANGELOG"
- echo "" >> "$CHANGELOG"
- echo "### Checksums" >> "$CHANGELOG"
- find . -name "ReFra-*.apk" -type f -print0 | sort -z | xargs -r0 sha256sum | awk '{gsub(".*/", "", $2); print "**"$2"**:", "`"$1"`"}' >> "$CHANGELOG"
- - name: Create Release
- id: create_release
- uses: softprops/action-gh-release@v3
- with:
- name: ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }} Release
- body_path: ${{ needs.build_maps.outputs.versionName }}-${{ needs.build_maps.outputs.versionCode }}-changelog.txt
- prerelease: false
- tag_name: ${{ needs.build_maps.outputs.versionName }}
- files: |
- ./**/ReFra-*.apk
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/validate-gradle-wrapper.yml b/.github/workflows/validate-gradle-wrapper.yml
new file mode 100644
index 0000000000..1f95d5adcd
--- /dev/null
+++ b/.github/workflows/validate-gradle-wrapper.yml
@@ -0,0 +1,11 @@
+name: Validate Gradle Wrapper
+
+on: [pull_request, push]
+
+jobs:
+ validation:
+ name: Validation
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v5
+ - uses: gradle/actions/wrapper-validation@v6
diff --git a/.gitignore b/.gitignore
index 2fe94ccf5b..1028aa0ab5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,6 @@ api.properties
/.kotlin
/.vscode
**/build
-**/.kotlin
\ No newline at end of file
+**/.kotlin
+
+*.jks
diff --git a/LICENSE b/LICENSE
index 7a4a3ea242..e05e6c724f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright [yyyy] [name of copyright owner]
+ Copyright 2026, IacobIonut01 and GrapheneOS Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index 845413c190..8818ecccaa 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,34 @@
-# ReFra
-> An Android Gallery app built with Jetpack Compose.
->
-> The goal of this project is to create and bring the Gallery app everyone wants, with the features everyone needs. FOSS
-
-
-[](https://github.com/IacobIonut01/Gallery/actions/workflows/nightly.yml)
-
-[](https://crowdin.com/project/gallery-compose)
-
-
-
-[](https://crowdin.com/project/gallery-compose)
-[](https://t.me/GalleryCompose)
-
-## Download
-[
](https://f-droid.org/packages/com.dot.gallery)
-[
](https://play.google.com/store/apps/details?id=com.dot.gallery.gplay&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)
-[
](https://github.com/IacobIonut01/Gallery/releases/latest)
-
-## Support
-- Translate the project using the link from above
-- Donations:
- - Use the links on the right side of the repo (Sponsor me)
- - More options available in-app (Settings -> Donate)
-## Frequent Questions
-- Why 'ReFra'?
- - Refra is a short form of 'refraction', which is the bending of light when it passes through different mediums. This app aims to refract our perception of media files, making them more accessible and easier to manage.
-- What is the `nomaps` variant?
- - The `nomaps` variant is a version of the app that does not include the maps features - Map Preview, Location Map Viewer. This is useful for users who do not need this feature and want to remove unecessary permissions like INTERNET access.
-- Why Google Play version is 'Paid'?
- - It's just another way to support the project while getting back automatic updates via Google Play
-- Why Android 11 is the minimum version required?
- - Some Media features and APIs require Android 11 as a minimum version [Trash feature, most APIs used in the app]
-- Will you support lower android versions?
- - While this is not a priority right now, I do have in mind to include support for lower Android versions at a cost of reduced features. If anyone volntueers to do so before me can request a pull request.
-- Can I verify the downloaded APK file?
- - Checksums of APKs are provided in the release notes. The signing certificate fingerprint is listed below:
- - SHA-256: `78:46:05:DD:50:75:BE:05:82:78:A5:42:5C:BD:E5:21:31:62:CB:B4:59:1B:44:28:F4:4E:75:E0:8C:C6:43:8A`
- - SHA-1: `AD:93:69:27:F2:3B:33:99:FC:C0:B2:8A:25:44:C8:1C:AA:42:B0:9A`
- - MD5: `73:FC:3C:60:14:D3:69:6D:1B:DA:34:F1:BF:5A:33:3C`
-- Will you add [X] feature?
- - Please open a new feature request under 'Issues' tab and if the feature will be considered useful and possible can be added.
-- Can you remove permission [X]?
- - Several permissions (e.g. Internet connectivity, location) are for showing a map preview of your current photo location data. If you do not need this feature, you can download a `nomaps` release from the [Releases page](https://github.com/IacobIonut01/Gallery/releases).
+# Gallery
+
+GrapheneOS Gallery app.
+
+This project is a fork of [ReFra](https://github.com/IacobIonut01/Gallery), originally developed
+by [IacobIonut01](https://github.com/IacobIonut01).
+
+## About
+
+Gallery is a modern Android media gallery built with Jetpack Compose. It supports browsing photos and videos, albums,
+media details, search, editing, trash, favorites, widgets, and other media-management features.
+
+## Development
+
+### Building
+
+GrapheneOS Gallery is built without all files access and maps, but with ML models.
+
+To quickly build and stage the release version in the GOS tree, use `scripts/build-and-copy-to-gos.sh`.
+
+Before running, do `ln -s "$HOME/.android/debug.keystore" app/release_key.jks` to use your debug key for release signing
+or create a keystore in `app/release_key.jks`.
+
+Set `GOS_ROOT` env variable pointing to the root of your GrapheneOS checkout.
+
+### Running CTS tests
+
+```shell
+atest --test-mapping external/Gallery:all
+```
+
+## License
+
+This project is licensed under the Apache License 2.0. See [LICENSE](LICENSE).
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 041f424dc9..9ffc6a4936 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,6 +1,5 @@
+import com.android.build.api.dsl.ApplicationBuildType
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
-import java.io.FileInputStream
-import java.util.Properties
plugins {
alias(libs.plugins.androidApplication)
@@ -11,42 +10,32 @@ plugins {
alias(libs.plugins.kotlin.compose.compiler)
id("kotlin-parcelize")
alias(libs.plugins.kotlinSerialization)
- id("apk-versioning")
}
-val abiVersionCodes = mapOf(
- "arm64-v8a" to 4,
- "armeabi-v7a" to 3,
- "x86_64" to 2,
- "x86" to 1,
- "universal" to 0
-)
-
-apkVersioning {
- flavorVersionCodes.set(abiVersionCodes)
- versionCodeMultiplier.set(10)
- outputFileName.set("{appName}-{versionName}-{versionCode}{suffix}-{flavorName}-{buildType}")
- variables.put("appName", "ReFra")
- variables.put("suffix", if (includeMaps) "" else "-nomaps")
-}
+val baseApplicationId = providers
+ .gradleProperty("baseApplicationId")
+ .get()
android {
namespace = "com.dot.gallery"
compileSdk = 37
defaultConfig {
- applicationId = "com.dot.gallery"
- minSdk = 29
+ applicationId = baseApplicationId
+ minSdk = 36
targetSdk = 37
- versionCode = 42101
- versionName = "4.2.1"
+ versionCode = 1
+ versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
- val mapsPrefix = if (includeMaps) "" else "-nomaps"
- base.archivesName.set("ReFra-${versionName}-$versionCode$mapsPrefix")
+ base.archivesName.set("Gallery")
+ }
+
+ testOptions {
+ unitTests.isIncludeAndroidResources = true
}
lint.baseline = file("lint-baseline.xml")
@@ -61,23 +50,19 @@ android {
}
buildTypes {
+ fun ApplicationBuildType.configureProvider() {
+ val authority = "$baseApplicationId${applicationIdSuffix.orEmpty()}.media_provider"
+ manifestPlaceholders["appProvider"] = authority
+ buildConfigField("String", "CONTENT_AUTHORITY", "\"$authority\"")
+ }
+
getByName("debug") {
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
- manifestPlaceholders["appProvider"] = "com.dot.gallery.debug.media_provider"
- buildConfigField("Boolean", "ALLOW_ALL_FILES_ACCESS", "$allowAllFilesAccess")
- buildConfigField("Boolean", "MAPS_ENABLED", "$includeMaps")
- buildConfigField(
- "String",
- "CONTENT_AUTHORITY",
- "\"com.dot.gallery.debug.media_provider\""
- )
- buildConfigField("Boolean", "ENABLE_INDEXING", "false")
+ configureProvider()
}
getByName("release") {
- manifestPlaceholders += mapOf(
- "appProvider" to "com.dot.gallery.media_provider"
- )
+ configureProvider()
isMinifyEnabled = true
isShrinkResources = true
setProguardFiles(
@@ -87,10 +72,6 @@ android {
)
)
signingConfig = signingConfigs.getByName("release")
- buildConfigField("Boolean", "ALLOW_ALL_FILES_ACCESS", "$allowAllFilesAccess")
- buildConfigField("Boolean", "MAPS_ENABLED", "$includeMaps")
- buildConfigField("String", "CONTENT_AUTHORITY", "\"com.dot.gallery.media_provider\"")
- buildConfigField("Boolean", "ENABLE_INDEXING", "true")
}
create("staging") {
initWith(getByName("release"))
@@ -99,14 +80,17 @@ android {
isShrinkResources = false
applicationIdSuffix = ".staging"
versionNameSuffix = "-staging"
- manifestPlaceholders["appProvider"] = "com.dot.staging.debug.media_provider"
- buildConfigField(
- "String",
- "CONTENT_AUTHORITY",
- "\"com.dot.staging.debug.media_provider\""
- )
- buildConfigField("Boolean", "ENABLE_INDEXING", "true")
- buildConfigField("Boolean", "MAPS_ENABLED", "$includeMaps")
+ configureProvider()
+ }
+
+ // Use to manually check performance with release config, but debug signing
+ create("perf") {
+ initWith(getByName("release"))
+ matchingFallbacks += "release"
+ applicationIdSuffix = ".perf"
+ versionNameSuffix = "-perf"
+ signingConfig = signingConfigs.getByName("debug")
+ configureProvider()
}
}
@@ -123,6 +107,9 @@ android {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
+ androidResources {
+ noCompress += listOf("json", "onnx", "txt")
+ }
assetPacks += listOf(":ml-models")
@@ -133,44 +120,22 @@ android {
sourceSets {
getByName("main") {
- // Conditional maps/nomaps source set
- if (includeMaps) {
- kotlin.srcDir("src/maps/kotlin")
- } else {
- kotlin.srcDir("src/nomaps/kotlin")
+ // For APK builds, include ML assets directly since asset packs are AAB-only
+ val isBundleBuild = gradle.startParameter.taskNames.any {
+ it.contains("bundle", ignoreCase = true)
}
- }
- // For withML APK builds, include ML model assets directly
- // (asset packs are AAB-only, so for APK builds we inline them)
- val isBundleBuild = gradle.startParameter.taskNames.any {
- it.contains("bundle", ignoreCase = true)
- }
- if (!isBundleBuild) {
- maybeCreate("withML").apply {
- assets.srcDirs("../ml-models/src/main/assets")
+ if (!isBundleBuild) {
+ assets.srcDirs("src/main/assets", "../ml-models/src/main/assets")
}
}
}
- flavorDimensions += listOf("abi", "ml")
- productFlavors {
- abiVersionCodes.forEach { (abi, _) ->
- create(abi) {
- dimension = "abi"
- if (abi == "universal") {
- ndk.abiFilters.addAll(listOf("x86", "x86_64", "armeabi-v7a", "arm64-v8a"))
- } else {
- ndk.abiFilters.add(abi)
- }
- }
- }
- create("withML") {
- dimension = "ml"
- buildConfigField("Boolean", "ML_MODELS_BUNDLED", "true")
- }
- create("noML") {
- dimension = "ml"
- buildConfigField("Boolean", "ML_MODELS_BUNDLED", "false")
+ splits {
+ abi {
+ isEnable = true
+ reset()
+ include("arm64-v8a", "x86_64")
+ isUniversalApk = false
}
}
@@ -260,8 +225,9 @@ dependencies {
implementation(libs.room.ktx)
// Coders
- implementation(libs.jxl.coder.coil)
+ implementation(libs.androidsvg)
implementation(libs.avif.coder.coil)
+ implementation(libs.jxl.coder.coil)
// Sketch
implementation(libs.sketch.compose)
@@ -290,9 +256,6 @@ dependencies {
implementation(libs.androidx.exifinterface)
implementation(libs.metadata.extractor)
- // NanoHTTPD - Embedded HTTP server for FCast media serving
- implementation(libs.nanohttpd)
-
// Datastore Preferences
implementation(libs.datastore.prefs)
@@ -309,7 +272,6 @@ dependencies {
implementation(libs.androidx.core.splashscreen)
// Jetpack Security
- implementation(libs.androidx.security.crypto)
implementation(libs.androidx.biometric)
// Composables - Core
@@ -328,40 +290,14 @@ dependencies {
implementation(libs.haze)
implementation(libs.haze.materials)
- // MapLibre Native SDK
- if (includeMaps) {
- implementation(libs.maplibre.native)
- }
-
// Tests
+ testImplementation(libs.androidx.work.testing)
testImplementation(libs.junit)
+ testImplementation(libs.kotlinx.coroutines.test)
+ testImplementation(libs.mockk)
+ testImplementation(libs.robolectric)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
debugImplementation(libs.compose.ui.tooling)
debugRuntimeOnly(libs.compose.ui.test.manifest)
}
-
-val includeMaps: Boolean
- get() {
- val fl = rootProject.file("app.properties")
- return try {
- val properties = Properties()
- properties.load(FileInputStream(fl))
- properties.getProperty("INCLUDE_MAPS", "true").toBoolean()
- } catch (_: Exception) {
- true
- }
- }
-
-val allowAllFilesAccess: Boolean
- get() {
- val fl = rootProject.file("app.properties")
-
- return try {
- val properties = Properties()
- properties.load(FileInputStream(fl))
- properties.getProperty("ALL_FILES_ACCESS", "true").toBoolean()
- } catch (_: Exception) {
- true
- }
- }
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 3bd5128b75..5d916496d0 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -36,9 +36,9 @@
-dontwarn org.tensorflow.lite.gpu.GpuDelegateFactory$Options$GpuBackend
-dontwarn org.tensorflow.lite.gpu.GpuDelegateFactory$Options
-# Keep custom Glide decoders and model loaders (HEIF/JXL/Encrypted)
+# Keep custom Glide decoders and model loaders (HEIF/JXL)
-keep class com.dot.gallery.core.decoder.glide.** { *; }
-keep class com.radzivon.bartoshyk.avif.** { *; }
-keep class com.awxkee.jxlcoder.** { *; }
-dontwarn com.radzivon.bartoshyk.avif.**
--dontwarn com.awxkee.jxlcoder.**
\ No newline at end of file
+-dontwarn com.awxkee.jxlcoder.**
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
index 0fb13d5d84..d3f69ccbe9 100644
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
+++ b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
- "identityHash": "2fe35fcd34db546153a2ddbaa2e5e76a",
+ "identityHash": "fa2b674e40b3649f795f7b8d591573ab",
"entities": [
{
"tableName": "pinned_table",
@@ -20,15 +20,1124 @@
"columnNames": [
"id"
]
+ }
+ },
+ {
+ "tableName": "blacklist",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "label",
+ "columnName": "label",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "wildcard",
+ "columnName": "wildcard",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "albumIds",
+ "columnName": "albumIds",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'[]'"
+ },
+ {
+ "fieldPath": "location",
+ "columnName": "location",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "matchedAlbums",
+ "columnName": "matchedAlbums",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'[]'"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "media",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "label",
+ "columnName": "label",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "uri",
+ "columnName": "uri",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "path",
+ "columnName": "path",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "relativePath",
+ "columnName": "relativePath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "albumID",
+ "columnName": "albumID",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "albumLabel",
+ "columnName": "albumLabel",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "expiryTimestamp",
+ "columnName": "expiryTimestamp",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "takenTimestamp",
+ "columnName": "takenTimestamp",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "fullDate",
+ "columnName": "fullDate",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mimeType",
+ "columnName": "mimeType",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "favorite",
+ "columnName": "favorite",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "trashed",
+ "columnName": "trashed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "size",
+ "columnName": "size",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "duration",
+ "columnName": "duration",
+ "affinity": "TEXT"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "media_version",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
+ "fields": [
+ {
+ "fieldPath": "version",
+ "columnName": "version",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "version"
+ ]
+ }
+ },
+ {
+ "tableName": "timeline_settings",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "groupTimelineByMonth",
+ "columnName": "groupTimelineByMonth",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "groupTimelineInAlbums",
+ "columnName": "groupTimelineInAlbums",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "timelineMediaOrder",
+ "columnName": "timelineMediaOrder",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
+ },
+ {
+ "fieldPath": "albumMediaOrder",
+ "columnName": "albumMediaOrder",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "classified_media",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "label",
+ "columnName": "label",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "uri",
+ "columnName": "uri",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "path",
+ "columnName": "path",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "relativePath",
+ "columnName": "relativePath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "albumID",
+ "columnName": "albumID",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "albumLabel",
+ "columnName": "albumLabel",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "expiryTimestamp",
+ "columnName": "expiryTimestamp",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "takenTimestamp",
+ "columnName": "takenTimestamp",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "fullDate",
+ "columnName": "fullDate",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mimeType",
+ "columnName": "mimeType",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "favorite",
+ "columnName": "favorite",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "trashed",
+ "columnName": "trashed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "size",
+ "columnName": "size",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "duration",
+ "columnName": "duration",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "category",
+ "columnName": "category",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "score",
+ "columnName": "score",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "media_metadata_core",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
+ "fields": [
+ {
+ "fieldPath": "mediaId",
+ "columnName": "mediaId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "imageDescription",
+ "columnName": "imageDescription",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "dateTimeOriginal",
+ "columnName": "dateTimeOriginal",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "manufacturerName",
+ "columnName": "manufacturerName",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "modelName",
+ "columnName": "modelName",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "aperture",
+ "columnName": "aperture",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "exposureTime",
+ "columnName": "exposureTime",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "iso",
+ "columnName": "iso",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "gpsLatitude",
+ "columnName": "gpsLatitude",
+ "affinity": "REAL"
+ },
+ {
+ "fieldPath": "gpsLongitude",
+ "columnName": "gpsLongitude",
+ "affinity": "REAL"
+ },
+ {
+ "fieldPath": "gpsLocationName",
+ "columnName": "gpsLocationName",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "gpsLocationNameCountry",
+ "columnName": "gpsLocationNameCountry",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "gpsLocationNameCity",
+ "columnName": "gpsLocationNameCity",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "imageWidth",
+ "columnName": "imageWidth",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "imageHeight",
+ "columnName": "imageHeight",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "imageResolutionX",
+ "columnName": "imageResolutionX",
+ "affinity": "REAL"
+ },
+ {
+ "fieldPath": "imageResolutionY",
+ "columnName": "imageResolutionY",
+ "affinity": "REAL"
+ },
+ {
+ "fieldPath": "resolutionUnit",
+ "columnName": "resolutionUnit",
+ "affinity": "INTEGER"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "mediaId"
+ ]
+ }
+ },
+ {
+ "tableName": "media_metadata_video",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
+ "fields": [
+ {
+ "fieldPath": "mediaId",
+ "columnName": "mediaId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "durationMs",
+ "columnName": "durationMs",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "videoWidth",
+ "columnName": "videoWidth",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "videoHeight",
+ "columnName": "videoHeight",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "frameRate",
+ "columnName": "frameRate",
+ "affinity": "REAL"
+ },
+ {
+ "fieldPath": "bitRate",
+ "columnName": "bitRate",
+ "affinity": "INTEGER"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "mediaId"
+ ]
+ }
+ },
+ {
+ "tableName": "media_metadata_flags",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
+ "fields": [
+ {
+ "fieldPath": "mediaId",
+ "columnName": "mediaId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNightMode",
+ "columnName": "isNightMode",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPanorama",
+ "columnName": "isPanorama",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPhotosphere",
+ "columnName": "isPhotosphere",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isLongExposure",
+ "columnName": "isLongExposure",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isMotionPhoto",
+ "columnName": "isMotionPhoto",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "mediaId"
+ ]
+ }
+ },
+ {
+ "tableName": "album_thumbnail",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
+ "fields": [
+ {
+ "fieldPath": "albumId",
+ "columnName": "albumId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "thumbnailUri",
+ "columnName": "thumbnailUri",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "albumId"
+ ]
+ }
+ },
+ {
+ "tableName": "image_embeddings",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` BLOB NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "embedding",
+ "columnName": "embedding",
+ "affinity": "BLOB",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "categories",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` BLOB, `referenceImageIds` TEXT NOT NULL DEFAULT '[]', `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "searchTerms",
+ "columnName": "searchTerms",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "embedding",
+ "columnName": "embedding",
+ "affinity": "BLOB"
+ },
+ {
+ "fieldPath": "referenceImageIds",
+ "columnName": "referenceImageIds",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'[]'"
+ },
+ {
+ "fieldPath": "threshold",
+ "columnName": "threshold",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isUserCreated",
+ "columnName": "isUserCreated",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPinned",
+ "columnName": "isPinned",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "createdAt",
+ "columnName": "createdAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "updatedAt",
+ "columnName": "updatedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "media_category",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "mediaId",
+ "columnName": "mediaId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryId",
+ "columnName": "categoryId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "similarityScore",
+ "columnName": "similarityScore",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "addedAt",
+ "columnName": "addedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isManuallyAdded",
+ "columnName": "isManuallyAdded",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "mediaId",
+ "categoryId"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_media_category_categoryId",
+ "unique": false,
+ "columnNames": [
+ "categoryId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
+ },
+ {
+ "name": "index_media_category_mediaId",
+ "unique": false,
+ "columnNames": [
+ "mediaId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
+ },
+ {
+ "name": "index_media_category_similarityScore",
+ "unique": false,
+ "columnNames": [
+ "similarityScore"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "categories",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "categoryId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "locked_table",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "album_groups",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "label",
+ "columnName": "label",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "album_group_members",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, PRIMARY KEY(`groupId`, `albumId`), FOREIGN KEY(`groupId`) REFERENCES `album_groups`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "groupId",
+ "columnName": "groupId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "albumId",
+ "columnName": "albumId",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "groupId",
+ "albumId"
+ ]
},
- "indices": [],
- "foreignKeys": []
+ "foreignKeys": [
+ {
+ "table": "album_groups",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "groupId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "merged_subfolder_table",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "collections",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `coverMediaId` INTEGER, `isPinned` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "label",
+ "columnName": "label",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "coverMediaId",
+ "columnName": "coverMediaId",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "isPinned",
+ "columnName": "isPinned",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sortOrder",
+ "columnName": "sortOrder",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "createdAt",
+ "columnName": "createdAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "updatedAt",
+ "columnName": "updatedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "collection_media",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`collectionId` INTEGER NOT NULL, `mediaId` INTEGER NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`collectionId`, `mediaId`), FOREIGN KEY(`collectionId`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "collectionId",
+ "columnName": "collectionId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mediaId",
+ "columnName": "mediaId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "addedAt",
+ "columnName": "addedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "collectionId",
+ "mediaId"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_collection_media_collectionId",
+ "unique": false,
+ "columnNames": [
+ "collectionId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_collectionId` ON `${TABLE_NAME}` (`collectionId`)"
+ },
+ {
+ "name": "index_collection_media_mediaId",
+ "unique": false,
+ "columnNames": [
+ "mediaId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "collections",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "collectionId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "collection_albums",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`collectionId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`collectionId`, `albumId`), FOREIGN KEY(`collectionId`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "collectionId",
+ "columnName": "collectionId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "albumId",
+ "columnName": "albumId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "addedAt",
+ "columnName": "addedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "collectionId",
+ "albumId"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_collection_albums_collectionId",
+ "unique": false,
+ "columnNames": [
+ "collectionId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_albums_collectionId` ON `${TABLE_NAME}` (`collectionId`)"
+ },
+ {
+ "name": "index_collection_albums_albumId",
+ "unique": false,
+ "columnNames": [
+ "albumId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_albums_albumId` ON `${TABLE_NAME}` (`albumId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "collections",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "collectionId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "scanned_media",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "category_classification_generation",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`singletonId` INTEGER NOT NULL, `generationId` TEXT NOT NULL, PRIMARY KEY(`singletonId`))",
+ "fields": [
+ {
+ "fieldPath": "singletonId",
+ "columnName": "singletonId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "generationId",
+ "columnName": "generationId",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "singletonId"
+ ]
+ }
+ },
+ {
+ "tableName": "generated_media_category_staging",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`generationId` TEXT NOT NULL, `mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`generationId`, `mediaId`, `categoryId`))",
+ "fields": [
+ {
+ "fieldPath": "generationId",
+ "columnName": "generationId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mediaId",
+ "columnName": "mediaId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryId",
+ "columnName": "categoryId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "similarityScore",
+ "columnName": "similarityScore",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "addedAt",
+ "columnName": "addedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "generationId",
+ "mediaId",
+ "categoryId"
+ ]
+ }
}
],
- "views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2fe35fcd34db546153a2ddbaa2e5e76a')"
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'fa2b674e40b3649f795f7b8d591573ab')"
]
}
}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/10.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/10.json
deleted file mode 100644
index bd815b9bde..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/10.json
+++ /dev/null
@@ -1,693 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 10,
- "identityHash": "59ea4892e44757f553f14c61eaf1088b",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- }
- ],
- "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, '59ea4892e44757f553f14c61eaf1088b')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/11.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/11.json
deleted file mode 100644
index 369942b2c0..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/11.json
+++ /dev/null
@@ -1,723 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 11,
- "identityHash": "cb817b5162c214f4ed65f810d7eb814e",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "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, 'cb817b5162c214f4ed65f810d7eb814e')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/12.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/12.json
deleted file mode 100644
index 4fa79bcfb8..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/12.json
+++ /dev/null
@@ -1,738 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 12,
- "identityHash": "26ff9ec9cc612eb24d80263f7bb14a7f",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "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, '26ff9ec9cc612eb24d80263f7bb14a7f')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/13.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/13.json
deleted file mode 100644
index cac44f4c41..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/13.json
+++ /dev/null
@@ -1,744 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 13,
- "identityHash": "2b64b3e250d8dae20e3cec3ab97553ac",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "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, '2b64b3e250d8dae20e3cec3ab97553ac')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/14.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/14.json
deleted file mode 100644
index f049c8084f..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/14.json
+++ /dev/null
@@ -1,899 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 14,
- "identityHash": "030b2719f7a9a7826a120e8e0f35c6d7",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `iconEmoji` TEXT)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "iconEmoji",
- "columnName": "iconEmoji",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "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, '030b2719f7a9a7826a120e8e0f35c6d7')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/15.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/15.json
deleted file mode 100644
index 3ff62c7318..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/15.json
+++ /dev/null
@@ -1,894 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 15,
- "identityHash": "11e6bf4e85347270a331b6ce4ef1768b",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "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, '11e6bf4e85347270a331b6ce4ef1768b')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/16.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/16.json
deleted file mode 100644
index 3dc4690ee3..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/16.json
+++ /dev/null
@@ -1,936 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 16,
- "identityHash": "4738f291117a025ffd4fdd42f305db17",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- }
- ],
- "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, '4738f291117a025ffd4fdd42f305db17')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/17.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/17.json
deleted file mode 100644
index 357bc504e0..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/17.json
+++ /dev/null
@@ -1,954 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 17,
- "identityHash": "27f461c4b5960eb23809047e82f82449",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "locked_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "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, '27f461c4b5960eb23809047e82f82449')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/18.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/18.json
deleted file mode 100644
index dd645667f7..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/18.json
+++ /dev/null
@@ -1,1022 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 18,
- "identityHash": "79d1c2631dec78b4b92d1865f147fe4c",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "locked_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_groups",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_group_members",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, PRIMARY KEY(`groupId`, `albumId`), FOREIGN KEY(`groupId`) REFERENCES `album_groups`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "groupId",
- "columnName": "groupId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "groupId",
- "albumId"
- ]
- },
- "foreignKeys": [
- {
- "table": "album_groups",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "groupId"
- ],
- "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, '79d1c2631dec78b4b92d1865f147fe4c')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/19.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/19.json
deleted file mode 100644
index 2e9b872566..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/19.json
+++ /dev/null
@@ -1,1040 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 19,
- "identityHash": "d986f5c74cdebc5b14bc23e589afc438",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "locked_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_groups",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_group_members",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, PRIMARY KEY(`groupId`, `albumId`), FOREIGN KEY(`groupId`) REFERENCES `album_groups`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "groupId",
- "columnName": "groupId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "groupId",
- "albumId"
- ]
- },
- "foreignKeys": [
- {
- "table": "album_groups",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "groupId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "merged_subfolder_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "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, 'd986f5c74cdebc5b14bc23e589afc438')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/2.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/2.json
deleted file mode 100644
index 20844acf5e..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/2.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 2,
- "identityHash": "57402321aff199c16e2f25a4a21623ba",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '57402321aff199c16e2f25a4a21623ba')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/20.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/20.json
deleted file mode 100644
index ebb23102a3..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/20.json
+++ /dev/null
@@ -1,1157 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 20,
- "identityHash": "4482c3954f6c26b5d7087d8dc9589e1c",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "locked_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_groups",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_group_members",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, PRIMARY KEY(`groupId`, `albumId`), FOREIGN KEY(`groupId`) REFERENCES `album_groups`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "groupId",
- "columnName": "groupId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "groupId",
- "albumId"
- ]
- },
- "foreignKeys": [
- {
- "table": "album_groups",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "groupId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "merged_subfolder_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "collections",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `coverMediaId` INTEGER, `isPinned` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "coverMediaId",
- "columnName": "coverMediaId",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "sortOrder",
- "columnName": "sortOrder",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "collection_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`collectionId` INTEGER NOT NULL, `mediaId` INTEGER NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`collectionId`, `mediaId`), FOREIGN KEY(`collectionId`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "collectionId",
- "columnName": "collectionId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "collectionId",
- "mediaId"
- ]
- },
- "indices": [
- {
- "name": "index_collection_media_collectionId",
- "unique": false,
- "columnNames": [
- "collectionId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_collectionId` ON `${TABLE_NAME}` (`collectionId`)"
- },
- {
- "name": "index_collection_media_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "collections",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "collectionId"
- ],
- "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, '4482c3954f6c26b5d7087d8dc9589e1c')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/21.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/21.json
deleted file mode 100644
index 57ec739e1a..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/21.json
+++ /dev/null
@@ -1,1164 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 21,
- "identityHash": "3a4d92718053c0aa2bf79126cc6eaab0",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `referenceImageIds` TEXT NOT NULL DEFAULT '[]', `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "referenceImageIds",
- "columnName": "referenceImageIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "locked_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_groups",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_group_members",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, PRIMARY KEY(`groupId`, `albumId`), FOREIGN KEY(`groupId`) REFERENCES `album_groups`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "groupId",
- "columnName": "groupId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "groupId",
- "albumId"
- ]
- },
- "foreignKeys": [
- {
- "table": "album_groups",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "groupId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "merged_subfolder_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "collections",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `coverMediaId` INTEGER, `isPinned` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "coverMediaId",
- "columnName": "coverMediaId",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "sortOrder",
- "columnName": "sortOrder",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "collection_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`collectionId` INTEGER NOT NULL, `mediaId` INTEGER NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`collectionId`, `mediaId`), FOREIGN KEY(`collectionId`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "collectionId",
- "columnName": "collectionId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "collectionId",
- "mediaId"
- ]
- },
- "indices": [
- {
- "name": "index_collection_media_collectionId",
- "unique": false,
- "columnNames": [
- "collectionId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_collectionId` ON `${TABLE_NAME}` (`collectionId`)"
- },
- {
- "name": "index_collection_media_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "collections",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "collectionId"
- ],
- "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, '3a4d92718053c0aa2bf79126cc6eaab0')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/22.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/22.json
deleted file mode 100644
index b7c393583d..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/22.json
+++ /dev/null
@@ -1,1228 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 22,
- "identityHash": "7b2b1066156f3c9af955c7fd535761b8",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT, `wildcard` TEXT, `albumIds` TEXT NOT NULL DEFAULT '[]', `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "albumIds",
- "columnName": "albumIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `gpsLocationName` TEXT, `gpsLocationNameCountry` TEXT, `gpsLocationNameCity` TEXT, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLocationName",
- "columnName": "gpsLocationName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCountry",
- "columnName": "gpsLocationNameCountry",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLocationNameCity",
- "columnName": "gpsLocationNameCity",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "album_thumbnail",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`albumId` INTEGER NOT NULL, `thumbnailUri` TEXT NOT NULL, PRIMARY KEY(`albumId`))",
- "fields": [
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "thumbnailUri",
- "columnName": "thumbnailUri",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "albumId"
- ]
- }
- },
- {
- "tableName": "image_embeddings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `embedding` TEXT NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "categories",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `searchTerms` TEXT NOT NULL, `embedding` TEXT, `referenceImageIds` TEXT NOT NULL DEFAULT '[]', `threshold` REAL NOT NULL, `isUserCreated` INTEGER NOT NULL, `isPinned` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "searchTerms",
- "columnName": "searchTerms",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "embedding",
- "columnName": "embedding",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "referenceImageIds",
- "columnName": "referenceImageIds",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- },
- {
- "fieldPath": "threshold",
- "columnName": "threshold",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "isUserCreated",
- "columnName": "isUserCreated",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_category",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `similarityScore` REAL NOT NULL, `addedAt` INTEGER NOT NULL, `isManuallyAdded` INTEGER NOT NULL, PRIMARY KEY(`mediaId`, `categoryId`), FOREIGN KEY(`categoryId`) REFERENCES `categories`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "categoryId",
- "columnName": "categoryId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "similarityScore",
- "columnName": "similarityScore",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isManuallyAdded",
- "columnName": "isManuallyAdded",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId",
- "categoryId"
- ]
- },
- "indices": [
- {
- "name": "index_media_category_categoryId",
- "unique": false,
- "columnNames": [
- "categoryId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_categoryId` ON `${TABLE_NAME}` (`categoryId`)"
- },
- {
- "name": "index_media_category_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- },
- {
- "name": "index_media_category_similarityScore",
- "unique": false,
- "columnNames": [
- "similarityScore"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_media_category_similarityScore` ON `${TABLE_NAME}` (`similarityScore`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "categories",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "categoryId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "edited_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `originalUri` TEXT NOT NULL, `backupPath` TEXT NOT NULL, `originalMimeType` TEXT NOT NULL, `editTimestamp` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "originalUri",
- "columnName": "originalUri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "backupPath",
- "columnName": "backupPath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "originalMimeType",
- "columnName": "originalMimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "editTimestamp",
- "columnName": "editTimestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "locked_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_groups",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "album_group_members",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, PRIMARY KEY(`groupId`, `albumId`), FOREIGN KEY(`groupId`) REFERENCES `album_groups`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "groupId",
- "columnName": "groupId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "groupId",
- "albumId"
- ]
- },
- "foreignKeys": [
- {
- "table": "album_groups",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "groupId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "merged_subfolder_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "collections",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `label` TEXT NOT NULL, `coverMediaId` INTEGER, `isPinned` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "coverMediaId",
- "columnName": "coverMediaId",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "isPinned",
- "columnName": "isPinned",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "sortOrder",
- "columnName": "sortOrder",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "createdAt",
- "columnName": "createdAt",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "updatedAt",
- "columnName": "updatedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "collection_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`collectionId` INTEGER NOT NULL, `mediaId` INTEGER NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`collectionId`, `mediaId`), FOREIGN KEY(`collectionId`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "collectionId",
- "columnName": "collectionId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "collectionId",
- "mediaId"
- ]
- },
- "indices": [
- {
- "name": "index_collection_media_collectionId",
- "unique": false,
- "columnNames": [
- "collectionId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_collectionId` ON `${TABLE_NAME}` (`collectionId`)"
- },
- {
- "name": "index_collection_media_mediaId",
- "unique": false,
- "columnNames": [
- "mediaId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_media_mediaId` ON `${TABLE_NAME}` (`mediaId`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "collections",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "collectionId"
- ],
- "referencedColumns": [
- "id"
- ]
- }
- ]
- },
- {
- "tableName": "collection_albums",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`collectionId` INTEGER NOT NULL, `albumId` INTEGER NOT NULL, `addedAt` INTEGER NOT NULL, PRIMARY KEY(`collectionId`, `albumId`), FOREIGN KEY(`collectionId`) REFERENCES `collections`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
- "fields": [
- {
- "fieldPath": "collectionId",
- "columnName": "collectionId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumId",
- "columnName": "albumId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "addedAt",
- "columnName": "addedAt",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "collectionId",
- "albumId"
- ]
- },
- "indices": [
- {
- "name": "index_collection_albums_collectionId",
- "unique": false,
- "columnNames": [
- "collectionId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_albums_collectionId` ON `${TABLE_NAME}` (`collectionId`)"
- },
- {
- "name": "index_collection_albums_albumId",
- "unique": false,
- "columnNames": [
- "albumId"
- ],
- "orders": [],
- "createSql": "CREATE INDEX IF NOT EXISTS `index_collection_albums_albumId` ON `${TABLE_NAME}` (`albumId`)"
- }
- ],
- "foreignKeys": [
- {
- "table": "collections",
- "onDelete": "CASCADE",
- "onUpdate": "NO ACTION",
- "columns": [
- "collectionId"
- ],
- "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, '7b2b1066156f3c9af955c7fd535761b8')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/3.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/3.json
deleted file mode 100644
index 06dd7d8b75..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/3.json
+++ /dev/null
@@ -1,80 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 3,
- "identityHash": "b923fda23747db68de4db23fb2360ff8",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b923fda23747db68de4db23fb2360ff8')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/4.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/4.json
deleted file mode 100644
index 57b91fbe92..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/4.json
+++ /dev/null
@@ -1,210 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 4,
- "identityHash": "d11e7f0b804e55f9526cc63d181876a1",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd11e7f0b804e55f9526cc63d181876a1')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/5.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/5.json
deleted file mode 100644
index 3c4cb0059c..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/5.json
+++ /dev/null
@@ -1,258 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 5,
- "identityHash": "65c73e58b535f1a24397f4143bdf1dde",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '65c73e58b535f1a24397f4143bdf1dde')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/6.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/6.json
deleted file mode 100644
index 3aeb006744..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/6.json
+++ /dev/null
@@ -1,380 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 6,
- "identityHash": "d85fa3d06047d72471daf8b524c6c943",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd85fa3d06047d72471daf8b524c6c943')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/7.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/7.json
deleted file mode 100644
index a6558ae80d..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/7.json
+++ /dev/null
@@ -1,516 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 7,
- "identityHash": "190a2664a6d02bbf298fe05a21a21a8c",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '190a2664a6d02bbf298fe05a21a21a8c')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/8.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/8.json
deleted file mode 100644
index 3c3a04e156..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/8.json
+++ /dev/null
@@ -1,669 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 8,
- "identityHash": "141b34baea78e63d0e752f1292567ea6",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- }
- ],
- "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, '141b34baea78e63d0e752f1292567ea6')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/9.json b/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/9.json
deleted file mode 100644
index 1fae8e8487..0000000000
--- a/app/schemas/com.dot.gallery.feature_node.data.data_source.InternalDatabase/9.json
+++ /dev/null
@@ -1,669 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 9,
- "identityHash": "141b34baea78e63d0e752f1292567ea6",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "blacklist",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `wildcard` TEXT, `location` INTEGER NOT NULL DEFAULT 0, `matchedAlbums` TEXT NOT NULL DEFAULT '[]', PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "wildcard",
- "columnName": "wildcard",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "location",
- "columnName": "location",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "matchedAlbums",
- "columnName": "matchedAlbums",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'[]'"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "media_version",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`version` TEXT NOT NULL, PRIMARY KEY(`version`))",
- "fields": [
- {
- "fieldPath": "version",
- "columnName": "version",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "version"
- ]
- }
- },
- {
- "tableName": "timeline_settings",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupTimelineByMonth` INTEGER NOT NULL DEFAULT 0, `groupTimelineInAlbums` INTEGER NOT NULL DEFAULT 0, `timelineMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}', `albumMediaOrder` TEXT NOT NULL DEFAULT '{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}')",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "groupTimelineByMonth",
- "columnName": "groupTimelineByMonth",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "groupTimelineInAlbums",
- "columnName": "groupTimelineInAlbums",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "timelineMediaOrder",
- "columnName": "timelineMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- },
- {
- "fieldPath": "albumMediaOrder",
- "columnName": "albumMediaOrder",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"orderType\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"},\"orderType_date\":{\"type\":\"com.dot.gallery.feature_node.domain.util.OrderType.Descending\"}}'"
- }
- ],
- "primaryKey": {
- "autoGenerate": true,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "classified_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uri` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, `category` TEXT, `score` REAL NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uri",
- "columnName": "uri",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "score",
- "columnName": "score",
- "affinity": "REAL",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "encrypted_media",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, `uuid` TEXT NOT NULL, `path` TEXT NOT NULL, `relativePath` TEXT NOT NULL, `albumID` INTEGER NOT NULL, `albumLabel` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `expiryTimestamp` INTEGER, `takenTimestamp` INTEGER, `fullDate` TEXT NOT NULL, `mimeType` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `trashed` INTEGER NOT NULL, `size` INTEGER NOT NULL, `duration` TEXT, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "label",
- "columnName": "label",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "path",
- "columnName": "path",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "relativePath",
- "columnName": "relativePath",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "albumID",
- "columnName": "albumID",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "albumLabel",
- "columnName": "albumLabel",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "timestamp",
- "columnName": "timestamp",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "expiryTimestamp",
- "columnName": "expiryTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "takenTimestamp",
- "columnName": "takenTimestamp",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "fullDate",
- "columnName": "fullDate",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mimeType",
- "columnName": "mimeType",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "favorite",
- "columnName": "favorite",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "trashed",
- "columnName": "trashed",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "size",
- "columnName": "size",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "duration",
- "columnName": "duration",
- "affinity": "TEXT"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- }
- },
- {
- "tableName": "vaults",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`uuid`))",
- "fields": [
- {
- "fieldPath": "uuid",
- "columnName": "uuid",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "uuid"
- ]
- }
- },
- {
- "tableName": "media_metadata_core",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `imageDescription` TEXT, `dateTimeOriginal` TEXT, `manufacturerName` TEXT, `modelName` TEXT, `aperture` TEXT, `exposureTime` TEXT, `iso` TEXT, `gpsLatitude` REAL, `gpsLongitude` REAL, `imageWidth` INTEGER NOT NULL, `imageHeight` INTEGER NOT NULL, `imageResolutionX` REAL, `imageResolutionY` REAL, `resolutionUnit` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageDescription",
- "columnName": "imageDescription",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "dateTimeOriginal",
- "columnName": "dateTimeOriginal",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "manufacturerName",
- "columnName": "manufacturerName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "modelName",
- "columnName": "modelName",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "aperture",
- "columnName": "aperture",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "exposureTime",
- "columnName": "exposureTime",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "iso",
- "columnName": "iso",
- "affinity": "TEXT"
- },
- {
- "fieldPath": "gpsLatitude",
- "columnName": "gpsLatitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "gpsLongitude",
- "columnName": "gpsLongitude",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageWidth",
- "columnName": "imageWidth",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageHeight",
- "columnName": "imageHeight",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "imageResolutionX",
- "columnName": "imageResolutionX",
- "affinity": "REAL"
- },
- {
- "fieldPath": "imageResolutionY",
- "columnName": "imageResolutionY",
- "affinity": "REAL"
- },
- {
- "fieldPath": "resolutionUnit",
- "columnName": "resolutionUnit",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_video",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `durationMs` INTEGER, `videoWidth` INTEGER, `videoHeight` INTEGER, `frameRate` REAL, `bitRate` INTEGER, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "durationMs",
- "columnName": "durationMs",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoWidth",
- "columnName": "videoWidth",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "videoHeight",
- "columnName": "videoHeight",
- "affinity": "INTEGER"
- },
- {
- "fieldPath": "frameRate",
- "columnName": "frameRate",
- "affinity": "REAL"
- },
- {
- "fieldPath": "bitRate",
- "columnName": "bitRate",
- "affinity": "INTEGER"
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- },
- {
- "tableName": "media_metadata_flags",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mediaId` INTEGER NOT NULL, `isNightMode` INTEGER NOT NULL, `isPanorama` INTEGER NOT NULL, `isPhotosphere` INTEGER NOT NULL, `isLongExposure` INTEGER NOT NULL, `isMotionPhoto` INTEGER NOT NULL, PRIMARY KEY(`mediaId`))",
- "fields": [
- {
- "fieldPath": "mediaId",
- "columnName": "mediaId",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNightMode",
- "columnName": "isNightMode",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPanorama",
- "columnName": "isPanorama",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPhotosphere",
- "columnName": "isPhotosphere",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isLongExposure",
- "columnName": "isLongExposure",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isMotionPhoto",
- "columnName": "isMotionPhoto",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "mediaId"
- ]
- }
- }
- ],
- "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, '141b34baea78e63d0e752f1292567ea6')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/debug/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json b/app/schemas/debug/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
deleted file mode 100644
index 0fb13d5d84..0000000000
--- a/app/schemas/debug/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 1,
- "identityHash": "2fe35fcd34db546153a2ddbaa2e5e76a",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2fe35fcd34db546153a2ddbaa2e5e76a')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/release/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json b/app/schemas/release/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
deleted file mode 100644
index 0fb13d5d84..0000000000
--- a/app/schemas/release/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 1,
- "identityHash": "2fe35fcd34db546153a2ddbaa2e5e76a",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2fe35fcd34db546153a2ddbaa2e5e76a')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/schemas/staging/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json b/app/schemas/staging/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
deleted file mode 100644
index 0fb13d5d84..0000000000
--- a/app/schemas/staging/com.dot.gallery.feature_node.data.data_source.InternalDatabase/1.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 1,
- "identityHash": "2fe35fcd34db546153a2ddbaa2e5e76a",
- "entities": [
- {
- "tableName": "pinned_table",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "autoGenerate": false,
- "columnNames": [
- "id"
- ]
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2fe35fcd34db546153a2ddbaa2e5e76a')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.avif b/app/src/androidTest/assets/GalleryDecoderTest.avif
new file mode 100644
index 0000000000..a5eef6234b
Binary files /dev/null and b/app/src/androidTest/assets/GalleryDecoderTest.avif differ
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.gif b/app/src/androidTest/assets/GalleryDecoderTest.gif
new file mode 100644
index 0000000000..15a0a828cb
Binary files /dev/null and b/app/src/androidTest/assets/GalleryDecoderTest.gif differ
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.jxl b/app/src/androidTest/assets/GalleryDecoderTest.jxl
new file mode 100644
index 0000000000..82fc79f8a3
Binary files /dev/null and b/app/src/androidTest/assets/GalleryDecoderTest.jxl differ
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.mp4 b/app/src/androidTest/assets/GalleryDecoderTest.mp4
new file mode 100644
index 0000000000..0869d5c2f7
Binary files /dev/null and b/app/src/androidTest/assets/GalleryDecoderTest.mp4 differ
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.png b/app/src/androidTest/assets/GalleryDecoderTest.png
new file mode 100644
index 0000000000..ccaef3e113
Binary files /dev/null and b/app/src/androidTest/assets/GalleryDecoderTest.png differ
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.svg b/app/src/androidTest/assets/GalleryDecoderTest.svg
new file mode 100644
index 0000000000..8516318374
--- /dev/null
+++ b/app/src/androidTest/assets/GalleryDecoderTest.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/app/src/androidTest/assets/GalleryDecoderTest.webp b/app/src/androidTest/assets/GalleryDecoderTest.webp
new file mode 100644
index 0000000000..d4bc2b5a4b
Binary files /dev/null and b/app/src/androidTest/assets/GalleryDecoderTest.webp differ
diff --git a/app/src/androidTest/java/com/dot/gallery/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/dot/gallery/ExampleInstrumentedTest.kt
deleted file mode 100644
index 35013b1a5d..0000000000
--- a/app/src/androidTest/java/com/dot/gallery/ExampleInstrumentedTest.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.dot.gallery
-
-import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.ext.junit.runners.AndroidJUnit4
-
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import org.junit.Assert.*
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-@RunWith(AndroidJUnit4::class)
-class ExampleInstrumentedTest {
- @Test
- fun useAppContext() {
- // Context of the app under test.
- val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- assertEquals("com.dot.gallery", appContext.packageName)
- }
-}
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/dot/gallery/benchmark/DataProcessingBenchmark.kt b/app/src/androidTest/java/com/dot/gallery/benchmark/DataProcessingBenchmark.kt
index 8349b23244..5f86e9ea56 100644
--- a/app/src/androidTest/java/com/dot/gallery/benchmark/DataProcessingBenchmark.kt
+++ b/app/src/androidTest/java/com/dot/gallery/benchmark/DataProcessingBenchmark.kt
@@ -9,14 +9,14 @@ import com.dot.gallery.benchmark.BenchmarkUtils.logInfo
import com.dot.gallery.benchmark.BenchmarkUtils.logSection
import com.dot.gallery.benchmark.BenchmarkUtils.logSummaryHeader
import com.dot.gallery.core.Constants
-import com.dot.gallery.feature_node.domain.model.Media
+import com.dot.gallery.feature_node.data.model.Media
import com.dot.gallery.feature_node.presentation.util.mapMediaToItem
+import kotlin.random.Random
import kotlinx.coroutines.runBlocking
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
-import kotlin.random.Random
/**
* Pure algorithm benchmarks using synthetic data at realistic sizes.
@@ -260,54 +260,6 @@ class DataProcessingBenchmark {
logComparison("HashSet vs find()", current, optimized)
}
- // ==========================================================================
- // 4. Issue #8: locationsMediaFlow — sortedBy per group vs pre-built Map
- // ==========================================================================
-
- @Test
- fun test5_locationsMedia_sortedFindVsMapLookup() {
- logSection("Issue #8: Locations — sorted+find per group vs Map lookup")
-
- data class LocationItem(val mediaId: Long, val location: String)
-
- val media = generateMedia(MEDIA_COUNT)
- val locationGroups = List(LOCATION_GROUP_COUNT) { i ->
- LocationItem(
- mediaId = Random.nextLong(0, MEDIA_COUNT.toLong()),
- location = "City_${i % 50}, Country_${i % 20}"
- )
- }.groupBy { it.location }
-
- logInfo("media: ${media.size}, location groups: ${locationGroups.size}")
-
- // CURRENT: sortedByDescending + find per group
- val current = benchmark(
- name = "CURRENT — sortedByDescending+find per group",
- iterations = 10
- ) {
- locationGroups.mapNotNull { (location, items) ->
- val found = media
- .sortedByDescending { it.definedTimestamp }
- .find { it.id == items.first().mediaId }
- found?.let { location to it }
- }
- }
-
- // OPTIMIZED: pre-built Map, O(1) lookup per group
- val optimized = benchmark(
- name = "OPTIMIZED — pre-built Map, O(1) lookup",
- iterations = 10
- ) {
- val mediaMap = HashMap(media.size)
- for (m in media) { mediaMap[m.id] = m }
- locationGroups.mapNotNull { (location, items) ->
- mediaMap[items.first().mediaId]?.let { location to it }
- }
- }
-
- logComparison("Map vs sorted+find", current, optimized)
- }
-
// ==========================================================================
// 5. Issue #3: Album isPinned — N individual DB queries vs batch Set
// ==========================================================================
diff --git a/app/src/androidTest/java/com/dot/gallery/core/decoder/glide/GalleryMediaRoutingDeviceTest.kt b/app/src/androidTest/java/com/dot/gallery/core/decoder/glide/GalleryMediaRoutingDeviceTest.kt
new file mode 100644
index 0000000000..58d963fb60
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/core/decoder/glide/GalleryMediaRoutingDeviceTest.kt
@@ -0,0 +1,197 @@
+package com.dot.gallery.core.decoder.glide
+
+import android.content.ContentResolver
+import android.content.ContentValues
+import android.graphics.Bitmap
+import android.graphics.drawable.ColorDrawable
+import android.net.Uri
+import android.os.Environment
+import android.provider.MediaStore
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.dot.gallery.GalleryApp
+import com.github.panpf.zoomimage.subsampling.SubsamplingImageGenerateResult
+import java.io.File
+import java.io.IOException
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import okio.buffer
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class GalleryMediaRoutingDeviceTest {
+ @Test
+ fun missingDeclaredMimeType_loadsMediaStoreVideoThumbnail() {
+ val application = ApplicationProvider.getApplicationContext()
+ val contentResolver = application.contentResolver
+ val videoUri = insertVideo(
+ contentResolver = contentResolver,
+ bytes = readFixture(name = "GalleryDecoderTest.mp4"),
+ )
+
+ try {
+ val bitmap = runBlocking {
+ withContext(context = Dispatchers.IO) {
+ Glide.with(application)
+ .asBitmap()
+ .load(galleryMediaModel(uri = videoUri, mimeType = null))
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ .get()
+ }
+ }
+
+ assertEquals(16, bitmap.width)
+ assertEquals(16, bitmap.height)
+ bitmap.recycle()
+ } finally {
+ contentResolver.delete(videoUri, null, null)
+ }
+ }
+
+ @Test
+ fun subsampling_acceptsVerifiedPlatformImagesAndRejectsSandboxFormats() {
+ val application = ApplicationProvider.getApplicationContext()
+ val pngFile = writeFixtureFile(
+ application = application,
+ name = "GalleryDecoderTest.png",
+ )
+ val jpegFile = application.cacheDir.resolve("GalleryDecoderTest.jpg")
+ val avifFile = writeFixtureFile(
+ application = application,
+ name = "GalleryDecoderTest.avif",
+ )
+ val jxlFile = writeFixtureFile(
+ application = application,
+ name = "GalleryDecoderTest.jxl",
+ )
+ writeJpeg(file = jpegFile)
+
+ try {
+ runBlocking {
+ listOf(pngFile, jpegFile).forEach { imageFile ->
+ val result = generateSubsamplingImage(
+ application = application,
+ file = imageFile,
+ )
+ assertTrue(result is SubsamplingImageGenerateResult.Success)
+ val success = result as SubsamplingImageGenerateResult.Success
+ val imageSource = success.subsamplingImage.imageSource.create()
+ imageSource.openSource().buffer().use { source ->
+ assertTrue(!source.exhausted())
+ }
+ }
+
+ listOf(avifFile, jxlFile).forEach { imageFile ->
+ val result = generateSubsamplingImage(
+ application = application,
+ file = imageFile,
+ )
+ assertTrue(result is SubsamplingImageGenerateResult.Error)
+ }
+ }
+ } finally {
+ pngFile.delete()
+ jpegFile.delete()
+ avifFile.delete()
+ jxlFile.delete()
+ }
+ }
+
+ private suspend fun generateSubsamplingImage(
+ application: GalleryApp,
+ file: File,
+ ): SubsamplingImageGenerateResult {
+ val generators = galleryMediaSubsamplingImageGenerators()
+ assertEquals(1, generators.size)
+ assertTrue(generators.single() is GalleryMediaSubsamplingImageGenerator)
+ return requireNotNull(
+ generators.single().generateImage(
+ context = application,
+ glide = Glide.get(application),
+ model = GalleryMediaModel(
+ uri = Uri.fromFile(file),
+ declaredMimeType = null,
+ ),
+ drawable = ColorDrawable(),
+ ),
+ )
+ }
+
+ private fun insertVideo(contentResolver: ContentResolver, bytes: ByteArray): Uri {
+ val uri = requireNotNull(
+ contentResolver.insert(
+ MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
+ ContentValues().apply {
+ put(
+ MediaStore.MediaColumns.DISPLAY_NAME,
+ "gallery-routing-${System.nanoTime()}.mp4",
+ )
+ put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
+ put(MediaStore.MediaColumns.RELATIVE_PATH, TEST_RELATIVE_PATH)
+ put(MediaStore.MediaColumns.IS_PENDING, 1)
+ },
+ ),
+ ) { "Failed to insert test video" }
+
+ try {
+ contentResolver.openOutputStream(uri)?.use { outputStream ->
+ outputStream.write(bytes)
+ } ?: throw IOException("Failed to write test video")
+ val updatedRows = contentResolver.update(
+ uri,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.IS_PENDING, 0)
+ },
+ null,
+ null,
+ )
+ check(updatedRows > 0) { "Failed to publish test video" }
+ return uri
+ } catch (failure: Exception) {
+ contentResolver.delete(uri, null, null)
+ throw failure
+ }
+ }
+
+ private fun readFixture(name: String): ByteArray {
+ val assets = InstrumentationRegistry.getInstrumentation().context.assets
+ return assets.open(name).use { inputStream ->
+ inputStream.readBytes()
+ }
+ }
+
+ private fun writeFixtureFile(application: GalleryApp, name: String): File {
+ val fixtureFile = application.cacheDir.resolve(name)
+ fixtureFile.outputStream().use { outputStream ->
+ outputStream.write(readFixture(name = name))
+ }
+ return fixtureFile
+ }
+
+ private fun writeJpeg(file: File) {
+ val bitmap = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888)
+ try {
+ file.outputStream().use { outputStream ->
+ check(bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)) {
+ "Failed to encode test JPEG"
+ }
+ }
+ } finally {
+ bitmap.recycle()
+ }
+ }
+
+ companion object {
+ private val TEST_RELATIVE_PATH =
+ "${Environment.DIRECTORY_MOVIES}/GalleryMediaRoutingTest"
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/core/ml/ManagedOrtSessionRaceTest.kt b/app/src/androidTest/java/com/dot/gallery/core/ml/ManagedOrtSessionRaceTest.kt
new file mode 100644
index 0000000000..7605acb269
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/core/ml/ManagedOrtSessionRaceTest.kt
@@ -0,0 +1,174 @@
+package com.dot.gallery.core.ml
+
+import ai.onnxruntime.OnnxTensor
+import ai.onnxruntime.OrtEnvironment
+import ai.onnxruntime.OrtSession
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import java.io.FileInputStream
+import java.nio.IntBuffer
+import java.nio.channels.FileChannel
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ManagedOrtSessionRaceTest {
+ private val environment = OrtEnvironment.getEnvironment()
+
+ @Test
+ fun closeWaitsForRunningTextInferenceResultConsumer() {
+ repeat(ITERATIONS) {
+ verifyCloseWaitsForRun()
+ }
+ }
+
+ private fun verifyCloseWaitsForRun() {
+ val runEntered = CountDownLatch(1)
+ val releaseRun = CountDownLatch(1)
+ val closeReturned = CountDownLatch(1)
+ val failure = AtomicReference()
+ val session = openTextSession()
+
+ val runner = Thread(
+ {
+ runTextInference(
+ session = session,
+ runEntered = runEntered,
+ releaseRun = releaseRun,
+ failure = failure,
+ )
+ },
+ "managed-ort-session-run",
+ )
+ val closer = Thread(
+ {
+ session.close()
+ closeReturned.countDown()
+ },
+ "managed-ort-session-close",
+ )
+
+ runner.start()
+ assertTrue(
+ "ONNX run did not enter result consumer",
+ runEntered.await(10, TimeUnit.SECONDS)
+ )
+
+ closer.start()
+ assertFalse(
+ "close returned while a run result was still in use",
+ closeReturned.await(250, TimeUnit.MILLISECONDS)
+ )
+
+ releaseRun.countDown()
+ runner.join(10_000)
+ closer.join(10_000)
+
+ assertFalse("ONNX run thread did not finish", runner.isAlive)
+ assertFalse("ONNX close thread did not finish", closer.isAlive)
+ assertTrue(
+ "close did not return after run completed",
+ closeReturned.await(0, TimeUnit.MILLISECONDS)
+ )
+ assertNull("ONNX run failed", failure.get())
+ }
+
+ private fun runTextInference(
+ session: ManagedOrtSession,
+ runEntered: CountDownLatch,
+ releaseRun: CountDownLatch,
+ failure: AtomicReference,
+ ) {
+ try {
+ OnnxTensor
+ .createTensor(environment, textInput(), TEXT_INPUT_SHAPE)
+ .use { inputIdsTensor ->
+ OnnxTensor
+ .createTensor(environment, attentionMask(), TEXT_INPUT_SHAPE)
+ .use { attentionMaskTensor ->
+ val inputs = mapOf(
+ "input_ids" to inputIdsTensor,
+ "attention_mask" to attentionMaskTensor,
+ )
+ session.run(inputs = inputs) { result ->
+ runEntered.countDown()
+ if (!releaseRun.await(10, TimeUnit.SECONDS)) {
+ fail("Timed out waiting to release ONNX result")
+ }
+ assertEquals("Unexpected ONNX output count", 1, result.size())
+ }
+ }
+ }
+ } catch (throwable: Throwable) {
+ failure.set(throwable)
+ }
+ }
+
+ private fun openTextSession(): ManagedOrtSession {
+ val context = InstrumentationRegistry.getInstrumentation().targetContext
+ val options = OrtSession.SessionOptions()
+ var closeOptions = true
+ try {
+ context.assets.openFd(TEXT_MODEL_NAME).use { descriptor ->
+ FileInputStream(descriptor.fileDescriptor).channel.use { channel ->
+ options.setOptimizationLevel(OrtSession.SessionOptions.OptLevel.ALL_OPT)
+ val model = channel.map(
+ FileChannel.MapMode.READ_ONLY,
+ descriptor.startOffset,
+ descriptor.length,
+ )
+ val session = environment.createSession(model, options)
+ closeOptions = false
+ return ManagedOrtSession(
+ environment = environment,
+ session = session,
+ options = options,
+ )
+ }
+ }
+ } finally {
+ if (closeOptions) {
+ options.close()
+ }
+ }
+ }
+
+ private fun textInput(): IntBuffer {
+ val buffer = IntBuffer.allocate(TEXT_TOKEN_COUNT)
+ buffer.put(TOKEN_BOS)
+ buffer.put(TOKEN_EOS)
+ while (buffer.position() < TEXT_TOKEN_COUNT) {
+ buffer.put(0)
+ }
+ buffer.flip()
+ return buffer
+ }
+
+ private fun attentionMask(): IntBuffer {
+ val buffer = IntBuffer.allocate(TEXT_TOKEN_COUNT)
+ buffer.put(1)
+ buffer.put(1)
+ while (buffer.position() < TEXT_TOKEN_COUNT) {
+ buffer.put(0)
+ }
+ buffer.flip()
+ return buffer
+ }
+
+ private companion object {
+ private const val ITERATIONS = 10
+ private const val TEXT_MODEL_NAME = "textual_quant.onnx"
+ private const val TEXT_TOKEN_COUNT = 77
+ private const val TOKEN_BOS = 49406
+ private const val TOKEN_EOS = 49407
+ private val TEXT_INPUT_SHAPE = longArrayOf(1, TEXT_TOKEN_COUNT.toLong())
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/core/sandbox/DecoderFixture.kt b/app/src/androidTest/java/com/dot/gallery/core/sandbox/DecoderFixture.kt
new file mode 100644
index 0000000000..c56c966aee
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/core/sandbox/DecoderFixture.kt
@@ -0,0 +1,10 @@
+package com.dot.gallery.core.sandbox
+
+internal data class DecoderFixture(
+ val name: String,
+ val mimeType: String,
+ val width: Int,
+ val height: Int,
+ val decodedWidth: Int,
+ val decodedHeight: Int,
+)
diff --git a/app/src/androidTest/java/com/dot/gallery/core/sandbox/IsolatedImageDecoderDeviceTest.kt b/app/src/androidTest/java/com/dot/gallery/core/sandbox/IsolatedImageDecoderDeviceTest.kt
new file mode 100644
index 0000000000..313db30069
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/core/sandbox/IsolatedImageDecoderDeviceTest.kt
@@ -0,0 +1,602 @@
+package com.dot.gallery.core.sandbox
+
+import android.graphics.drawable.AnimatedImageDrawable
+import android.net.Uri
+import android.os.ParcelFileDescriptor
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.bumptech.glide.Glide
+import com.bumptech.glide.Priority
+import com.bumptech.glide.load.Options
+import com.bumptech.glide.load.data.DataFetcher
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.dot.gallery.GalleryApp
+import com.dot.gallery.core.decoder.SandboxedSketchHeifDecoder
+import com.dot.gallery.core.decoder.SandboxedSketchJxlDecoder
+import com.dot.gallery.core.decoder.glide.GalleryMediaData
+import com.dot.gallery.core.decoder.glide.GalleryMediaModel
+import com.dot.gallery.core.decoder.glide.GalleryMediaModelLoader
+import com.dot.gallery.core.decoder.glide.GalleryMediaSource
+import com.dot.gallery.core.decoder.glide.galleryMediaModel
+import com.github.panpf.sketch.BitmapImage
+import com.github.panpf.sketch.decode.Decoder
+import com.github.panpf.sketch.request.ImageRequest
+import com.github.panpf.sketch.request.RequestContext
+import com.github.panpf.sketch.sketch
+import com.github.panpf.sketch.source.FileDataSource
+import java.io.ByteArrayInputStream
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import java.util.concurrent.CountDownLatch
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.withTimeout
+import kotlinx.coroutines.withTimeoutOrNull
+import okio.Path.Companion.toOkioPath
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class IsolatedImageDecoderDeviceTest {
+ private val decoder = ApplicationProvider
+ .getApplicationContext()
+ .isolatedImageDecoder
+
+ @After
+ fun unbindDecoder() {
+ decoder.unbind()
+ }
+
+ @Test
+ fun validAvifAndJxl_decodeRepeatedlyWithExpectedDimensionsAndPixels() {
+ runBlocking {
+ listOf(
+ DecoderFixture(
+ name = "GalleryDecoderTest.avif",
+ mimeType = "image/avif",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ DecoderFixture(
+ name = "GalleryDecoderTest.jxl",
+ mimeType = "image/jxl",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ ).forEach { fixture ->
+ val encodedBytes = readFixture(name = fixture.name)
+ repeat(times = 5) {
+ val result = decoder.decode(
+ inputStream = ByteArrayInputStream(encodedBytes),
+ mimeType = fixture.mimeType,
+ targetWidth = 64,
+ targetHeight = 64,
+ )
+
+ assertNotNull(result)
+ val decodedResult = requireNotNull(result)
+ assertEquals(fixture.width, decodedResult.originalSize.width)
+ assertEquals(fixture.height, decodedResult.originalSize.height)
+ assertEquals(fixture.decodedWidth, decodedResult.bitmap.width)
+ assertEquals(fixture.decodedHeight, decodedResult.bitmap.height)
+ assertPixelDataIsNotEmpty(result = decodedResult)
+ decodedResult.bitmap.recycle()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun concurrentRequests_completeWithoutReliablePipeFailures() {
+ runBlocking {
+ val fixtures = listOf(
+ DecoderFixture(
+ name = "GalleryDecoderTest.avif",
+ mimeType = "image/avif",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 48,
+ decodedHeight = 36,
+ ),
+ DecoderFixture(
+ name = "GalleryDecoderTest.jxl",
+ mimeType = "image/jxl",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 48,
+ decodedHeight = 36,
+ ),
+ )
+ fixtures.flatMap { fixture ->
+ val encodedBytes = readFixture(name = fixture.name)
+ List(size = 4) {
+ async {
+ decoder.decode(
+ inputStream = ByteArrayInputStream(encodedBytes),
+ mimeType = fixture.mimeType,
+ targetWidth = 48,
+ targetHeight = 48,
+ )
+ }
+ }
+ }.awaitAll().forEach { result ->
+ assertNotNull(result)
+ requireNotNull(result).bitmap.recycle()
+ }
+ }
+ }
+
+ @Test
+ fun emptyMalformedAndUnsupportedInputs_failClosed() {
+ runBlocking {
+ assertNull(
+ decoder.decode(
+ inputStream = ByteArrayInputStream(ByteArray(size = 0)),
+ mimeType = "image/avif",
+ ),
+ )
+ assertNull(
+ decoder.decode(
+ inputStream = ByteArrayInputStream("not an image".encodeToByteArray()),
+ mimeType = "image/jxl",
+ ),
+ )
+ assertNull(
+ decoder.decode(
+ inputStream = ByteArrayInputStream(readFixture(name = "GalleryDecoderTest.avif")),
+ mimeType = "image/jpeg",
+ ),
+ )
+ }
+ }
+
+ @Test
+ fun earlyServiceRejection_returnsPromptlyAndPreservesFollowingDecode() {
+ runBlocking {
+ val rejectedResult = withTimeout(timeMillis = EARLY_REJECTION_TIMEOUT_MILLIS) {
+ decoder.decode(
+ inputStream = ByteArrayInputStream(
+ ByteArray(size = EARLY_REJECTION_INPUT_BYTES),
+ ),
+ mimeType = "image/jpeg",
+ )
+ }
+ assertNull(rejectedResult)
+
+ val recoveredResult = decoder.decode(
+ inputStream = ByteArrayInputStream(
+ readFixture(name = "GalleryDecoderTest.avif"),
+ ),
+ mimeType = "image/avif",
+ targetWidth = 32,
+ targetHeight = 32,
+ )
+ assertNotNull(recoveredResult)
+ requireNotNull(recoveredResult).bitmap.recycle()
+ }
+ }
+
+ @Test
+ fun writerFailureAndCancellation_failWithoutHangingTheConnection() {
+ runBlocking {
+ assertNull(
+ decoder.decode(
+ inputStream = ThrowingInputStream(),
+ mimeType = "image/avif",
+ ),
+ )
+
+ val cancelledResult = withTimeoutOrNull(timeMillis = 100L) {
+ decoder.decode(
+ inputStream = CloseAwareBlockingInputStream(),
+ mimeType = "image/avif",
+ )
+ }
+ assertNull(cancelledResult)
+
+ val recoveredResult = decoder.decode(
+ inputStream = ByteArrayInputStream(
+ readFixture(name = "GalleryDecoderTest.avif"),
+ ),
+ mimeType = "image/avif",
+ targetWidth = 32,
+ targetHeight = 32,
+ )
+ assertNotNull(recoveredResult)
+ requireNotNull(recoveredResult).bitmap.recycle()
+ }
+ }
+
+ @Test
+ fun glideRoute_decodesAvifAndJxlOnlyThroughVerifiedModels() {
+ runBlocking {
+ val application = ApplicationProvider.getApplicationContext()
+ listOf(
+ DecoderFixture(
+ name = "GalleryDecoderTest.avif",
+ mimeType = "image/avif",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ DecoderFixture(
+ name = "GalleryDecoderTest.jxl",
+ mimeType = "image/jxl",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ ).forEach { fixture ->
+ val fixtureFile = application.cacheDir.resolve(fixture.name)
+ try {
+ fixtureFile.outputStream().use { outputStream ->
+ outputStream.write(readFixture(name = fixture.name))
+ }
+ val requestManager = Glide.with(application)
+ val target = requestManager
+ .asBitmap()
+ .load(
+ galleryMediaModel(
+ uri = Uri.fromFile(fixtureFile),
+ mimeType = fixture.mimeType,
+ ),
+ )
+ .override(64, 64)
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ try {
+ val bitmap = withContext(Dispatchers.IO) { target.get() }
+ assertEquals(fixture.decodedWidth, bitmap.width)
+ assertEquals(fixture.decodedHeight, bitmap.height)
+ } finally {
+ requestManager.clear(target)
+ }
+ } finally {
+ fixtureFile.delete()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun glideRoute_routesSandboxSignaturesDeclaredAsVideoByBytes() {
+ runBlocking {
+ val application = ApplicationProvider.getApplicationContext()
+ listOf(
+ DecoderFixture(
+ name = "GalleryDecoderTest.avif",
+ mimeType = "image/avif",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ DecoderFixture(
+ name = "GalleryDecoderTest.jxl",
+ mimeType = "image/jxl",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ ).forEach { fixture ->
+ val fixtureFile = application.cacheDir.resolve(fixture.name)
+ try {
+ fixtureFile.outputStream().use { outputStream ->
+ outputStream.write(readFixture(name = fixture.name))
+ }
+ val requestManager = Glide.with(application)
+ val target = requestManager
+ .asBitmap()
+ .load(
+ galleryMediaModel(
+ uri = Uri.fromFile(fixtureFile),
+ mimeType = "video/mp4",
+ ),
+ )
+ .override(64, 64)
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ try {
+ val bitmap = withContext(Dispatchers.IO) { target.get() }
+ assertEquals(fixture.decodedWidth, bitmap.width)
+ assertEquals(fixture.decodedHeight, bitmap.height)
+ } finally {
+ requestManager.clear(target)
+ }
+ } finally {
+ fixtureFile.delete()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun glideRoute_preservesPlatformAnimationAndVideoDecoders() {
+ runBlocking {
+ val application = ApplicationProvider.getApplicationContext()
+ val pngFile = writeFixtureFile(application = application, name = "GalleryDecoderTest.png")
+ val gifFile = writeFixtureFile(application = application, name = "GalleryDecoderTest.gif")
+ val webpFile = writeFixtureFile(application = application, name = "GalleryDecoderTest.webp")
+ val videoFile = writeFixtureFile(application = application, name = "GalleryDecoderTest.mp4")
+ try {
+ withContext(Dispatchers.IO) {
+ val requestManager = Glide.with(application)
+ val pngTarget = requestManager
+ .asBitmap()
+ .load(
+ galleryMediaModel(
+ uri = Uri.fromFile(pngFile),
+ mimeType = "image/png",
+ ),
+ )
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ try {
+ val pngBitmap = pngTarget.get()
+ assertEquals(16, pngBitmap.width)
+ assertEquals(16, pngBitmap.height)
+ } finally {
+ requestManager.clear(pngTarget)
+ }
+
+ val gifTarget = requestManager
+ .asGif()
+ .load(
+ galleryMediaModel(
+ uri = Uri.fromFile(gifFile),
+ mimeType = "image/gif",
+ ),
+ )
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ try {
+ val gifDrawable = gifTarget.get()
+ assertTrue(gifDrawable.frameCount > 1)
+ gifDrawable.stop()
+ } finally {
+ requestManager.clear(gifTarget)
+ }
+
+ val webpTarget = requestManager
+ .asDrawable()
+ .load(
+ galleryMediaModel(
+ uri = Uri.fromFile(webpFile),
+ mimeType = "image/webp",
+ ),
+ )
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ try {
+ val animatedWebp = webpTarget.get()
+ assertTrue(
+ "Expected AnimatedImageDrawable, got ${animatedWebp::class.java.name}",
+ animatedWebp is AnimatedImageDrawable,
+ )
+ (animatedWebp as AnimatedImageDrawable).stop()
+ } finally {
+ requestManager.clear(webpTarget)
+ }
+
+ val videoTarget = requestManager
+ .asBitmap()
+ .load(
+ galleryMediaModel(
+ uri = Uri.fromFile(videoFile),
+ mimeType = "video/mp4",
+ ),
+ )
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .submit()
+ try {
+ val videoBitmap = videoTarget.get()
+ assertEquals(16, videoBitmap.width)
+ assertEquals(16, videoBitmap.height)
+ } finally {
+ requestManager.clear(videoTarget)
+ }
+ }
+ } finally {
+ pngFile.delete()
+ gifFile.delete()
+ webpFile.delete()
+ videoFile.delete()
+ }
+ }
+ }
+
+ @Test
+ fun galleryMediaLoader_rejectsNonSeekableDeclaredVideo() {
+ val (readDescriptor, writeDescriptor) = ParcelFileDescriptor.createPipe()
+ writeDescriptor.close()
+ val mediaSource = object : GalleryMediaSource {
+ override fun getMimeType(uri: Uri): String {
+ return "video/mp4"
+ }
+
+ override fun openInputStream(uri: Uri): InputStream? {
+ error("Stream path must not be used for declared video")
+ }
+
+ override fun openFileDescriptor(uri: Uri): ParcelFileDescriptor {
+ return readDescriptor
+ }
+ }
+ val loader = GalleryMediaModelLoader(mediaSource = mediaSource)
+ val loadData = loader.buildLoadData(
+ model = GalleryMediaModel(
+ uri = Uri.parse("content://gallery-test/non-seekable-video"),
+ declaredMimeType = "video/mp4",
+ ),
+ width = 64,
+ height = 64,
+ options = Options(),
+ )
+ val callback = RecordingMediaCallback()
+
+ loadData.fetcher.loadData(Priority.NORMAL, callback)
+
+ assertNull(callback.data)
+ assertNotNull(callback.failure)
+ }
+
+ @Test
+ fun sketchAdapters_readSizeAndDecodeThroughIsolatedService() {
+ runBlocking {
+ val application = ApplicationProvider.getApplicationContext()
+ listOf(
+ DecoderFixture(
+ name = "GalleryDecoderTest.avif",
+ mimeType = "image/avif",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ DecoderFixture(
+ name = "GalleryDecoderTest.jxl",
+ mimeType = "image/jxl",
+ width = 4000,
+ height = 3000,
+ decodedWidth = 64,
+ decodedHeight = 48,
+ ),
+ ).forEach { fixture ->
+ val fixtureFile = application.cacheDir.resolve(fixture.name)
+ try {
+ fixtureFile.outputStream().use { outputStream ->
+ outputStream.write(readFixture(name = fixture.name))
+ }
+ val request = ImageRequest(application, fixtureFile.toURI().toString()) {
+ size(width = 64, height = 64)
+ setExtra(key = "realMimeType", value = fixture.mimeType)
+ }
+ val requestContext = RequestContext(
+ sketch = application.sketch,
+ request = request,
+ )
+ val dataSource = FileDataSource(path = fixtureFile.toOkioPath())
+ val sketchDecoder: Decoder = when (fixture.mimeType) {
+ "image/avif" -> SandboxedSketchHeifDecoder(
+ requestContext = requestContext,
+ dataSource = dataSource,
+ mimeType = fixture.mimeType,
+ )
+
+ else -> SandboxedSketchJxlDecoder(
+ requestContext = requestContext,
+ dataSource = dataSource,
+ )
+ }
+
+ val imageInfo = sketchDecoder.getImageInfo()
+ assertEquals(fixture.width, imageInfo.width)
+ assertEquals(fixture.height, imageInfo.height)
+
+ val imageData = sketchDecoder.decode()
+ val bitmap = (imageData.image as BitmapImage).bitmap
+ assertEquals(fixture.decodedWidth, bitmap.width)
+ assertEquals(fixture.decodedHeight, bitmap.height)
+ assertTrue(bitmap.byteCount > 0)
+ bitmap.recycle()
+ } finally {
+ fixtureFile.delete()
+ }
+ }
+ }
+ }
+
+ private fun readFixture(name: String): ByteArray {
+ val assets = InstrumentationRegistry.getInstrumentation().context.assets
+ return assets.open(name).use { inputStream ->
+ inputStream.readBytes()
+ }
+ }
+
+ private fun writeFixtureFile(application: GalleryApp, name: String): File {
+ val fixtureFile = application.cacheDir.resolve(name)
+ fixtureFile.outputStream().use { outputStream ->
+ outputStream.write(readFixture(name = name))
+ }
+ return fixtureFile
+ }
+
+ private fun assertPixelDataIsNotEmpty(result: IsolatedImageDecodeResult) {
+ val pixels = IntArray(size = result.bitmap.width * result.bitmap.height)
+ result.bitmap.getPixels(
+ pixels,
+ 0,
+ result.bitmap.width,
+ 0,
+ 0,
+ result.bitmap.width,
+ result.bitmap.height,
+ )
+ val firstPixel = pixels.first()
+ check(pixels.any { pixel -> pixel != firstPixel }) {
+ "Decoded image contained no varying pixel data"
+ }
+ }
+
+ companion object {
+ private const val EARLY_REJECTION_INPUT_BYTES = 1_000_000
+ private const val EARLY_REJECTION_TIMEOUT_MILLIS = 5_000L
+ }
+}
+
+private class ThrowingInputStream : InputStream() {
+ override fun read(): Int {
+ throw IOException("Synthetic writer failure")
+ }
+}
+
+private class CloseAwareBlockingInputStream : InputStream() {
+ private val closed = CountDownLatch(1)
+
+ override fun read(): Int {
+ closed.await()
+ return -1
+ }
+
+ override fun close() {
+ closed.countDown()
+ }
+}
+
+private class RecordingMediaCallback : DataFetcher.DataCallback {
+ var data: GalleryMediaData? = null
+ private set
+ var failure: Exception? = null
+ private set
+
+ override fun onDataReady(data: GalleryMediaData?) {
+ this.data = data
+ }
+
+ override fun onLoadFailed(exception: Exception) {
+ failure = exception
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/core/sandbox/MediaPreviewDecoderDeviceTest.kt b/app/src/androidTest/java/com/dot/gallery/core/sandbox/MediaPreviewDecoderDeviceTest.kt
new file mode 100644
index 0000000000..7a086880ca
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/core/sandbox/MediaPreviewDecoderDeviceTest.kt
@@ -0,0 +1,417 @@
+package com.dot.gallery.core.sandbox
+
+import android.content.ContentValues
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.net.Uri
+import android.provider.MediaStore
+import android.system.Os
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.dot.gallery.GalleryApp
+import kotlin.math.abs
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class MediaPreviewDecoderDeviceTest {
+ private val application = ApplicationProvider.getApplicationContext()
+ private val contentResolver = application.contentResolver
+ private val decoder = application.mediaPreviewDecoder
+ private val insertedUris = mutableListOf()
+
+ @After
+ fun deleteFixtures() {
+ insertedUris.forEach { uri ->
+ contentResolver.delete(uri, null, null)
+ }
+ }
+
+ @Test
+ fun imageAndVideoFixtures_decodeToBoundedNonEmptyPreviews() {
+ runBlocking {
+ listOf(
+ Fixture(name = "GalleryDecoderTest.png", mimeType = "image/png", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.gif", mimeType = "image/gif", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.webp", mimeType = "image/webp", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.svg", mimeType = "image/svg+xml", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.avif", mimeType = "image/avif", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.jxl", mimeType = "image/jxl", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.mp4", mimeType = "video/mp4", isVideo = true),
+ ).forEach { fixture ->
+ val uri = insertFixture(fixture = fixture)
+ val result = decoder.decode(
+ uri = uri,
+ mimeType = fixture.mimeType,
+ isVideo = fixture.isVideo,
+ )
+
+ assertNotNull(fixture.name, result)
+ requireNotNull(result).let { bitmap ->
+ assertEquals(PREVIEW_SIZE, bitmap.width)
+ assertEquals(PREVIEW_SIZE, bitmap.height)
+ assertBitmapHasPixels(bitmap = bitmap)
+ bitmap.recycle()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun recognizedImageSignature_overridesVideoMimeType() {
+ runBlocking {
+ val uri = insertFixture(
+ fixture = Fixture(
+ name = "GalleryDecoderTest.avif",
+ mimeType = "video/mp4",
+ isVideo = true,
+ ),
+ )
+
+ val result = decoder.decode(
+ uri = uri,
+ mimeType = "video/mp4",
+ isVideo = true,
+ )
+
+ assertNotNull(result)
+ requireNotNull(result).recycle()
+ }
+ }
+
+ @Test
+ fun videoLargerThanImageLimit_decodesThumbnail() {
+ runBlocking {
+ val uri = insertFixture(
+ fixture = Fixture(
+ name = "GalleryDecoderTest.mp4",
+ mimeType = "video/mp4",
+ isVideo = true,
+ ),
+ minimumSize = LARGE_VIDEO_SIZE_BYTES,
+ )
+
+ val result = decoder.decode(
+ uri = uri,
+ mimeType = "video/mp4",
+ isVideo = true,
+ )
+
+ assertNotNull(result)
+ requireNotNull(result).recycle()
+ }
+ }
+
+ @Test
+ fun videoWithUnknownStatSize_decodesThumbnail() {
+ runBlocking {
+ val uri = Uri.parse("content://${application.packageName}.unknownsize/video")
+
+ val result = withTimeout(timeMillis = DEVICE_TEST_TIMEOUT_MILLIS) {
+ decoder.decode(
+ uri = uri,
+ mimeType = "video/mp4",
+ isVideo = true,
+ )
+ }
+
+ assertNotNull(result)
+ requireNotNull(result).recycle()
+ }
+ }
+
+ @Test
+ fun svgLargerThanLimit_isRejected() {
+ runBlocking {
+ val uri = insertFixture(
+ fixture = Fixture(
+ name = "GalleryDecoderTest.svg",
+ mimeType = "image/svg+xml",
+ isVideo = false,
+ ),
+ minimumSize = LARGE_SVG_SIZE_BYTES,
+ )
+
+ val result = decoder.decode(
+ uri = uri,
+ mimeType = "image/svg+xml",
+ isVideo = false,
+ )
+
+ assertNull(result)
+ }
+ }
+
+ @Test
+ fun nonSquarePlatformImages_decodeToSquarePreviews() {
+ runBlocking {
+ listOf(
+ GeneratedFixture(
+ name = "GalleryDecoderLandscape.png",
+ mimeType = "image/png",
+ width = 640,
+ height = 320,
+ format = Bitmap.CompressFormat.PNG,
+ ),
+ GeneratedFixture(
+ name = "GalleryDecoderPortrait.jpg",
+ mimeType = "image/jpeg",
+ width = 320,
+ height = 640,
+ format = Bitmap.CompressFormat.JPEG,
+ ),
+ ).forEach { fixture ->
+ val uri = insertGeneratedFixture(fixture = fixture)
+
+ val result = decoder.decode(
+ uri = uri,
+ mimeType = fixture.mimeType,
+ isVideo = false,
+ )
+
+ assertNotNull(fixture.name, result)
+ requireNotNull(result).let { bitmap ->
+ assertEquals(PREVIEW_SIZE, bitmap.width)
+ assertEquals(PREVIEW_SIZE, bitmap.height)
+ assertBitmapHasPixels(bitmap = bitmap)
+ bitmap.recycle()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun smallNonSquareImages_preserveCenteredShapeAspectRatio() {
+ runBlocking {
+ listOf(
+ GeneratedFixture(
+ name = "GalleryDecoderSmallLandscape.png",
+ mimeType = "image/png",
+ width = 32,
+ height = 16,
+ format = Bitmap.CompressFormat.PNG,
+ ),
+ GeneratedFixture(
+ name = "GalleryDecoderSmallPortrait.png",
+ mimeType = "image/png",
+ width = 16,
+ height = 32,
+ format = Bitmap.CompressFormat.PNG,
+ ),
+ ).forEach { fixture ->
+ val uri = insertGeneratedFixture(
+ fixture = fixture,
+ drawGeometryPattern = true,
+ )
+
+ val result = decoder.decode(
+ uri = uri,
+ mimeType = fixture.mimeType,
+ isVideo = false,
+ )
+
+ assertNotNull(fixture.name, result)
+ requireNotNull(result).let { bitmap ->
+ assertCenteredShapeIsSquare(name = fixture.name, bitmap = bitmap)
+ bitmap.recycle()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun concurrentPreviewRequests_completeInDedicatedIsolatedInstance() {
+ runBlocking {
+ val fixtures = listOf(
+ Fixture(name = "GalleryDecoderTest.png", mimeType = "image/png", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.avif", mimeType = "image/avif", isVideo = false),
+ Fixture(name = "GalleryDecoderTest.mp4", mimeType = "video/mp4", isVideo = true),
+ ).map { fixture -> fixture to insertFixture(fixture = fixture) }
+
+ fixtures.flatMap { (fixture, uri) ->
+ List(size = 3) {
+ async {
+ decoder.decode(
+ uri = uri,
+ mimeType = fixture.mimeType,
+ isVideo = fixture.isVideo,
+ )
+ }
+ }
+ }.awaitAll().forEach { result ->
+ assertNotNull(result)
+ requireNotNull(result).recycle()
+ }
+ }
+ }
+
+ private fun insertFixture(fixture: Fixture, minimumSize: Long? = null): Uri {
+ val collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
+ val uri = requireNotNull(
+ contentResolver.insert(
+ collection,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.DISPLAY_NAME, "analysis_${fixture.name}")
+ put(MediaStore.MediaColumns.MIME_TYPE, fixture.mimeType)
+ put(MediaStore.MediaColumns.RELATIVE_PATH, "Download/ReFraAnalysisTests")
+ put(MediaStore.MediaColumns.IS_PENDING, 1)
+ },
+ ),
+ )
+ insertedUris += uri
+ contentResolver.openOutputStream(uri, "w").use { outputStream ->
+ requireNotNull(outputStream).write(readFixture(name = fixture.name))
+ }
+ minimumSize?.let { size ->
+ contentResolver.openFileDescriptor(uri, "rw").use { descriptor ->
+ Os.ftruncate(requireNotNull(descriptor).fileDescriptor, size)
+ }
+ }
+ contentResolver.update(
+ uri,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.IS_PENDING, 0)
+ },
+ null,
+ null,
+ )
+ return uri
+ }
+
+ private fun insertGeneratedFixture(
+ fixture: GeneratedFixture,
+ drawGeometryPattern: Boolean = false,
+ ): Uri {
+ val collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
+ val uri = requireNotNull(
+ contentResolver.insert(
+ collection,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.DISPLAY_NAME, "analysis_${fixture.name}")
+ put(MediaStore.MediaColumns.MIME_TYPE, fixture.mimeType)
+ put(MediaStore.MediaColumns.RELATIVE_PATH, "Download/ReFraAnalysisTests")
+ put(MediaStore.MediaColumns.IS_PENDING, 1)
+ },
+ ),
+ )
+ insertedUris += uri
+ val bitmap = Bitmap.createBitmap(fixture.width, fixture.height, Bitmap.Config.ARGB_8888)
+ try {
+ when {
+ drawGeometryPattern -> {
+ bitmap.eraseColor(GEOMETRY_BACKGROUND_COLOR)
+ Canvas(bitmap).drawCircle(
+ fixture.width / 2f,
+ fixture.height / 2f,
+ minOf(fixture.width, fixture.height) * GEOMETRY_RADIUS_FRACTION,
+ Paint(Paint.ANTI_ALIAS_FLAG).apply {
+ color = GEOMETRY_FOREGROUND_COLOR
+ },
+ )
+ }
+
+ else -> bitmap.eraseColor(Color.MAGENTA)
+ }
+ contentResolver.openOutputStream(uri, "w").use { outputStream ->
+ check(
+ bitmap.compress(
+ fixture.format,
+ GENERATED_IMAGE_QUALITY,
+ requireNotNull(outputStream),
+ ),
+ )
+ }
+ } finally {
+ bitmap.recycle()
+ }
+ contentResolver.update(
+ uri,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.IS_PENDING, 0)
+ },
+ null,
+ null,
+ )
+ return uri
+ }
+
+ private fun readFixture(name: String): ByteArray {
+ return InstrumentationRegistry.getInstrumentation().context.assets.open(name).use { input ->
+ input.readBytes()
+ }
+ }
+
+ private fun assertBitmapHasPixels(bitmap: Bitmap) {
+ val pixels = IntArray(bitmap.width * bitmap.height)
+ bitmap.getPixels(
+ pixels,
+ 0,
+ bitmap.width,
+ 0,
+ 0,
+ bitmap.width,
+ bitmap.height,
+ )
+ assertTrue(pixels.any { pixel -> pixel != 0 })
+ }
+
+ private fun assertCenteredShapeIsSquare(name: String, bitmap: Bitmap) {
+ val foregroundCoordinates = buildList {
+ for (y in 0 until bitmap.height) {
+ for (x in 0 until bitmap.width) {
+ val pixel = bitmap.getPixel(x, y)
+ if (Color.green(pixel) > Color.red(pixel)) {
+ add(x to y)
+ }
+ }
+ }
+ }
+ assertTrue("$name has no foreground shape", foregroundCoordinates.isNotEmpty())
+ val shapeWidth = foregroundCoordinates.maxOf { (x, _) -> x } -
+ foregroundCoordinates.minOf { (x, _) -> x } + 1
+ val shapeHeight = foregroundCoordinates.maxOf { (_, y) -> y } -
+ foregroundCoordinates.minOf { (_, y) -> y } + 1
+ assertTrue(
+ "$name shape was distorted to ${shapeWidth}x${shapeHeight}",
+ abs(shapeWidth - shapeHeight) <= GEOMETRY_SIZE_TOLERANCE_PIXELS,
+ )
+ }
+
+ private data class Fixture(
+ val name: String,
+ val mimeType: String,
+ val isVideo: Boolean,
+ )
+
+ private data class GeneratedFixture(
+ val name: String,
+ val mimeType: String,
+ val width: Int,
+ val height: Int,
+ val format: Bitmap.CompressFormat,
+ )
+
+ companion object {
+ private const val GEOMETRY_BACKGROUND_COLOR = Color.RED
+ private const val GEOMETRY_FOREGROUND_COLOR = Color.GREEN
+ private const val GEOMETRY_RADIUS_FRACTION = 0.375f
+ private const val GEOMETRY_SIZE_TOLERANCE_PIXELS = 8
+ private const val GENERATED_IMAGE_QUALITY = 90
+ private const val LARGE_SVG_SIZE_BYTES = 17L * 1024L * 1024L
+ private const val LARGE_VIDEO_SIZE_BYTES = 129L * 1024L * 1024L
+ private const val PREVIEW_SIZE = 224
+ private const val DEVICE_TEST_TIMEOUT_MILLIS = 10_000L
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/core/util/ext/ContentResolverInsertDeviceTest.kt b/app/src/androidTest/java/com/dot/gallery/core/util/ext/ContentResolverInsertDeviceTest.kt
new file mode 100644
index 0000000000..c16dd27fb5
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/core/util/ext/ContentResolverInsertDeviceTest.kt
@@ -0,0 +1,147 @@
+package com.dot.gallery.core.util.ext
+
+import android.content.ContentResolver
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import java.io.IOException
+import java.util.UUID
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import org.junit.Assert.assertArrayEquals
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class ContentResolverInsertDeviceTest {
+
+ private val contentResolver: ContentResolver =
+ InstrumentationRegistry.getInstrumentation().targetContext.contentResolver
+
+ @Test
+ fun saveRawStream_publishesOnlyAfterSuccessfulWrite() {
+ runBlocking {
+ val displayName = "gallery-pending-${UUID.randomUUID()}.png"
+ val expectedBytes = byteArrayOf(1, 2, 3, 4)
+ var destinationUri: Uri? = null
+ try {
+ destinationUri = contentResolver.saveRawStream(
+ writeBlock = { outputStream -> outputStream.write(expectedBytes) },
+ mimeType = "image/png",
+ displayName = displayName,
+ )
+
+ assertTrue(destinationUri != null)
+ val values = queryPublishedValues(uri = requireNotNull(destinationUri))
+ assertEquals(0, values.isPending)
+ assertTrue(values.dateModified > 0L)
+ val actualBytes = contentResolver.openInputStream(destinationUri)?.use { input ->
+ input.readBytes()
+ }
+ assertArrayEquals(expectedBytes, actualBytes)
+ } finally {
+ destinationUri?.let { uri -> contentResolver.delete(uri, null, null) }
+ }
+ }
+ }
+
+ @Test
+ fun saveRawStream_deletesRowWhenWriteFails() {
+ runBlocking {
+ val displayName = "gallery-failed-${UUID.randomUUID()}.png"
+
+ val destinationUri = contentResolver.saveRawStream(
+ writeBlock = { outputStream ->
+ outputStream.write(byteArrayOf(1, 2, 3))
+ throw IOException("forced failure")
+ },
+ mimeType = "image/png",
+ displayName = displayName,
+ )
+
+ assertNull(destinationUri)
+ assertEquals(0, countRows(displayName = displayName))
+ }
+ }
+
+ @Test
+ fun saveRawStream_cancelledBeforePublicationDeletesPendingRow() {
+ runBlocking {
+ val displayName = "gallery-cancelled-${UUID.randomUUID()}.png"
+ val writeStarted = CountDownLatch(1)
+ val releaseWrite = CountDownLatch(1)
+ val saveJob = launch(Dispatchers.IO) {
+ contentResolver.saveRawStream(
+ writeBlock = { outputStream ->
+ outputStream.write(byteArrayOf(1, 2, 3))
+ writeStarted.countDown()
+ check(releaseWrite.await(TEST_TIMEOUT_SECONDS, TimeUnit.SECONDS))
+ },
+ mimeType = "image/png",
+ displayName = displayName,
+ )
+ }
+
+ assertTrue(writeStarted.await(TEST_TIMEOUT_SECONDS, TimeUnit.SECONDS))
+ saveJob.cancel()
+ releaseWrite.countDown()
+ withTimeout(TEST_TIMEOUT_MILLIS.milliseconds) {
+ saveJob.cancelAndJoin()
+ }
+
+ assertEquals(0, countRows(displayName = displayName))
+ }
+ }
+
+ private fun queryPublishedValues(uri: Uri): PublishedValues {
+ return contentResolver.query(
+ uri,
+ arrayOf(MediaStore.MediaColumns.IS_PENDING, MediaStore.MediaColumns.DATE_MODIFIED),
+ null,
+ null,
+ )?.use { cursor ->
+ check(cursor.moveToFirst())
+ PublishedValues(
+ isPending = cursor.getInt(0),
+ dateModified = cursor.getLong(1),
+ )
+ } ?: error("Inserted media could not be queried")
+ }
+
+ private fun countRows(displayName: String): Int {
+ val queryArgs = Bundle().apply {
+ putString(
+ ContentResolver.QUERY_ARG_SQL_SELECTION,
+ "${MediaStore.MediaColumns.DISPLAY_NAME} = ?",
+ )
+ putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(displayName))
+ }
+ return contentResolver.query(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ arrayOf(MediaStore.MediaColumns._ID),
+ queryArgs,
+ null,
+ )?.use { cursor -> cursor.count } ?: 0
+ }
+
+ private class PublishedValues(
+ val isPending: Int,
+ val dateModified: Long,
+ )
+
+ private companion object {
+ private const val TEST_TIMEOUT_MILLIS = 5_000L
+ private const val TEST_TIMEOUT_SECONDS = 5L
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/feature_node/data/data_source/mediastore/queries/MediaFlowPagingDeviceTest.kt b/app/src/androidTest/java/com/dot/gallery/feature_node/data/data_source/mediastore/queries/MediaFlowPagingDeviceTest.kt
new file mode 100644
index 0000000000..d9d9a8af6e
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/feature_node/data/data_source/mediastore/queries/MediaFlowPagingDeviceTest.kt
@@ -0,0 +1,126 @@
+package com.dot.gallery.feature_node.data.data_source.mediastore.queries
+
+import android.content.ContentResolver
+import android.content.ContentUris
+import android.content.ContentValues
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.dot.gallery.core.util.MediaStoreBuckets
+import com.dot.gallery.feature_node.data.data_source.mediastore.MediaQuery
+import com.dot.gallery.feature_node.data.model.Media
+import java.util.UUID
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class MediaFlowPagingDeviceTest {
+
+ private val contentResolver: ContentResolver =
+ InstrumentationRegistry.getInstrumentation().targetContext.contentResolver
+
+ @Test
+ fun consecutivePages_areAscendingLimitedAndNonOverlapping() {
+ runBlocking {
+ val initialHighestId = getHighestMediaId()
+ val insertedUris = mutableListOf()
+ try {
+ repeat(3) { index ->
+ insertedUris += insertImage(index = index)
+ }
+ val insertedIds = insertedUris.map(ContentUris::parseId)
+
+ val firstPage = loadPage(afterId = initialHighestId, limit = 2)
+ val secondPage = loadPage(afterId = firstPage.last().id, limit = 2)
+
+ assertEquals(insertedIds.take(2), firstPage.map { media -> media.id })
+ assertEquals(insertedIds.drop(2), secondPage.map { media -> media.id })
+ } finally {
+ insertedUris.forEach { uri -> contentResolver.delete(uri, null, null) }
+ }
+ }
+ }
+
+ private suspend fun loadPage(afterId: Long, limit: Int): List {
+ return MediaFlow(
+ contentResolver = contentResolver,
+ buckedId = MediaStoreBuckets.MEDIA_STORE_BUCKET_TIMELINE.id,
+ skipBatching = true,
+ afterId = afterId,
+ limit = limit,
+ ).flowData().first()
+ }
+
+ private fun getHighestMediaId(): Long {
+ val queryArgs = Bundle().apply {
+ putString(
+ ContentResolver.QUERY_ARG_SQL_SORT_ORDER,
+ "${MediaStore.Files.FileColumns._ID} DESC",
+ )
+ putInt(ContentResolver.QUERY_ARG_LIMIT, 1)
+ }
+ return contentResolver.query(
+ MediaQuery.MediaStoreFileUri,
+ arrayOf(MediaStore.Files.FileColumns._ID),
+ queryArgs,
+ null,
+ )?.use { cursor ->
+ when {
+ cursor.moveToFirst() -> cursor.getLong(0)
+ else -> 0L
+ }
+ } ?: 0L
+ }
+
+ private fun insertImage(index: Int): Uri {
+ val destinationUri = contentResolver.insert(
+ MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
+ ContentValues().apply {
+ put(
+ MediaStore.MediaColumns.DISPLAY_NAME,
+ "media-flow-${UUID.randomUUID()}-$index.png",
+ )
+ put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
+ put(MediaStore.MediaColumns.RELATIVE_PATH, TEST_RELATIVE_PATH)
+ put(MediaStore.MediaColumns.IS_PENDING, 1)
+ },
+ ) ?: error("Could not insert MediaStore test image")
+ return try {
+ contentResolver.openOutputStream(destinationUri)?.use { outputStream ->
+ outputStream.write(PNG_SIGNATURE)
+ } ?: error("Could not open MediaStore test image")
+ val updatedRows = contentResolver.update(
+ destinationUri,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.IS_PENDING, 0)
+ },
+ null,
+ null,
+ )
+ check(updatedRows == 1) { "Could not publish MediaStore test image" }
+ destinationUri
+ } catch (exception: Exception) {
+ contentResolver.delete(destinationUri, null, null)
+ throw exception
+ }
+ }
+
+ private companion object {
+ private const val TEST_RELATIVE_PATH = "Pictures/ReFraMediaFlowTests"
+ private val PNG_SIGNATURE = byteArrayOf(
+ 0x89.toByte(),
+ 0x50,
+ 0x4E,
+ 0x47,
+ 0x0D,
+ 0x0A,
+ 0x1A,
+ 0x0A,
+ )
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/feature_node/data/repository/MediaCopyRepositoryDeviceTest.kt b/app/src/androidTest/java/com/dot/gallery/feature_node/data/repository/MediaCopyRepositoryDeviceTest.kt
new file mode 100644
index 0000000000..cfee2d4c9a
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/feature_node/data/repository/MediaCopyRepositoryDeviceTest.kt
@@ -0,0 +1,136 @@
+package com.dot.gallery.feature_node.data.repository
+
+import android.content.ContentResolver
+import android.content.ContentValues
+import android.net.Uri
+import android.os.Environment
+import android.provider.MediaStore
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import java.io.IOException
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertArrayEquals
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class MediaCopyRepositoryDeviceTest {
+
+ @Test
+ fun copyMedia_publishesByteIdenticalMediaStoreDestination() {
+ val contentResolver = InstrumentationRegistry.getInstrumentation()
+ .targetContext
+ .contentResolver
+ val sourceBytes = byteArrayOf(1, 3, 5, 7, 9)
+ var sourceUri: Uri? = null
+ var destinationUri: Uri? = null
+
+ try {
+ val insertedSourceUri = insertTestMedia(
+ contentResolver = contentResolver,
+ displayName = "media-copy-source-${System.nanoTime()}.jpg",
+ bytes = sourceBytes,
+ )
+ sourceUri = insertedSourceUri
+ val repository = MediaCopyRepositoryImpl(
+ contentResolver = contentResolver,
+ ioDispatcher = Dispatchers.IO,
+ )
+
+ val publishedDestinationUri = requireNotNull(
+ runBlocking {
+ repository.copyMedia(
+ sourceUri = insertedSourceUri,
+ destinationPath = testRelativePath,
+ onBytesCopied = {},
+ )
+ },
+ ) { "Media copy failed" }
+ destinationUri = publishedDestinationUri
+
+ assertEquals(
+ 0,
+ getPendingState(
+ contentResolver = contentResolver,
+ uri = publishedDestinationUri,
+ ),
+ )
+ assertArrayEquals(
+ sourceBytes,
+ readBytes(
+ contentResolver = contentResolver,
+ uri = publishedDestinationUri,
+ ),
+ )
+ } finally {
+ destinationUri?.let { uri ->
+ contentResolver.delete(uri, null, null)
+ }
+ sourceUri?.let { uri ->
+ contentResolver.delete(uri, null, null)
+ }
+ }
+ }
+
+ private fun insertTestMedia(
+ contentResolver: ContentResolver,
+ displayName: String,
+ bytes: ByteArray,
+ ): Uri {
+ val uri = requireNotNull(
+ contentResolver.insert(
+ MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.DISPLAY_NAME, displayName)
+ put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
+ put(MediaStore.MediaColumns.RELATIVE_PATH, testRelativePath)
+ put(MediaStore.MediaColumns.IS_PENDING, 1)
+ },
+ ),
+ ) { "Failed to insert source test media" }
+
+ try {
+ contentResolver.openOutputStream(uri)?.use { output ->
+ output.write(bytes)
+ } ?: throw IOException("Failed to open source test media")
+ val publishedRows = contentResolver.update(
+ uri,
+ ContentValues().apply {
+ put(MediaStore.MediaColumns.IS_PENDING, 0)
+ },
+ null,
+ null,
+ )
+ check(publishedRows > 0) { "Failed to publish source test media" }
+ return uri
+ } catch (exception: Exception) {
+ contentResolver.delete(uri, null, null)
+ throw exception
+ }
+ }
+
+ private fun getPendingState(contentResolver: ContentResolver, uri: Uri): Int {
+ return contentResolver.query(
+ uri,
+ arrayOf(MediaStore.MediaColumns.IS_PENDING),
+ null,
+ null,
+ null,
+ )?.use { cursor ->
+ check(cursor.moveToFirst()) { "Destination row is missing" }
+ cursor.getInt(0)
+ } ?: error("Failed to query destination row")
+ }
+
+ private fun readBytes(contentResolver: ContentResolver, uri: Uri): ByteArray {
+ return contentResolver.openInputStream(uri)?.use { input ->
+ input.readBytes()
+ } ?: error("Failed to read destination media")
+ }
+
+ companion object {
+ private val testRelativePath = Environment.DIRECTORY_PICTURES + "/GalleryMediaCopyTest"
+ }
+}
diff --git a/app/src/androidTest/java/com/dot/gallery/feature_node/presentation/securereview/SecureReviewEntryPointTest.kt b/app/src/androidTest/java/com/dot/gallery/feature_node/presentation/securereview/SecureReviewEntryPointTest.kt
new file mode 100644
index 0000000000..b4f00bebd6
--- /dev/null
+++ b/app/src/androidTest/java/com/dot/gallery/feature_node/presentation/securereview/SecureReviewEntryPointTest.kt
@@ -0,0 +1,44 @@
+package com.dot.gallery.feature_node.presentation.securereview
+
+import android.content.Intent
+import android.provider.MediaStore
+import androidx.lifecycle.Lifecycle
+import androidx.test.core.app.ActivityScenario
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.dot.gallery.feature_node.presentation.standalone.StandaloneActivity
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class SecureReviewEntryPointTest {
+
+ @Test
+ fun standaloneActivity_rejectsExplicitSecureReviewIntent() {
+ val intent = Intent(
+ ApplicationProvider.getApplicationContext(),
+ StandaloneActivity::class.java,
+ ).apply {
+ action = MediaStore.ACTION_REVIEW_SECURE
+ }
+
+ ActivityScenario.launch(intent).use { scenario ->
+ assertEquals(Lifecycle.State.DESTROYED, scenario.state)
+ }
+ }
+
+ @Test
+ fun secureReviewActivity_rejectsWrongAction() {
+ val intent = Intent(
+ ApplicationProvider.getApplicationContext(),
+ SecureReviewActivity::class.java,
+ ).apply {
+ action = Intent.ACTION_VIEW
+ }
+
+ ActivityScenario.launch(intent).use { scenario ->
+ assertEquals(Lifecycle.State.DESTROYED, scenario.state)
+ }
+ }
+}
diff --git a/app/src/arm64-v8aRelease/generated/baselineProfiles/baseline-prof.txt b/app/src/arm64-v8aRelease/generated/baselineProfiles/baseline-prof.txt
index f1f53a2cf4..f664bdb450 100644
--- a/app/src/arm64-v8aRelease/generated/baselineProfiles/baseline-prof.txt
+++ b/app/src/arm64-v8aRelease/generated/baselineProfiles/baseline-prof.txt
@@ -18879,25 +18879,6 @@ SPLandroidx/savedstate/internal/SavedStateRegistryImpl$Companion;->()V
SPLandroidx/savedstate/internal/SavedStateRegistryImpl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
Landroidx/savedstate/internal/SynchronizedObject;
SPLandroidx/savedstate/internal/SynchronizedObject;->()V
-Landroidx/security/crypto/MasterKey;
-SPLandroidx/security/crypto/MasterKey;->(Ljava/lang/String;Ljava/lang/Object;)V
-Landroidx/security/crypto/MasterKey$Builder;
-SPLandroidx/security/crypto/MasterKey$Builder;->(Landroid/content/Context;)V
-SPLandroidx/security/crypto/MasterKey$Builder;->(Landroid/content/Context;Ljava/lang/String;)V
-SPLandroidx/security/crypto/MasterKey$Builder;->build()Landroidx/security/crypto/MasterKey;
-SPLandroidx/security/crypto/MasterKey$Builder;->setKeyScheme(Landroidx/security/crypto/MasterKey$KeyScheme;)Landroidx/security/crypto/MasterKey$Builder;
-Landroidx/security/crypto/MasterKey$Builder$Api23Impl;
-SPLandroidx/security/crypto/MasterKey$Builder$Api23Impl;->build(Landroidx/security/crypto/MasterKey$Builder;)Landroidx/security/crypto/MasterKey;
-Landroidx/security/crypto/MasterKey$KeyScheme;
-SPLandroidx/security/crypto/MasterKey$KeyScheme;->$values()[Landroidx/security/crypto/MasterKey$KeyScheme;
-SPLandroidx/security/crypto/MasterKey$KeyScheme;->()V
-SPLandroidx/security/crypto/MasterKey$KeyScheme;->(Ljava/lang/String;I)V
-Landroidx/security/crypto/MasterKeys;
-SPLandroidx/security/crypto/MasterKeys;->()V
-SPLandroidx/security/crypto/MasterKeys;->createAES256GCMKeyGenParameterSpec(Ljava/lang/String;)Landroid/security/keystore/KeyGenParameterSpec;
-SPLandroidx/security/crypto/MasterKeys;->getOrCreate(Landroid/security/keystore/KeyGenParameterSpec;)Ljava/lang/String;
-SPLandroidx/security/crypto/MasterKeys;->keyExists(Ljava/lang/String;)Z
-SPLandroidx/security/crypto/MasterKeys;->validate(Landroid/security/keystore/KeyGenParameterSpec;)V
Landroidx/sqlite/SQLite;
SPLandroidx/sqlite/SQLite;->execSQL(Landroidx/sqlite/SQLiteConnection;Ljava/lang/String;)V
Landroidx/sqlite/SQLiteConnection;
@@ -22796,49 +22777,16 @@ SPLcom/dot/gallery/core/Settings$Misc$rememberGridSize$1$1$value$1;->invokeSuspe
Lcom/dot/gallery/core/SettingsKt;
SPLcom/dot/gallery/core/SettingsKt;->()V
SPLcom/dot/gallery/core/SettingsKt;->getDataStore(Landroid/content/Context;)Landroidx/datastore/core/DataStore;
-Lcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->handles(Ljava/io/File;)Z
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->handles(Ljava/lang/Object;)Z
-Lcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;->build(Lcom/bumptech/glide/load/model/MultiModelLoaderFactory;)Lcom/bumptech/glide/load/model/ModelLoader;
-Lcom/dot/gallery/core/decoder/glide/EncryptedGenericImageDecoder;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedGenericImageDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedGenericImageDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
-Lcom/dot/gallery/core/decoder/glide/EncryptedMediaStream;
-Lcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->handles(Landroid/net/Uri;)Z
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->handles(Ljava/lang/Object;)Z
-Lcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;->build(Lcom/bumptech/glide/load/model/MultiModelLoaderFactory;)Lcom/bumptech/glide/load/model/ModelLoader;
-Lcom/dot/gallery/core/decoder/glide/EncryptedVideoFrameDecoder;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedVideoFrameDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedVideoFrameDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;Lkotlin/jvm/functions/Function0;)V
Lcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->()V
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->handles(Ljava/io/InputStream;Lcom/bumptech/glide/load/Options;)Z
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->handles(Ljava/lang/Object;Lcom/bumptech/glide/load/Options;)Z
-Lcom/dot/gallery/core/decoder/glide/HeifEncryptedDecoder;
-SPLcom/dot/gallery/core/decoder/glide/HeifEncryptedDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/HeifEncryptedDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
-Lcom/dot/gallery/core/decoder/glide/IsEncryptedVaultFileKt;
-SPLcom/dot/gallery/core/decoder/glide/IsEncryptedVaultFileKt;->isEncryptedVaultFile(Ljava/io/File;)Z
Lcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->()V
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->handles(Ljava/io/InputStream;Lcom/bumptech/glide/load/Options;)Z
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->handles(Ljava/lang/Object;Lcom/bumptech/glide/load/Options;)Z
-Lcom/dot/gallery/core/decoder/glide/JxlEncryptedDecoder;
-SPLcom/dot/gallery/core/decoder/glide/JxlEncryptedDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/JxlEncryptedDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
Lcom/dot/gallery/core/presentation/components/AppBarKt;
SPLcom/dot/gallery/core/presentation/components/AppBarKt;->$r8$lambda$DsPR7b3BsTxlzkrJf3l-Kymmt-Y(I)I
SPLcom/dot/gallery/core/presentation/components/AppBarKt;->$r8$lambda$Vay4j8nd0PNlEP9MEQJtcWNVJKY(Ljava/util/List;Landroidx/navigation/NavController;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Landroidx/compose/animation/AnimatedVisibilityScope;Landroidx/compose/runtime/Composer;I)Lkotlin/Unit;
@@ -23530,7 +23478,6 @@ Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$15QqL12KsHwPyPiG3qbiCHi8Dhs(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MetadataDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$2QDUjMU4Hx8kYc7tO3hlvnIgsW8(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/ImageEmbeddingDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$711IgaQTzxOzDjGMNmIWCtjJyBU(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MediaDao_Impl;
-SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$A6DCbF69_hYXBjdmUra8K7PT9YI(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;
PLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$L85sszyn6t4C4HmsRrdgfiM6Ac0(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/ClassifierDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$ZfOKcFvP4FXN5mKwqbyGoFRl4-A(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/BlacklistDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$w69ZHrj2x99hkAuAipMHFUH2Pew(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/AlbumThumbnailDao_Impl;
@@ -23544,7 +23491,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_imageE
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_mediaDao$lambda$2(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MediaDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_metadataDao$lambda$5(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MetadataDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_pinnedDao$lambda$0(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl;
-SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_vaultDao$lambda$4(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->access$internalInitInvalidationTracker(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;Landroidx/sqlite/SQLiteConnection;)V
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->createAutoMigrations(Ljava/util/Map;)Ljava/util/List;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->createInvalidationTracker()Landroidx/room/InvalidationTracker;
@@ -23559,7 +23505,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getMeta
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getPinnedDao()Lcom/dot/gallery/feature_node/data/data_source/PinnedDao;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getRequiredAutoMigrationSpecClasses()Ljava/util/Set;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getRequiredTypeConverterClasses()Ljava/util/Map;
-SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getVaultDao()Lcom/dot/gallery/feature_node/data/data_source/VaultDao;
Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$ExternalSyntheticLambda0;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$ExternalSyntheticLambda0;->(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)V
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object;
@@ -23587,12 +23532,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$External
Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$createOpenDelegate$_openDelegate$1;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$createOpenDelegate$_openDelegate$1;->(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)V
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$createOpenDelegate$_openDelegate$1;->onOpen(Landroidx/sqlite/SQLiteConnection;)V
-Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder;->(Landroid/content/Context;)V
-Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder$Companion;
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder$Companion;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
Lcom/dot/gallery/feature_node/data/data_source/MediaDao;
PLcom/dot/gallery/feature_node/data/data_source/MediaDao;->updateMedia$suspendImpl(Lcom/dot/gallery/feature_node/data/data_source/MediaDao;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
PLcom/dot/gallery/feature_node/data/data_source/MediaDao;->updateMedia(Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -23752,27 +23691,6 @@ Lcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;
SPLcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;->()V
SPLcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
SPLcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;->getRequiredConverters()Ljava/util/List;
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao;
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;->(Landroidx/room/RoomDatabase;)V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;->getVaults()Lkotlinx/coroutines/flow/Flow;
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$$ExternalSyntheticLambda4;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$$ExternalSyntheticLambda4;->(Ljava/lang/String;)V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$1;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$1;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$2;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$2;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$3;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$3;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$4;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$4;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$5;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$5;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;->getRequiredConverters()Ljava/util/List;
Lcom/dot/gallery/feature_node/data/data_source/mediastore/MediaQuery;
SPLcom/dot/gallery/feature_node/data/data_source/mediastore/MediaQuery;->()V
SPLcom/dot/gallery/feature_node/data/data_source/mediastore/MediaQuery;->()V
@@ -23820,7 +23738,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/mediastore/queries/QueryFlow;->
SPLcom/dot/gallery/feature_node/data/data_source/mediastore/queries/QueryFlow;->()V
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->()V
-SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->(Landroid/content/Context;Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;)V
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->access$getDatabase$p(Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;)Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getAlbumThumbnails()Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getAlbums(Lcom/dot/gallery/feature_node/domain/util/MediaOrder;)Lkotlinx/coroutines/flow/Flow;
@@ -23834,7 +23751,6 @@ SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getPinnedA
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getSetting(Landroidx/datastore/preferences/core/Preferences$Key;Ljava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getTimelineSettings()Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getTrashed()Lkotlinx/coroutines/flow/Flow;
-SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getVaults()Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->updateInternalDatabase(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$Companion;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$Companion;->()V
@@ -23894,8 +23810,6 @@ SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getSetting$$
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getSetting$$inlined$map$1$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getTrashed$$inlined$map$1;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getTrashed$$inlined$map$1;->(Lkotlinx/coroutines/flow/Flow;)V
-Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getVaults$$inlined$map$1;
-SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getVaults$$inlined$map$1;->(Lkotlinx/coroutines/flow/Flow;Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;)V
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$updateInternalDatabase$1;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$updateInternalDatabase$1;->(Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;Lkotlin/coroutines/Continuation;)V
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$updateInternalDatabase$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
@@ -24071,10 +23985,6 @@ Lcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;
SPLcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;->()V
SPLcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;->()V
SPLcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;->equals(Ljava/lang/Object;)Z
-Lcom/dot/gallery/feature_node/domain/model/VaultState;
-SPLcom/dot/gallery/feature_node/domain/model/VaultState;->()V
-SPLcom/dot/gallery/feature_node/domain/model/VaultState;->(Ljava/util/List;Z)V
-SPLcom/dot/gallery/feature_node/domain/model/VaultState;->(Ljava/util/List;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;
Lcom/dot/gallery/feature_node/domain/util/Converters;
SPLcom/dot/gallery/feature_node/domain/util/Converters;->()V
@@ -25134,7 +25044,6 @@ SPLcom/dot/gallery/feature_node/presentation/util/AppBottomSheetStateKt$$Externa
Lcom/dot/gallery/feature_node/presentation/util/ContextExtKt;
SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->()V
SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->getMediaStoreVersion(Landroid/content/Context;)Ljava/lang/String;
-SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->isManageFilesAllowed()Z
PLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->isMediaUpToDate(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Landroid/content/Context;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->isMetadataUpToDate(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Landroid/content/Context;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
PLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->launchManageMedia(Landroid/content/Context;)V
@@ -25264,9 +25173,6 @@ SPLcom/dot/gallery/feature_node/presentation/util/Screen$TimelineScreen;->
Lcom/dot/gallery/feature_node/presentation/util/Screen$TrashedScreen;
SPLcom/dot/gallery/feature_node/presentation/util/Screen$TrashedScreen;->()V
SPLcom/dot/gallery/feature_node/presentation/util/Screen$TrashedScreen;->()V
-Lcom/dot/gallery/feature_node/presentation/util/Screen$VaultScreen;
-SPLcom/dot/gallery/feature_node/presentation/util/Screen$VaultScreen;->()V
-SPLcom/dot/gallery/feature_node/presentation/util/Screen$VaultScreen;->()V
Lcom/dot/gallery/feature_node/presentation/util/SharedElementsExtKt;
SPLcom/dot/gallery/feature_node/presentation/util/SharedElementsExtKt;->mediaSharedElement$lambda$4$lambda$0(Landroidx/compose/runtime/MutableState;)Z
SPLcom/dot/gallery/feature_node/presentation/util/SharedElementsExtKt;->mediaSharedElement(Landroidx/compose/animation/SharedTransitionScope;Landroidx/compose/ui/Modifier;ZLcom/dot/gallery/feature_node/domain/model/Media;Landroidx/compose/animation/AnimatedVisibilityScope;Landroidx/compose/runtime/Composer;II)Landroidx/compose/ui/Modifier;
@@ -25305,21 +25211,13 @@ SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->
SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-Lcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules$KeyModule;
-SPLcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules$KeyModule;->provide()Z
-Lcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_BindsModule_Binds_LazyMapKey;
-SPLcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_BindsModule_Binds_LazyMapKey;->()V
-Lcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_KeyModule_Provide_LazyMapKey;
-SPLcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_KeyModule_Provide_LazyMapKey;->()V
Lcom/dot/gallery/injection/AppModule;
SPLcom/dot/gallery/injection/AppModule;->()V
SPLcom/dot/gallery/injection/AppModule;->()V
SPLcom/dot/gallery/injection/AppModule;->provideDatabase(Landroid/app/Application;)Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;
SPLcom/dot/gallery/injection/AppModule;->provideEventHandler()Lcom/dot/gallery/feature_node/domain/util/EventHandler;
-SPLcom/dot/gallery/injection/AppModule;->provideKeychainHolder(Landroid/content/Context;)Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;
SPLcom/dot/gallery/injection/AppModule;->provideMediaDistributor(Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;Lcom/dot/gallery/feature_node/domain/util/EventHandler;)Lcom/dot/gallery/core/MediaDistributor;
SPLcom/dot/gallery/injection/AppModule;->provideMediaHandler(Landroid/content/Context;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;)Lcom/dot/gallery/core/MediaHandler;
-SPLcom/dot/gallery/injection/AppModule;->provideMediaRepository(Landroid/content/Context;Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;)Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;
SPLcom/dot/gallery/injection/AppModule;->provideMediaSelector()Lcom/dot/gallery/core/MediaSelector;
SPLcom/dot/gallery/injection/AppModule;->provideSearchHelper(Landroid/content/Context;)Lcom/dot/gallery/feature_node/presentation/search/SearchHelper;
SPLcom/dot/gallery/injection/AppModule;->provideWorkManager(Landroid/content/Context;)Landroidx/work/WorkManager;
@@ -25327,14 +25225,11 @@ Lcom/dot/gallery/injection/AppModule_ProvideDatabaseFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideDatabaseFactory;->provideDatabase(Landroid/app/Application;)Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;
Lcom/dot/gallery/injection/AppModule_ProvideEventHandlerFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideEventHandlerFactory;->provideEventHandler()Lcom/dot/gallery/feature_node/domain/util/EventHandler;
-Lcom/dot/gallery/injection/AppModule_ProvideKeychainHolderFactory;
-SPLcom/dot/gallery/injection/AppModule_ProvideKeychainHolderFactory;->provideKeychainHolder(Landroid/content/Context;)Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;
Lcom/dot/gallery/injection/AppModule_ProvideMediaDistributorFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideMediaDistributorFactory;->provideMediaDistributor(Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;Lcom/dot/gallery/feature_node/domain/util/EventHandler;)Lcom/dot/gallery/core/MediaDistributor;
Lcom/dot/gallery/injection/AppModule_ProvideMediaHandlerFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideMediaHandlerFactory;->provideMediaHandler(Landroid/content/Context;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;)Lcom/dot/gallery/core/MediaHandler;
Lcom/dot/gallery/injection/AppModule_ProvideMediaRepositoryFactory;
-SPLcom/dot/gallery/injection/AppModule_ProvideMediaRepositoryFactory;->provideMediaRepository(Landroid/content/Context;Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;)Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;
Lcom/dot/gallery/injection/AppModule_ProvideMediaSelectorFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideMediaSelectorFactory;->provideMediaSelector()Lcom/dot/gallery/core/MediaSelector;
Lcom/dot/gallery/injection/AppModule_ProvideSearchHelperFactory;
@@ -29376,4 +29271,4 @@ Lokio/internal/ResourceFileSystem$$ExternalSyntheticLambda1;
SPLokio/internal/ResourceFileSystem$$ExternalSyntheticLambda1;->(Lokio/internal/ResourceFileSystem;)V
Lokio/internal/ResourceFileSystem$Companion;
SPLokio/internal/ResourceFileSystem$Companion;->()V
-SPLokio/internal/ResourceFileSystem$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
\ No newline at end of file
+SPLokio/internal/ResourceFileSystem$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
diff --git a/app/src/arm64-v8aRelease/generated/baselineProfiles/startup-prof.txt b/app/src/arm64-v8aRelease/generated/baselineProfiles/startup-prof.txt
index f1f53a2cf4..f664bdb450 100644
--- a/app/src/arm64-v8aRelease/generated/baselineProfiles/startup-prof.txt
+++ b/app/src/arm64-v8aRelease/generated/baselineProfiles/startup-prof.txt
@@ -18879,25 +18879,6 @@ SPLandroidx/savedstate/internal/SavedStateRegistryImpl$Companion;->()V
SPLandroidx/savedstate/internal/SavedStateRegistryImpl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
Landroidx/savedstate/internal/SynchronizedObject;
SPLandroidx/savedstate/internal/SynchronizedObject;->()V
-Landroidx/security/crypto/MasterKey;
-SPLandroidx/security/crypto/MasterKey;->(Ljava/lang/String;Ljava/lang/Object;)V
-Landroidx/security/crypto/MasterKey$Builder;
-SPLandroidx/security/crypto/MasterKey$Builder;->(Landroid/content/Context;)V
-SPLandroidx/security/crypto/MasterKey$Builder;->(Landroid/content/Context;Ljava/lang/String;)V
-SPLandroidx/security/crypto/MasterKey$Builder;->build()Landroidx/security/crypto/MasterKey;
-SPLandroidx/security/crypto/MasterKey$Builder;->setKeyScheme(Landroidx/security/crypto/MasterKey$KeyScheme;)Landroidx/security/crypto/MasterKey$Builder;
-Landroidx/security/crypto/MasterKey$Builder$Api23Impl;
-SPLandroidx/security/crypto/MasterKey$Builder$Api23Impl;->build(Landroidx/security/crypto/MasterKey$Builder;)Landroidx/security/crypto/MasterKey;
-Landroidx/security/crypto/MasterKey$KeyScheme;
-SPLandroidx/security/crypto/MasterKey$KeyScheme;->$values()[Landroidx/security/crypto/MasterKey$KeyScheme;
-SPLandroidx/security/crypto/MasterKey$KeyScheme;->()V
-SPLandroidx/security/crypto/MasterKey$KeyScheme;->(Ljava/lang/String;I)V
-Landroidx/security/crypto/MasterKeys;
-SPLandroidx/security/crypto/MasterKeys;->()V
-SPLandroidx/security/crypto/MasterKeys;->createAES256GCMKeyGenParameterSpec(Ljava/lang/String;)Landroid/security/keystore/KeyGenParameterSpec;
-SPLandroidx/security/crypto/MasterKeys;->getOrCreate(Landroid/security/keystore/KeyGenParameterSpec;)Ljava/lang/String;
-SPLandroidx/security/crypto/MasterKeys;->keyExists(Ljava/lang/String;)Z
-SPLandroidx/security/crypto/MasterKeys;->validate(Landroid/security/keystore/KeyGenParameterSpec;)V
Landroidx/sqlite/SQLite;
SPLandroidx/sqlite/SQLite;->execSQL(Landroidx/sqlite/SQLiteConnection;Ljava/lang/String;)V
Landroidx/sqlite/SQLiteConnection;
@@ -22796,49 +22777,16 @@ SPLcom/dot/gallery/core/Settings$Misc$rememberGridSize$1$1$value$1;->invokeSuspe
Lcom/dot/gallery/core/SettingsKt;
SPLcom/dot/gallery/core/SettingsKt;->()V
SPLcom/dot/gallery/core/SettingsKt;->getDataStore(Landroid/content/Context;)Landroidx/datastore/core/DataStore;
-Lcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->handles(Ljava/io/File;)Z
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader;->handles(Ljava/lang/Object;)Z
-Lcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedFileModelLoader$Factory;->build(Lcom/bumptech/glide/load/model/MultiModelLoaderFactory;)Lcom/bumptech/glide/load/model/ModelLoader;
-Lcom/dot/gallery/core/decoder/glide/EncryptedGenericImageDecoder;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedGenericImageDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedGenericImageDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
-Lcom/dot/gallery/core/decoder/glide/EncryptedMediaStream;
-Lcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->handles(Landroid/net/Uri;)Z
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader;->handles(Ljava/lang/Object;)Z
-Lcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;->(Landroid/content/Context;)V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedUriModelLoader$Factory;->build(Lcom/bumptech/glide/load/model/MultiModelLoaderFactory;)Lcom/bumptech/glide/load/model/ModelLoader;
-Lcom/dot/gallery/core/decoder/glide/EncryptedVideoFrameDecoder;
-SPLcom/dot/gallery/core/decoder/glide/EncryptedVideoFrameDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/EncryptedVideoFrameDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;Lkotlin/jvm/functions/Function0;)V
Lcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->()V
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->handles(Ljava/io/InputStream;Lcom/bumptech/glide/load/Options;)Z
SPLcom/dot/gallery/core/decoder/glide/HeifBitmapDecoder;->handles(Ljava/lang/Object;Lcom/bumptech/glide/load/Options;)Z
-Lcom/dot/gallery/core/decoder/glide/HeifEncryptedDecoder;
-SPLcom/dot/gallery/core/decoder/glide/HeifEncryptedDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/HeifEncryptedDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
-Lcom/dot/gallery/core/decoder/glide/IsEncryptedVaultFileKt;
-SPLcom/dot/gallery/core/decoder/glide/IsEncryptedVaultFileKt;->isEncryptedVaultFile(Ljava/io/File;)Z
Lcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->()V
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->handles(Ljava/io/InputStream;Lcom/bumptech/glide/load/Options;)Z
SPLcom/dot/gallery/core/decoder/glide/JxlBitmapDecoder;->handles(Ljava/lang/Object;Lcom/bumptech/glide/load/Options;)Z
-Lcom/dot/gallery/core/decoder/glide/JxlEncryptedDecoder;
-SPLcom/dot/gallery/core/decoder/glide/JxlEncryptedDecoder;->()V
-SPLcom/dot/gallery/core/decoder/glide/JxlEncryptedDecoder;->(Lcom/bumptech/glide/load/engine/bitmap_recycle/BitmapPool;)V
Lcom/dot/gallery/core/presentation/components/AppBarKt;
SPLcom/dot/gallery/core/presentation/components/AppBarKt;->$r8$lambda$DsPR7b3BsTxlzkrJf3l-Kymmt-Y(I)I
SPLcom/dot/gallery/core/presentation/components/AppBarKt;->$r8$lambda$Vay4j8nd0PNlEP9MEQJtcWNVJKY(Ljava/util/List;Landroidx/navigation/NavController;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Landroidx/compose/animation/AnimatedVisibilityScope;Landroidx/compose/runtime/Composer;I)Lkotlin/Unit;
@@ -23530,7 +23478,6 @@ Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$15QqL12KsHwPyPiG3qbiCHi8Dhs(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MetadataDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$2QDUjMU4Hx8kYc7tO3hlvnIgsW8(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/ImageEmbeddingDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$711IgaQTzxOzDjGMNmIWCtjJyBU(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MediaDao_Impl;
-SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$A6DCbF69_hYXBjdmUra8K7PT9YI(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;
PLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$L85sszyn6t4C4HmsRrdgfiM6Ac0(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/ClassifierDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$ZfOKcFvP4FXN5mKwqbyGoFRl4-A(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/BlacklistDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->$r8$lambda$w69ZHrj2x99hkAuAipMHFUH2Pew(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/AlbumThumbnailDao_Impl;
@@ -23544,7 +23491,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_imageE
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_mediaDao$lambda$2(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MediaDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_metadataDao$lambda$5(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/MetadataDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_pinnedDao$lambda$0(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl;
-SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->_vaultDao$lambda$4(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->access$internalInitInvalidationTracker(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;Landroidx/sqlite/SQLiteConnection;)V
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->createAutoMigrations(Ljava/util/Map;)Ljava/util/List;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->createInvalidationTracker()Landroidx/room/InvalidationTracker;
@@ -23559,7 +23505,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getMeta
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getPinnedDao()Lcom/dot/gallery/feature_node/data/data_source/PinnedDao;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getRequiredAutoMigrationSpecClasses()Ljava/util/Set;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getRequiredTypeConverterClasses()Ljava/util/Map;
-SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;->getVaultDao()Lcom/dot/gallery/feature_node/data/data_source/VaultDao;
Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$ExternalSyntheticLambda0;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$ExternalSyntheticLambda0;->(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)V
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object;
@@ -23587,12 +23532,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$$External
Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$createOpenDelegate$_openDelegate$1;
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$createOpenDelegate$_openDelegate$1;->(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl;)V
SPLcom/dot/gallery/feature_node/data/data_source/InternalDatabase_Impl$createOpenDelegate$_openDelegate$1;->onOpen(Landroidx/sqlite/SQLiteConnection;)V
-Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder;->(Landroid/content/Context;)V
-Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder$Companion;
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder$Companion;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/KeychainHolder$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
Lcom/dot/gallery/feature_node/data/data_source/MediaDao;
PLcom/dot/gallery/feature_node/data/data_source/MediaDao;->updateMedia$suspendImpl(Lcom/dot/gallery/feature_node/data/data_source/MediaDao;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
PLcom/dot/gallery/feature_node/data/data_source/MediaDao;->updateMedia(Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -23752,27 +23691,6 @@ Lcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;
SPLcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;->()V
SPLcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
SPLcom/dot/gallery/feature_node/data/data_source/PinnedDao_Impl$Companion;->getRequiredConverters()Ljava/util/List;
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao;
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;->(Landroidx/room/RoomDatabase;)V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl;->getVaults()Lkotlinx/coroutines/flow/Flow;
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$$ExternalSyntheticLambda4;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$$ExternalSyntheticLambda4;->(Ljava/lang/String;)V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$1;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$1;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$2;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$2;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$3;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$3;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$4;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$4;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$5;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$5;->()V
-Lcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;->()V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-SPLcom/dot/gallery/feature_node/data/data_source/VaultDao_Impl$Companion;->getRequiredConverters()Ljava/util/List;
Lcom/dot/gallery/feature_node/data/data_source/mediastore/MediaQuery;
SPLcom/dot/gallery/feature_node/data/data_source/mediastore/MediaQuery;->()V
SPLcom/dot/gallery/feature_node/data/data_source/mediastore/MediaQuery;->()V
@@ -23820,7 +23738,6 @@ SPLcom/dot/gallery/feature_node/data/data_source/mediastore/queries/QueryFlow;->
SPLcom/dot/gallery/feature_node/data/data_source/mediastore/queries/QueryFlow;->()V
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->()V
-SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->(Landroid/content/Context;Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;)V
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->access$getDatabase$p(Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;)Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getAlbumThumbnails()Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getAlbums(Lcom/dot/gallery/feature_node/domain/util/MediaOrder;)Lkotlinx/coroutines/flow/Flow;
@@ -23834,7 +23751,6 @@ SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getPinnedA
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getSetting(Landroidx/datastore/preferences/core/Preferences$Key;Ljava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getTimelineSettings()Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getTrashed()Lkotlinx/coroutines/flow/Flow;
-SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->getVaults()Lkotlinx/coroutines/flow/Flow;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;->updateInternalDatabase(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$Companion;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$Companion;->()V
@@ -23894,8 +23810,6 @@ SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getSetting$$
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getSetting$$inlined$map$1$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getTrashed$$inlined$map$1;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getTrashed$$inlined$map$1;->(Lkotlinx/coroutines/flow/Flow;)V
-Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getVaults$$inlined$map$1;
-SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$getVaults$$inlined$map$1;->(Lkotlinx/coroutines/flow/Flow;Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;)V
Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$updateInternalDatabase$1;
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$updateInternalDatabase$1;->(Lcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl;Lkotlin/coroutines/Continuation;)V
SPLcom/dot/gallery/feature_node/data/repository/MediaRepositoryImpl$updateInternalDatabase$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
@@ -24071,10 +23985,6 @@ Lcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;
SPLcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;->()V
SPLcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;->()V
SPLcom/dot/gallery/feature_node/domain/model/UIEvent$UpdateDatabase;->equals(Ljava/lang/Object;)Z
-Lcom/dot/gallery/feature_node/domain/model/VaultState;
-SPLcom/dot/gallery/feature_node/domain/model/VaultState;->()V
-SPLcom/dot/gallery/feature_node/domain/model/VaultState;->(Ljava/util/List;Z)V
-SPLcom/dot/gallery/feature_node/domain/model/VaultState;->(Ljava/util/List;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;
Lcom/dot/gallery/feature_node/domain/util/Converters;
SPLcom/dot/gallery/feature_node/domain/util/Converters;->()V
@@ -25134,7 +25044,6 @@ SPLcom/dot/gallery/feature_node/presentation/util/AppBottomSheetStateKt$$Externa
Lcom/dot/gallery/feature_node/presentation/util/ContextExtKt;
SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->()V
SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->getMediaStoreVersion(Landroid/content/Context;)Ljava/lang/String;
-SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->isManageFilesAllowed()Z
PLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->isMediaUpToDate(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Landroid/content/Context;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
SPLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->isMetadataUpToDate(Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Landroid/content/Context;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
PLcom/dot/gallery/feature_node/presentation/util/ContextExtKt;->launchManageMedia(Landroid/content/Context;)V
@@ -25264,9 +25173,6 @@ SPLcom/dot/gallery/feature_node/presentation/util/Screen$TimelineScreen;->
Lcom/dot/gallery/feature_node/presentation/util/Screen$TrashedScreen;
SPLcom/dot/gallery/feature_node/presentation/util/Screen$TrashedScreen;->()V
SPLcom/dot/gallery/feature_node/presentation/util/Screen$TrashedScreen;->()V
-Lcom/dot/gallery/feature_node/presentation/util/Screen$VaultScreen;
-SPLcom/dot/gallery/feature_node/presentation/util/Screen$VaultScreen;->()V
-SPLcom/dot/gallery/feature_node/presentation/util/Screen$VaultScreen;->()V
Lcom/dot/gallery/feature_node/presentation/util/SharedElementsExtKt;
SPLcom/dot/gallery/feature_node/presentation/util/SharedElementsExtKt;->mediaSharedElement$lambda$4$lambda$0(Landroidx/compose/runtime/MutableState;)Z
SPLcom/dot/gallery/feature_node/presentation/util/SharedElementsExtKt;->mediaSharedElement(Landroidx/compose/animation/SharedTransitionScope;Landroidx/compose/ui/Modifier;ZLcom/dot/gallery/feature_node/domain/model/Media;Landroidx/compose/animation/AnimatedVisibilityScope;Landroidx/compose/runtime/Composer;II)Landroidx/compose/ui/Modifier;
@@ -25305,21 +25211,13 @@ SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->
SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
SPLcom/dot/gallery/feature_node/presentation/util/StateExtKt$mapMediaToItem$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-Lcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules$KeyModule;
-SPLcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules$KeyModule;->provide()Z
-Lcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_BindsModule_Binds_LazyMapKey;
-SPLcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_BindsModule_Binds_LazyMapKey;->()V
-Lcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_KeyModule_Provide_LazyMapKey;
-SPLcom/dot/gallery/feature_node/presentation/vault/VaultViewModel_HiltModules_KeyModule_Provide_LazyMapKey;->()V
Lcom/dot/gallery/injection/AppModule;
SPLcom/dot/gallery/injection/AppModule;->()V
SPLcom/dot/gallery/injection/AppModule;->()V
SPLcom/dot/gallery/injection/AppModule;->provideDatabase(Landroid/app/Application;)Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;
SPLcom/dot/gallery/injection/AppModule;->provideEventHandler()Lcom/dot/gallery/feature_node/domain/util/EventHandler;
-SPLcom/dot/gallery/injection/AppModule;->provideKeychainHolder(Landroid/content/Context;)Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;
SPLcom/dot/gallery/injection/AppModule;->provideMediaDistributor(Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;Lcom/dot/gallery/feature_node/domain/util/EventHandler;)Lcom/dot/gallery/core/MediaDistributor;
SPLcom/dot/gallery/injection/AppModule;->provideMediaHandler(Landroid/content/Context;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;)Lcom/dot/gallery/core/MediaHandler;
-SPLcom/dot/gallery/injection/AppModule;->provideMediaRepository(Landroid/content/Context;Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;)Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;
SPLcom/dot/gallery/injection/AppModule;->provideMediaSelector()Lcom/dot/gallery/core/MediaSelector;
SPLcom/dot/gallery/injection/AppModule;->provideSearchHelper(Landroid/content/Context;)Lcom/dot/gallery/feature_node/presentation/search/SearchHelper;
SPLcom/dot/gallery/injection/AppModule;->provideWorkManager(Landroid/content/Context;)Landroidx/work/WorkManager;
@@ -25327,14 +25225,11 @@ Lcom/dot/gallery/injection/AppModule_ProvideDatabaseFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideDatabaseFactory;->provideDatabase(Landroid/app/Application;)Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;
Lcom/dot/gallery/injection/AppModule_ProvideEventHandlerFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideEventHandlerFactory;->provideEventHandler()Lcom/dot/gallery/feature_node/domain/util/EventHandler;
-Lcom/dot/gallery/injection/AppModule_ProvideKeychainHolderFactory;
-SPLcom/dot/gallery/injection/AppModule_ProvideKeychainHolderFactory;->provideKeychainHolder(Landroid/content/Context;)Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;
Lcom/dot/gallery/injection/AppModule_ProvideMediaDistributorFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideMediaDistributorFactory;->provideMediaDistributor(Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;Lcom/dot/gallery/feature_node/domain/util/EventHandler;)Lcom/dot/gallery/core/MediaDistributor;
Lcom/dot/gallery/injection/AppModule_ProvideMediaHandlerFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideMediaHandlerFactory;->provideMediaHandler(Landroid/content/Context;Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;)Lcom/dot/gallery/core/MediaHandler;
Lcom/dot/gallery/injection/AppModule_ProvideMediaRepositoryFactory;
-SPLcom/dot/gallery/injection/AppModule_ProvideMediaRepositoryFactory;->provideMediaRepository(Landroid/content/Context;Landroidx/work/WorkManager;Lcom/dot/gallery/feature_node/data/data_source/InternalDatabase;Lcom/dot/gallery/feature_node/data/data_source/KeychainHolder;)Lcom/dot/gallery/feature_node/domain/repository/MediaRepository;
Lcom/dot/gallery/injection/AppModule_ProvideMediaSelectorFactory;
SPLcom/dot/gallery/injection/AppModule_ProvideMediaSelectorFactory;->provideMediaSelector()Lcom/dot/gallery/core/MediaSelector;
Lcom/dot/gallery/injection/AppModule_ProvideSearchHelperFactory;
@@ -29376,4 +29271,4 @@ Lokio/internal/ResourceFileSystem$$ExternalSyntheticLambda1;
SPLokio/internal/ResourceFileSystem$$ExternalSyntheticLambda1;->(Lokio/internal/ResourceFileSystem;)V
Lokio/internal/ResourceFileSystem$Companion;
SPLokio/internal/ResourceFileSystem$Companion;->()V
-SPLokio/internal/ResourceFileSystem$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
\ No newline at end of file
+SPLokio/internal/ResourceFileSystem$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000000..6a32c6100d
--- /dev/null
+++ b/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/app/src/debug/kotlin/com/dot/gallery/core/sandbox/UnknownSizeVideoProvider.kt b/app/src/debug/kotlin/com/dot/gallery/core/sandbox/UnknownSizeVideoProvider.kt
new file mode 100644
index 0000000000..bc87a595e5
--- /dev/null
+++ b/app/src/debug/kotlin/com/dot/gallery/core/sandbox/UnknownSizeVideoProvider.kt
@@ -0,0 +1,143 @@
+package com.dot.gallery.core.sandbox
+
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.content.res.AssetFileDescriptor
+import android.database.Cursor
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.net.Uri
+import android.os.Bundle
+import android.os.CancellationSignal
+import android.os.ParcelFileDescriptor
+import androidx.core.graphics.createBitmap
+import java.io.ByteArrayOutputStream
+import java.io.FileNotFoundException
+import java.io.IOException
+
+class UnknownSizeVideoProvider : ContentProvider() {
+
+ override fun onCreate(): Boolean {
+ return true
+ }
+
+ override fun getType(uri: Uri): String {
+ return VIDEO_MIME_TYPE
+ }
+
+ override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor {
+ return openPipe(
+ uri = uri,
+ mimeType = VIDEO_MIME_TYPE,
+ bytes = MP4_HEADER_BYTES,
+ )
+ }
+
+ override fun openTypedAssetFile(
+ uri: Uri,
+ mimeTypeFilter: String,
+ opts: Bundle?,
+ signal: CancellationSignal?,
+ ): AssetFileDescriptor {
+ val descriptor = openPipe(
+ uri = uri,
+ mimeType = IMAGE_MIME_TYPE,
+ bytes = createThumbnailBytes(),
+ )
+ return AssetFileDescriptor(
+ descriptor,
+ 0L,
+ AssetFileDescriptor.UNKNOWN_LENGTH,
+ )
+ }
+
+ override fun query(
+ uri: Uri,
+ projection: Array?,
+ selection: String?,
+ selectionArgs: Array?,
+ sortOrder: String?,
+ ): Cursor? {
+ return null
+ }
+
+ override fun insert(uri: Uri, values: ContentValues?): Uri? {
+ return null
+ }
+
+ override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
+ return 0
+ }
+
+ override fun update(
+ uri: Uri,
+ values: ContentValues?,
+ selection: String?,
+ selectionArgs: Array?,
+ ): Int {
+ return 0
+ }
+
+ private fun openPipe(uri: Uri, mimeType: String, bytes: ByteArray): ParcelFileDescriptor {
+ return openPipeHelper(uri, mimeType, null, bytes) { output, _, _, _, pipeBytes ->
+ try {
+ ParcelFileDescriptor.AutoCloseOutputStream(output).use { stream ->
+ stream.write(pipeBytes)
+ }
+ } catch (_: IOException) {
+ // The reader may close the pipe before consuming the complete fixture.
+ }
+ }
+ }
+
+ private fun createThumbnailBytes(): ByteArray {
+ val bitmap = createBitmap(
+ width = THUMBNAIL_SIZE,
+ height = THUMBNAIL_SIZE,
+ config = Bitmap.Config.ARGB_8888,
+ )
+ return try {
+ bitmap.eraseColor(Color.CYAN)
+ ByteArrayOutputStream().use { output ->
+ if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, output)) {
+ throw FileNotFoundException("Unable to create test thumbnail")
+ }
+ output.toByteArray()
+ }
+ } finally {
+ bitmap.recycle()
+ }
+ }
+
+ companion object {
+ private const val IMAGE_MIME_TYPE = "image/png"
+ private const val THUMBNAIL_SIZE = 224
+ private const val VIDEO_MIME_TYPE = "video/mp4"
+ private val MP4_HEADER_BYTES = byteArrayOf(
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x66,
+ 0x74,
+ 0x79,
+ 0x70,
+ 0x69,
+ 0x73,
+ 0x6F,
+ 0x6D,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x69,
+ 0x73,
+ 0x6F,
+ 0x6D,
+ 0x6D,
+ 0x70,
+ 0x34,
+ 0x32,
+ )
+ }
+}
diff --git a/app/src/debug/res/values/ic_launcher_background.xml b/app/src/debug/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000000..caa0f82f59
--- /dev/null
+++ b/app/src/debug/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #E53935
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 50cf33f92b..6dbb7d0507 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,24 +14,18 @@
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
@@ -62,53 +55,31 @@
+ android:theme="@style/Theme.Gallery">
-
+
+
-
-
-
+
+
+
-
-
-
-
+
-
-
-
+
@@ -117,51 +88,27 @@
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -197,6 +144,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:foregroundServiceType="dataSync" />
-
\ No newline at end of file
+
diff --git a/app/src/main/kotlin/com/dot/gallery/GalleryApp.kt b/app/src/main/kotlin/com/dot/gallery/GalleryApp.kt
index eb6b3142e5..ccf8cf10cd 100644
--- a/app/src/main/kotlin/com/dot/gallery/GalleryApp.kt
+++ b/app/src/main/kotlin/com/dot/gallery/GalleryApp.kt
@@ -12,14 +12,16 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.dot.gallery.core.MediaDistributor
-import com.dot.gallery.core.ml.ModelManager
-import com.dot.gallery.core.decoder.supportHeifDecoder
-import com.dot.gallery.core.decoder.supportJxlDecoder
-import com.dot.gallery.core.decoder.supportVaultDecoder
+import com.dot.gallery.core.decoder.supportSandboxedHeifDecoder
+import com.dot.gallery.core.decoder.supportSandboxedJxlDecoder
import com.dot.gallery.core.decoder.supportVideoFrame2
+import com.dot.gallery.core.ml.ModelManager
+import com.dot.gallery.core.sandbox.IsolatedImageDecoder
+import com.dot.gallery.core.sandbox.MediaPreviewDecoder
+import com.dot.gallery.core.sandbox.SandboxedDecoderHolder
import com.dot.gallery.core.workers.MetadataCollectionWorker
-import com.dot.gallery.core.workers.TempVaultCleanupWorker
-import com.dot.gallery.feature_node.domain.repository.MediaRepository
+import com.dot.gallery.feature_node.data.repository.MediaRepository
+import com.dot.gallery.feature_node.domain.use_case.AiMediaAnalysis
import com.github.panpf.sketch.PlatformContext
import com.github.panpf.sketch.SingletonSketch
import com.github.panpf.sketch.Sketch
@@ -35,12 +37,12 @@ import com.github.panpf.sketch.request.supportPauseLoadWhenScrolling
import com.github.panpf.sketch.resize.Precision
import com.github.panpf.sketch.util.appCacheDirectory
import dagger.hilt.android.HiltAndroidApp
-import okio.FileSystem
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
-import javax.inject.Inject
+import okio.FileSystem
@HiltAndroidApp
class GalleryApp : Application(), SingletonSketch.Factory, Configuration.Provider {
@@ -53,9 +55,8 @@ class GalleryApp : Application(), SingletonSketch.Factory, Configuration.Provide
supportVideoFrame2()
supportAnimatedWebp()
supportAnimatedHeif()
- supportHeifDecoder()
- supportJxlDecoder()
- supportVaultDecoder()
+ supportSandboxedHeifDecoder()
+ supportSandboxedJxlDecoder()
}
val diskCache = DiskCache.Builder(context, FileSystem.SYSTEM)
.directory(context.appCacheDirectory())
@@ -101,6 +102,15 @@ class GalleryApp : Application(), SingletonSketch.Factory, Configuration.Provide
@Inject
lateinit var modelManager: ModelManager
+ @Inject
+ internal lateinit var isolatedImageDecoder: IsolatedImageDecoder
+
+ @Inject
+ internal lateinit var mediaPreviewDecoder: MediaPreviewDecoder
+
+ @Inject
+ internal lateinit var aiMediaAnalysis: AiMediaAnalysis
+
private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onCreate() {
@@ -110,6 +120,8 @@ class GalleryApp : Application(), SingletonSketch.Factory, Configuration.Provide
super.onCreate()
+ SandboxedDecoderHolder.init(isolatedImageDecoder)
+
workManager.enqueueUniqueWork(
uniqueWorkName = "MetadataCollection",
existingWorkPolicy = ExistingWorkPolicy.APPEND_OR_REPLACE,
@@ -117,13 +129,11 @@ class GalleryApp : Application(), SingletonSketch.Factory, Configuration.Provide
.build()
)
- // Schedule periodic cleanup of stale decrypted temp files.
- TempVaultCleanupWorker.schedule(workManager)
-
- // Initialize ML models (copies from assets on withML, checks presence on noML)
+ // Initial bundled-model availability probe; UI and workers observe this result.
appScope.launch {
- modelManager.initializeModels()
+ aiMediaAnalysis.initialize()
+ modelManager.refreshStatus()
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/EditBackupManager.kt b/app/src/main/kotlin/com/dot/gallery/core/EditBackupManager.kt
deleted file mode 100644
index 5104208fe9..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/EditBackupManager.kt
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023-2026 IacobIacob01
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.dot.gallery.core
-
-import android.content.ContentValues
-import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.net.Uri
-import android.provider.MediaStore
-import com.dot.gallery.feature_node.data.data_source.EditHistoryDao
-import com.dot.gallery.feature_node.domain.model.EditedMedia
-import com.dot.gallery.feature_node.presentation.util.printDebug
-import com.dot.gallery.feature_node.presentation.util.printError
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.withContext
-import java.io.File
-import java.io.FileInputStream
-import java.io.IOException
-import java.io.InputStream
-import java.io.OutputStream
-
-class EditBackupManager(
- private val context: Context,
- private val editHistoryDao: EditHistoryDao
-) {
-
- private val backupDir: File
- get() = File(context.filesDir, BACKUP_DIR_NAME).also { if (!it.exists()) it.mkdirs() }
-
- /**
- * Back up the original image bytes before an override edit.
- * If a backup already exists for this media, it is preserved (first edit's original).
- */
- suspend fun backupOriginal(mediaId: Long, uri: Uri, mimeType: String): Boolean =
- withContext(Dispatchers.IO) {
- try {
- // If already backed up, keep the first original
- if (editHistoryDao.hasOriginalBackup(mediaId)) {
- printDebug("Backup already exists for mediaId=$mediaId, keeping original")
- // Update the edit timestamp
- editHistoryDao.getEditedMedia(mediaId)?.let { existing ->
- editHistoryDao.upsertEditedMedia(
- existing.copy(editTimestamp = System.currentTimeMillis())
- )
- }
- return@withContext true
- }
-
- val backupFile = File(backupDir, "$mediaId.bak")
- val bytesCopied = streamCopyFromUri(uri, backupFile)
- if (bytesCopied < 0) return@withContext false
-
- editHistoryDao.upsertEditedMedia(
- EditedMedia(
- mediaId = mediaId,
- originalUri = uri,
- backupPath = backupFile.absolutePath,
- originalMimeType = mimeType,
- editTimestamp = System.currentTimeMillis()
- )
- )
- printDebug("Backed up original for mediaId=$mediaId ($bytesCopied bytes)")
- true
- } catch (e: Exception) {
- printError("Failed to backup original for mediaId=$mediaId: ${e.message}")
- false
- }
- }
-
- /**
- * Restore the original image from backup, writing it back to the media URI.
- * Returns the decoded original Bitmap on success, or null on failure.
- */
- suspend fun restoreOriginal(mediaId: Long): Bitmap? = withContext(Dispatchers.IO) {
- try {
- val editedMedia = editHistoryDao.getEditedMedia(mediaId)
- ?: return@withContext null
-
- val backupFile = File(editedMedia.backupPath)
- if (!backupFile.exists()) {
- printError("Backup file not found: ${editedMedia.backupPath}")
- editHistoryDao.deleteEditedMedia(mediaId)
- return@withContext null
- }
-
- val bitmap = FileInputStream(backupFile).use { fis ->
- BitmapFactory.decodeStream(fis)
- } ?: return@withContext null
-
- bitmap
- } catch (e: Exception) {
- printError("Failed to restore original for mediaId=$mediaId: ${e.message}")
- null
- }
- }
-
- /**
- * Get an InputStream for the original backup file.
- * Caller is responsible for closing the stream.
- */
- suspend fun getOriginalStream(mediaId: Long): InputStream? = withContext(Dispatchers.IO) {
- val editedMedia = editHistoryDao.getEditedMedia(mediaId) ?: return@withContext null
- val backupFile = File(editedMedia.backupPath)
- if (!backupFile.exists()) return@withContext null
- FileInputStream(backupFile)
- }
-
- /**
- * Write original bytes back to a media URI and clean up the backup.
- */
- suspend fun revertToOriginal(mediaId: Long): Boolean = withContext(Dispatchers.IO) {
- try {
- val editedMedia = editHistoryDao.getEditedMedia(mediaId)
- ?: return@withContext false
-
- val backupFile = File(editedMedia.backupPath)
- if (!backupFile.exists()) {
- editHistoryDao.deleteEditedMedia(mediaId)
- return@withContext false
- }
-
- // Stream-copy backup back to the media URI (constant memory)
- val outStream = context.contentResolver.openOutputStream(editedMedia.originalUri)
- ?: throw IOException("Failed to open output stream for ${editedMedia.originalUri}")
- FileInputStream(backupFile).use { fis ->
- outStream.use { out ->
- fis.copyTo(out, bufferSize = STREAM_BUFFER_SIZE)
- }
- }
-
- // Update IS_PENDING to 0
- context.contentResolver.update(
- editedMedia.originalUri,
- ContentValues().apply { put(MediaStore.MediaColumns.IS_PENDING, 0) },
- null
- )
-
- // Clean up
- backupFile.delete()
- editHistoryDao.deleteEditedMedia(mediaId)
- printDebug("Reverted mediaId=$mediaId to original")
- true
- } catch (e: Exception) {
- printError("Failed to revert mediaId=$mediaId: ${e.message}")
- false
- }
- }
-
- /**
- * Delete a backup (e.g., when the media itself is deleted).
- */
- suspend fun deleteBackup(mediaId: Long) = withContext(Dispatchers.IO) {
- val editedMedia = editHistoryDao.getEditedMedia(mediaId) ?: return@withContext
- File(editedMedia.backupPath).delete()
- editHistoryDao.deleteEditedMedia(mediaId)
- }
-
- /**
- * Check if a media item has a recoverable original.
- */
- suspend fun hasOriginalBackup(mediaId: Long): Boolean =
- editHistoryDao.hasOriginalBackup(mediaId)
-
- /**
- * Flow-based check for UI reactivity.
- */
- fun hasOriginalBackupFlow(mediaId: Long): Flow =
- editHistoryDao.hasOriginalBackupFlow(mediaId)
-
- /**
- * Clean up orphaned backups (where the media no longer exists).
- */
- suspend fun cleanupOrphans(existingMediaIds: List) = withContext(Dispatchers.IO) {
- val allEdited = editHistoryDao.getAllEditedMedia()
- val orphans = allEdited.filter { it.mediaId !in existingMediaIds }
- orphans.forEach { File(it.backupPath).delete() }
- editHistoryDao.deleteOrphans(existingMediaIds)
- }
-
- /**
- * Data class describing a single backup entry for the UI.
- */
- data class BackupInfo(
- val mediaId: Long,
- val originalUri: Uri,
- val originalMimeType: String,
- val backupPath: String,
- val sizeBytes: Long,
- val editTimestamp: Long
- )
-
- /**
- * Returns total disk space used by all edit backups, in bytes.
- */
- suspend fun getTotalBackupSize(): Long = withContext(Dispatchers.IO) {
- val dir = backupDir
- if (!dir.exists()) return@withContext 0L
- dir.listFiles()?.sumOf { it.length() } ?: 0L
- }
-
- /**
- * Returns a list of all backup entries with file sizes.
- */
- suspend fun getAllBackupInfo(): List = withContext(Dispatchers.IO) {
- editHistoryDao.getAllEditedMedia().mapNotNull { edited ->
- val file = File(edited.backupPath)
- if (file.exists()) {
- BackupInfo(
- mediaId = edited.mediaId,
- originalUri = edited.originalUri,
- originalMimeType = edited.originalMimeType,
- backupPath = edited.backupPath,
- sizeBytes = file.length(),
- editTimestamp = edited.editTimestamp
- )
- } else null
- }
- }
-
- /**
- * Delete backups older than the given age in milliseconds.
- * Returns the number of backups deleted.
- */
- suspend fun deleteBackupsOlderThan(maxAgeMs: Long): Int = withContext(Dispatchers.IO) {
- val cutoff = System.currentTimeMillis() - maxAgeMs
- val allEdited = editHistoryDao.getAllEditedMedia()
- var count = 0
- allEdited.filter { it.editTimestamp < cutoff }.forEach { edited ->
- File(edited.backupPath).delete()
- editHistoryDao.deleteEditedMedia(edited.mediaId)
- count++
- }
- count
- }
-
- /**
- * Delete specific backups by media ID list.
- */
- suspend fun deleteBackups(mediaIds: List) = withContext(Dispatchers.IO) {
- mediaIds.forEach { id ->
- val edited = editHistoryDao.getEditedMedia(id) ?: return@forEach
- File(edited.backupPath).delete()
- editHistoryDao.deleteEditedMedia(id)
- }
- }
-
- /**
- * Delete all backups.
- */
- suspend fun deleteAllBackups() = withContext(Dispatchers.IO) {
- val allEdited = editHistoryDao.getAllEditedMedia()
- allEdited.forEach { File(it.backupPath).delete() }
- allEdited.forEach { editHistoryDao.deleteEditedMedia(it.mediaId) }
- }
-
- /**
- * Stream-copy content from a Uri to a File using a fixed-size buffer.
- * Returns the number of bytes copied, or -1 on failure.
- */
- private fun streamCopyFromUri(uri: Uri, destFile: File): Long {
- val inputStream: InputStream = context.contentResolver.openInputStream(uri)
- ?: return -1
- return inputStream.use { src ->
- destFile.outputStream().use { dst ->
- src.copyTo(dst, bufferSize = STREAM_BUFFER_SIZE)
- }
- }
- }
-
- companion object {
- private const val BACKUP_DIR_NAME = "edit_backups"
- private const val STREAM_BUFFER_SIZE = 8192
- const val AUTO_CLEANUP_AGE_MS = 90L * 24 * 60 * 60 * 1000 // 90 days
- }
-}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaDistributor.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaDistributor.kt
index e1697c2a8c..69e5d63808 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/MediaDistributor.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaDistributor.kt
@@ -1,21 +1,16 @@
package com.dot.gallery.core
+import com.dot.gallery.feature_node.data.model.CollectionWithCount
+import com.dot.gallery.feature_node.data.model.IgnoredAlbum
+import com.dot.gallery.feature_node.data.model.LockedAlbum
+import com.dot.gallery.feature_node.data.model.Media
+import com.dot.gallery.feature_node.data.model.MergedSubfolderAlbum
+import com.dot.gallery.feature_node.data.model.PinnedAlbum
+import com.dot.gallery.feature_node.data.model.TimelineSettings
+import com.dot.gallery.feature_node.data.util.MediaGroupType
import com.dot.gallery.feature_node.domain.model.AlbumState
-import com.dot.gallery.feature_node.domain.model.CollectionWithCount
-import com.dot.gallery.feature_node.domain.model.GeoMedia
-import com.dot.gallery.feature_node.domain.model.IgnoredAlbum
-import com.dot.gallery.feature_node.domain.model.ImageEmbedding
-import com.dot.gallery.feature_node.domain.model.Media
-import com.dot.gallery.feature_node.domain.model.LocationMedia
-import com.dot.gallery.feature_node.domain.util.MediaGroupType
import com.dot.gallery.feature_node.domain.model.MediaMetadataState
import com.dot.gallery.feature_node.domain.model.MediaState
-import com.dot.gallery.feature_node.domain.model.LockedAlbum
-import com.dot.gallery.feature_node.domain.model.MergedSubfolderAlbum
-import com.dot.gallery.feature_node.domain.model.PinnedAlbum
-import com.dot.gallery.feature_node.domain.model.TimelineSettings
-import com.dot.gallery.feature_node.domain.model.Vault
-import com.dot.gallery.feature_node.domain.model.VaultState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
@@ -66,15 +61,6 @@ interface MediaDistributor {
* Media Metadata
*/
val metadataFlow: Flow
- val locationsMediaFlow: Flow>
- val geoMediaFlow: Flow>
-
- /**
- * Vault
- */
- val vaultsMediaFlow: StateFlow
- fun vaultMediaFlow(vault: Vault?): StateFlow>
-
/**
* Collections
*/
@@ -83,14 +69,4 @@ interface MediaDistributor {
fun collectionAlbumIdsInCollection(collectionId: Long): Flow>
fun collectionMediaFlow(collectionId: Long): StateFlow>
- /**
- * Search
- */
- val imageEmbeddingsFlow: StateFlow>
-
-
- fun locationBasedMedia(
- gpsLocationNameCity: String,
- gpsLocationNameCountry: String
- ): Flow>
-}
\ No newline at end of file
+}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaDistributorImpl.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaDistributorImpl.kt
index b7b90838f6..25784dfb73 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/MediaDistributorImpl.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaDistributorImpl.kt
@@ -2,6 +2,7 @@ package com.dot.gallery.core
import android.content.Context
import android.media.MediaScannerConnection
+import android.provider.MediaStore
import androidx.compose.runtime.compositionLocalOf
import androidx.work.WorkInfo
import androidx.work.WorkManager
@@ -9,40 +10,40 @@ import com.dot.gallery.core.Settings.Misc.DEFAULT_DATE_FORMAT
import com.dot.gallery.core.Settings.Misc.EXTENDED_DATE_FORMAT
import com.dot.gallery.core.Settings.Misc.WEEKLY_DATE_FORMAT
import com.dot.gallery.core.presentation.components.FilterKind
-import com.dot.gallery.feature_node.domain.model.Album
-import com.dot.gallery.feature_node.domain.model.AlbumGroup
-import com.dot.gallery.feature_node.domain.model.AlbumGroupMember
+import com.dot.gallery.feature_node.data.data_source.ScannedMediaDao
+import com.dot.gallery.feature_node.data.model.Album
+import com.dot.gallery.feature_node.data.model.AlbumGroup
+import com.dot.gallery.feature_node.data.model.AlbumGroupMember
+import com.dot.gallery.feature_node.data.model.AlbumThumbnail
+import com.dot.gallery.feature_node.data.model.CollectionWithCount
+import com.dot.gallery.feature_node.data.model.IgnoredAlbum
+import com.dot.gallery.feature_node.data.model.LockedAlbum
+import com.dot.gallery.feature_node.data.model.Media
+import com.dot.gallery.feature_node.data.model.MergedSubfolderAlbum
+import com.dot.gallery.feature_node.data.model.PinnedAlbum
+import com.dot.gallery.feature_node.data.model.ScannedMedia
+import com.dot.gallery.feature_node.data.model.TimelineSettings
+import com.dot.gallery.feature_node.data.model.shouldIgnore
+import com.dot.gallery.feature_node.data.repository.MediaRepository
+import com.dot.gallery.feature_node.data.util.MediaGroupType
+import com.dot.gallery.feature_node.data.util.MediaOrder
+import com.dot.gallery.feature_node.data.util.OrderType
+import com.dot.gallery.feature_node.data.util.mapLocked
+import com.dot.gallery.feature_node.data.util.mapPinned
+import com.dot.gallery.feature_node.data.util.removeBlacklisted
import com.dot.gallery.feature_node.domain.model.AlbumGroupWithAlbums
import com.dot.gallery.feature_node.domain.model.AlbumState
-import com.dot.gallery.feature_node.domain.model.AlbumThumbnail
-import com.dot.gallery.feature_node.domain.model.CollectionWithCount
-import com.dot.gallery.feature_node.domain.model.GeoMedia
-import com.dot.gallery.feature_node.domain.model.IgnoredAlbum
-import com.dot.gallery.feature_node.domain.model.ImageEmbedding
-import com.dot.gallery.feature_node.domain.model.LocationMedia
-import com.dot.gallery.feature_node.domain.model.Media
import com.dot.gallery.feature_node.domain.model.MediaMetadataState
import com.dot.gallery.feature_node.domain.model.MediaState
-import com.dot.gallery.feature_node.domain.model.LockedAlbum
-import com.dot.gallery.feature_node.domain.model.MergedSubfolderAlbum
-import com.dot.gallery.feature_node.domain.model.PinnedAlbum
-import com.dot.gallery.feature_node.domain.model.TimelineSettings
import com.dot.gallery.feature_node.domain.model.UIEvent
-import com.dot.gallery.feature_node.domain.model.Vault
-import com.dot.gallery.feature_node.domain.model.VaultState
-import com.dot.gallery.feature_node.domain.model.shouldIgnore
-import com.dot.gallery.feature_node.domain.repository.MediaRepository
import com.dot.gallery.feature_node.domain.util.EventHandler
-import com.dot.gallery.feature_node.domain.util.MediaOrder
-import com.dot.gallery.feature_node.domain.util.OrderType
-import com.dot.gallery.feature_node.domain.util.MediaGroupType
-import com.dot.gallery.feature_node.domain.util.mapLocked
-import com.dot.gallery.feature_node.domain.util.mapPinned
-import com.dot.gallery.feature_node.domain.util.removeBlacklisted
import com.dot.gallery.feature_node.presentation.util.mapMediaToItem
import com.dot.gallery.feature_node.presentation.util.mediaFlow
import dagger.hilt.android.qualifiers.ApplicationContext
-import android.provider.MediaStore
+import java.util.concurrent.ConcurrentHashMap
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.collections.immutable.toPersistentMap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -54,6 +55,7 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
@@ -62,9 +64,6 @@ import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import java.util.concurrent.ConcurrentHashMap
-import javax.inject.Inject
-import javax.inject.Singleton
val LocalMediaDistributor = compositionLocalOf {
error("No MediaDistributor provided!!! This is likely due to a missing Hilt injection in the Composable hierarchy.")
@@ -75,7 +74,8 @@ class MediaDistributorImpl @Inject constructor(
@param:ApplicationContext private val context: Context,
private val repository: MediaRepository,
private val eventHandler: EventHandler,
- workManager: WorkManager
+ workManager: WorkManager,
+ private val scannedMediaDao: ScannedMediaDao,
) : MediaDistributor {
private val sharingMethod = SharingStarted.WhileSubscribed(5_000L)
@@ -86,9 +86,18 @@ class MediaDistributorImpl @Inject constructor(
/**
* Tracks media IDs that have already been submitted for a MediaStore rescan
* to avoid redundant scanning of the same files.
+ * Persisted to the Room database so entries are cleaned when media is deleted.
+ * Loaded asynchronously to avoid blocking the main thread during startup.
*/
private val rescanRequestedIds = ConcurrentHashMap.newKeySet()
+ init {
+ appScope.launch {
+ rescanRequestedIds.addAll(scannedMediaDao.getScannedIds())
+ scannedMediaDao.removeStaleEntries()
+ }
+ }
+
/**
* Pull-to-refresh
*/
@@ -108,9 +117,13 @@ class MediaDistributorImpl @Inject constructor(
/**
* Album Media Sort preference flow
*/
- private val albumMediaSortFlow: StateFlow =
+ private val albumMediaSortFlow: StateFlow =
Settings.Album.getAlbumMediaSortFlow(context)
- .stateIn(appScope, SharingStarted.Eagerly, Settings.Album.LastSort(OrderType.Descending, FilterKind.DATE))
+ .stateIn(
+ scope = appScope,
+ started = SharingStarted.Eagerly,
+ initialValue = Settings.Album.LastSort(OrderType.Descending, FilterKind.DATE),
+ )
/**
* Common
@@ -363,8 +376,37 @@ class MediaDistributorImpl @Inject constructor(
/**
* Media
*/
+ private val allMediaResourceFlow: SharedFlow>> =
+ repository.mediaFlow(-1L, null)
+ .shareIn(
+ scope = appScope,
+ started = sharingMethod,
+ replay = 1,
+ )
+
+ private val mediaMappingOptionsFlow: Flow = combine(
+ settingsFlow,
+ dateFormatsFlow,
+ groupSimilarMedia,
+ enabledGroupTypes,
+ ) { settings, dateFormats, shouldGroupSimilar, groupTypes ->
+ MediaMappingOptions(
+ groupByMonth = settings?.groupTimelineByMonth == true,
+ groupSimilarMedia = shouldGroupSimilar,
+ enabledGroupTypes = groupTypes,
+ defaultDateFormat = dateFormats.first,
+ extendedDateFormat = dateFormats.second,
+ weeklyDateFormat = dateFormats.third,
+ )
+ }.distinctUntilChanged()
+
override val timelineMediaFlow: SharedFlow> =
- mediaFlow(-1L, null, triggerDatabaseUpdate = true)
+ mediaFlow(
+ source = allMediaResourceFlow,
+ albumId = -1L,
+ target = null,
+ triggerDatabaseUpdate = true,
+ )
@OptIn(ExperimentalCoroutinesApi::class)
@Suppress("UNCHECKED_CAST")
@@ -372,28 +414,18 @@ class MediaDistributorImpl @Inject constructor(
hasPermission.flatMapLatest { granted ->
if (!granted) flowOf(emptyMap())
else combine(
- repository.mediaFlow(-1L, null),
+ allMediaResourceFlow,
albumsFlow,
- settingsFlow,
+ mediaMappingOptionsFlow,
blacklistedAlbumsFlow,
- dateFormatsFlow,
albumMediaSortFlow,
- groupSimilarMedia,
- enabledGroupTypes
) { values ->
val allMediaResult = values[0] as Resource>
val albumState = values[1] as AlbumState
- val settings = values[2] as TimelineSettings?
+ val options = values[2] as MediaMappingOptions
@Suppress("UNCHECKED_CAST")
val blacklistedAlbums = values[3] as List
- @Suppress("UNCHECKED_CAST")
- val dateFormats = values[4] as Triple
- val albumSort = values[5] as Settings.Album.LastSort
- val shouldGroupSimilar = values[6] as Boolean
- @Suppress("UNCHECKED_CAST")
- val groupTypes = values[7] as Set
-
- val (defaultDateFormat, extendedDateFormat, weeklyDateFormat) = dateFormats
+ val albumSort = values[4] as Settings.Album.LastSort
val allMedia = allMediaResult.data ?: emptyList()
val albumIds = albumState.albums.mapTo(HashSet()) { it.id }
@@ -420,12 +452,12 @@ class MediaDistributorImpl @Inject constructor(
data = sorter.sortMedia(filtered),
error = "",
albumId = albumId,
- groupByMonth = settings?.groupTimelineByMonth == true,
- groupSimilarMedia = shouldGroupSimilar,
- enabledGroupTypes = groupTypes,
- defaultDateFormat = defaultDateFormat,
- extendedDateFormat = extendedDateFormat,
- weeklyDateFormat = weeklyDateFormat
+ groupByMonth = options.groupByMonth,
+ groupSimilarMedia = options.groupSimilarMedia,
+ enabledGroupTypes = options.enabledGroupTypes,
+ defaultDateFormat = options.defaultDateFormat,
+ extendedDateFormat = options.extendedDateFormat,
+ weeklyDateFormat = options.weeklyDateFormat,
)
}
result
@@ -438,89 +470,90 @@ class MediaDistributorImpl @Inject constructor(
override val favoritesMediaFlow: SharedFlow> =
- mediaFlow(-1L, Constants.Target.TARGET_FAVORITES)
+ mediaFlow(
+ source = repository.mediaFlow(-1L, Constants.Target.TARGET_FAVORITES),
+ albumId = -1L,
+ target = Constants.Target.TARGET_FAVORITES,
+ )
override val trashMediaFlow: SharedFlow> =
- mediaFlow(-1L, Constants.Target.TARGET_TRASH)
+ mediaFlow(
+ source = repository.mediaFlow(-1L, Constants.Target.TARGET_TRASH),
+ albumId = -1L,
+ target = Constants.Target.TARGET_TRASH,
+ )
@OptIn(ExperimentalCoroutinesApi::class)
@Suppress("UNCHECKED_CAST")
- private fun mediaFlow(albumId: Long, target: String?, triggerDatabaseUpdate: Boolean = false) = hasPermission.flatMapLatest { granted ->
- if (!granted) flowOf(MediaState(
- error = "No permission to access media",
- isLoading = false
- ))
- else combine(
- repository.mediaFlow(albumId, target),
- settingsFlow,
- blacklistedAlbumsFlow,
- lockedAlbumsFlow,
- dateFormatsFlow,
- albumMediaSortFlow,
- groupSimilarMedia,
- enabledGroupTypes
- ) { values ->
- val result = values[0] as Resource>
- val settings = values[1] as TimelineSettings?
- @Suppress("UNCHECKED_CAST")
- val blacklistedAlbums = values[2] as List
- @Suppress("UNCHECKED_CAST")
- val lockedAlbums = values[3] as List
- @Suppress("UNCHECKED_CAST")
- val dateFormats = values[4] as Triple
- val albumSort = values[5] as Settings.Album.LastSort
- val shouldGroupSimilar = values[6] as Boolean
- @Suppress("UNCHECKED_CAST")
- val groupTypes = values[7] as Set
-
- val (defaultDateFormat, extendedDateFormat, weeklyDateFormat) = dateFormats
-
- if (result is Resource.Error) return@combine MediaState(
- error = result.message ?: "",
- isLoading = false
- )
- // Use custom sort for album timelines, default sort for favorites/trash
- val sorter = if (target == null && albumId > 0) {
- when (albumSort.kind) {
- FilterKind.DATE -> MediaOrder.Date(albumSort.orderType)
- FilterKind.DATE_MODIFIED -> MediaOrder.DateModified(albumSort.orderType)
- FilterKind.NAME -> MediaOrder.Label(albumSort.orderType)
- }
+ private fun mediaFlow(
+ source: Flow>>,
+ albumId: Long,
+ target: String?,
+ triggerDatabaseUpdate: Boolean = false,
+ ): SharedFlow> {
+ return hasPermission.flatMapLatest { granted ->
+ if (!granted) {
+ flowOf(
+ MediaState(
+ error = "No permission to access media",
+ isLoading = false,
+ ),
+ )
} else {
- MediaOrder.Default
- }
- val lockedAlbumIds = lockedAlbums.mapTo(HashSet()) { it.id }
- val data = (result.data ?: emptyList()).toMutableList().apply {
- removeAll { media -> blacklistedAlbums.any { it.shouldIgnore(media, albumId) } }
- // Hide media from locked albums in the main timeline
- if (albumId == -1L && target == null) {
- removeAll { media -> media.albumID in lockedAlbumIds }
+ combine(
+ source,
+ mediaMappingOptionsFlow,
+ blacklistedAlbumsFlow,
+ lockedAlbumsFlow,
+ ) { values ->
+ val result = values[0] as Resource>
+ val options = values[1] as MediaMappingOptions
+ @Suppress("UNCHECKED_CAST")
+ val blacklistedAlbums = values[2] as List
+ @Suppress("UNCHECKED_CAST")
+ val lockedAlbums = values[3] as List
+
+ if (result is Resource.Error) {
+ return@combine MediaState(
+ error = result.message ?: "",
+ isLoading = false,
+ )
+ }
+ val lockedAlbumIds = lockedAlbums.mapTo(HashSet()) { it.id }
+ val data = (result.data ?: emptyList()).toMutableList().apply {
+ removeAll { media ->
+ blacklistedAlbums.any { it.shouldIgnore(media, albumId) }
+ }
+ if (albumId == -1L && target == null) {
+ removeAll { media -> media.albumID in lockedAlbumIds }
+ }
+ }
+ mapMediaToItem(
+ data = MediaOrder.Default.sortMedia(data),
+ error = result.message ?: "",
+ albumId = albumId,
+ groupByMonth = options.groupByMonth,
+ groupSimilarMedia = options.groupSimilarMedia,
+ enabledGroupTypes = options.enabledGroupTypes,
+ defaultDateFormat = options.defaultDateFormat,
+ extendedDateFormat = options.extendedDateFormat,
+ weeklyDateFormat = options.weeklyDateFormat,
+ )
}
}
- mapMediaToItem(
- data = sorter.sortMedia(data),
- error = result.message ?: "",
- albumId = albumId,
- groupByMonth = settings?.groupTimelineByMonth == true,
- groupSimilarMedia = shouldGroupSimilar,
- enabledGroupTypes = groupTypes,
- defaultDateFormat = defaultDateFormat,
- extendedDateFormat = extendedDateFormat,
- weeklyDateFormat = weeklyDateFormat
- )
- }
- }.mapLatest {
- if (triggerDatabaseUpdate) {
- eventHandler.pushEvent(UIEvent.UpdateDatabase)
- }
- triggerRescanForMissingDateTaken(it.media)
- it
- }.shareIn(
- scope = appScope,
- started = sharingMethod,
- replay = 1
- )
+ }.mapLatest { mediaState ->
+ if (triggerDatabaseUpdate) {
+ eventHandler.pushEvent(UIEvent.UpdateDatabase)
+ }
+ triggerRescanForMissingDateTaken(mediaState.media)
+ mediaState
+ }.shareIn(
+ scope = appScope,
+ started = sharingMethod,
+ replay = 1,
+ )
+ }
/**
* Media Metadata
@@ -534,108 +567,12 @@ class MediaDistributorImpl @Inject constructor(
) { metadata, isRunning, progress ->
MediaMetadataState(
metadata = metadata,
+ metadataById = metadata.associateBy { item -> item.mediaId }.toPersistentMap(),
isLoading = isRunning,
isLoadingProgress = progress
)
}
- override fun locationBasedMedia(
- gpsLocationNameCity: String,
- gpsLocationNameCountry: String
- ): Flow> = combine(
- repository.getMetadata(),
- repository.getCompleteMedia()
- ) { metadata, media ->
- val matchingMediaIds = metadata
- .filter {
- it.gpsLocationNameCity == gpsLocationNameCity &&
- it.gpsLocationNameCountry == gpsLocationNameCountry
- }
- .mapTo(HashSet()) { it.mediaId }
- val filteredMedia = media.data.orEmpty().filter {
- it.id in matchingMediaIds
- }
- return@combine mapMediaToItem(
- data = filteredMedia,
- error = media.message ?: "",
- albumId = -1L,
- defaultDateFormat = dateFormatsFlow.value.first,
- extendedDateFormat = dateFormatsFlow.value.second,
- weeklyDateFormat = dateFormatsFlow.value.third
- )
- }
-
- private val locationsAndGeoMediaFlow: SharedFlow, List>> = combine(
- repository.getMetadata(),
- timelineMediaFlow
- ) { metadata, timelineState ->
- val mediaById = HashMap(timelineState.media.size)
- for (m in timelineState.media) { mediaById[m.id] = m }
-
- val locationGroupMap = LinkedHashMap()
- val geoList = ArrayList(metadata.size / 2)
-
- for (meta in metadata) {
- val media = mediaById[meta.mediaId] ?: continue
-
- if (meta.gpsLocationNameCity != null && meta.gpsLocationNameCountry != null) {
- val key = "${meta.gpsLocationNameCity}, ${meta.gpsLocationNameCountry}"
- val existing = locationGroupMap[key]
- if (existing == null || media.definedTimestamp > existing.definedTimestamp) {
- locationGroupMap[key] = media
- }
- }
-
- if (meta.gpsLatitude != null && meta.gpsLongitude != null) {
- geoList.add(
- GeoMedia(
- mediaId = meta.mediaId,
- latitude = meta.gpsLatitude,
- longitude = meta.gpsLongitude,
- locationCity = meta.gpsLocationNameCity,
- locationCountry = meta.gpsLocationNameCountry,
- media = media
- )
- )
- }
- }
-
- val locations = locationGroupMap.entries
- .map { (location, media) -> LocationMedia(media = media, location = location) }
- .sortedBy { it.location }
-
- Pair(locations, geoList)
- }.shareIn(appScope, sharingMethod, replay = 1)
-
- override val locationsMediaFlow: Flow> =
- locationsAndGeoMediaFlow.map { it.first }
-
- override val geoMediaFlow: Flow> =
- locationsAndGeoMediaFlow.map { it.second }
-
- /**
- * Vault
- */
- override val vaultsMediaFlow: StateFlow = repository.getVaults()
- .map { VaultState(it.data ?: emptyList(), isLoading = false) }
- .stateIn(appScope, started = sharingMethod, VaultState())
-
- override fun vaultMediaFlow(vault: Vault?): StateFlow> = combine(
- repository.getEncryptedMedia(vault),
- settingsFlow,
- dateFormatsFlow
- ) { result, settings, (defaultDateFormat, extendedDateFormat, weeklyDateFormat) ->
- mapMediaToItem(
- data = result.data ?: emptyList(),
- error = result.message ?: "",
- albumId = -1L,
- groupByMonth = settings?.groupTimelineByMonth == true,
- defaultDateFormat = defaultDateFormat,
- extendedDateFormat = extendedDateFormat,
- weeklyDateFormat = weeklyDateFormat
- )
- }.stateIn(appScope, sharingMethod, MediaState())
-
/**
* Collections
*/
@@ -686,17 +623,6 @@ class MediaDistributorImpl @Inject constructor(
)
}.stateIn(appScope, sharingMethod, MediaState())
- /**
- * Search
- */
- override val imageEmbeddingsFlow: StateFlow> =
- repository.getImageEmbeddings()
- .stateIn(
- scope = appScope,
- started = prioritySharingMethod,
- initialValue = emptyList()
- )
-
/**
* Triggers a MediaStore rescan for media items that have null DATE_TAKEN.
* When files are transferred between devices, MediaStore may not have
@@ -705,7 +631,7 @@ class MediaDistributorImpl @Inject constructor(
* to read EXIF immediately, populating DATE_TAKEN and triggering a
* ContentResolver change notification that refreshes the timeline.
*/
- private fun triggerRescanForMissingDateTaken(media: List) {
+ private suspend fun triggerRescanForMissingDateTaken(media: List) {
val toScan = media.filter { it.takenTimestamp == null && rescanRequestedIds.add(it.id) }
if (toScan.isEmpty()) return
val paths = toScan.mapNotNull { it.path.takeIf { p -> p.isNotBlank() } }.toTypedArray()
@@ -713,6 +639,7 @@ class MediaDistributorImpl @Inject constructor(
if (paths.isNotEmpty()) {
MediaScannerConnection.scanFile(context, paths, mimeTypes, null)
}
+ scannedMediaDao.insertAll(toScan.map { ScannedMedia(id = it.id) })
}
private fun mergeSubfolderAlbums(
@@ -784,4 +711,4 @@ class MediaDistributorImpl @Inject constructor(
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaHandler.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaHandler.kt
index 93221e81c7..b35b5bcef3 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/MediaHandler.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaHandler.kt
@@ -4,10 +4,9 @@ import android.graphics.Bitmap
import android.net.Uri
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
-import com.dot.gallery.feature_node.domain.model.Media
-import com.dot.gallery.feature_node.domain.model.Vault
-import kotlinx.coroutines.flow.Flow
+import com.dot.gallery.feature_node.data.model.Media
import java.util.UUID
+import kotlinx.coroutines.flow.Flow
interface MediaHandler {
@@ -55,15 +54,6 @@ interface MediaHandler {
displayName: String
): Uri?
- suspend fun overrideImage(
- uri: Uri,
- bitmap: Bitmap,
- format: Bitmap.CompressFormat,
- mimeType: String,
- relativePath: String,
- displayName: String
- ): Boolean
-
suspend fun getCategoryForMediaId(mediaId: Long): String?
fun getClassifiedMediaCountAtCategory(category: String): Flow
@@ -74,7 +64,6 @@ interface MediaHandler {
suspend fun updateAlbumThumbnail(albumId: Long, newThumbnail: Uri)
fun hasAlbumThumbnail(albumId: Long): Flow
suspend fun collectMetadataFor(media: Media)
- suspend fun addMedia(vault: Vault, media: T)
fun rotateImage(media: T, degrees: Int): UUID
-}
\ No newline at end of file
+}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaHandlerImpl.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaHandlerImpl.kt
index 6cbd6c9624..3bd5178b69 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/MediaHandlerImpl.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaHandlerImpl.kt
@@ -8,19 +8,15 @@ import androidx.activity.result.IntentSenderRequest
import androidx.compose.runtime.compositionLocalOf
import androidx.work.WorkManager
import com.dot.gallery.core.Settings.Misc.getTrashEnabled
-import com.dot.gallery.core.workers.VaultOperationWorker
-import com.dot.gallery.core.workers.enqueueVaultOperation
import com.dot.gallery.core.workers.rotateImage
-import com.dot.gallery.feature_node.domain.util.getUri
-import com.dot.gallery.feature_node.domain.model.Media
-import com.dot.gallery.feature_node.domain.model.Vault
-import com.dot.gallery.feature_node.domain.repository.MediaRepository
+import com.dot.gallery.feature_node.data.model.Media
+import com.dot.gallery.feature_node.data.repository.MediaRepository
import com.dot.gallery.feature_node.presentation.util.mediaPair
+import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.withContext
-import javax.inject.Inject
val LocalMediaHandler = compositionLocalOf {
error("No MediaHandler provided!!! This is likely due to a missing Hilt injection in the Composable hierarchy.")
@@ -74,14 +70,6 @@ class MediaHandlerImpl @Inject constructor(
}
}
- override suspend fun addMedia(vault: Vault, media: T) {
- workManager.enqueueVaultOperation(
- operation = VaultOperationWorker.OP_ENCRYPT,
- media = listOf(media.getUri()),
- vault = vault
- )
- }
-
override fun rotateImage(
media: T,
degrees: Int
@@ -131,15 +119,6 @@ class MediaHandlerImpl @Inject constructor(
displayName: String
): Uri? = repository.saveImage(bitmap, format, mimeType, relativePath, displayName)
- override suspend fun overrideImage(
- uri: Uri,
- bitmap: Bitmap,
- format: Bitmap.CompressFormat,
- mimeType: String,
- relativePath: String,
- displayName: String
- ): Boolean = repository.overrideImage(uri, bitmap, format, mimeType, relativePath, displayName)
-
override suspend fun getCategoryForMediaId(mediaId: Long): String? =
repository.getCategoryForMediaId(mediaId)
@@ -160,4 +139,4 @@ class MediaHandlerImpl @Inject constructor(
override suspend fun collectMetadataFor(media: Media) = repository.collectMetadataFor(media)
-}
\ No newline at end of file
+}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaMappingOptions.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaMappingOptions.kt
new file mode 100644
index 0000000000..f5f684ee3a
--- /dev/null
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaMappingOptions.kt
@@ -0,0 +1,12 @@
+package com.dot.gallery.core
+
+import com.dot.gallery.feature_node.data.util.MediaGroupType
+
+internal data class MediaMappingOptions(
+ val groupByMonth: Boolean,
+ val groupSimilarMedia: Boolean,
+ val enabledGroupTypes: Set,
+ val defaultDateFormat: String,
+ val extendedDateFormat: String,
+ val weeklyDateFormat: String,
+)
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaSelector.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaSelector.kt
index 29a9f55f8a..1cd312d8bf 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/MediaSelector.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaSelector.kt
@@ -1,6 +1,6 @@
package com.dot.gallery.core
-import com.dot.gallery.feature_node.domain.model.Media
+import com.dot.gallery.feature_node.data.model.Media
import com.dot.gallery.feature_node.domain.model.MediaState
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/app/src/main/kotlin/com/dot/gallery/core/MediaSelectorImpl.kt b/app/src/main/kotlin/com/dot/gallery/core/MediaSelectorImpl.kt
index 519f03023b..d40625dfc9 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/MediaSelectorImpl.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/MediaSelectorImpl.kt
@@ -1,7 +1,7 @@
package com.dot.gallery.core
import androidx.compose.runtime.compositionLocalOf
-import com.dot.gallery.feature_node.domain.model.Media
+import com.dot.gallery.feature_node.data.model.Media
import com.dot.gallery.feature_node.domain.model.MediaState
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/app/src/main/kotlin/com/dot/gallery/core/Settings.kt b/app/src/main/kotlin/com/dot/gallery/core/Settings.kt
index 46ecdf846b..c4e96014ff 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/Settings.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/Settings.kt
@@ -43,9 +43,9 @@ import com.dot.gallery.core.presentation.components.FilterKind
import com.dot.gallery.core.util.SdkCompat
import com.dot.gallery.core.util.rememberPreference
import com.dot.gallery.core.util.rememberPreferenceSerializable
+import com.dot.gallery.feature_node.data.util.OrderType
import com.dot.gallery.feature_node.domain.model.SearchHistory
import com.dot.gallery.feature_node.domain.model.SelectionSheetConfig
-import com.dot.gallery.feature_node.domain.util.OrderType
import com.dot.gallery.feature_node.presentation.mediaview.rememberedDerivedState
import com.dot.gallery.feature_node.presentation.util.Screen
import com.dot.gallery.feature_node.presentation.util.printDebug
@@ -241,6 +241,29 @@ object Settings {
}
+ object Security {
+ const val METADATA_ISOLATION_SHARED = "shared"
+ const val METADATA_ISOLATION_HYBRID = "hybrid"
+ const val METADATA_ISOLATION_PER_FILE = "per_file"
+ const val DEFAULT_METADATA_ISOLATION_MODE = METADATA_ISOLATION_HYBRID
+
+ private val METADATA_ISOLATION_MODE = stringPreferencesKey("metadata_isolation_mode")
+
+ @Composable
+ fun rememberMetadataIsolationMode(): MutableState {
+ return rememberPreference(
+ key = METADATA_ISOLATION_MODE,
+ defaultValue = DEFAULT_METADATA_ISOLATION_MODE
+ )
+ }
+
+ fun getMetadataIsolationMode(context: Context): Flow {
+ return context.dataStore.data.map {
+ it[METADATA_ISOLATION_MODE] ?: DEFAULT_METADATA_ISOLATION_MODE
+ }
+ }
+ }
+
object Misc {
private val USER_CHOICE_MEDIA_MANAGER = booleanPreferencesKey("use_media_manager")
@@ -274,12 +297,6 @@ object Settings {
fun rememberLastScreen() =
rememberPreference(key = LAST_SCREEN, defaultValue = Screen.TimelineScreen())
- private val LAST_SEEN_VERSION = stringPreferencesKey("last_seen_version")
-
- @Composable
- fun rememberLastSeenVersion() =
- rememberPreference(key = LAST_SEEN_VERSION, defaultValue = "")
-
private val FORCED_LAST_SCREEN = booleanPreferencesKey("forced_last_screen")
@Composable
@@ -512,12 +529,6 @@ object Settings {
fun rememberAutoHideOnVideoPlay() =
rememberPreference(key = AUTO_HIDE_ON_VIDEO_PLAY, defaultValue = true)
- val NO_CLASSIFICATION = booleanPreferencesKey("no_classification")
-
- @Composable
- fun rememberNoClassification() =
- rememberPreference(key = NO_CLASSIFICATION, defaultValue = false)
-
val DATE_HEADER_FORMAT = stringPreferencesKey("date_header_format")
@Composable
@@ -605,14 +616,6 @@ object Settings {
defaultValue = SelectionSheetConfig()
)
- const val ALIAS_REFRA = "ReFra"
- const val ALIAS_GALLERY = "Gallery"
- private val APP_NAME_ALIAS = stringPreferencesKey("app_name_alias")
-
- @Composable
- fun rememberAppNameAlias() =
- rememberPreference(key = APP_NAME_ALIAS, defaultValue = ALIAS_REFRA)
-
const val FAV_ICON_DISABLED = "disabled"
const val FAV_ICON_BOTTOM_END = "bottom_end"
const val FAV_ICON_BOTTOM_START = "bottom_start"
@@ -653,17 +656,6 @@ object Settings {
}
- object Vault {
- const val ENCRYPT_ASK = "ask"
- const val ENCRYPT_DELETE = "delete"
- const val ENCRYPT_KEEP = "keep"
-
- private val VAULT_ENCRYPT_BEHAVIOR = stringPreferencesKey("vault_encrypt_behavior")
-
- @Composable
- fun rememberVaultEncryptBehavior() =
- rememberPreference(key = VAULT_ENCRYPT_BEHAVIOR, defaultValue = ENCRYPT_ASK)
- }
}
sealed class Position {
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/DecoderExt.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/DecoderExt.kt
index 91a34d6e4a..da0ecc0c9d 100644
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/DecoderExt.kt
+++ b/app/src/main/kotlin/com/dot/gallery/core/decoder/DecoderExt.kt
@@ -2,15 +2,15 @@ package com.dot.gallery.core.decoder
import android.graphics.Bitmap
import com.github.panpf.sketch.asImage
-import com.github.panpf.sketch.request.ImageData
import com.github.panpf.sketch.decode.ImageInfo
import com.github.panpf.sketch.decode.internal.createScaledTransformed
+import com.github.panpf.sketch.request.ImageData
import com.github.panpf.sketch.request.RequestContext
import com.github.panpf.sketch.source.DataSource
import com.github.panpf.sketch.util.Size
import com.github.panpf.sketch.util.calculateScaleMultiplierWithOneSide
-import okio.buffer
import kotlin.math.roundToInt
+import okio.buffer
inline fun DataSource.getImageInfo(
requestContext: RequestContext,
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedBitmapFactoryDecoder.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedBitmapFactoryDecoder.kt
deleted file mode 100644
index cdfa0c8667..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedBitmapFactoryDecoder.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.dot.gallery.core.decoder
-
-import com.dot.gallery.BuildConfig
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.github.panpf.sketch.ComponentRegistry
-import com.github.panpf.sketch.Image
-import com.github.panpf.sketch.asImage
-import com.github.panpf.sketch.decode.DecodeConfig
-import com.github.panpf.sketch.decode.Decoder
-import com.github.panpf.sketch.decode.ImageInfo
-import com.github.panpf.sketch.decode.internal.DecodeHelper
-import com.github.panpf.sketch.decode.internal.ExifOrientationHelper
-import com.github.panpf.sketch.decode.internal.HelperDecoder
-import com.github.panpf.sketch.decode.internal.supportBitmapRegionDecoder
-import com.github.panpf.sketch.fetch.FetchResult
-import com.github.panpf.sketch.request.ImageRequest
-import com.github.panpf.sketch.request.RequestContext
-import com.github.panpf.sketch.request.get
-import com.github.panpf.sketch.source.DataSource
-import com.github.panpf.sketch.source.FileDataSource
-import com.github.panpf.sketch.util.Rect
-
-fun ComponentRegistry.Builder.supportVaultDecoder(): ComponentRegistry.Builder = apply {
- add(EncryptedRawImageDecoder.Factory())
- add(EncryptedBitmapFactoryDecoder.Factory())
- add(EncryptedVideoFrameDecoder.Factory())
-}
-
-/**
- * Raw image formats that need special handling for animation or quality preservation.
- * These are handled by EncryptedRawImageDecoder instead of EncryptedBitmapFactoryDecoder.
- */
-private val RAW_IMAGE_MIME_TYPES = listOf(
- "image/gif",
- "image/webp",
- "image/svg+xml",
- "image/bmp"
-)
-
-open class EncryptedBitmapFactoryDecoder(
- requestContext: RequestContext,
- dataSource: DataSource,
-) : HelperDecoder(
- requestContext = requestContext,
- dataSource = dataSource,
- decodeHelperFactory = { EncryptedBitmapFactoryDecodeHelper(requestContext.request, dataSource) }
-) {
-
- class Factory : Decoder.Factory {
-
- override val key: String = "EncryptedBitmapFactoryDecoder"
-
- override val sortWeight: Int = 0
-
- override fun create(
- requestContext: RequestContext,
- fetchResult: FetchResult
- ): Decoder? {
- val mimeType = requestContext.request.extras?.get("realMimeType") as String? ?: return null
- val dataSource = fetchResult.dataSource as? FileDataSource ?: return null
- val path = dataSource.getFile().path
- // Don't handle raw image formats - let EncryptedRawImageDecoder handle them for animation support
- if (mimeType in RAW_IMAGE_MIME_TYPES) return null
- return if (path.toString().contains(BuildConfig.APPLICATION_ID) && mimeType.startsWith("image"))
- EncryptedBitmapFactoryDecoder(requestContext, dataSource)
- else null
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- return other != null && this::class == other::class
- }
-
- override fun hashCode(): Int {
- return this::class.hashCode()
- }
-
- override fun toString(): String = "EncryptedBitmapFactoryDecoder"
- }
-}
-
-private class EncryptedBitmapFactoryDecodeHelper(val request: ImageRequest, private val dataSource: DataSource) :
- DecodeHelper {
-
- private val keychainHolder = KeychainHolder(request.context)
-
- private var _cachedImageInfo: ImageInfo? = null
-
- override suspend fun getImageInfo(): ImageInfo {
- return _cachedImageInfo ?: dataSource.readEncryptedImageInfo(keychainHolder, exifOrientationHelper).also { _cachedImageInfo = it }
- }
-
- override suspend fun isSupportRegion(): Boolean {
- // The result returns null, which means unknown, but future versions may support it, so it is still worth trying.
- return supportBitmapRegionDecoder(getImageInfo().mimeType) != false
- }
-
- private val exifOrientation: Int by lazy { dataSource.readEncryptedExifOrientation(keychainHolder) }
- private val exifOrientationHelper by lazy { ExifOrientationHelper(exifOrientation) }
-
- override suspend fun decode(sampleSize: Int): Image {
- val decodeConfig = DecodeConfig(request, getImageInfo().mimeType, isOpaque = false).apply {
- this.sampleSize = sampleSize
- }
- val bitmap = dataSource.decodeEncryptedBitmap(
- keychainHolder = keychainHolder,
- config = decodeConfig,
- exifOrientationHelper = exifOrientationHelper
- )
- return bitmap.asImage()
- }
-
- override suspend fun decodeRegion(region: Rect, sampleSize: Int): Image {
- val decodeConfig = DecodeConfig(request, getImageInfo().mimeType, isOpaque = false).apply {
- this.sampleSize = sampleSize
- }
- val bitmap = dataSource.decodeEncryptedRegionBitmap(
- keychainHolder = keychainHolder,
- srcRect = region,
- config = decodeConfig,
- imageSize = getImageInfo().size,
- exifOrientationHelper = exifOrientationHelper
- )
- return bitmap.asImage()
- }
-
- override fun close() {
-
- }
-
- override fun toString(): String {
- return "EncryptedBitmapFactoryDecodeHelper(uri='${request.uri}', dataSource=$dataSource)"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedDecoderExt.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedDecoderExt.kt
deleted file mode 100644
index 4ae0dd87a1..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedDecoderExt.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.dot.gallery.core.decoder
-
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.graphics.BitmapRegionDecoder
-import android.os.Build.VERSION
-import android.os.Build.VERSION_CODES
-import androidx.core.net.toFile
-import androidx.exifinterface.media.ExifInterface
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.github.panpf.sketch.decode.DecodeConfig
-import com.github.panpf.sketch.decode.ImageInfo
-import com.github.panpf.sketch.decode.ImageInvalidException
-import com.github.panpf.sketch.decode.internal.ExifOrientationHelper
-import com.github.panpf.sketch.decode.internal.checkImageInfo
-import com.github.panpf.sketch.decode.toBitmapOptions
-import com.github.panpf.sketch.source.ContentDataSource
-import com.github.panpf.sketch.source.DataSource
-import com.github.panpf.sketch.source.FileDataSource
-import com.github.panpf.sketch.util.Rect
-import com.github.panpf.sketch.util.Size
-import com.github.panpf.sketch.util.toAndroidRect
-import java.io.File
-import java.io.IOException
-
-fun T.getFile(): File {
- return when (this) {
- is ContentDataSource -> contentUri.toFile()
- is FileDataSource -> path.toFile()
- else -> throw IllegalArgumentException("Unsupported DataSource type")
- }
-}
-
-/**
- * Decode encrypted bitmap using BitmapFactory
- */
-@Throws(IOException::class)
-fun DataSource.decodeEncryptedBitmap(
- keychainHolder: KeychainHolder,
- config: DecodeConfig? = null,
- exifOrientationHelper: ExifOrientationHelper? = null
-): Bitmap {
- val options = config?.toBitmapOptions()
- val encryptedFile = getFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- val bitmap = BitmapFactory.decodeByteArray(
- decrypted.readBytes(),
- 0,
- decrypted.readBytes().size,
- options.apply { this?.outMimeType = decrypted.mimeType }
- ) ?: throw ImageInvalidException("decode return null at decodeEncryptedBitmap")
- val exifOrientationHelper1 =
- exifOrientationHelper ?: ExifOrientationHelper(readEncryptedExifOrientation(keychainHolder))
- return exifOrientationHelper1.applyToBitmap(bitmap) ?: bitmap
-}
-
-/**
- * Use EncryptedBitmapRegionDecoder to decode part of a bitmap region
- */
-@Throws(IOException::class)
-fun DataSource.decodeEncryptedRegionBitmap(
- keychainHolder: KeychainHolder,
- srcRect: Rect,
- config: DecodeConfig? = null,
- imageSize: Size? = null,
- exifOrientationHelper: ExifOrientationHelper? = null
-): Bitmap {
- val encryptedFile = getFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- val regionDecoder = if (VERSION.SDK_INT >= VERSION_CODES.S) {
- BitmapRegionDecoder.newInstance(decrypted.readBytes(), 0, decrypted.readBytes().size)
- } else {
- @Suppress("DEPRECATION")
- BitmapRegionDecoder.newInstance(
- decrypted.readBytes(),
- 0,
- decrypted.readBytes().size,
- false
- )
- }
- val imageSize1 =
- imageSize ?: readEncryptedImageInfo(keychainHolder, exifOrientationHelper).size
- val exifOrientationHelper1 =
- exifOrientationHelper ?: ExifOrientationHelper(
- readEncryptedExifOrientation(
- keychainHolder
- )
- )
- val originalRegion = exifOrientationHelper1.applyToRect(
- srcRect = srcRect,
- spaceSize = imageSize1,
- reverse = true
- )
- val bitmapOptions = config?.toBitmapOptions()
- val regionBitmap = try {
- regionDecoder.decodeRegion(originalRegion.toAndroidRect(), bitmapOptions)
- ?: throw ImageInvalidException("decode return null at decodeEncryptedRegionBitmap")
- } finally {
- regionDecoder.recycle()
- }
-
- val correctedRegionImage =
- exifOrientationHelper1.applyToBitmap(regionBitmap) ?: regionBitmap
- return correctedRegionImage
-
-}
-
-@Throws(IOException::class)
-fun DataSource.readEncryptedExifOrientation(keychainHolder: KeychainHolder): Int {
- val encryptedFile = getFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- return decrypted.readBytes().inputStream().use {
- ExifInterface(it).getAttributeInt(
- ExifInterface.TAG_ORIENTATION,
- ExifInterface.ORIENTATION_UNDEFINED
- )
- }
-}
-
-@Throws(IOException::class)
-fun DataSource.readEncryptedImageInfoWithIgnoreExifOrientation(keychainHolder: KeychainHolder): ImageInfo {
- val boundOptions = BitmapFactory.Options().apply {
- inJustDecodeBounds = true
- }
- val encryptedFile = getFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- try {
- BitmapFactory.decodeByteArray(
- decrypted.readBytes(),
- 0,
- decrypted.readBytes().size,
- boundOptions
- )
- } catch (e: Exception) {
- e.printStackTrace()
- throw ImageInvalidException("decode return null at readEncryptedImageInfoWithIgnoreExifOrientation")
- }
-
- val imageSize = Size(width = boundOptions.outWidth, height = boundOptions.outHeight)
- return ImageInfo(size = imageSize, mimeType = decrypted.mimeType)
- .apply { checkImageInfo(this) }
-}
-
-/**
- * Read image information using BitmapFactory. Parse Exif orientation
- */
-fun DataSource.readEncryptedImageInfo(
- keychainHolder: KeychainHolder,
- helper: ExifOrientationHelper?
-): ImageInfo {
- val imageInfo = readEncryptedImageInfoWithIgnoreExifOrientation(keychainHolder)
- val exifOrientationHelper = if (helper != null) {
- helper
- } else {
- val exifOrientation =
- readEncryptedExifOrientationWithMimeType(keychainHolder, imageInfo.mimeType)
- ExifOrientationHelper(exifOrientation)
- }
- val correctedImageSize = exifOrientationHelper.applyToSize(imageInfo.size)
- return imageInfo.copy(size = correctedImageSize)
-}
-
-/**
- * Read the Exif orientation attribute of the image, if the mimeType is not supported, return [ExifInterface.ORIENTATION_UNDEFINED]
- */
-@Throws(IOException::class)
-fun DataSource.readEncryptedExifOrientationWithMimeType(
- keychainHolder: KeychainHolder,
- mimeType: String
-): Int =
- if (ExifInterface.isSupportedMimeType(mimeType)) {
- readEncryptedExifOrientation(keychainHolder)
- } else {
- ExifInterface.ORIENTATION_UNDEFINED
- }
-
-/**
- * Decode image width, height, MIME type. Parse Exif orientation
- */
-fun DataSource.readEncryptedImageInfo(keychainHolder: KeychainHolder): ImageInfo =
- readEncryptedImageInfo(keychainHolder, null)
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedPanoramaImageLoader.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedPanoramaImageLoader.kt
deleted file mode 100644
index ca45cb2d0b..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedPanoramaImageLoader.kt
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2026 IacobIacob01
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.dot.gallery.core.decoder
-
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.graphics.BitmapRegionDecoder
-import android.graphics.Rect
-import android.os.Build
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.dot.gallery.libs.panoramaviewer.PanoramaImageLoader
-import com.dot.gallery.libs.panoramaviewer.PanoramaLog
-import java.io.File
-
-/**
- * A [PanoramaImageLoader] that decrypts encrypted vault media before decoding.
- *
- * This loader decrypts the `.enc` file using [KeychainHolder] to obtain the raw
- * image bytes, then creates a [BitmapRegionDecoder] from those bytes for
- * progressive region loading — exactly like the default loader, but with a
- * decryption step up front.
- *
- * The decrypted bytes are held in memory for the lifetime of the loader so that
- * [loadBase] and [loadRegion] can create region decoders without re-decrypting.
- * Call [close] to release the decoder and allow the byte array to be GC'd.
- *
- * ## Usage
- *
- * ```kotlin
- * val loader = remember(media) {
- * EncryptedPanoramaImageLoader(keychainHolder, encryptedFile)
- * }
- * PanoramaViewer(
- * imageUri = Uri.EMPTY,
- * projectionType = projectionType,
- * imageLoader = loader,
- * modifier = Modifier.fillMaxSize()
- * )
- * ```
- *
- * @param keychainHolder The keychain used to decrypt the encrypted media file.
- * @param encryptedFile The `.enc` file on disk containing the encrypted image.
- */
-class EncryptedPanoramaImageLoader(
- private val keychainHolder: KeychainHolder,
- private val encryptedFile: File
-) : PanoramaImageLoader {
-
- private var decoder: BitmapRegionDecoder? = null
- private var decryptedBytes: ByteArray? = null
-
- override var imageWidth: Int = 0
- private set
- override var imageHeight: Int = 0
- private set
-
- override fun initialize(): Boolean {
- PanoramaLog.d("EncryptedPanoramaImageLoader.initialize() file=${encryptedFile.name}")
-
- // Decrypt the file to get raw image bytes
- val bytes = try {
- keychainHolder.decryptVaultMedia(encryptedFile).readBytes()
- } catch (e: Exception) {
- PanoramaLog.e("EncryptedPanoramaImageLoader.initialize() decryption failed", e)
- return false
- }
- decryptedBytes = bytes
-
- // Read dimensions
- val opts = BitmapFactory.Options().apply { inJustDecodeBounds = true }
- BitmapFactory.decodeByteArray(bytes, 0, bytes.size, opts)
- imageWidth = opts.outWidth
- imageHeight = opts.outHeight
- PanoramaLog.d("EncryptedPanoramaImageLoader.initialize() size=${imageWidth}x${imageHeight}")
-
- if (imageWidth <= 0 || imageHeight <= 0) {
- PanoramaLog.e("EncryptedPanoramaImageLoader.initialize() invalid dimensions")
- return false
- }
-
- // Create region decoder
- decoder = try {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- BitmapRegionDecoder.newInstance(bytes, 0, bytes.size)
- } else {
- @Suppress("DEPRECATION")
- BitmapRegionDecoder.newInstance(bytes, 0, bytes.size, false)
- }
- } catch (e: Exception) {
- PanoramaLog.e("EncryptedPanoramaImageLoader.initialize() BitmapRegionDecoder failed", e)
- return false
- }
-
- PanoramaLog.d("EncryptedPanoramaImageLoader.initialize() decoder created: ${decoder != null}")
- return decoder != null
- }
-
- override fun loadBase(maxDimension: Int): Bitmap? {
- val d = decoder ?: run {
- // Fallback: decode full image from bytes
- val bytes = decryptedBytes ?: return null
- var sampleSize = 1
- while (imageWidth / sampleSize > maxDimension || imageHeight / sampleSize > maxDimension) {
- sampleSize *= 2
- }
- val opts = BitmapFactory.Options().apply {
- inSampleSize = sampleSize
- inPreferredConfig = Bitmap.Config.ARGB_8888
- }
- return try {
- BitmapFactory.decodeByteArray(bytes, 0, bytes.size, opts)
- } catch (e: Exception) {
- PanoramaLog.e("EncryptedPanoramaImageLoader.loadBase() fallback failed", e)
- null
- }
- }
-
- var sampleSize = 1
- while (imageWidth / sampleSize > maxDimension || imageHeight / sampleSize > maxDimension) {
- sampleSize *= 2
- }
- val opts = BitmapFactory.Options().apply {
- inSampleSize = sampleSize
- inPreferredConfig = Bitmap.Config.ARGB_8888
- }
- return try {
- d.decodeRegion(Rect(0, 0, imageWidth, imageHeight), opts)
- } catch (e: Exception) {
- PanoramaLog.e("EncryptedPanoramaImageLoader.loadBase() decodeRegion failed", e)
- null
- }
- }
-
- override fun loadRegion(
- left: Int,
- top: Int,
- right: Int,
- bottom: Int,
- maxDimension: Int
- ): Bitmap? {
- val d = decoder ?: return null
-
- val clampedLeft = left.coerceIn(0, imageWidth)
- val clampedTop = top.coerceIn(0, imageHeight)
- val clampedRight = right.coerceIn(0, imageWidth)
- val clampedBottom = bottom.coerceIn(0, imageHeight)
-
- if (clampedRight <= clampedLeft || clampedBottom <= clampedTop) return null
-
- val regionW = clampedRight - clampedLeft
- val regionH = clampedBottom - clampedTop
- var sampleSize = 1
- while (regionW / sampleSize > maxDimension || regionH / sampleSize > maxDimension) {
- sampleSize *= 2
- }
-
- val opts = BitmapFactory.Options().apply {
- inSampleSize = sampleSize
- inPreferredConfig = Bitmap.Config.ARGB_8888
- }
- return try {
- d.decodeRegion(Rect(clampedLeft, clampedTop, clampedRight, clampedBottom), opts)
- } catch (e: Exception) {
- PanoramaLog.e("EncryptedPanoramaImageLoader.loadRegion() failed", e)
- null
- }
- }
-
- override fun close() {
- PanoramaLog.d("EncryptedPanoramaImageLoader.close()")
- decoder?.recycle()
- decoder = null
- decryptedBytes = null
- }
-}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRawImageDecoder.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRawImageDecoder.kt
deleted file mode 100644
index 747237fda9..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRawImageDecoder.kt
+++ /dev/null
@@ -1,289 +0,0 @@
-@file:Suppress("DEPRECATION")
-
-package com.dot.gallery.core.decoder
-
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.graphics.ImageDecoder
-import android.graphics.Movie
-import android.graphics.drawable.AnimatedImageDrawable
-import android.os.Build
-import androidx.annotation.RequiresApi
-import com.dot.gallery.BuildConfig
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.github.panpf.sketch.asImage
-import com.github.panpf.sketch.decode.DecodeConfig
-import com.github.panpf.sketch.request.ImageData
-import com.github.panpf.sketch.decode.Decoder
-import com.github.panpf.sketch.decode.ImageInfo
-import com.github.panpf.sketch.drawable.AnimatableDrawable
-import com.github.panpf.sketch.drawable.MovieDrawable
-import com.github.panpf.sketch.drawable.ScaledAnimatableDrawable
-import com.github.panpf.sketch.fetch.FetchResult
-import com.github.panpf.sketch.request.RequestContext
-import com.github.panpf.sketch.request.animatedTransformation
-import com.github.panpf.sketch.request.animationEndCallback
-import com.github.panpf.sketch.request.animationStartCallback
-import com.github.panpf.sketch.request.get
-import com.github.panpf.sketch.request.repeatCount
-import com.github.panpf.sketch.source.DataSource
-import com.github.panpf.sketch.source.FileDataSource
-import com.github.panpf.sketch.util.animatable2CompatCallbackOf
-import com.github.panpf.sketch.util.safeToSoftware
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import java.nio.ByteBuffer
-
-/**
- * Decoder for encrypted raw image formats (GIF, WebP, SVG, BMP).
- *
- * - GIF: Always animated using MovieDrawable
- * - WebP: Animated using AnimatedImageDrawable on API 28+, static fallback otherwise
- * - SVG, BMP: Static bitmap decoding
- *
- * This ensures raw image formats in the vault display properly in full-screen MediaView,
- * preserving animation for GIF and animated WebP files.
- */
-class EncryptedRawImageDecoder(
- private val requestContext: RequestContext,
- private val dataSource: DataSource,
- private val mimeType: String,
-) : Decoder {
-
- private val keychainHolder = KeychainHolder(requestContext.request.context)
-
- private var _imageInfo: ImageInfo? = null
- private var cachedBytes: ByteArray? = null
-
- override suspend fun getImageInfo(): ImageInfo {
- if (_imageInfo == null) {
- _imageInfo = readImageInfo()
- }
- return _imageInfo!!
- }
-
- private fun getDecryptedBytes(): ByteArray {
- if (cachedBytes == null) {
- val encryptedFile = dataSource.getFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- cachedBytes = decrypted.readBytes()
- }
- return cachedBytes!!
- }
-
- private fun readImageInfo(): ImageInfo {
- val bytes = getDecryptedBytes()
- return when (mimeType) {
- "image/gif" -> readGifImageInfo(bytes)
- "image/webp" -> readWebPImageInfo(bytes)
- else -> readBitmapImageInfo(bytes)
- }
- }
-
- private fun readGifImageInfo(bytes: ByteArray): ImageInfo {
- val movie = Movie.decodeByteArray(bytes, 0, bytes.size)
- return if (movie != null) {
- ImageInfo(movie.width(), movie.height(), mimeType)
- } else {
- // Fallback to BitmapFactory
- readBitmapImageInfo(bytes)
- }
- }
-
- private fun readWebPImageInfo(bytes: ByteArray): ImageInfo {
- return readBitmapImageInfo(bytes)
- }
-
- private fun readBitmapImageInfo(bytes: ByteArray): ImageInfo {
- val options = BitmapFactory.Options().apply {
- inJustDecodeBounds = true
- }
- BitmapFactory.decodeByteArray(bytes, 0, bytes.size, options)
- return ImageInfo(options.outWidth, options.outHeight, mimeType)
- }
-
- private fun isAnimatedWebP(bytes: ByteArray): Boolean {
- // WebP header: RIFF....WEBP
- // Check for VP8X chunk with animation flag
- if (bytes.size < 20) return false
-
- // Check RIFF header
- if (bytes[0] != 'R'.code.toByte() ||
- bytes[1] != 'I'.code.toByte() ||
- bytes[2] != 'F'.code.toByte() ||
- bytes[3] != 'F'.code.toByte()) return false
-
- // Check WEBP
- if (bytes[8] != 'W'.code.toByte() ||
- bytes[9] != 'E'.code.toByte() ||
- bytes[10] != 'B'.code.toByte() ||
- bytes[11] != 'P'.code.toByte()) return false
-
- // Check VP8X chunk (extended format that can contain animation)
- if (bytes[12] != 'V'.code.toByte() ||
- bytes[13] != 'P'.code.toByte() ||
- bytes[14] != '8'.code.toByte() ||
- bytes[15] != 'X'.code.toByte()) return false
-
- // Animation flag is bit 1 (0x02) of the flags byte at offset 16
- return (bytes[16].toInt() and 0x02) != 0
- }
-
- override suspend fun decode(): ImageData {
- val bytes = getDecryptedBytes()
-
- return when (mimeType) {
- "image/gif" -> decodeGif(bytes)
- "image/webp" -> decodeWebP(bytes)
- else -> decodeStaticBitmap(bytes)
- }
- }
-
- private suspend fun decodeGif(bytes: ByteArray): ImageData {
- val request = requestContext.request
-
- val movie = Movie.decodeByteArray(bytes, 0, bytes.size)
- ?: throw IllegalStateException("Failed to decode GIF movie")
-
- val decodeConfig = DecodeConfig(request, mimeType, isOpaque = movie.isOpaque)
- val config = decodeConfig.colorType.safeToSoftware()
-
- val movieDrawable = MovieDrawable(movie, config).apply {
- setRepeatCount(request.repeatCount ?: 0)
- setAnimatedTransformation(request.animatedTransformation)
- }
-
- val animatableDrawable = AnimatableDrawable(movieDrawable).apply {
- val onStart = request.animationStartCallback
- val onEnd = request.animationEndCallback
- if (onStart != null || onEnd != null) {
- @Suppress("OPT_IN_USAGE")
- GlobalScope.launch(Dispatchers.Main) {
- registerAnimationCallback(animatable2CompatCallbackOf(onStart, onEnd))
- }
- }
- }
-
- val resize = requestContext.computeResize(getImageInfo().size)
- return ImageData(
- image = animatableDrawable.asImage(),
- imageInfo = getImageInfo(),
- dataFrom = dataSource.dataFrom,
- resize = resize,
- transformeds = null,
- extras = null,
- )
- }
-
- private suspend fun decodeWebP(bytes: ByteArray): ImageData {
- val isAnimated = isAnimatedWebP(bytes)
-
- return if (isAnimated && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- decodeAnimatedWebP(bytes)
- } else {
- decodeStaticBitmap(bytes)
- }
- }
-
- @RequiresApi(Build.VERSION_CODES.P)
- private suspend fun decodeAnimatedWebP(bytes: ByteArray): ImageData {
- val request = requestContext.request
-
- val source = ImageDecoder.createSource(ByteBuffer.wrap(bytes))
- val drawable = ImageDecoder.decodeDrawable(source) { decoder, info, _ ->
- decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
- }
-
- if (drawable is AnimatedImageDrawable) {
- drawable.repeatCount = request.repeatCount
- ?.takeIf { it != 0 }
- ?: AnimatedImageDrawable.REPEAT_INFINITE
-
- val scaledDrawable = ScaledAnimatableDrawable(drawable).apply {
- val onStart = request.animationStartCallback
- val onEnd = request.animationEndCallback
- if (onStart != null || onEnd != null) {
- @Suppress("OPT_IN_USAGE")
- GlobalScope.launch(Dispatchers.Main) {
- registerAnimationCallback(animatable2CompatCallbackOf(onStart, onEnd))
- }
- }
- }
-
- val resize = requestContext.computeResize(getImageInfo().size)
- return ImageData(
- image = scaledDrawable.asImage(),
- imageInfo = getImageInfo(),
- dataFrom = dataSource.dataFrom,
- resize = resize,
- transformeds = null,
- extras = null,
- )
- } else {
- // Not animated, fall back to static decoding
- return decodeStaticBitmap(bytes)
- }
- }
-
- private suspend fun decodeStaticBitmap(bytes: ByteArray): ImageData {
- val request = requestContext.request
- val decodeConfig = DecodeConfig(request, mimeType, isOpaque = false)
- val config = decodeConfig.colorType.safeToSoftware()
-
- val options = BitmapFactory.Options().apply {
- inPreferredConfig = config
- }
-
- val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size, options)
- ?: throw IllegalStateException("Failed to decode bitmap for $mimeType")
-
- val resize = requestContext.computeResize(getImageInfo().size)
- return ImageData(
- image = bitmap.asImage(),
- imageInfo = getImageInfo(),
- dataFrom = dataSource.dataFrom,
- resize = resize,
- transformeds = null,
- extras = null,
- )
- }
-
- class Factory : Decoder.Factory {
-
- override val key: String = "EncryptedRawImageDecoder"
-
- override val sortWeight: Int = 0
-
- private val supportedMimeTypes = listOf(
- "image/gif",
- "image/webp",
- "image/svg+xml",
- "image/bmp"
- )
-
- override fun create(
- requestContext: RequestContext,
- fetchResult: FetchResult
- ): Decoder? {
- val mimeType = requestContext.request.extras?.get("realMimeType") as? String ?: return null
- if (mimeType !in supportedMimeTypes) return null
- val dataSource = fetchResult.dataSource as? FileDataSource ?: return null
- val path = dataSource.getFile().path
- return if (path.toString().contains(BuildConfig.APPLICATION_ID))
- EncryptedRawImageDecoder(requestContext, dataSource, mimeType)
- else null
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- return other != null && this::class == other::class
- }
-
- override fun hashCode(): Int {
- return this::class.hashCode()
- }
-
- override fun toString(): String = "EncryptedRawImageDecoder"
- }
-}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRegionDecoder.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRegionDecoder.kt
deleted file mode 100644
index eccb2f5dd1..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRegionDecoder.kt
+++ /dev/null
@@ -1,139 +0,0 @@
-package com.dot.gallery.core.decoder
-
-import android.graphics.BitmapFactory
-import android.graphics.BitmapRegionDecoder
-import android.graphics.Rect
-import android.os.Build.VERSION
-import android.os.Build.VERSION_CODES
-import androidx.core.net.toFile
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.github.panpf.zoomimage.subsampling.BitmapTileImage
-import com.github.panpf.zoomimage.subsampling.ContentImageSource
-import com.github.panpf.zoomimage.subsampling.ImageInfo
-import com.github.panpf.zoomimage.subsampling.ImageSource
-import com.github.panpf.zoomimage.subsampling.RegionDecoder
-import com.github.panpf.zoomimage.subsampling.SubsamplingImage
-import com.github.panpf.zoomimage.subsampling.TileBitmap
-import com.github.panpf.zoomimage.subsampling.internal.ExifOrientationHelper
-import com.github.panpf.zoomimage.util.IntRectCompat
-
-class EncryptedRegionDecoder(
- override val subsamplingImage: SubsamplingImage,
- val imageSource: ImageSource,
- private val keychainHolder: KeychainHolder,
-) : RegionDecoder {
-
- private var bitmapRegionDecoder: BitmapRegionDecoder? = null
-
- private val exifOrientationHelper: ExifOrientationHelper by lazy {
- val exifOrientation = imageSource.readEncryptedExifOrientation(keychainHolder)
- ExifOrientationHelper(exifOrientation)
- }
-
- override val imageInfo: ImageInfo by lazy { imageSource.readEncryptedImageInfo(keychainHolder) }
-
- override fun close() {
- bitmapRegionDecoder?.recycle()
- }
-
- override fun copy(): RegionDecoder {
- return EncryptedRegionDecoder(
- subsamplingImage = subsamplingImage,
- imageSource = imageSource,
- keychainHolder = keychainHolder
- )
- }
-
- override fun decodeRegion(region: IntRectCompat, sampleSize: Int): TileBitmap {
- prepare()
- val options = BitmapFactory.Options().apply {
- inSampleSize = sampleSize
- }
- val originalRegion = exifOrientationHelper
- .applyToRect(region, imageInfo.size, reverse = true)
- val bitmap = bitmapRegionDecoder!!.decodeRegion(originalRegion.toAndroidRect(), options)
- val tileImage = BitmapTileImage(bitmap)
- val correctedImage = exifOrientationHelper.applyToTileImage(tileImage)
- return correctedImage.bitmap
- }
-
- override fun prepare() {
- if (bitmapRegionDecoder != null) return
-
- val decrypted = keychainHolder.decryptVaultMedia(
- (imageSource as ContentImageSource).uri.toFile()
- )
-
- bitmapRegionDecoder = kotlin.runCatching {
- if (VERSION.SDK_INT >= VERSION_CODES.S) {
- BitmapRegionDecoder.newInstance(decrypted.readBytes(), 0, decrypted.readBytes().size)
- } else {
- @Suppress("DEPRECATION")
- BitmapRegionDecoder.newInstance(decrypted.readBytes(), 0, decrypted.readBytes().size, false)
- }
- }.apply {
- if (isFailure) {
- throw exceptionOrNull()!!
- }
- }.getOrThrow()
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class != other::class) return false
- other as EncryptedRegionDecoder
- if (subsamplingImage != other.subsamplingImage) return false
- if (imageSource != other.imageSource) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = subsamplingImage.hashCode()
- result = 31 * result + imageSource.hashCode()
- return result
- }
-
- override fun toString(): String {
- return "EncryptedRegionDecoder(subsamplingImage=$subsamplingImage, imageSource=$imageSource)"
- }
-
- private fun IntRectCompat.toAndroidRect(): Rect {
- return Rect(left, top, right, bottom)
- }
-
- class Factory(private val keychainHolder: KeychainHolder) : RegionDecoder.Factory {
-
- override suspend fun accept(subsamplingImage: SubsamplingImage): Boolean = true
-
- override fun checkSupport(mimeType: String): Boolean? = when (mimeType) {
- "image/jpeg", "image/png", "image/webp" -> true
- "image/gif", "image/bmp", "image/svg+xml" -> false
- "image/heic", "image/heif" -> true
- "image/avif" -> if (VERSION.SDK_INT <= 34) false else null
- else -> null
- }
-
- override fun create(
- subsamplingImage: SubsamplingImage,
- imageSource: ImageSource,
- ): EncryptedRegionDecoder = EncryptedRegionDecoder(
- subsamplingImage = subsamplingImage,
- imageSource = imageSource,
- keychainHolder = keychainHolder
- )
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- return other != null && this::class == other::class
- }
-
- override fun hashCode(): Int {
- return this::class.hashCode()
- }
-
- override fun toString(): String {
- return "EncryptedRegionDecoder"
- }
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRegionDecoderExt.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRegionDecoderExt.kt
deleted file mode 100644
index 84202d115e..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedRegionDecoderExt.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.dot.gallery.core.decoder
-
-import android.graphics.BitmapFactory
-import androidx.core.net.toFile
-import androidx.exifinterface.media.ExifInterface
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.github.panpf.sketch.decode.ImageInvalidException
-import com.github.panpf.sketch.decode.internal.ExifOrientationHelper
-import com.github.panpf.sketch.util.Size
-import com.github.panpf.zoomimage.subsampling.ContentImageSource
-import com.github.panpf.zoomimage.subsampling.ImageInfo
-import com.github.panpf.zoomimage.subsampling.ImageSource
-import com.github.panpf.zoomimage.util.IntSizeCompat
-import com.github.panpf.zoomimage.util.isEmpty
-import java.io.IOException
-
-@Throws(IOException::class)
-fun ImageSource.readEncryptedExifOrientation(keychainHolder: KeychainHolder): Int {
- return with(this as ContentImageSource) {
- val encryptedFile = uri.toFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- decrypted.readBytes().inputStream().use {
- ExifInterface(it).getAttributeInt(
- ExifInterface.TAG_ORIENTATION,
- ExifInterface.ORIENTATION_UNDEFINED
- )
- }
- }
-}
-
-@Throws(IOException::class)
-fun ImageSource.readEncryptedImageInfoWithIgnoreExifOrientation(keychainHolder: KeychainHolder): ImageInfo {
- with(this as ContentImageSource) {
- val boundOptions = BitmapFactory.Options().apply {
- inJustDecodeBounds = true
- }
- val encryptedFile = uri.toFile()
- val decrypted = keychainHolder.decryptVaultMedia(encryptedFile)
- try {
- BitmapFactory.decodeByteArray(
- decrypted.readBytes(),
- 0,
- decrypted.readBytes().size,
- boundOptions.apply { this.outMimeType = decrypted.mimeType }
- )
- } catch (e: Exception) {
- e.printStackTrace()
- throw ImageInvalidException("decode return null at readEncryptedImageInfoWithIgnoreExifOrientation")
- }
-
- val mimeType = decrypted.mimeType
- val imageSize = IntSizeCompat(width = boundOptions.outWidth, height = boundOptions.outHeight)
- return ImageInfo(size = imageSize, mimeType = mimeType)
- .apply { checkImageInfo(this) }
- }
-}
-
-/**
- * Check if the image is valid
- */
-fun checkImageSize(imageSize: IntSizeCompat) {
- if (imageSize.isEmpty()) {
- throw ImageInvalidException("Invalid image size. size=$imageSize")
- }
-}
-
-/**
- * Check if the image is valid
- */
-fun checkImageInfo(imageInfo: ImageInfo) {
- checkImageSize(imageInfo.size)
-}
-
- /**
- * Read image information using BitmapFactory. Parse Exif orientation
- */
-fun ImageSource.readEncryptedImageInfo(keychainHolder: KeychainHolder, helper: ExifOrientationHelper?): ImageInfo {
- val imageInfo = readEncryptedImageInfoWithIgnoreExifOrientation(keychainHolder)
- val exifOrientationHelper = if (helper != null) {
- helper
- } else {
- val exifOrientation = readEncryptedExifOrientationWithMimeType(keychainHolder, imageInfo.mimeType)
- ExifOrientationHelper(exifOrientation)
- }
- val correctedImageSize = exifOrientationHelper.applyToSize(Size(width = imageInfo.size.width, height = imageInfo.size.height))
- return imageInfo.copy(size = correctedImageSize.toIntSizedCompat())
-}
- fun Size.toIntSizedCompat() = IntSizeCompat(width = width, height = height)
-
-/**
- * Read the Exif orientation attribute of the image, if the mimeType is not supported, return [ExifInterface.ORIENTATION_UNDEFINED]
- */
-@Throws(IOException::class)
-fun ImageSource.readEncryptedExifOrientationWithMimeType(keychainHolder: KeychainHolder, mimeType: String): Int =
- if (ExifInterface.isSupportedMimeType(mimeType)) {
- readEncryptedExifOrientation(keychainHolder)
- } else {
- ExifInterface.ORIENTATION_UNDEFINED
- }
-
-/**
- * Decode image width, height, MIME type. Parse Exif orientation
- */
-fun ImageSource.readEncryptedImageInfo(keychainHolder: KeychainHolder): ImageInfo = readEncryptedImageInfo(keychainHolder,null)
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedVideoFrameDecoder.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedVideoFrameDecoder.kt
deleted file mode 100644
index d5c0b598e5..0000000000
--- a/app/src/main/kotlin/com/dot/gallery/core/decoder/EncryptedVideoFrameDecoder.kt
+++ /dev/null
@@ -1,215 +0,0 @@
-package com.dot.gallery.core.decoder
-
-import android.media.MediaMetadataRetriever
-import android.media.MediaMetadataRetriever.BitmapParams
-import androidx.exifinterface.media.ExifInterface
-import com.dot.gallery.feature_node.data.data_source.KeychainHolder
-import com.github.panpf.sketch.Image
-import com.github.panpf.sketch.Sketch
-import com.github.panpf.sketch.asImage
-import com.github.panpf.sketch.decode.DecodeConfig
-import com.github.panpf.sketch.decode.DecodeException
-import com.github.panpf.sketch.decode.Decoder
-import com.github.panpf.sketch.decode.ImageInfo
-import com.github.panpf.sketch.decode.internal.DecodeHelper
-import com.github.panpf.sketch.decode.internal.ExifOrientationHelper
-import com.github.panpf.sketch.decode.internal.HelperDecoder
-import com.github.panpf.sketch.decode.internal.checkImageInfo
-import com.github.panpf.sketch.fetch.FetchResult
-import com.github.panpf.sketch.request.ImageRequest
-import com.github.panpf.sketch.request.RequestContext
-import com.github.panpf.sketch.request.get
-import com.github.panpf.sketch.request.videoFrameMicros
-import com.github.panpf.sketch.request.videoFrameOption
-import com.github.panpf.sketch.request.videoFramePercent
-import com.github.panpf.sketch.source.ContentDataSource
-import com.github.panpf.sketch.source.DataSource
-import com.github.panpf.sketch.source.FileDataSource
-import com.github.panpf.sketch.source.getFileOrNull
-import com.github.panpf.sketch.util.Rect
-import com.github.panpf.sketch.util.Size
-import com.github.panpf.sketch.util.div
-import java.io.File
-import java.io.FileOutputStream
-
-class EncryptedVideoFrameDecoder(
- private val requestContext: RequestContext,
- private val dataSource: DataSource,
- private val mimeType: String,
-) : HelperDecoder(
- requestContext = requestContext,
- dataSource = dataSource,
- decodeHelperFactory = {
- EncryptedVideoFrameDecodeHelper(
- sketch = requestContext.sketch,
- request = requestContext.request,
- dataSource = dataSource,
- mimeType = mimeType
- )
- }
-) {
-
- class Factory : Decoder.Factory {
-
- override val key: String = "EncryptedVideoFrameDecoder"
-
- override val sortWeight: Int = 0
-
- override fun create(
- requestContext: RequestContext,
- fetchResult: FetchResult
- ): EncryptedVideoFrameDecoder? {
- val mimeType = requestContext.request.extras?.get("realMimeType") as String? ?: return null
- val dataSource = fetchResult.dataSource as? FileDataSource ?: return null
- if (mimeType.startsWith("video")) {
- return EncryptedVideoFrameDecoder(
- requestContext = requestContext,
- dataSource = dataSource,
- mimeType = mimeType
- )
- }
- return null
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- return other != null && this::class == other::class
- }
-
- override fun hashCode(): Int {
- return this::class.hashCode()
- }
-
- override fun toString(): String = "EncryptedVideoFrameDecoder"
- }
-}
-
-private class EncryptedVideoFrameDecodeHelper(
- val sketch: Sketch,
- val request: ImageRequest,
- val dataSource: DataSource,
- private val mimeType: String,
-) : DecodeHelper {
-
- private var _cachedImageInfo: ImageInfo? = null
-
- override suspend fun getImageInfo(): ImageInfo {
- return _cachedImageInfo ?: readInfo().also { _cachedImageInfo = it }
- }
-
- override suspend fun isSupportRegion(): Boolean = false
-
- private val keychainHolder = KeychainHolder(request.context)
- private val tempFile by lazy {
- dataSource.getFileOrNull(sketch)?.toFile()?.let { createDecryptedVideoFile(it) }
- }
- private val mediaMetadataRetriever by lazy {
- MediaMetadataRetriever().apply {
- if (dataSource is ContentDataSource) {
- setDataSource(request.context, dataSource.contentUri)
- } else {
- tempFile?.let {
- setDataSource(it.path)
- } ?: throw Exception("Unsupported DataSource: ${dataSource::class}")
- }
- }
- }
- private val exifOrientation: Int by lazy { readExifOrientation() }
- private val exifOrientationHelper by lazy { ExifOrientationHelper(exifOrientation) }
-
- private fun createDecryptedVideoFile(file: File): File {
- // Create a temporary file
- val tempFile = File.createTempFile("${file.name}.temp", null)
- val decrypted = keychainHolder.decryptVaultMedia(file)
-
- // Write decrypted content to the temporary file (streaming for large files)
- decrypted.openStream().use { input ->
- FileOutputStream(tempFile).use { output ->
- input.copyTo(output)
- }
- }
-
- return tempFile
- }
-
- override suspend fun decode(sampleSize: Int): Image {
- val frameMicros = request.videoFrameMicros
- ?: request.videoFramePercent?.let { percentDuration ->
- val duration = mediaMetadataRetriever
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
- ?.toLongOrNull() ?: 0L
- (duration * percentDuration * 1000).toLong()
- }
- ?: 0L
- val option = request.videoFrameOption ?: MediaMetadataRetriever.OPTION_CLOSEST_SYNC
- val imageSize = getImageInfo().size
- val dstSize = imageSize / sampleSize.toFloat()
- val config = DecodeConfig(request, getImageInfo().mimeType, isOpaque = false)
- val bitmapParams = BitmapParams().apply {
- config.colorType?.also { preferredConfig = it }
- }
- val bitmap = mediaMetadataRetriever.getScaledFrameAtTime(
- /* timeUs = */ frameMicros,
- /* option = */ option,
- /* dstWidth = */ dstSize.width,
- /* dstHeight = */ dstSize.height,
- /* params = */ bitmapParams
- ) ?: throw DecodeException(
- "Failed to getScaledFrameAtTime. " +
- "frameMicros=$frameMicros, " +
- "option=${optionToName(option)}, " +
- "dstSize=$dstSize, " +
- "imageSize=$imageSize, " +
- "preferredConfig=${config.colorType}"
- )
- val correctedBitmap = exifOrientationHelper.applyToBitmap(bitmap) ?: bitmap
- return correctedBitmap.asImage()
- }
-
- override suspend fun decodeRegion(region: Rect, sampleSize: Int): Image {
- throw UnsupportedOperationException("Unsupported region decode")
- }
-
- private fun readInfo(): ImageInfo {
- val srcWidth = mediaMetadataRetriever
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
- val srcHeight = mediaMetadataRetriever
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0
- val imageSize = Size(width = srcWidth, height = srcHeight)
- val correctedImageSize = exifOrientationHelper.applyToSize(imageSize)
- return ImageInfo(size = correctedImageSize, mimeType = mimeType)
- .apply { checkImageInfo(this) }
- }
-
- private fun readExifOrientation(): Int {
- val videoRotation = mediaMetadataRetriever
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)
- ?.toIntOrNull() ?: 0
- val exifOrientation = when (videoRotation) {
- 90 -> ExifInterface.ORIENTATION_ROTATE_90
- 180 -> ExifInterface.ORIENTATION_ROTATE_180
- 270 -> ExifInterface.ORIENTATION_ROTATE_270
- else -> ExifInterface.ORIENTATION_UNDEFINED
- }
- return exifOrientation
- }
-
- private fun optionToName(option: Int): String {
- return when (option) {
- MediaMetadataRetriever.OPTION_CLOSEST -> "CLOSEST"
- MediaMetadataRetriever.OPTION_CLOSEST_SYNC -> "CLOSEST_SYNC"
- MediaMetadataRetriever.OPTION_NEXT_SYNC -> "NEXT_SYNC"
- MediaMetadataRetriever.OPTION_PREVIOUS_SYNC -> "PREVIOUS_SYNC"
- else -> "Unknown($option)"
- }
- }
-
- override fun toString(): String {
- return "VideoFrameDecodeHelper(uri='${request.uri}', dataSource=$dataSource, mimeType=$mimeType)"
- }
-
- override fun close() {
- mediaMetadataRetriever.close()
- tempFile?.delete()
- }
-}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/ImageFileFormat.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/ImageFileFormat.kt
new file mode 100644
index 0000000000..69a2d15917
--- /dev/null
+++ b/app/src/main/kotlin/com/dot/gallery/core/decoder/ImageFileFormat.kt
@@ -0,0 +1,17 @@
+package com.dot.gallery.core.decoder
+
+internal enum class ImageFileFormat(
+ val sandboxMimeType: String? = null,
+) {
+ ANIMATED_WEBP,
+ AVIF(sandboxMimeType = "image/avif"),
+ BMP,
+ GIF,
+ HEIF(sandboxMimeType = "image/heif"),
+ JPEG,
+ JXL(sandboxMimeType = "image/jxl"),
+ PNG,
+ SVG,
+ TIFF,
+ WEBP;
+}
diff --git a/app/src/main/kotlin/com/dot/gallery/core/decoder/ImageHeaderClassifier.kt b/app/src/main/kotlin/com/dot/gallery/core/decoder/ImageHeaderClassifier.kt
new file mode 100644
index 0000000000..5ba1068b54
--- /dev/null
+++ b/app/src/main/kotlin/com/dot/gallery/core/decoder/ImageHeaderClassifier.kt
@@ -0,0 +1,244 @@
+package com.dot.gallery.core.decoder
+
+internal const val IMAGE_HEADER_BYTES = 4 * 1024
+
+internal fun classifyImageHeader(header: ByteArray, length: Int): ImageFileFormat? {
+ val availableBytes = length.coerceIn(minimumValue = 0, maximumValue = header.size)
+ return when {
+ isJxlCodestream(header = header, length = availableBytes) -> ImageFileFormat.JXL
+ isJxlContainer(header = header, length = availableBytes) -> ImageFileFormat.JXL
+ isJpeg(header = header, length = availableBytes) -> ImageFileFormat.JPEG
+ isPng(header = header, length = availableBytes) -> ImageFileFormat.PNG
+ isGif(header = header, length = availableBytes) -> ImageFileFormat.GIF
+ isAnimatedWebp(header = header, length = availableBytes) -> ImageFileFormat.ANIMATED_WEBP
+ isWebp(header = header, length = availableBytes) -> ImageFileFormat.WEBP
+ isBmp(header = header, length = availableBytes) -> ImageFileFormat.BMP
+ isTiff(header = header, length = availableBytes) -> ImageFileFormat.TIFF
+ isSvg(header = header, length = availableBytes) -> ImageFileFormat.SVG
+ else -> classifyIsoBaseMediaFormat(header = header, length = availableBytes)
+ }
+}
+
+private fun isJxlCodestream(header: ByteArray, length: Int): Boolean {
+ return length >= 2 && header[0] == 0xFF.toByte() && header[1] == 0x0A.toByte()
+}
+
+private fun isJxlContainer(header: ByteArray, length: Int): Boolean {
+ return matchesBytes(
+ header = header,
+ length = length,
+ offset = 0,
+ expected = byteArrayOf(
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x0C,
+ 0x4A,
+ 0x58,
+ 0x4C,
+ 0x20,
+ 0x0D,
+ 0x0A,
+ 0x87.toByte(),
+ 0x0A,
+ ),
+ )
+}
+
+private fun isJpeg(header: ByteArray, length: Int): Boolean {
+ return matchesBytes(
+ header = header,
+ length = length,
+ offset = 0,
+ expected = byteArrayOf(0xFF.toByte(), 0xD8.toByte(), 0xFF.toByte()),
+ )
+}
+
+private fun isPng(header: ByteArray, length: Int): Boolean {
+ return matchesBytes(
+ header = header,
+ length = length,
+ offset = 0,
+ expected = byteArrayOf(
+ 0x89.toByte(),
+ 0x50,
+ 0x4E,
+ 0x47,
+ 0x0D,
+ 0x0A,
+ 0x1A,
+ 0x0A,
+ ),
+ )
+}
+
+private fun isGif(header: ByteArray, length: Int): Boolean {
+ return matchesAscii(header = header, length = length, offset = 0, expected = "GIF87a") ||
+ matchesAscii(header = header, length = length, offset = 0, expected = "GIF89a")
+}
+
+private fun isWebp(header: ByteArray, length: Int): Boolean {
+ return matchesAscii(header = header, length = length, offset = 0, expected = "RIFF") &&
+ matchesAscii(header = header, length = length, offset = 8, expected = "WEBP")
+}
+
+private fun isAnimatedWebp(header: ByteArray, length: Int): Boolean {
+ return isWebp(header = header, length = length) &&
+ matchesAscii(header = header, length = length, offset = 12, expected = "VP8X") &&
+ length > WEBP_EXTENDED_FLAGS_OFFSET &&
+ header[WEBP_EXTENDED_FLAGS_OFFSET].toInt() and WEBP_ANIMATION_FLAG != 0
+}
+
+private fun isBmp(header: ByteArray, length: Int): Boolean {
+ return matchesAscii(header = header, length = length, offset = 0, expected = "BM")
+}
+
+private fun isTiff(header: ByteArray, length: Int): Boolean {
+ val littleEndian = byteArrayOf(0x49, 0x49, 0x2A, 0x00)
+ val bigEndian = byteArrayOf(0x4D, 0x4D, 0x00, 0x2A)
+ return matchesBytes(
+ header = header,
+ length = length,
+ offset = 0,
+ expected = littleEndian,
+ ) || matchesBytes(
+ header = header,
+ length = length,
+ offset = 0,
+ expected = bigEndian,
+ )
+}
+
+private fun isSvg(header: ByteArray, length: Int): Boolean {
+ val searchLimit = minOf(length, SVG_SEARCH_BYTES)
+ if (searchLimit == 0) {
+ return false
+ }
+
+ val headerText = header.decodeToString(
+ startIndex = 0,
+ endIndex = searchLimit,
+ throwOnInvalidSequence = false,
+ )
+ return SVG_TAG_REGEX.containsMatchIn(input = headerText)
+}
+
+private fun classifyIsoBaseMediaFormat(header: ByteArray, length: Int): ImageFileFormat? {
+ var offset = 0
+ while (offset + ISO_BOX_HEADER_BYTES <= length) {
+ val boxSize = readUnsignedInt(header = header, offset = offset)
+ if (boxSize < ISO_BOX_HEADER_BYTES.toLong() || boxSize > Int.MAX_VALUE.toLong()) {
+ return null
+ }
+
+ val boxEnd = offset + boxSize.toInt()
+ if (boxEnd > length) {
+ return null
+ }
+
+ if (
+ boxSize >= MINIMUM_FTYP_BOX_BYTES &&
+ matchesAscii(header = header, length = length, offset = offset + 4, expected = "ftyp")
+ ) {
+ return classifyFtypBox(
+ header = header,
+ boxStart = offset,
+ boxEnd = boxEnd,
+ )
+ }
+ offset = boxEnd
+ }
+ return null
+}
+
+private fun classifyFtypBox(header: ByteArray, boxStart: Int, boxEnd: Int): ImageFileFormat? {
+ val brandsStart = boxStart + ISO_BOX_HEADER_BYTES
+ if (brandsStart + BRAND_BYTES > boxEnd) {
+ return null
+ }
+
+ val primaryBrand = classifyBrand(header = header, offset = brandsStart)
+ var hasHeifBrand = primaryBrand == ImageFileFormat.HEIF
+ if (primaryBrand == ImageFileFormat.AVIF) {
+ return ImageFileFormat.AVIF
+ }
+
+ var brandOffset = brandsStart + MAJOR_BRAND_AND_MINOR_VERSION_BYTES
+ while (brandOffset + BRAND_BYTES <= boxEnd) {
+ when (classifyBrand(header = header, offset = brandOffset)) {
+ ImageFileFormat.AVIF -> return ImageFileFormat.AVIF
+ ImageFileFormat.HEIF -> hasHeifBrand = true
+ else -> Unit
+ }
+ brandOffset += BRAND_BYTES
+ }
+ return ImageFileFormat.HEIF.takeIf { hasHeifBrand }
+}
+
+private fun classifyBrand(header: ByteArray, offset: Int): ImageFileFormat? {
+ val brand = String(header, offset, BRAND_BYTES, Charsets.ISO_8859_1)
+ return when (brand) {
+ "avif", "avis" -> ImageFileFormat.AVIF
+ in HEIF_BRANDS -> ImageFileFormat.HEIF
+ else -> null
+ }
+}
+
+private fun matchesAscii(
+ header: ByteArray,
+ length: Int,
+ offset: Int,
+ expected: String,
+): Boolean {
+ return matchesBytes(
+ header = header,
+ length = length,
+ offset = offset,
+ expected = expected.toByteArray(Charsets.ISO_8859_1),
+ )
+}
+
+private fun matchesBytes(
+ header: ByteArray,
+ length: Int,
+ offset: Int,
+ expected: ByteArray,
+): Boolean {
+ if (offset < 0 || offset + expected.size > length) {
+ return false
+ }
+ return expected.indices.all { index ->
+ header[offset + index] == expected[index]
+ }
+}
+
+private fun readUnsignedInt(header: ByteArray, offset: Int): Long {
+ return ((header[offset].toLong() and 0xFFL) shl 24) or
+ ((header[offset + 1].toLong() and 0xFFL) shl 16) or
+ ((header[offset + 2].toLong() and 0xFFL) shl 8) or
+ (header[offset + 3].toLong() and 0xFFL)
+}
+
+private const val BRAND_BYTES = 4
+private const val ISO_BOX_HEADER_BYTES = 8
+private const val MAJOR_BRAND_AND_MINOR_VERSION_BYTES = 8
+private const val MINIMUM_FTYP_BOX_BYTES = 16L
+private const val WEBP_ANIMATION_FLAG = 1 shl 1
+private const val WEBP_EXTENDED_FLAGS_OFFSET = 20
+private const val SVG_SEARCH_BYTES = 1024
+
+private val SVG_TAG_REGEX = Regex(pattern = "