Improve loading on Android, switch to posthog

This commit is contained in:
Jackson Harper
2023-09-14 14:48:30 +08:00
parent c12cf4d5bc
commit fcbbc083a7
6 changed files with 67 additions and 35 deletions

View File

@ -144,7 +144,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.9' implementation 'com.google.code.gson:gson:2.8.9'
implementation 'com.pspdfkit:pspdfkit:8.4.1' implementation 'com.pspdfkit:pspdfkit:8.4.1'
implementation 'com.segment.analytics.kotlin:android:1.10.0' implementation 'com.posthog.android:posthog:1.+'
implementation 'io.intercom.android:intercom-sdk:15.1.0' implementation 'io.intercom.android:intercom-sdk:15.1.0'
// Room Deps // Room Deps

View File

@ -1,36 +1,34 @@
package app.omnivore.omnivore package app.omnivore.omnivore
import android.content.Context import android.content.Context
import com.segment.analytics.kotlin.android.Analytics import com.posthog.android.PostHog
import com.segment.analytics.kotlin.core.* import com.posthog.android.Properties
import io.intercom.android.sdk.Intercom import io.intercom.android.sdk.Intercom
import io.intercom.android.sdk.identity.Registration import io.intercom.android.sdk.identity.Registration
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
class EventTracker @Inject constructor(val app: Context) { class EventTracker @Inject constructor(val app: Context) {
val segmentAnalytics: Analytics private val posthog: PostHog
init { init {
val writeKey = app.getString(R.string.segment_write_key) val posthogClientKey = app.getString(R.string.posthog_client_key)
val posthogInstanceAddress = app.getString(R.string.posthog_instance_address)
segmentAnalytics = Analytics(writeKey, app.applicationContext) { posthog = PostHog.Builder(app, posthogClientKey, posthogInstanceAddress)
trackApplicationLifecycleEvents = true .captureApplicationLifecycleEvents()
application = app.applicationContext .build()
useLifecycleObserver = true
} PostHog.setSingletonInstance(posthog)
} }
fun registerUser(userID: String) { fun registerUser(userID: String) {
segmentAnalytics.identify(userID) posthog.identify(userID)
Intercom.client().loginIdentifiedUser(Registration.create().withUserId(userID)) Intercom.client().loginIdentifiedUser(Registration.create().withUserId(userID))
} }
fun debugMessage(message: String) { fun track(eventName: String, properties: Properties = Properties()) {
track(message) posthog.capture(eventName, properties)
}
fun track(eventName: String, jsonObject: JSONObject = JSONObject()) {
segmentAnalytics.track(eventName, jsonObject)
} }
} }

View File

@ -13,6 +13,7 @@ import android.webkit.JavascriptInterface
import android.webkit.WebResourceRequest import android.webkit.WebResourceRequest
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@ -35,6 +36,7 @@ fun WebReader(
val javascriptActionLoopUUID: UUID by webReaderViewModel val javascriptActionLoopUUID: UUID by webReaderViewModel
.javascriptActionLoopUUIDLiveData .javascriptActionLoopUUIDLiveData
.observeAsState(UUID.randomUUID()) .observeAsState(UUID.randomUUID())
val isDarkMode = isSystemInDarkTheme()
WebView.setWebContentsDebuggingEnabled(true) WebView.setWebContentsDebuggingEnabled(true)
@ -56,7 +58,19 @@ fun WebReader(
alpha = 1.0f alpha = 1.0f
viewModel?.showNavBar() viewModel?.showNavBar()
currentTheme?.let { theme -> currentTheme?.let { theme ->
setBackgroundColor(theme.backgroundColor.toInt()); val bg = when (theme) {
Themes.SYSTEM -> {
if (isDarkMode) {
Color.BLACK
} else {
Color.WHITE
}
}
else -> {
theme.backgroundColor
}
}
setBackgroundColor(bg.toInt());
} }
webViewClient = object : WebViewClient() { webViewClient = object : WebViewClient() {

View File

@ -58,6 +58,8 @@ class WebReaderLoadingContainerActivity: ComponentActivity() {
val requestID = intent.getStringExtra("SAVED_ITEM_REQUEST_ID") val requestID = intent.getStringExtra("SAVED_ITEM_REQUEST_ID")
val slug = intent.getStringExtra("SAVED_ITEM_SLUG") val slug = intent.getStringExtra("SAVED_ITEM_SLUG")
viewModel.loadItem(slug = slug, requestID = requestID)
setContent { setContent {
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
val useDarkIcons = !isSystemInDarkTheme() val useDarkIcons = !isSystemInDarkTheme()
@ -140,7 +142,6 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null,
val maxToolbarHeight = 48.dp val maxToolbarHeight = 48.dp
webReaderViewModel.maxToolbarHeightPx = with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() } webReaderViewModel.maxToolbarHeightPx = with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() }
webReaderViewModel.loadItem(slug = slug, requestID = requestID)
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()

View File

@ -7,11 +7,11 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat.startActivity import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.* import androidx.lifecycle.*
import app.omnivore.omnivore.DatastoreKeys import app.omnivore.omnivore.DatastoreKeys
import app.omnivore.omnivore.DatastoreRepository import app.omnivore.omnivore.DatastoreRepository
import app.omnivore.omnivore.EventTracker
import app.omnivore.omnivore.dataService.* import app.omnivore.omnivore.dataService.*
import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
import app.omnivore.omnivore.graphql.generated.type.SetLabelsInput import app.omnivore.omnivore.graphql.generated.type.SetLabelsInput
@ -20,7 +20,6 @@ import app.omnivore.omnivore.networking.*
import app.omnivore.omnivore.persistence.entities.SavedItem import app.omnivore.omnivore.persistence.entities.SavedItem
import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCrossRef import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCrossRef
import app.omnivore.omnivore.persistence.entities.SavedItemLabel import app.omnivore.omnivore.persistence.entities.SavedItemLabel
import app.omnivore.omnivore.ui.components.LabelSwatchHelper
import app.omnivore.omnivore.ui.library.SavedItemAction import app.omnivore.omnivore.ui.library.SavedItemAction
import com.apollographql.apollo3.api.Optional import com.apollographql.apollo3.api.Optional
import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull
@ -28,9 +27,6 @@ import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -46,7 +42,7 @@ data class AnnotationWebViewMessage(
) )
enum class Themes(val themeKey: String, val backgroundColor: Long, val foregroundColor: Long) { enum class Themes(val themeKey: String, val backgroundColor: Long, val foregroundColor: Long) {
SYSTEM("System", 0xFFFFFFFF, 0xFF000000), SYSTEM("System", 0xFF000000, 0xFF000000),
LIGHT("Light", 0xFFFFFFFF, 0xFF000000), LIGHT("Light", 0xFFFFFFFF, 0xFF000000),
SEPIA("Sepia", 0xFFFBF0D9, 0xFF000000), SEPIA("Sepia", 0xFFFBF0D9, 0xFF000000),
DARK("Dark", 0xFF2F3030, 0xFFFFFFFF), DARK("Dark", 0xFF2F3030, 0xFFFFFFFF),
@ -58,7 +54,8 @@ enum class Themes(val themeKey: String, val backgroundColor: Long, val foregroun
class WebReaderViewModel @Inject constructor( class WebReaderViewModel @Inject constructor(
private val datastoreRepo: DatastoreRepository, private val datastoreRepo: DatastoreRepository,
private val dataService: DataService, private val dataService: DataService,
private val networker: Networker private val networker: Networker,
private val eventTracker: EventTracker,
): ViewModel() { ): ViewModel() {
var lastJavascriptActionLoopUUID: UUID = UUID.randomUUID() var lastJavascriptActionLoopUUID: UUID = UUID.randomUUID()
var javascriptDispatchQueue: MutableList<String> = mutableListOf() var javascriptDispatchQueue: MutableList<String> = mutableListOf()
@ -174,6 +171,13 @@ class WebReaderViewModel @Inject constructor(
if (webReaderParams != null) { if (webReaderParams != null) {
Log.d("reader", "data loaded from server") Log.d("reader", "data loaded from server")
eventTracker.track("link_read",
com.posthog.android.Properties()
.putValue("linkID", webReaderParams.item.savedItemId)
.putValue("slug", webReaderParams.item.slug)
.putValue("originalArticleURL", webReaderParams.item.pageURLString)
.putValue("loaded_from", "network")
)
webReaderParamsLiveData.postValue(webReaderParams) webReaderParamsLiveData.postValue(webReaderParams)
isLoading = false isLoading = false
} }
@ -185,6 +189,13 @@ class WebReaderViewModel @Inject constructor(
if (webReaderParams != null && isSuccessful) { if (webReaderParams != null && isSuccessful) {
this.slug = webReaderParams.item.slug this.slug = webReaderParams.item.slug
eventTracker.track("link_read",
com.posthog.android.Properties()
.putValue("linkID", webReaderParams.item.savedItemId)
.putValue("slug", webReaderParams.item.slug)
.putValue("originalArticleURL", webReaderParams.item.pageURLString)
.putValue("loaded_from", "request_id")
)
webReaderParamsLiveData.postValue(webReaderParams) webReaderParamsLiveData.postValue(webReaderParams)
isLoading = false isLoading = false
} else if (requestCount < 7) { } else if (requestCount < 7) {
@ -210,14 +221,21 @@ class WebReaderViewModel @Inject constructor(
labelsJSONString = Gson().toJson(persistedItem.labels) labelsJSONString = Gson().toJson(persistedItem.labels)
) )
Log.d("sync", "data loaded from db") val webReaderParams = WebReaderParams(
webReaderParamsLiveData.postValue( persistedItem.savedItem,
WebReaderParams( articleContent,
persistedItem.savedItem, persistedItem.labels
articleContent,
persistedItem.labels
)
) )
Log.d("sync", "data loaded from db")
eventTracker.track("link_read",
com.posthog.android.Properties()
.putValue("linkID", webReaderParams.item.savedItemId)
.putValue("slug", webReaderParams.item.slug)
.putValue("originalArticleURL", webReaderParams.item.pageURLString)
.putValue("loaded_from", "db")
)
webReaderParamsLiveData.postValue(webReaderParams)
} }
isLoading = false isLoading = false
} }

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="pspdfkit_license_key">unset</string> <string name="pspdfkit_license_key">unset</string>
<string name="segment_write_key">unset</string> <string name="posthog_client_key">unset</string>
<string name="posthog_instance_address">unset</string>
<string name="intercom_api_key">unset</string> <string name="intercom_api_key">unset</string>
<string name="intercom_app_id">unset</string> <string name="intercom_app_id">unset</string>
</resources> </resources>