-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from gooGofZ/1.2.0
Version 1.2.0
- Loading branch information
Showing
14 changed files
with
847 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
...in/java/com/googof/bitcointimechainwidgets/mempool/blockheight/BlockHeightGlanceWidget.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...com/googof/bitcointimechainwidgets/mempool/blockheight/BlockHeightGlanceWidgetReceiver.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
...src/main/java/com/googof/bitcointimechainwidgets/mempool/blockheight/BlockHeightWorker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
Oops, something went wrong.