Skip to content

Commit

Permalink
Merge pull request #423 from supabase-community/2.1.0
Browse files Browse the repository at this point in the history
Release 2.1.0
  • Loading branch information
jan-tennert authored Jan 30, 2024
2 parents 705dba2 + b186d15 commit 6cf1fdc
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.lifecycle.ProcessLifecycleOwner
import androidx.startup.Initializer
import co.touchlab.kermit.Logger
import io.github.jan.supabase.annotations.SupabaseInternal
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

private var appContext: Context? = null
Expand All @@ -30,33 +31,35 @@ private fun addLifecycleCallbacks(gotrue: Auth) {
val lifecycle = ProcessLifecycleOwner.get().lifecycle
gotrue as AuthImpl
val scope = gotrue.authScope
lifecycle.addObserver(
object : DefaultLifecycleObserver {
scope.launch(Dispatchers.Main) {
lifecycle.addObserver(
object : DefaultLifecycleObserver {

override fun onStart(owner: LifecycleOwner) {
if(!gotrue.isAutoRefreshRunning && gotrue.config.alwaysAutoRefresh) {
Logger.d("Auth") {
"Starting auto refresh"
}
scope.launch {
try {
gotrue.startAutoRefreshForCurrentSession()
} catch(e: IllegalStateException) {
Logger.d("Auth") {
"No session found for auto refresh"
override fun onStart(owner: LifecycleOwner) {
if(!gotrue.isAutoRefreshRunning && gotrue.config.alwaysAutoRefresh) {
Logger.d("Auth") {
"Starting auto refresh"
}
scope.launch {
try {
gotrue.startAutoRefreshForCurrentSession()
} catch(e: IllegalStateException) {
Logger.d("Auth") {
"No session found for auto refresh"
}
}
}
}
}
}
override fun onStop(owner: LifecycleOwner) {
if(gotrue.isAutoRefreshRunning) {
Logger.d("Auth") { "Cancelling auto refresh because app is switching to the background" }
scope.launch {
gotrue.stopAutoRefreshForCurrentSession()
override fun onStop(owner: LifecycleOwner) {
if(gotrue.isAutoRefreshRunning) {
Logger.d("Auth") { "Cancelling auto refresh because app is switching to the background" }
scope.launch {
gotrue.stopAutoRefreshForCurrentSession()
}
}
}
}
}
)
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ package io.github.jan.supabase.postgrest.query.filter
/**
* Represents a filter operation for a column using a specific operator and a value.
*/
data class FilterOperation(val column: String, val operator: FilterOperator, val value: String)
data class FilterOperation(val column: String, val operator: FilterOperator, val value: Any)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import kotlin.reflect.KProperty1
@PostgrestFilterDSL
class PostgrestFilterBuilder(
@PublishedApi internal val propertyConversionMethod: PropertyConversionMethod,
@PublishedApi internal val _params: MutableMap<String, List<String>> = mutableMapOf()
@PublishedApi internal val _params: MutableMap<String, List<String>> = mutableMapOf(),
val isInLogicalExpression: Boolean = false
) {

val params: Map<String, List<String>>
Expand Down Expand Up @@ -186,7 +187,7 @@ class PostgrestFilterBuilder(
@PostgrestFilterDSL
inline fun or(negate: Boolean = false, filter: @PostgrestFilterDSL PostgrestFilterBuilder.() -> Unit) {
val prefix = if(negate) "not." else ""
_params[prefix + "or"] = listOf(formatJoiningFilter(filter))
_params[prefix + "or"] = listOf(formatJoiningFilter(filter)) + if(isInLogicalExpression) _params[prefix + "and"] ?: emptyList() else emptyList()
}

/**
Expand All @@ -195,7 +196,7 @@ class PostgrestFilterBuilder(
@PostgrestFilterDSL
inline fun and(negate: Boolean = false, filter: @PostgrestFilterDSL PostgrestFilterBuilder.() -> Unit) {
val prefix = if (negate) "not." else ""
_params[prefix + "and"] = listOf(formatJoiningFilter(filter))
_params[prefix + "and"] = listOf(formatJoiningFilter(filter)) + if(isInLogicalExpression) _params[prefix + "and"] ?: emptyList() else emptyList()
}

/**
Expand Down Expand Up @@ -361,7 +362,7 @@ class PostgrestFilterBuilder(
}

@PublishedApi internal inline fun PostgrestFilterBuilder.formatJoiningFilter(filter: PostgrestFilterBuilder.() -> Unit): String {
val params = PostgrestFilterBuilder(propertyConversionMethod).apply(filter).params
val params = PostgrestFilterBuilder(propertyConversionMethod, isInLogicalExpression = true).apply(filter).params
val formattedFilter = params.toList().joinToString(",") {
it.second.joinToString(",") { filter ->
val isLogicalOperator = filter.startsWith("(") && filter.endsWith(")")
Expand Down
1 change: 1 addition & 0 deletions Realtime/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ kotlin {
val commonMain by getting {
dependencies {
api(project(":gotrue-kt"))
api(project(":postgrest-kt"))
api(libs.ktor.client.websockets)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package io.github.jan.supabase.realtime

import io.github.jan.supabase.annotations.SupabaseInternal
import io.github.jan.supabase.postgrest.query.filter.FilterOperation
import io.github.jan.supabase.postgrest.query.filter.FilterOperator

/**
* Used to filter postgres changes
*/
@Suppress("DEPRECATION")
class PostgresChangeFilter(private val event: String, private val schema: String) {

/**
Expand All @@ -17,6 +20,36 @@ class PostgresChangeFilter(private val event: String, private val schema: String
* E.g.: "user_id=eq.1"
*/
var filter: String? = null
@Deprecated("Use the new `filter` method instead") set

/**
* Filters the received changes in your table.
* @param filter The filter operation. Note that only some operators are supported. See [Postgres Changes](https://supabase.com/docs/guides/realtime/postgres-changes?language=kotlin#available-filters) for more information.
*/
fun filter(filter: FilterOperation) {
val filterValue = when(filter.operator) {
FilterOperator.EQ, FilterOperator.NEQ, FilterOperator.GT, FilterOperator.GTE, FilterOperator.LT, FilterOperator.LTE -> filter.value.toString()
FilterOperator.IN -> {
if(filter.value is List<*>) {
(filter.value as List<*>).joinToString(",", prefix = "(", postfix = ")") { it.toString() }
} else {
filter.value.toString()
}
}
else -> throw UnsupportedOperationException("Unsupported filter operator: ${filter.operator}")
}
this.filter = "${filter.column}=${filter.operator.name.lowercase()}.$filterValue"
}

/**
* Filters the received changes in your table.
* @param column The column name
* @param operator The filter operator. Note that only some operators are supported. See [Postgres Changes](https://supabase.com/docs/guides/realtime/postgres-changes?language=kotlin#available-filters) for more information.
* @param value The value to filter for. This can be context dependent. E.g. for the `IN` operator this can be a list of values, however you can also provide a String.
*/
fun filter(column: String, operator: FilterOperator, value: Any) {
filter(FilterOperation(column, operator, value))
}

@SupabaseInternal
fun buildConfig() = PostgresJoinConfig(schema, table, filter, event)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ sealed interface Realtime : MainPlugin<Realtime.Config>, CustomSerializationPlug
* @property reconnectDelay The delay between reconnect attempts. Defaults to 7 seconds
* @property heartbeatInterval The interval between heartbeat messages. Defaults to 15 seconds
* @property connectOnSubscribe Whether to connect to the websocket when subscribing to a channel. Defaults to true
* @property disconnectOnNoSubscriptions Whether to disconnect from the websocket when there are no more subscriptions. Defaults to true
* @property serializer A serializer used for serializing/deserializing objects e.g. in [PresenceAction.decodeJoinsAs] or [RealtimeChannel.broadcast]. Defaults to [KotlinXSerializer]
*/
data class Config(
Expand All @@ -104,6 +105,7 @@ sealed interface Realtime : MainPlugin<Realtime.Config>, CustomSerializationPlug
override var jwtToken: String? = null,
var disconnectOnSessionLoss: Boolean = true,
var connectOnSubscribe: Boolean = true,
var disconnectOnNoSubscriptions: Boolean = true,
): MainConfig, CustomSerializationConfig {

override var serializer: SupabaseSerializer? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fun RealtimeChannel.presenceChangeFlow(): Flow<PresenceAction> {
}

/**
* You can listen for postgres changes in a channel.
* Listen for postgres changes in a channel.
*
* Example:
* ```kotlin
Expand All @@ -136,6 +136,8 @@ fun RealtimeChannel.presenceChangeFlow(): Flow<PresenceAction> {
* }.map { it.decodeRecord<Product>() }
* ```
*
* If you just want to check for changes and also retrieve initial values, you can use the [postgresListDataFlow] or [postgresSingleDataFlow] functions.
*
* @param T The event type you want to listen to (e.g. [PostgresAction.Update] for updates or only [PostgresAction] for all)
* @param schema The schema name of the table that is being monitored. For normal supabase tables that might be "public".
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.github.jan.supabase.realtime.annotations.ChannelDsl
@ChannelDsl
class RealtimeChannelBuilder @PublishedApi internal constructor(private val topic: String, private val realtimeImpl: RealtimeImpl) {

private var broadcastJoinConfig = BroadcastJoinConfig(false, false)
private var broadcastJoinConfig = BroadcastJoinConfig(acknowledgeBroadcasts = false, receiveOwnBroadcasts = false)
private var presenceJoinConfig = PresenceJoinConfig("")

/**
Expand Down
Loading

0 comments on commit 6cf1fdc

Please sign in to comment.