Initial commit: BountyBoard Android client
Native Kotlin + Jetpack Compose (Material 3) client for the BountyBoard platform. Cookie-session + CSRF auth with a configurable base URL, the full role-based feature set (admin / consultant / developer), local + OIDC SSO sign-in, and background push notifications (WorkManager poll) for alerts and messages. Bundles the app's editorial "ledger" design system and the original Fraunces / Schibsted Grotesk / Spline Sans Mono typefaces. Includes a prebuilt debug APK (BountyBoard-debug.apk) for side-loading. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package com.anypreta.bountyboard
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.anypreta.bountyboard.data.push.PushNotifier
|
||||
import com.anypreta.bountyboard.di.LocalAppContainer
|
||||
import com.anypreta.bountyboard.ui.nav.AppRoot
|
||||
import com.anypreta.bountyboard.ui.theme.BBTheme
|
||||
import com.anypreta.bountyboard.ui.theme.BountyBoardTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
private val requestNotifPermission =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { /* no-op */ }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
installSplashScreen()
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
val container = (application as BountyBoardApp).container
|
||||
|
||||
// Deep link from a tapped system notification.
|
||||
intent?.getStringExtra(PushNotifier.EXTRA_ROUTE)?.let { container.setDeepLink(it) }
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) !=
|
||||
PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
requestNotifPermission.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
setContent {
|
||||
val themeId by container.settings.theme.collectAsStateWithLifecycle(initialValue = "light")
|
||||
CompositionLocalProvider(LocalAppContainer provides container) {
|
||||
BountyBoardTheme(theme = BBTheme.from(themeId)) {
|
||||
AppRoot()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
val container = (application as BountyBoardApp).container
|
||||
intent.getStringExtra(PushNotifier.EXTRA_ROUTE)?.let { container.setDeepLink(it) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user