Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.brainwallet.data.repository
import com.brainwallet.data.source.RemoteConfigSource
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import timber.log.Timber

@Serializable
data class ShopProxy(
@SerialName("widget_url") val widget: String = ""
)

interface ShopProxyRepository {
val shopProxy: StateFlow<List<ShopProxy>>
suspend fun refresh()
}

class ShopProxyRepositoryImpl(
private val remoteConfigSource: RemoteConfigSource,
private val json: Json,
) : ShopProxyRepository {

private val _shopProxy = MutableStateFlow<List<ShopProxy>>(emptyList())
override val shopProxy: StateFlow<List<ShopProxy>> = _shopProxy.asStateFlow()

override suspend fun refresh() {
runCatching { remoteConfigSource.fetchAndActivate() }
.onFailure { Timber.e(it, "RemoteConfig fetch failed") }

val rawJson = remoteConfigSource.getString(RemoteConfigSource.PATH_SHOP_CONTENT)
Timber.d("ShopProxy rawJson: '$rawJson'")

runCatching {
val wrapper = json.decodeFromString<ShopProxyWrapper>(rawJson)
Timber.d("ShopProxy parsed: ${wrapper.shopProxy}")
_shopProxy.value = wrapper.shopProxy
}.onFailure { Timber.e(it, "RemoteConfig parse failed") }
}

@Serializable
private data class ShopProxyWrapper(
@SerialName("shop_data") val shopProxy: List<ShopProxy> = emptyList()
)
}
8 changes: 7 additions & 1 deletion app/src/main/java/com/brainwallet/di/RemoteConfigModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.brainwallet.di
import com.brainwallet.data.repository.FirebaseRemoteConfigRepositoryImpl
import com.brainwallet.data.repository.HubContentRepository
import com.brainwallet.data.repository.HubContentRepositoryImpl
import com.brainwallet.data.repository.ShopProxyRepository
import com.brainwallet.data.repository.ShopProxyRepositoryImpl
import com.brainwallet.data.source.RemoteConfigSource
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import org.koin.dsl.module
Expand All @@ -11,10 +13,14 @@ val remoteConfigModule = module {
single {
FirebaseRemoteConfig.getInstance().apply {
setDefaultsAsync(
mapOf(RemoteConfigSource.KEY_FEATURE_GAMEHUB_CONTENT to "[]")
mapOf(
RemoteConfigSource.KEY_FEATURE_GAMEHUB_CONTENT to "[]",
RemoteConfigSource.PATH_SHOP_CONTENT to "{\"shop_data\":{}}"
)
)
}
}
single<RemoteConfigSource> { FirebaseRemoteConfigRepositoryImpl(get()) }
single<HubContentRepository> { HubContentRepositoryImpl(get(), get()) }
single<ShopProxyRepository> { ShopProxyRepositoryImpl(get(), get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ data class ShopBentoState(
val regionData: String = "",
val countryIso: String = "US",
val darkMode: Boolean = true,
val shouldSlide: Boolean = false
val shouldSlide: Boolean = false,
val shopBaseUrl: String = ""
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import org.koin.android.annotation.KoinViewModel
import java.util.Locale
import android.telephony.TelephonyManager
import com.brainwallet.data.repository.SettingRepository
import com.brainwallet.data.repository.ShopProxyRepository

@KoinViewModel
class ShopBentoViewModel(
private val app: Application,
private val settingRepository: SettingRepository,
private val shopProxyRepository: ShopProxyRepository
) : BrainwalletViewModel<ShopBentoEvent>() {

private val _state = MutableStateFlow(ShopBentoState())
Expand All @@ -34,6 +36,15 @@ class ShopBentoViewModel(
}
}
}
viewModelScope.launch {
shopProxyRepository.refresh()
shopProxyRepository.shopProxy.collect { shopList ->
val widget = shopList.firstOrNull()?.widget.orEmpty()
_state.update {
it.copy(shopBaseUrl = widget)
}
}
}
}
private fun getCountryIso(): String {
val telephonyManager = app.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.brainwallet.ui.composable

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.grunt.brainwallet.core.presentation.theme.BrainwalletTheme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.PreviewLightDark
import com.brainwallet.ui.theme.lavender
import com.brainwallet.ui.theme.midnight

@Composable
fun BrainwalletLoadingIndicator(
modifier: Modifier = Modifier,
color: Color = BrainwalletTheme.colors.content
) {
CircularProgressIndicator(
color = lavender,
trackColor = midnight,
strokeWidth = 5.dp,
modifier = Modifier.size(48.dp).then(modifier)
)
}

@PreviewLightDark
@Composable
private fun BrainwalletLoadingIndicatorPreview() {
Box(modifier = Modifier) {
BrainwalletLoadingIndicator()
}
}
78 changes: 47 additions & 31 deletions app/src/main/java/com/brainwallet/ui/screens/main/WebModalScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,87 @@ import android.view.ViewGroup
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.brainwallet.navigation.OnNavigate
import com.brainwallet.tools.manager.AnalyticsManager
import com.brainwallet.ui.composable.BrainwalletLoadingIndicator
import com.brainwallet.ui.theme.bentoDarkSurfaceGradient

@Composable
fun WebModalScreen(
onNavigate: OnNavigate,
url: String,
modifier: Modifier = Modifier,
) {
val eventString = if (url.contains("bitrefill")) {
"user_did_tap_bitrefill"
"user_did_tap_shop_bento"
} else {
"user_did_tap_linktree"
}
LaunchedEffect(Unit) {
AnalyticsManager.logCustomEvent(eventString)
}

var isLoading by remember { mutableStateOf(true) }

Card(
modifier = modifier
.fillMaxSize()
.background(brush = bentoDarkSurfaceGradient),
modifier = modifier.fillMaxSize(),
shape = RoundedCornerShape(18.dp),
colors = CardDefaults.cardColors(containerColor = Color.Transparent),
) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
WebView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)

setBackgroundColor(0)

settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.useWideViewPort = true
Box(
modifier = Modifier
.fillMaxSize()
.background(brush = bentoDarkSurfaceGradient),
) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
WebView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
setBackgroundColor(0)
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.useWideViewPort = true

webViewClient = object : WebViewClient() {
webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
isLoading = true
}

override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
}

override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
isLoading = false
}
}
}
}
},
update = {
it.loadUrl(url)
},
update = { it.loadUrl(url) }
)

if (isLoading) {
BrainwalletLoadingIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
)
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/res/xml/remote_config_defaults.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</entry>
<entry>
<key>path_shop_content</key>
<value>https://www.bitrefill.com/?ref=bAshL935</value>
<value>{"shop_data":[{ "widget_url":"https://www.bitrefill.com/?ref=2h186s7q"}]}</value>
</entry>
<entry>
<key>key_api_baseurl_prod_new_enabled</key>
Expand Down
Loading