Skip to content
Draft
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
Expand Up @@ -56,7 +56,7 @@ class HeadlinesPreviewContentTest {
// Verify settings and preview section
composeTestRule.onNodeWithTag("WidgetEdit").assertExists()
composeTestRule.onNodeWithTag("headlines_preview_carousel").assertExists()
composeTestRule.onNodeWithTag("headline_card_small").assertExists()
composeTestRule.onNodeWithTag("headline_card_wide").assertExists()

// Verify buttons
composeTestRule.onNodeWithTag("buttons_row").assertExists()
Expand Down Expand Up @@ -162,7 +162,7 @@ class HeadlinesPreviewContentTest {
composeTestRule.onNodeWithTag("divider").assertExists()
composeTestRule.onNodeWithTag("WidgetEdit").assertExists()
composeTestRule.onNodeWithTag("headlines_preview_carousel").assertExists()
composeTestRule.onNodeWithTag("headline_card_small").assertExists()
composeTestRule.onNodeWithTag("headline_card_wide").assertExists()
composeTestRule.onNodeWithTag("buttons_row").assertExists()
composeTestRule.onNodeWithTag("WidgetDelete").assertExists()
composeTestRule.onNodeWithTag("WidgetSave").assertExists()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package to.bitkit.appwidget.config

import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.Intent
import android.os.Bundle
Expand All @@ -20,6 +19,7 @@ import to.bitkit.appwidget.ui.price.PriceGlanceWidget
import to.bitkit.appwidget.ui.weather.WeatherGlanceReceiver
import to.bitkit.appwidget.ui.weather.WeatherGlanceWidget
import to.bitkit.ui.theme.AppThemeSurface
import to.bitkit.ui.utils.enableAppEdgeToEdge
import to.bitkit.utils.Logger

@AndroidEntryPoint
Expand All @@ -34,6 +34,7 @@ class AppWidgetConfigActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableAppEdgeToEdge()

val appWidgetId = intent?.extras?.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
Expand All @@ -58,7 +59,9 @@ class AppWidgetConfigActivity : ComponentActivity() {
onConfirm = {
when (viewModel.uiState.value.type) {
AppWidgetType.PRICE -> PriceGlanceWidget().updateAll(this@AppWidgetConfigActivity)
AppWidgetType.HEADLINES -> HeadlinesGlanceWidget().updateAll(this@AppWidgetConfigActivity)
AppWidgetType.HEADLINES -> HeadlinesGlanceWidget().updateAll(
this@AppWidgetConfigActivity,
)
AppWidgetType.BLOCKS -> BlocksGlanceWidget().updateAll(this@AppWidgetConfigActivity)
AppWidgetType.FACTS -> Unit
AppWidgetType.WEATHER -> WeatherGlanceWidget().updateAll(this@AppWidgetConfigActivity)
Expand All @@ -68,7 +71,7 @@ class AppWidgetConfigActivity : ComponentActivity() {
AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetId,
)
setResult(Activity.RESULT_OK, result)
setResult(RESULT_OK, result)
finish()
},
onCancel = { finish() },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package to.bitkit.appwidget.config

import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -61,10 +60,7 @@ internal fun BlocksConfigContent(
)
}

ScreenColumn(
noBackground = true,
modifier = Modifier.background(Colors.Gray7)
) {
ScreenColumn {
AppTopBar(
titleText = stringResource(R.string.widgets__blocks__name),
onBackClick = onCancel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package to.bitkit.appwidget.config

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -43,10 +42,7 @@ internal fun HeadlinesConfigContent(
val prefs = state.headlinePreferences
val previewArticle = state.previewArticle

ScreenColumn(
noBackground = true,
modifier = Modifier.background(Colors.Gray7)
) {
ScreenColumn {
AppTopBar(
titleText = stringResource(R.string.widgets__news__name),
onBackClick = onCancel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package to.bitkit.appwidget.config

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -44,10 +43,7 @@ internal fun PriceConfigContent(
val prefs = state.pricePreferences
val selectedPair = prefs.enabledPairs.firstOrNull() ?: TradingPair.BTC_USD

ScreenColumn(
noBackground = true,
modifier = Modifier.background(Colors.Gray7)
) {
ScreenColumn {
AppTopBar(
titleText = stringResource(R.string.widgets__price__name),
onBackClick = onCancel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package to.bitkit.appwidget.config

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -37,15 +36,11 @@ internal fun WeatherConfigContent(
onReset: () -> Unit,
onSave: () -> Unit,
onCancel: () -> Unit,
modifier: Modifier = Modifier,
) {
val prefs = state.weatherPreferences
val weather = state.previewWeather

ScreenColumn(
noBackground = true,
modifier = modifier.background(Colors.Gray7)
) {
ScreenColumn {
AppTopBar(
titleText = stringResource(R.string.widgets__weather__name),
onBackClick = onCancel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package to.bitkit.appwidget.ui.facts

import android.content.Intent
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.glance.GlanceModifier
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.LocalContext
import androidx.glance.LocalSize
import androidx.glance.appwidget.action.actionStartActivity
import androidx.glance.layout.Alignment
import androidx.glance.layout.Box
import androidx.glance.layout.fillMaxSize
Expand All @@ -18,6 +20,7 @@ import to.bitkit.appwidget.ui.components.CaptionB
import to.bitkit.appwidget.ui.components.GlanceLayoutDimens
import to.bitkit.appwidget.ui.components.GlanceWidgetScaffold
import to.bitkit.appwidget.ui.theme.GlanceTextStyles
import to.bitkit.ui.MainActivity

private val BADGE_SIZE = 32.dp
private val BADGE_RESERVED_END = 40.dp
Expand All @@ -28,8 +31,11 @@ fun FactsGlanceContent(
fact: String?,
) {
val context = LocalContext.current
val openAppIntent = Intent(context, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}

GlanceWidgetScaffold {
GlanceWidgetScaffold(onClick = actionStartActivity(openAppIntent)) {
if (fact == null) {
CaptionB(text = context.getString(R.string.appwidget__loading))
return@GlanceWidgetScaffold
Expand Down
46 changes: 29 additions & 17 deletions app/src/main/java/to/bitkit/data/widgets/PriceService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import to.bitkit.models.WidgetType
import to.bitkit.utils.AppError
import to.bitkit.utils.Logger
import java.text.NumberFormat
import java.util.Currency
import java.util.Locale
import javax.inject.Inject
import javax.inject.Singleton
Expand Down Expand Up @@ -147,24 +146,15 @@ class PriceService @Inject constructor(
)
}

private fun formatPrice(pair: TradingPair, price: Double): String {
private fun formatPrice(
pair: TradingPair,
price: Double,
locale: Locale = Locale.getDefault(),
): String {
return runCatching {
val currency = Currency.getInstance(pair.quote)
val numberFormat = NumberFormat.getCurrencyInstance(Locale.US).apply {
this.currency = currency
maximumFractionDigits = when {
price >= 1000 -> 0
price >= 1 -> 2
else -> 6
}
}

// Format and remove currency symbol, keeping only the number with formatting
val formatted = numberFormat.format(price)
val currencySymbol = currency.symbol
formatted.replace(currencySymbol, "").trim()
formatPriceValue(price = price, locale = locale)
}.onFailure {
Logger.warn("Error formatting price for ${pair.displayName}", e = it, context = TAG)
Logger.warn("Failed to format price for '${pair.displayName}'", it, context = TAG)
}.getOrDefault(String.format(Locale.US, "%.2f", price))
}

Expand All @@ -180,3 +170,25 @@ sealed class PriceError(message: String) : AppError(message) {
class InvalidResponse(override val message: String) : PriceError(message)
class NetworkError(override val message: String) : PriceError(message)
}

private const val GROUPED_PRICE_THRESHOLD = 1_000.0
private const val STANDARD_PRICE_THRESHOLD = 1.0
private const val GROUPED_PRICE_DECIMALS = 0
private const val STANDARD_PRICE_DECIMALS = 2
private const val SMALL_PRICE_DECIMALS = 6
private const val MIN_PRICE_DECIMALS = 0

internal fun formatPriceValue(
price: Double,
locale: Locale = Locale.getDefault(),
): String {
return NumberFormat.getNumberInstance(locale).apply {
maximumFractionDigits = when {
price >= GROUPED_PRICE_THRESHOLD -> GROUPED_PRICE_DECIMALS
price >= STANDARD_PRICE_THRESHOLD -> STANDARD_PRICE_DECIMALS
else -> SMALL_PRICE_DECIMALS
}
minimumFractionDigits = MIN_PRICE_DECIMALS
isGroupingUsed = true
}.format(price)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package to.bitkit.ui.screens.widgets.blocks

import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -40,6 +39,7 @@ fun BlocksEditScreen(
blocksViewModel: BlocksViewModel,
onBack: () -> Unit,
navigatePreview: () -> Unit,
modifier: Modifier = Modifier,
) {
val customPreference by blocksViewModel.customPreferences.collectAsStateWithLifecycle()
val currentBlock by blocksViewModel.currentBlock.collectAsStateWithLifecycle()
Expand Down Expand Up @@ -67,6 +67,7 @@ fun BlocksEditScreen(
onClickShowSource = { blocksViewModel.toggleShowSource() },
onClickReset = { blocksViewModel.resetCustomPreferences() },
onClickPreview = navigatePreview,
modifier = modifier
)
}

Expand All @@ -84,12 +85,10 @@ private fun Content(
onClickPreview: () -> Unit,
blocksPreferences: BlocksPreferences,
block: BlockModel,
modifier: Modifier = Modifier,
) {
ScreenColumn(
noBackground = true,
modifier = Modifier
.background(Colors.Gray7)
.testTag("blocks_edit_screen")
modifier = modifier.testTag("blocks_edit_screen")
) {
AppTopBar(
titleText = stringResource(R.string.widgets__blocks__name),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package to.bitkit.ui.screens.widgets.blocks

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -37,6 +36,7 @@ fun BlocksPreviewScreen(
onClose: () -> Unit,
onBack: () -> Unit,
navigateEditWidget: () -> Unit,
modifier: Modifier = Modifier,
) {
val customBlocksPreferences by blocksViewModel.customPreferences.collectAsStateWithLifecycle()
val currentBlock by blocksViewModel.currentBlock.collectAsStateWithLifecycle()
Expand All @@ -60,6 +60,7 @@ fun BlocksPreviewScreen(
blocksViewModel.savePreferences()
onClose()
},
modifier = modifier
)
}

Expand All @@ -72,12 +73,10 @@ private fun Content(
isBlocksWidgetEnabled: Boolean,
blocksPreferences: BlocksPreferences,
block: BlockModel?,
modifier: Modifier = Modifier,
) {
ScreenColumn(
noBackground = true,
modifier = Modifier
.background(Colors.Gray7)
.testTag("blocks_preview_screen")
modifier = modifier.testTag("blocks_preview_screen")
) {
AppTopBar(
titleText = stringResource(R.string.widgets__blocks__name),
Expand Down
Loading
Loading