RIP Flipper

pull/3321/head
Alex Baker 10 months ago
parent 7ed406fbbc
commit 6fe9b0b255

@ -194,9 +194,6 @@ dependencies {
implementation(libs.markwon.tables) implementation(libs.markwon.tables)
implementation(libs.markwon.tasklist) implementation(libs.markwon.tasklist)
debugImplementation(libs.facebook.flipper)
debugImplementation(libs.facebook.flipper.network)
debugImplementation(libs.facebook.soloader)
debugImplementation(libs.leakcanary) debugImplementation(libs.leakcanary)
debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation(libs.kotlin.reflect) debugImplementation(libs.kotlin.reflect)

@ -7,10 +7,6 @@
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="GoogleAppIndexingWarning"> tools:ignore="GoogleAppIndexingWarning">
<activity
android:exported="true"
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"/>
</application> </application>
</manifest> </manifest>

@ -3,14 +3,6 @@ package org.tasks
import android.app.Application import android.app.Application
import android.os.StrictMode import android.os.StrictMode
import android.os.StrictMode.VmPolicy import android.os.StrictMode.VmPolicy
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.android.utils.FlipperUtils
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin
import com.facebook.flipper.plugins.inspector.DescriptorMapping
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin
import com.facebook.soloader.SoLoader
import com.todoroo.andlib.utility.AndroidUtilities.atLeastOreo import com.todoroo.andlib.utility.AndroidUtilities.atLeastOreo
import com.todoroo.andlib.utility.AndroidUtilities.atLeastQ import com.todoroo.andlib.utility.AndroidUtilities.atLeastQ
import leakcanary.AppWatcher import leakcanary.AppWatcher
@ -27,18 +19,9 @@ class BuildSetup @Inject constructor(
fun setup() { fun setup() {
Timber.plant(Timber.DebugTree()) Timber.plant(Timber.DebugTree())
Timber.plant(fileLogger) Timber.plant(fileLogger)
SoLoader.init(context, false)
if (preferences.getBoolean(R.string.p_leakcanary, false)) { if (preferences.getBoolean(R.string.p_leakcanary, false)) {
AppWatcher.manualInstall(context) AppWatcher.manualInstall(context)
} }
if (preferences.getBoolean(R.string.p_flipper, false) && FlipperUtils.shouldEnableFlipper(context)) {
val client = AndroidFlipperClient.getInstance(context)
client.addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()))
client.addPlugin(DatabasesFlipperPlugin(context))
client.addPlugin(NetworkFlipperPlugin())
client.addPlugin(SharedPreferencesFlipperPlugin(context))
client.start()
}
if (preferences.getBoolean(R.string.p_strict_mode_thread, false)) { if (preferences.getBoolean(R.string.p_strict_mode_thread, false)) {
val builder = StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog() val builder = StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog()
if (preferences.getBoolean(R.string.p_crash_main_queries, false)) { if (preferences.getBoolean(R.string.p_crash_main_queries, false)) {

@ -1,39 +0,0 @@
package org.tasks
import android.content.Context
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpResponse
import dagger.hilt.android.qualifiers.ApplicationContext
import okhttp3.OkHttpClient
import java.io.IOException
import javax.inject.Inject
class DebugNetworkInterceptor @Inject constructor(@param:ApplicationContext private val context: Context) {
fun apply(builder: OkHttpClient.Builder?) {
builder?.addNetworkInterceptor(FlipperOkhttpInterceptor(getNetworkPlugin(context)))
}
@Throws(IOException::class)
fun <T> execute(request: HttpRequest, responseClass: Class<T>): T? {
val interceptor = FlipperHttpInterceptor(getNetworkPlugin(context), responseClass)
request
.setInterceptor(interceptor)
.setResponseInterceptor(interceptor)
.execute()
return interceptor.response
}
@Throws(IOException::class)
fun <T> report(httpResponse: HttpResponse, responseClass: Class<T>, start: Long, finish: Long): T? {
val interceptor = FlipperHttpInterceptor(getNetworkPlugin(context), responseClass)
interceptor.report(httpResponse, start, finish)
return interceptor.response
}
private fun getNetworkPlugin(context: Context): NetworkFlipperPlugin {
return AndroidFlipperClient.getInstance(context).getPlugin(NetworkFlipperPlugin.ID)!!
}
}

@ -1,82 +0,0 @@
package org.tasks
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.facebook.flipper.plugins.network.NetworkReporter
import com.facebook.flipper.plugins.network.NetworkReporter.ResponseInfo
import com.google.api.client.http.*
import com.google.api.client.json.GenericJson
import org.tasks.data.UUIDHelper
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber
import java.io.ByteArrayOutputStream
import java.io.IOException
internal class FlipperHttpInterceptor<T>(private val plugin: NetworkFlipperPlugin, private val responseClass: Class<T>) : HttpExecuteInterceptor, HttpResponseInterceptor {
private val requestId = UUIDHelper.newUUID()
var response: T? = null
private set
override fun intercept(request: HttpRequest) {
plugin.reportRequest(toRequestInfo(request, currentTimeMillis()))
}
@Throws(IOException::class)
override fun interceptResponse(response: HttpResponse) {
plugin.reportResponse(toResponseInfo(response, currentTimeMillis()))
}
@Throws(IOException::class)
fun report(response: HttpResponse, start: Long, end: Long) {
plugin.reportRequest(toRequestInfo(response.request, start))
plugin.reportResponse(toResponseInfo(response, end))
}
private fun toRequestInfo(request: HttpRequest, timestamp: Long): NetworkReporter.RequestInfo {
val requestInfo = NetworkReporter.RequestInfo()
requestInfo.method = request.requestMethod
requestInfo.body = bodyToByteArray(request.content)
requestInfo.headers = getHeaders(request.headers)
requestInfo.requestId = requestId
requestInfo.timeStamp = timestamp
requestInfo.uri = request.url.toString()
return requestInfo
}
@Throws(IOException::class)
private fun toResponseInfo(response: HttpResponse, timestamp: Long): ResponseInfo {
val responseInfo = ResponseInfo()
responseInfo.timeStamp = timestamp
responseInfo.headers = getHeaders(response.headers)
responseInfo.requestId = requestId
responseInfo.statusCode = response.statusCode
responseInfo.statusReason = response.statusMessage
this.response = response.parseAs(responseClass)
if (this.response is GenericJson) {
try {
responseInfo.body = (this.response as GenericJson).toPrettyString().toByteArray()
} catch (e: IOException) {
Timber.e(e)
}
}
return responseInfo
}
private fun getHeaders(headers: HttpHeaders): List<NetworkReporter.Header> {
return headers.map { (name, value) -> NetworkReporter.Header(name, value.toString()) }
}
private fun bodyToByteArray(content: HttpContent?): ByteArray? {
if (content == null) {
return null
}
val output = ByteArrayOutputStream()
try {
content.writeTo(output)
} catch (e: IOException) {
Timber.e(e)
return null
}
return output.toByteArray()
}
}

@ -30,7 +30,6 @@ class Debug : InjectingPreferenceFragment() {
override suspend fun setupPreferences(savedInstanceState: Bundle?) { override suspend fun setupPreferences(savedInstanceState: Bundle?) {
for (pref in listOf( for (pref in listOf(
R.string.p_leakcanary, R.string.p_leakcanary,
R.string.p_flipper,
R.string.p_strict_mode_vm, R.string.p_strict_mode_vm,
R.string.p_strict_mode_thread, R.string.p_strict_mode_thread,
R.string.p_crash_main_queries R.string.p_crash_main_queries

@ -4,7 +4,6 @@
<string name="debug_strict_mode_thread">Strict mode - Thread</string> <string name="debug_strict_mode_thread">Strict mode - Thread</string>
<string name="debug_strict_mode_vm">Strict mode - VM</string> <string name="debug_strict_mode_vm">Strict mode - VM</string>
<string name="debug_leakcanary">LeakCanary</string> <string name="debug_leakcanary">LeakCanary</string>
<string name="debug_flipper">Flipper</string>
<string name="debug_pro">Unlock pro</string> <string name="debug_pro">Unlock pro</string>
<string name="debug_purchase">Purchase %s</string> <string name="debug_purchase">Purchase %s</string>
<string name="debug_consume">Consume %s</string> <string name="debug_consume">Consume %s</string>

@ -6,11 +6,6 @@
android:key="@string/p_leakcanary" android:key="@string/p_leakcanary"
android:title="@string/debug_leakcanary" /> android:title="@string/debug_leakcanary" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="@string/p_flipper"
android:title="@string/debug_flipper"/>
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="false" android:defaultValue="false"
android:key="@string/p_strict_mode_vm" android:key="@string/p_strict_mode_vm"

@ -6,9 +6,7 @@ import com.google.api.services.tasks.Tasks
import com.google.api.services.tasks.model.Task import com.google.api.services.tasks.model.Task
import com.google.api.services.tasks.model.TaskList import com.google.api.services.tasks.model.TaskList
import com.google.api.services.tasks.model.TaskLists import com.google.api.services.tasks.model.TaskLists
import org.tasks.DebugNetworkInterceptor
import org.tasks.googleapis.BaseInvoker import org.tasks.googleapis.BaseInvoker
import org.tasks.preferences.Preferences
import java.io.IOException import java.io.IOException
/** /**
@ -19,9 +17,7 @@ import java.io.IOException
*/ */
class GtasksInvoker( class GtasksInvoker(
credentials: HttpCredentialsAdapter, credentials: HttpCredentialsAdapter,
preferences: Preferences, ) : BaseInvoker(credentials) {
interceptor: DebugNetworkInterceptor
) : BaseInvoker(credentials, preferences, interceptor) {
private val service = private val service =
Tasks.Builder(NetHttpTransport(), GsonFactory(), credentials) Tasks.Builder(NetHttpTransport(), GsonFactory(), credentials)
.setApplicationName(APP_NAME) .setApplicationName(APP_NAME)

@ -10,19 +10,15 @@ import com.google.api.services.drive.model.File
import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter
import com.todoroo.astrid.gtasks.api.HttpNotFoundException import com.todoroo.astrid.gtasks.api.HttpNotFoundException
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.DebugNetworkInterceptor
import org.tasks.backup.BackupConstants import org.tasks.backup.BackupConstants
import org.tasks.files.FileHelper import org.tasks.files.FileHelper
import org.tasks.googleapis.BaseInvoker import org.tasks.googleapis.BaseInvoker
import org.tasks.preferences.Preferences
import java.io.IOException import java.io.IOException
class DriveInvoker( class DriveInvoker(
@param:ApplicationContext private val context: Context, @param:ApplicationContext private val context: Context,
preferences: Preferences,
credentialsAdapter: HttpCredentialsAdapter, credentialsAdapter: HttpCredentialsAdapter,
interceptor: DebugNetworkInterceptor ) : BaseInvoker(credentialsAdapter) {
) : BaseInvoker(credentialsAdapter, preferences, interceptor) {
private val service = private val service =
Drive.Builder(NetHttpTransport(), GsonFactory(), credentialsAdapter) Drive.Builder(NetHttpTransport(), GsonFactory(), credentialsAdapter)
.setApplicationName(APP_NAME) .setApplicationName(APP_NAME)

@ -8,16 +8,11 @@ import com.todoroo.astrid.gtasks.api.HttpNotFoundException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.tasks.BuildConfig import org.tasks.BuildConfig
import org.tasks.DebugNetworkInterceptor
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber import timber.log.Timber
import java.io.IOException import java.io.IOException
abstract class BaseInvoker( abstract class BaseInvoker(
private val credentialsAdapter: HttpCredentialsAdapter, private val credentialsAdapter: HttpCredentialsAdapter,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor
) { ) {
@Throws(IOException::class) @Throws(IOException::class)
protected suspend fun <T> execute(request: AbstractGoogleJsonClientRequest<T>): T? = execute(request, false) protected suspend fun <T> execute(request: AbstractGoogleJsonClientRequest<T>): T? = execute(request, false)
@ -28,15 +23,7 @@ abstract class BaseInvoker(
credentialsAdapter.checkToken() credentialsAdapter.checkToken()
Timber.d(caller) Timber.d(caller)
val response: T? = try { val response: T? = try {
if (preferences.isFlipperEnabled) { request.execute()
val start = currentTimeMillis()
val httpResponse = request.executeUnparsed()
interceptor.report(httpResponse, request.responseClass, start,
currentTimeMillis()
)
} else {
request.execute()
}
} catch (e: HttpResponseException) { } catch (e: HttpResponseException) {
return@withContext if (e.statusCode == 401 && !retry) { return@withContext if (e.statusCode == 401 && !retry) {
credentialsAdapter.invalidateToken() credentialsAdapter.invalidateToken()

@ -6,7 +6,6 @@ import com.google.api.services.tasks.TasksScopes
import com.todoroo.astrid.gtasks.api.GtasksInvoker import com.todoroo.astrid.gtasks.api.GtasksInvoker
import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.DebugNetworkInterceptor
import org.tasks.R import org.tasks.R
import org.tasks.drive.DriveInvoker import org.tasks.drive.DriveInvoker
import org.tasks.gtasks.GoogleAccountManager import org.tasks.gtasks.GoogleAccountManager
@ -17,23 +16,18 @@ class InvokerFactory @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
private val googleAccountManager: GoogleAccountManager, private val googleAccountManager: GoogleAccountManager,
private val preferences: Preferences, private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor
) { ) {
fun getDriveInvoker() = DriveInvoker( fun getDriveInvoker() = DriveInvoker(
context, context,
preferences,
HttpCredentialsAdapter( HttpCredentialsAdapter(
googleAccountManager, googleAccountManager,
preferences.getStringValue(R.string.p_google_drive_backup_account) ?: "", preferences.getStringValue(R.string.p_google_drive_backup_account) ?: "",
DriveScopes.DRIVE_FILE DriveScopes.DRIVE_FILE
), ),
interceptor
) )
fun getGtasksInvoker(account: String) = GtasksInvoker( fun getGtasksInvoker(account: String) = GtasksInvoker(
HttpCredentialsAdapter(googleAccountManager, account, TasksScopes.TASKS), HttpCredentialsAdapter(googleAccountManager, account, TasksScopes.TASKS),
preferences,
interceptor
) )
} }

@ -23,11 +23,9 @@ import net.openid.appauth.AuthState
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.internal.tls.OkHostnameVerifier import okhttp3.internal.tls.OkHostnameVerifier
import org.tasks.BuildConfig import org.tasks.BuildConfig
import org.tasks.DebugNetworkInterceptor
import org.tasks.caldav.TasksCookieJar import org.tasks.caldav.TasksCookieJar
import org.tasks.data.entity.CaldavAccount import org.tasks.data.entity.CaldavAccount
import org.tasks.extensions.Context.cookiePersistor import org.tasks.extensions.Context.cookiePersistor
import org.tasks.preferences.Preferences
import org.tasks.security.KeyStoreEncryption import org.tasks.security.KeyStoreEncryption
import org.tasks.sync.microsoft.MicrosoftService import org.tasks.sync.microsoft.MicrosoftService
import org.tasks.sync.microsoft.requestTokenRefresh import org.tasks.sync.microsoft.requestTokenRefresh
@ -37,8 +35,6 @@ import javax.net.ssl.SSLContext
class HttpClientFactory @Inject constructor( class HttpClientFactory @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
private val encryption: KeyStoreEncryption, private val encryption: KeyStoreEncryption,
) { ) {
suspend fun newClient(foreground: Boolean) = newClient( suspend fun newClient(foreground: Boolean) = newClient(
@ -85,9 +81,6 @@ class HttpClientFactory @Inject constructor(
block(builder) block(builder)
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
return builder.build() return builder.build()
} }

@ -12,26 +12,19 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.tasks.DebugNetworkInterceptor
import org.tasks.R import org.tasks.R
import org.tasks.data.entity.Place import org.tasks.data.entity.Place
import org.tasks.preferences.Preferences
import java.io.IOException import java.io.IOException
import javax.inject.Inject import javax.inject.Inject
class GeocoderMapbox @Inject constructor( class GeocoderMapbox @Inject constructor(
@ApplicationContext context: Context, @ApplicationContext context: Context,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
) : Geocoder { ) : Geocoder {
private val token = context.getString(R.string.mapbox_key) private val token = context.getString(R.string.mapbox_key)
override suspend fun reverseGeocode(mapPosition: MapPosition): Place? = override suspend fun reverseGeocode(mapPosition: MapPosition): Place? =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val builder = OkHttpClient().newBuilder() val builder = OkHttpClient().newBuilder()
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
val client = builder.build() val client = builder.build()
val url = "https://api.mapbox.com/geocoding/v5/mapbox.places/${mapPosition.longitude},${mapPosition.latitude}.json?access_token=$token" val url = "https://api.mapbox.com/geocoding/v5/mapbox.places/${mapPosition.longitude},${mapPosition.latitude}.json?access_token=$token"
val response = client.newCall(Request.Builder().get().url(url).build()).execute() val response = client.newCall(Request.Builder().get().url(url).build()).execute()

@ -11,18 +11,14 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.tasks.DebugNetworkInterceptor
import org.tasks.R import org.tasks.R
import org.tasks.data.entity.Place import org.tasks.data.entity.Place
import org.tasks.location.GeocoderMapbox.Companion.toPlace import org.tasks.location.GeocoderMapbox.Companion.toPlace
import org.tasks.preferences.Preferences
import java.io.IOException import java.io.IOException
import javax.inject.Inject import javax.inject.Inject
class PlaceSearchMapbox @Inject constructor( class PlaceSearchMapbox @Inject constructor(
@ApplicationContext context: Context, @ApplicationContext context: Context,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
) : PlaceSearch { ) : PlaceSearch {
val token = context.getString(R.string.mapbox_key) val token = context.getString(R.string.mapbox_key)
@ -35,9 +31,6 @@ class PlaceSearchMapbox @Inject constructor(
override suspend fun search(query: String, bias: MapPosition?): List<PlaceSearchResult> = override suspend fun search(query: String, bias: MapPosition?): List<PlaceSearchResult> =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val builder = OkHttpClient().newBuilder() val builder = OkHttpClient().newBuilder()
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
val proximity = bias?.let { val proximity = bias?.let {
"&proximity=${bias.longitude},${bias.latitude}" "&proximity=${bias.longitude},${bias.latitude}"
} }

@ -489,9 +489,6 @@ class Preferences @JvmOverloads constructor(
fun <T> getPrefs(c: Class<T>): Map<String, T> = fun <T> getPrefs(c: Class<T>): Map<String, T> =
prefs.all.filter { (_, value) -> c.isInstance(value) } as Map<String, T> prefs.all.filter { (_, value) -> c.isInstance(value) } as Map<String, T>
val isFlipperEnabled: Boolean
get() = BuildConfig.DEBUG && getBoolean(R.string.p_flipper, false)
var isPositionHackEnabled: Boolean var isPositionHackEnabled: Boolean
get() = getLong(R.string.p_google_tasks_position_hack, 0) > currentTimeMillis() - ONE_WEEK get() = getLong(R.string.p_google_tasks_position_hack, 0) > currentTimeMillis() - ONE_WEEK
set(value) { setLong(R.string.p_google_tasks_position_hack, if (value) currentTimeMillis() else 0) } set(value) { setLong(R.string.p_google_tasks_position_hack, if (value) currentTimeMillis() else 0) }

@ -370,7 +370,6 @@
<string name="p_strict_mode_vm">strict_mode_vm</string> <string name="p_strict_mode_vm">strict_mode_vm</string>
<string name="p_strict_mode_thread">strict_mode_thread</string> <string name="p_strict_mode_thread">strict_mode_thread</string>
<string name="p_leakcanary">p_leakcanary</string> <string name="p_leakcanary">p_leakcanary</string>
<string name="p_flipper">p_flipper</string>
<string name="p_debug_pro">debug_pro</string> <string name="p_debug_pro">debug_pro</string>
<string name="p_crash_main_queries">debug_crash_main_queries</string> <string name="p_crash_main_queries">debug_crash_main_queries</string>
<string name="p_sync_ongoing">sync_ongoing</string> <string name="p_sync_ongoing">sync_ongoing</string>

@ -1,12 +0,0 @@
package org.tasks
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpResponse
import okhttp3.OkHttpClient
import javax.inject.Inject
class DebugNetworkInterceptor @Inject constructor() {
fun apply(builder: OkHttpClient.Builder?) {}
fun <T> execute(httpRequest: HttpRequest?, responseClass: Class<T>?): T? = null
fun <T> report(httpResponse: HttpResponse?, responseClass: Class<T>?, start: Long, finish: Long): T? = null
}

@ -20,7 +20,6 @@ desugar_jdk_libs = "2.1.3"
etebase = "2.3.2" etebase = "2.3.2"
firebase = "33.8.0" firebase = "33.8.0"
firebase-crashlytics-gradle = "3.0.2" firebase-crashlytics-gradle = "3.0.2"
flipper = "0.273.0"
google-oauth2 = "1.30.1" google-oauth2 = "1.30.1"
google-api-drive = "v3-rev20250122-2.0.0" google-api-drive = "v3-rev20250122-2.0.0"
google-api-tasks = "v1-rev20250105-2.0.0" google-api-tasks = "v1-rev20250105-2.0.0"
@ -58,7 +57,6 @@ recyclerview = "1.4.0"
rfc5545-datetime = "0.2.4" rfc5545-datetime = "0.2.4"
room = "2.7.0-alpha13" room = "2.7.0-alpha13"
shortcut-badger = "1.1.22" shortcut-badger = "1.1.22"
soloader = "0.12.1"
timber = "5.0.1" timber = "5.0.1"
swiperefreshlayout = "1.1.0" swiperefreshlayout = "1.1.0"
work = "2.10.0" work = "2.10.0"
@ -116,9 +114,6 @@ dmfs-opentasks-provider = { module = "com.github.tasks.opentasks:opentasks-provi
dmfs-recur = { module = "org.dmfs:lib-recur", version.ref = "lib-recur" } dmfs-recur = { module = "org.dmfs:lib-recur", version.ref = "lib-recur" }
dmfs-rfc5545-datetime = { module = "org.dmfs:rfc5545-datetime", version.ref = "rfc5545-datetime" } dmfs-rfc5545-datetime = { module = "org.dmfs:rfc5545-datetime", version.ref = "rfc5545-datetime" }
etebase = { module = "com.etebase:client", version.ref = "etebase" } etebase = { module = "com.etebase:client", version.ref = "etebase" }
facebook-flipper = { module = "com.facebook.flipper:flipper", version.ref = "flipper" }
facebook-flipper-network = { module = "com.facebook.flipper:flipper-network-plugin", version.ref = "flipper" }
facebook-soloader = { module = "com.facebook.soloader:soloader", version.ref = "soloader" }
firebase = { module = "com.google.firebase:firebase-bom", version.ref = "firebase" } firebase = { module = "com.google.firebase:firebase-bom", version.ref = "firebase" }
firebase-config-ktx = { module = "com.google.firebase:firebase-config-ktx" } firebase-config-ktx = { module = "com.google.firebase:firebase-config-ktx" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" } firebase-analytics = { module = "com.google.firebase:firebase-analytics" }

Loading…
Cancel
Save