Skip to content

Commit

Permalink
Remove RxJava entirely (#804)
Browse files Browse the repository at this point in the history
  • Loading branch information
ZacSweers authored Jul 10, 2023
1 parent 54c68e5 commit 1a24908
Show file tree
Hide file tree
Showing 40 changed files with 184 additions and 349 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ libraries, patterns, API quirks, and more. It's been a very fun project to spike
## Technologies

- Kotlin
- RxJava 3/AutoDispose
- Kotlin Coroutines
- Debugging tooling as a first class citizen in the debug build
- Leak Canary, Scalpel, debug drawer, Flipper, bug reporting, the works
- AndroidX/Jetpack
Expand Down
14 changes: 5 additions & 9 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ tasks.matching { it.name == "licenseeDebug" }.configureEach { enabled = false }
licensee {
allow("Apache-2.0")
allow("MIT")
allow("MIT-0")
allow("CC0-1.0")
allowUrl("http://opensource.org/licenses/BSD-2-Clause")
allowUrl("https://developer.android.com/studio/terms.html")
allowUrl("https://jsoup.org/license")
Expand Down Expand Up @@ -454,8 +454,6 @@ androidComponents {
"META-INF/NOTICE",
"META-INF/NOTICE.txt",
"META-INF/README.md",
"META-INF/rxjava.properties",
"META-INF/services/javax.annotation.processing.Processor",
)
}
}
Expand Down Expand Up @@ -549,14 +547,13 @@ dependencies {
implementation(libs.moshi.shimo)
implementation(libs.okhttp.core)
implementation(libs.retrofit.core)
implementation(libs.retrofit.rxJava3)
implementation(libs.rx.android)
implementation(libs.rx.dogTag)
implementation(libs.rx.dogTagAutoDispose)
implementation(libs.rx.java)
implementation(libs.sqldelight.driver.android)
implementation(libs.sqldelight.paging)
implementation(libs.sqldelight.primitiveAdapters)
implementation(libs.sqldelight.runtime)
implementation(libs.telephoto.zoomableImageCoil)
implementation(libs.xmlutil.serialization)
implementation(projects.libraries.auth)
implementation(projects.libraries.di)
implementation(projects.libraries.di.android)
implementation(projects.libraries.gemoji.db)
Expand Down Expand Up @@ -585,5 +582,4 @@ dependencies {
testImplementation(libs.test.truth)

androidTestImplementation(libs.misc.jsr305)
androidTestImplementation(libs.rx.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ import dagger.Provides
import dev.zacsweers.catchup.appconfig.AppConfig
import dev.zacsweers.catchup.di.AppScope
import dev.zacsweers.catchup.di.SingleIn
import io.reactivex.rxjava3.core.Single
import io.sweers.catchup.BuildConfig
import io.sweers.catchup.libraries.retrofitconverters.delegatingCallFactory
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.Body
import retrofit2.http.Headers
Expand All @@ -44,7 +42,7 @@ interface ImgurUploadApi {
@Headers("Authorization: Client-ID ${BuildConfig.IMGUR_CLIENT_ACCESS_TOKEN}")
@POST("image")
@Wrapped(path = ["data", "link"])
fun postImage(@Part file: MultipartBody.Part): Single<String>
suspend fun postImage(@Part file: MultipartBody.Part): String
}

interface GitHubIssueApi {
Expand All @@ -57,7 +55,7 @@ interface GitHubIssueApi {
)
@POST("repos/zacsweers/catchup/issues")
@Wrapped(path = ["html_url"])
fun createIssue(@Body issue: GitHubIssue): Single<String>
suspend fun createIssue(@Body issue: GitHubIssue): String
}

@JsonClass(generateAdapter = true) data class GitHubIssue(val title: String, val body: String)
Expand All @@ -71,13 +69,11 @@ object BugReportModule {
internal fun provideImgurService(
client: Lazy<OkHttpClient>,
moshi: Moshi,
rxJavaCallAdapterFactory: RxJava3CallAdapterFactory,
appConfig: AppConfig
): ImgurUploadApi {
return Retrofit.Builder()
.baseUrl("https://api.imgur.com/3/")
.delegatingCallFactory(client)
.addCallAdapterFactory(rxJavaCallAdapterFactory)
.addConverterFactory(
MoshiConverterFactory.create(moshi.newBuilder().add(Wrapped.ADAPTER_FACTORY).build())
)
Expand All @@ -91,13 +87,11 @@ object BugReportModule {
internal fun provideGithubIssueService(
client: Lazy<OkHttpClient>,
moshi: Moshi,
rxJavaCallAdapterFactory: RxJava3CallAdapterFactory,
appConfig: AppConfig
): GitHubIssueApi {
return Retrofit.Builder()
.baseUrl("https://api.github.com/")
.delegatingCallFactory(client)
.addCallAdapterFactory(rxJavaCallAdapterFactory)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.validateEagerly(appConfig.isDebug)
.build()
Expand Down
182 changes: 91 additions & 91 deletions app/src/debug/kotlin/io/sweers/catchup/ui/bugreport/BugReportLens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,13 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dev.zacsweers.catchup.appconfig.AppConfig
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import io.sweers.catchup.R
import io.sweers.catchup.data.LumberYard
import io.sweers.catchup.ui.bugreport.BugReportDialog.ReportListener
import io.sweers.catchup.ui.bugreport.BugReportView.Report
import io.sweers.catchup.util.buildMarkdown
import java.io.File
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
Expand Down Expand Up @@ -77,20 +72,22 @@ constructor(
}

override suspend fun onBugReportSubmit(context: Context, report: Report) {
if (report.includeLogs) {
try {
val logs = withContext(Dispatchers.IO) { lumberYard.save() }
submitReport(context, report, logs)
} catch (e: Exception) {
Toast.makeText(context, "Couldn't attach the logs.", Toast.LENGTH_SHORT).show()
withContext(Dispatchers.IO) {
if (report.includeLogs) {
try {
val logs = lumberYard.save()
submitReport(context, report, logs)
} catch (e: Exception) {
Toast.makeText(context, "Couldn't attach the logs.", Toast.LENGTH_SHORT).show()
submitReport(context, report, null)
}
} else {
submitReport(context, report, null)
}
} else {
submitReport(context, report, null)
}
}

private fun submitReport(
private suspend fun submitReport(
context: Context,
report: Report,
logs: File?,
Expand Down Expand Up @@ -143,7 +140,12 @@ constructor(
}

@SuppressLint("NewApi") // False positive
private fun uploadIssue(context: Context, report: Report, body: StringBuilder, logs: File?) {
private suspend fun uploadIssue(
context: Context,
report: Report,
body: StringBuilder,
logs: File?
) {
val channelId = "bugreports"
val notificationManager =
context.getSystemService<NotificationManager>()
Expand Down Expand Up @@ -171,7 +173,7 @@ constructor(
}

val finalScreenshot = screenshot
val screenshotStringStream =
val screenshotText =
if (report.includeScreenshot && finalScreenshot != null) {
imgurUploadApi
.postImage(
Expand All @@ -181,88 +183,86 @@ constructor(
finalScreenshot.asRequestBody("image/*".toMediaTypeOrNull())
)
)
.map { "\n\n!${buildMarkdown { link(it, "Screenshot") }}" }
} else Single.just("\n\nNo screenshot provided")
.let { "\n\n!${buildMarkdown { link(it, "Screenshot") }}" }
} else {
"\n\nNo screenshot provided"
}

// TODO change to coroutines
val disposable =
screenshotStringStream
.map { screenshotText ->
body.append(screenshotText)
val screenshotMarkdown = buildMarkdown {
newline(2)
h4("Logs")
if (report.includeLogs && logs != null) {
codeBlock(logs.readText())
} else {
text("No logs provided")
}
val bodyText =
with(body) {
append(screenshotText)
val screenshotMarkdown = buildMarkdown {
newline(2)
h4("Logs")
if (report.includeLogs && logs != null) {
codeBlock(logs.readText())
} else {
text("No logs provided")
}
body.append(screenshotMarkdown)
body.toString()
}
.flatMap { bodyText -> gitHubIssueApi.createIssue(GitHubIssue(report.title, bodyText)) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { notificationManager.notify(notificationId, notificationBuilder.build()) }
.doOnDispose {
NotificationCompat.Builder(context, channelId)
.apply {
setSmallIcon(R.drawable.ic_error_black_24dp)
color = ContextCompat.getColor(context, R.color.colorAccent)
setContentTitle("Upload canceled")
setContentInfo("Probably because the activity was killed ¯\\_(ツ)_/¯")
setAutoCancel(true)
}
.let { notificationManager.notify(notificationId, it.build()) }
}
.subscribe { issueUrl: String?, error: Throwable? ->
issueUrl?.let {
NotificationCompat.Builder(context, channelId)
.apply {
setSmallIcon(R.drawable.ic_check_black_24dp)
color = ContextCompat.getColor(context, R.color.colorAccent)
setContentTitle("Bug report successfully uploaded")
setContentText(it)
val uri = it.toUri()
val resultIntent = Intent(Intent.ACTION_VIEW, uri)
setContentIntent(
PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_IMMUTABLE)
)
setAutoCancel(true)
append(screenshotMarkdown)
toString()
}

try {
withContext(Dispatchers.Main) {
notificationManager.notify(notificationId, notificationBuilder.build())
}
// TODO change to eithernet
val issueUrl = gitHubIssueApi.createIssue(GitHubIssue(report.title, bodyText))
NotificationCompat.Builder(context, channelId)
.apply {
setSmallIcon(R.drawable.ic_check_black_24dp)
color = ContextCompat.getColor(context, R.color.colorAccent)
setContentTitle("Bug report successfully uploaded")
setContentText(issueUrl)
val uri = issueUrl.toUri()
val resultIntent = Intent(Intent.ACTION_VIEW, uri)
setContentIntent(
PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_IMMUTABLE)
)
setAutoCancel(true)

val shareIntent = Intent(Intent.ACTION_SEND, uri)
shareIntent.setDataAndType(null, "text/plain")
shareIntent.putExtra(Intent.EXTRA_TEXT, it)
shareIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
val shareIntent = Intent(Intent.ACTION_SEND, uri)
shareIntent.setDataAndType(null, "text/plain")
shareIntent.putExtra(Intent.EXTRA_TEXT, issueUrl)
shareIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

addAction(
NotificationCompat.Action(
R.drawable.ic_share_black_24dp,
"Share link",
PendingIntent.getActivity(context, 0, shareIntent, PendingIntent.FLAG_IMMUTABLE)
)
)
}
.let { notificationManager.notify(notificationId, it.build()) }
addAction(
NotificationCompat.Action(
R.drawable.ic_share_black_24dp,
"Share link",
PendingIntent.getActivity(context, 0, shareIntent, PendingIntent.FLAG_IMMUTABLE)
)
)
}
.let { notificationManager.notify(notificationId, it.build()) }
} catch (e: Exception) {
withContext(Dispatchers.Main) {
NotificationCompat.Builder(context, channelId)
.apply {
setSmallIcon(R.drawable.ic_error_black_24dp)
color = ContextCompat.getColor(context, R.color.colorAccent)
setContentTitle("Upload failed")
setContentInfo(
"Bug report upload failed. Please try again. If problem persists, take consolation in knowing you got farther than I did."
)
setAutoCancel(true)
}
error?.let {
NotificationCompat.Builder(context, channelId)
.apply {
setSmallIcon(R.drawable.ic_error_black_24dp)
color = ContextCompat.getColor(context, R.color.colorAccent)
setContentTitle("Upload failed")
setContentInfo(
"Bug report upload failed. Please try again. If problem persists, take consolation in knowing you got farther than I did."
)
setAutoCancel(true)
}
.let { notificationManager.notify(notificationId, it.build()) }
.let { notificationManager.notify(notificationId, it.build()) }
}
} finally {
withContext(Dispatchers.Main) {
NotificationCompat.Builder(context, channelId)
.apply {
setSmallIcon(R.drawable.ic_error_black_24dp)
color = ContextCompat.getColor(context, R.color.colorAccent)
setContentTitle("Upload canceled")
setContentInfo("Probably because the activity was killed ¯\\_(ツ)_/¯")
setAutoCancel(true)
}
}

activity.lifecycleScope.launch {
suspendCancellableCoroutine { it.invokeOnCancellation { disposable.dispose() } }
.let { notificationManager.notify(notificationId, it.build()) }
}
}
}

Expand Down
16 changes: 0 additions & 16 deletions app/src/main/assets/generated_licenses.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,6 @@
"owner": "pdvrieze",
"name": "xmlutil"
},
{
"owner": "reactive-streams",
"name": "reactive-streams"
},
{
"owner": "ReactiveX",
"name": "RxAndroid"
},
{
"owner": "ReactiveX",
"name": "RxJava"
},
{
"owner": "saket",
"name": "telephoto"
Expand Down Expand Up @@ -143,10 +131,6 @@
"owner": "Tickaroo",
"name": "tikxml"
},
{
"owner": "uber",
"name": "RxDogTag"
},
{
"owner": "unbescape",
"name": "unbescape"
Expand Down
Loading

0 comments on commit 1a24908

Please sign in to comment.