v0.2.3: true ticking countdown via a tiny native module (no deps)
Some checks failed
build-apk / build (push) Has been cancelled
Some checks failed
build-apk / build (push) Has been cancelled
Replaces the static status notification with a native Android chronometer that counts DOWN to the session end — the system ticks it every second with zero app CPU/battery, visible without opening the app. - modules/bbp-notify: a ~50-line local Expo module using only NotificationCompat (setWhen + setUsesChronometer + setChronometerCountDown + ongoing). Zero third-party dependencies, no Firebase — fits the de-Googled ethos. Verified: autolinks + Kotlin compiles. - sessionStatus.ts uses it when present, else falls back to the expo-notifications static expiry-time notification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b9bd6bd1c6
commit
d0f31d5278
103 changed files with 204 additions and 14 deletions
|
|
@ -3,14 +3,14 @@
|
|||
"name": "BigBrainParking",
|
||||
"slug": "bigbrainparking",
|
||||
"scheme": "bigbrainparking",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.3",
|
||||
"orientation": "portrait",
|
||||
"userInterfaceStyle": "automatic",
|
||||
"newArchEnabled": true,
|
||||
"icon": "./assets/icon.png",
|
||||
"android": {
|
||||
"package": "top.mowden.bigbrainparking",
|
||||
"versionCode": 12,
|
||||
"versionCode": 13,
|
||||
"edgeToEdgeEnabled": true,
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
|
|
|
|||
27
app/modules/bbp-notify/android/build.gradle
Normal file
27
app/modules/bbp-notify/android/build.gradle
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
group = 'expo.modules.bbpnotify'
|
||||
version = '0.1.0'
|
||||
|
||||
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
||||
apply from: expoModulesCorePlugin
|
||||
applyKotlinExpoModulesCorePlugin()
|
||||
useCoreDependencies()
|
||||
useDefaultAndroidSdkVersions()
|
||||
useExpoPublishing()
|
||||
|
||||
android {
|
||||
namespace "expo.modules.bbpnotify"
|
||||
defaultConfig {
|
||||
versionCode 1
|
||||
versionName "0.1.0"
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.core:core-ktx:1.13.1"
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package expo.modules.bbpnotify;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = false;
|
||||
public static final String LIBRARY_PACKAGE_NAME = "expo.modules.bbpnotify";
|
||||
public static final String BUILD_TYPE = "release";
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
#Mon Jul 13 20:59:42 PDT 2026
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/home/hank/Downloads/Software/ParkSmarter/app/modules/bbp-notify/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/home/hank/Downloads/Software/ParkSmarter/app/modules/bbp-notify/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="release$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/home/hank/Downloads/Software/ParkSmarter/app/modules/bbp-notify/android/src/release/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="release" generated-set="release$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/home/hank/Downloads/Software/ParkSmarter/app/modules/bbp-notify/android/src/release/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/home/hank/Downloads/Software/ParkSmarter/app/modules/bbp-notify/android/build/generated/res/resValues/release"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated" generated-set="generated$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/home/hank/Downloads/Software/ParkSmarter/app/modules/bbp-notify/android/build/generated/res/resValues/release"/></dataSet><mergedItems/></merger>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
R_DEF: Internal format may change without notice
|
||||
local
|
||||
|
|
@ -0,0 +1 @@
|
|||
0 Warning/Error
|
||||
|
|
@ -0,0 +1 @@
|
|||
expo.modules.bbpnotify
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,2 @@
|
|||
1
|
||||
0
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,89 @@
|
|||
package expo.modules.bbpnotify
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import expo.modules.kotlin.modules.Module
|
||||
import expo.modules.kotlin.modules.ModuleDefinition
|
||||
|
||||
/**
|
||||
* A tiny, self-contained module that posts an ongoing notification whose "time"
|
||||
* is a native Android chronometer counting DOWN to the session's end. The system
|
||||
* ticks it every second with no app CPU/battery — works while the app is closed.
|
||||
*
|
||||
* Uses only platform APIs (NotificationCompat) — no third-party dependencies.
|
||||
*/
|
||||
class BbpNotifyModule : Module() {
|
||||
override fun definition() = ModuleDefinition {
|
||||
Name("BbpNotify")
|
||||
|
||||
AsyncFunction("showCountdown") { title: String, body: String, endTimeMillis: Double ->
|
||||
val ctx = appContext.reactContext ?: return@AsyncFunction
|
||||
ensureChannel(ctx)
|
||||
|
||||
val builder = NotificationCompat.Builder(ctx, CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentText(body)
|
||||
.setSmallIcon(ctx.applicationInfo.icon)
|
||||
.setOngoing(true)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setShowWhen(true)
|
||||
.setWhen(endTimeMillis.toLong())
|
||||
.setUsesChronometer(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
builder.setChronometerCountDown(true)
|
||||
}
|
||||
|
||||
ctx.packageManager.getLaunchIntentForPackage(ctx.packageName)?.let { launch ->
|
||||
builder.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
ctx,
|
||||
0,
|
||||
launch,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
NotificationManagerCompat.from(ctx).notify(NOTIF_ID, builder.build())
|
||||
} catch (_: SecurityException) {
|
||||
// POST_NOTIFICATIONS not granted yet; caller requests it separately.
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFunction("clear") {
|
||||
val ctx = appContext.reactContext
|
||||
if (ctx != null) {
|
||||
NotificationManagerCompat.from(ctx).cancel(NOTIF_ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ensureChannel(ctx: Context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val mgr = ctx.getSystemService(NotificationManager::class.java)
|
||||
if (mgr.getNotificationChannel(CHANNEL_ID) == null) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
"Active parking",
|
||||
NotificationManager.IMPORTANCE_LOW,
|
||||
)
|
||||
channel.setShowBadge(false)
|
||||
mgr.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL_ID = "session-status"
|
||||
private const val NOTIF_ID = 42421
|
||||
}
|
||||
}
|
||||
6
app/modules/bbp-notify/expo-module.config.json
Normal file
6
app/modules/bbp-notify/expo-module.config.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"platforms": ["android"],
|
||||
"android": {
|
||||
"modules": ["expo.modules.bbpnotify.BbpNotifyModule"]
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue