diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 352eefa8a..0afb0ac05 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -9,6 +9,7 @@ plugins {
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp)
alias(libs.plugins.imgly).apply(false)
+ alias(libs.plugins.kotlin.serialization)
}
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
@@ -128,6 +129,10 @@ dependencies {
implementation(libs.bundles.room)
ksp(libs.androidx.room.compiler)
+
+ implementation(platform(libs.supabase.bom))
+ implementation(libs.supabase.postgrest)
+ implementation(libs.ktor.client.android)
}
// Apply the PESDKPlugin
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 698161e19..813ab6a49 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,8 @@
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
+
+
diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/App.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/App.kt
index ef2768318..1b2ad213f 100644
--- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/App.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/App.kt
@@ -6,6 +6,14 @@ import com.simplemobiletools.commons.extensions.checkUseEnglish
import com.squareup.picasso.Downloader
import com.squareup.picasso.Picasso
import okhttp3.Request
+import com.simplemobiletools.gallery.pro.extensions.favoritesDB
+import com.simplemobiletools.gallery.pro.helpers.supabase
+import com.simplemobiletools.gallery.pro.models.Favorite
+import io.github.jan.supabase.postgrest.postgrest
+import kotlinx.coroutines.CoroutineScope
+import android.util.Log
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
import okhttp3.Response
class App : Application() {
@@ -18,5 +26,17 @@ class App : Application() {
override fun shutdown() {}
}).build())
+
+ // Fetches favorites from Supabase on startup.
+ // This is a simple one-way sync that overwrites the local database.
+ // A more robust two-way sync would be needed for a production environment.
+ CoroutineScope(Dispatchers.IO).launch {
+ try {
+ val favorites = supabase.postgrest["favorites"].select().decodeList()
+ favoritesDB.insertAll(favorites)
+ } catch (e: Exception) {
+ Log.e("Supabase", "Error fetching favorites", e)
+ }
+ }
}
}
diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt
index 2ef92ecfc..85b1e4fcf 100644
--- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt
@@ -47,6 +47,12 @@ import java.io.File
import java.io.FileInputStream
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
+import android.util.Log
+import com.simplemobiletools.gallery.pro.helpers.supabase
+import io.github.jan.supabase.postgrest.postgrest
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
import kotlin.collections.set
import kotlin.math.max
@@ -838,16 +844,28 @@ fun Context.getFavoritePaths(): ArrayList {
}
}
-fun Context.getFavoriteFromPath(path: String) = Favorite(null, path, path.getFilenameFromPath(), path.getParentPath())
+fun Context.getFavoriteFromPath(path: String) = Favorite(id = null, fullPath = path, filename = path.getFilenameFromPath(), parentPath = path.getParentPath())
fun Context.updateFavorite(path: String, isFavorite: Boolean) {
try {
if (isFavorite) {
- favoritesDB.insert(getFavoriteFromPath(path))
+ val favorite = getFavoriteFromPath(path)
+ favoritesDB.insert(favorite)
+ CoroutineScope(Dispatchers.IO).launch {
+ supabase.postgrest["favorites"].upsert(favorite, onConflict = "full_path")
+ }
} else {
favoritesDB.deleteFavoritePath(path)
+ CoroutineScope(Dispatchers.IO).launch {
+ supabase.postgrest["favorites"].delete {
+ filter {
+ eq("full_path", path)
+ }
+ }
+ }
}
} catch (e: Exception) {
+ Log.e("Supabase", "Error updating favorite", e)
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}
diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Supabase.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Supabase.kt
new file mode 100644
index 000000000..80969293b
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Supabase.kt
@@ -0,0 +1,11 @@
+package com.simplemobiletools.gallery.pro.helpers
+
+import io.github.jan.supabase.createSupabaseClient
+import io.github.jan.supabase.postgrest.Postgrest
+
+val supabase = createSupabaseClient(
+ supabaseUrl = "https://your-project-url.supabase.co",
+ supabaseKey = "your-anon-key"
+) {
+ install(Postgrest)
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Favorite.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Favorite.kt
index a1bd56ac3..7682a445e 100644
--- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Favorite.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Favorite.kt
@@ -4,11 +4,14 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+@Serializable
@Entity(tableName = "favorites", indices = [Index(value = ["full_path"], unique = true)])
data class Favorite(
- @PrimaryKey(autoGenerate = true) var id: Int?,
- @ColumnInfo(name = "full_path") var fullPath: String,
+ @PrimaryKey(autoGenerate = true) var id: Long?,
+ @ColumnInfo(name = "full_path") @SerialName("full_path") var fullPath: String,
@ColumnInfo(name = "filename") var filename: String,
- @ColumnInfo(name = "parent_path") var parentPath: String
-)
+ @ColumnInfo(name = "parent_path") @SerialName("parent_path") var parentPath: String
+)
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a2c137ee6..38556b5f2 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -5,6 +5,7 @@ imgly = "10.7.3"
kotlin = "1.8.22"
#KSP
ksp = "1.8.22-1.0.11"
+kotlin-serialization = "1.8.22"
#AndroidX
androidx-swiperefreshlayout = "1.1.0"
androidx-constraintlayout = "2.1.4"
@@ -44,6 +45,9 @@ app-version-appId = "com.simplemobiletools.gallery.pro"
app-version-versionCode = "396"
app-version-versionName = "6.28.1"
subsamplingScaleImageView = "80efdaa570"
+supabase = "3.2.4"
+ktor = "3.3.0"
+
[libraries]
#AndroidX
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3Exoplayer" }
@@ -74,6 +78,9 @@ awebp = { module = "com.github.penfeizhou.android.animation:awebp", version.ref
glide-compiler = { module = "com.github.bumptech.glide:ksp", version.ref = "glideCompiler" }
zjupure-webpdecoder = { module = "com.github.zjupure:webpdecoder", version.ref = "zjupureWebpdecoder" }
picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" }
+supabase-bom = { group = "io.github.jan-tennert.supabase", name = "bom", version.ref = "supabase" }
+supabase-postgrest = { group = "io.github.jan-tennert.supabase", name = "postgrest-kt" }
+ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktor" }
[bundles]
room = [
"androidx-room-ktx",
@@ -84,3 +91,4 @@ android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
imgly = { id = "ly.img.android.sdk", version.ref = "imgly" }
+kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin-serialization" }