Skip to content

Commit

Permalink
Merge pull request #10 from gooGofZ/1.2.0
Browse files Browse the repository at this point in the history
Version 1.2.0
  • Loading branch information
gooGofZ authored Dec 31, 2022
2 parents ee023d7 + 3b99202 commit d93a8b6
Show file tree
Hide file tree
Showing 14 changed files with 847 additions and 13 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ android {
applicationId "com.googof.bitcointimechainwidgets"
minSdkVersion 26
targetSdkVersion 33
versionCode 7
versionName "1.1.2"
versionCode 8
versionName "1.2.0"
multiDexEnabled true
}

Expand Down
40 changes: 30 additions & 10 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.BitcoinTimechainWidgets"
>
<!-- <receiver-->
<!-- android:name="com.googof.bitcointimechainwidgets.MempoolAppWidget"-->
<!-- android:exported="false">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
<!-- </intent-filter>-->

<!-- <meta-data-->
<!-- android:name="android.appwidget.provider"-->
<!-- android:resource="@xml/mempool_app_widget_info" />-->
<!-- </receiver>-->
<receiver
android:name="com.googof.bitcointimechainwidgets.mempool.MempoolGlanceWidgetReceiver"
android:label="Mempool Glance"
Expand All @@ -39,6 +29,36 @@
android:resource="@xml/mempool_app_widget_info_glance" />
</receiver>

<receiver
android:name="com.googof.bitcointimechainwidgets.mempool.transactionfees.TransactionFeesGlanceWidgetReceiver"
android:label="Transaction Fees"
android:enabled="@bool/glance_appwidget_available"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/transaction_fees_widget_info_glance" />
</receiver>


<receiver
android:name="com.googof.bitcointimechainwidgets.mempool.blockheight.BlockHeightGlanceWidgetReceiver"
android:label="Block Height"
android:enabled="@bool/glance_appwidget_available"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/block_height_widget_glance" />
</receiver>


<receiver
android:name="com.googof.bitcointimechainwidgets.quotes.QuoteInfoGlanceWidgetReceiver"
android:label="Bitcoin Quotes Glance"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fun AppWidgetColumn(
@Composable
fun appWidgetBackgroundModifier() = GlanceModifier
.fillMaxSize()
.padding(10.dp)
.padding(8.dp)
.appWidgetBackground()
.background(GlanceTheme.colors.background)
.appWidgetBackgroundCornerRadius()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.googof.bitcointimechainwidgets.mempool

import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.glance.*
import androidx.glance.action.ActionParameters
import androidx.glance.action.clickable
import androidx.glance.appwidget.CircularProgressIndicator
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.action.ActionCallback
import androidx.glance.appwidget.action.actionRunCallback
import androidx.glance.appwidget.appWidgetBackground
import androidx.glance.layout.*
import androidx.glance.text.FontStyle
import androidx.glance.text.FontWeight
import androidx.glance.text.Text
import androidx.glance.text.TextStyle
import androidx.glance.unit.ColorProvider
import com.googof.bitcointimechainwidgets.AppWidgetBox
import com.googof.bitcointimechainwidgets.AppWidgetColumn
import com.googof.bitcointimechainwidgets.GlanceTheme
import com.googof.bitcointimechainwidgets.R
import com.googof.bitcointimechainwidgets.mempool.blockheight.BlockHeightWorker
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class BlockHeightGlanceWidget : GlanceAppWidget() {

// Override the state definition to use our custom one using Kotlin serialization
override val stateDefinition = MempoolInfoStateDefinition

@Composable
override fun Content() {
val mempoolInfo = currentState<MempoolInfo>()
GlanceTheme {
when (mempoolInfo) {
MempoolInfo.Loading -> {
AppWidgetBox(
contentAlignment = Alignment.Center,
modifier = GlanceModifier.appWidgetBackground()
.background(R.color.widget_background_color)
) {
CircularProgressIndicator(color = ColorProvider(R.color.white))
}
}
is MempoolInfo.Available -> {
AppWidgetColumn(
modifier = GlanceModifier.appWidgetBackground()
.background(R.color.widget_background_color)
) {
BlockHeightCompose(mempoolInfo)
}
}

is MempoolInfo.Unavailable -> {
AppWidgetColumn(
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text("Data not available")
Button("Refresh", actionRunCallback<UpdateBlockHeightAction>())
}
}
}
}
}
}


@Composable
fun BlockHeightCompose(mempoolInfo: MempoolInfo.Available) {
Column(
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = GlanceModifier.fillMaxSize()
.clickable(actionRunCallback<UpdateBlockHeightAction>()),
) {

Text(
text = "Block Height",
style = TextStyle(
color = ColorProvider(R.color.widget_text_color),
),
modifier = GlanceModifier.clickable(actionRunCallback<UpdateBlockHeightAction>())
)

Text(
text = mempoolInfo.blockHeight,
style = TextStyle(
color = ColorProvider(R.color.widget_text_color),
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
),
modifier = GlanceModifier.clickable(actionRunCallback<UpdateBlockHeightAction>())
)
}
}

/**
* Force update the info after user click
*/
class UpdateBlockHeightAction : ActionCallback {
override suspend fun onAction(
context: Context,
glanceId: GlanceId,
parameters: ActionParameters
) {
// Force the worker to refresh
BlockHeightWorker.enqueue(context = context, force = true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.googof.bitcointimechainwidgets.mempool.blockheight

import android.content.Context
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import com.googof.bitcointimechainwidgets.mempool.BlockHeightGlanceWidget

class BlockHeightGlanceWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget = BlockHeightGlanceWidget()

override fun onEnabled(context: Context) {
super.onEnabled(context)
BlockHeightWorker.enqueue(context)
}

override fun onDisabled(context: Context) {
super.onDisabled(context)
BlockHeightWorker.cancel(context)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.googof.bitcointimechainwidgets.mempool.blockheight

import android.content.Context
import androidx.glance.GlanceId
import androidx.glance.appwidget.GlanceAppWidgetManager
import androidx.glance.appwidget.state.updateAppWidgetState
import androidx.glance.appwidget.updateAll
import androidx.work.*
import com.googof.bitcointimechainwidgets.mempool.BlockHeightGlanceWidget
import com.googof.bitcointimechainwidgets.mempool.MempoolInfo
import com.googof.bitcointimechainwidgets.mempool.MempoolInfoStateDefinition
import com.googof.bitcointimechainwidgets.mempool.MempoolRepo
import java.time.Duration

class BlockHeightWorker(
private val context: Context,
workerParameters: WorkerParameters
) : CoroutineWorker(context, workerParameters) {

companion object {
private val uniqueWorkName = BlockHeightWorker::class.java.simpleName
fun enqueue(context: Context, force: Boolean = false) {
val manager = WorkManager.getInstance(context)
val requestBuilder = PeriodicWorkRequestBuilder<BlockHeightWorker>(
Duration.ofMinutes(15)
)
var workPolicy = ExistingPeriodicWorkPolicy.KEEP

// Replace any enqueued work and expedite the request
if (force) {
workPolicy = ExistingPeriodicWorkPolicy.REPLACE
}

manager.enqueueUniquePeriodicWork(
uniqueWorkName,
workPolicy,
requestBuilder.build()
)
}

/**
* Cancel any ongoing worker
*/
fun cancel(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(uniqueWorkName)
}
}

override suspend fun doWork(): Result {
val manager = GlanceAppWidgetManager(context)
val glanceIds = manager.getGlanceIds(BlockHeightGlanceWidget::class.java)
return try {
// Update state to indicate loading
setWidgetState(glanceIds, MempoolInfo.Loading)
// Update state with new data
setWidgetState(glanceIds, MempoolRepo.getMempoolInfo())

Result.success()
} catch (e: Exception) {
setWidgetState(glanceIds, MempoolInfo.Unavailable(e.message.orEmpty()))
if (runAttemptCount < 10) {
// Exponential backoff strategy will avoid the request to repeat
// too fast in case of failures.
Result.retry()
} else {
Result.failure()
}
}
}

private suspend fun setWidgetState(glanceIds: List<GlanceId>, newState: MempoolInfo) {
glanceIds.forEach { glanceId ->
updateAppWidgetState(
context = context,
definition = MempoolInfoStateDefinition,
glanceId = glanceId,
updateState = { newState }
)
}
BlockHeightGlanceWidget().updateAll(context)
}
}
Loading

0 comments on commit d93a8b6

Please sign in to comment.