mirror of
https://github.com/usetrmnl/trmnl-android.git
synced 2026-04-29 13:35:26 -07:00
@@ -19,4 +19,9 @@ object AppConfig {
|
||||
* Ref: https://discord.com/channels/1281055965508141100/1284986536357662740/1364623667337760910
|
||||
*/
|
||||
const val TRMNL_API_SERVER_BASE_URL = "https://trmnl.app/"
|
||||
|
||||
/**
|
||||
* URL for the TRMNL Android app on GitHub.
|
||||
*/
|
||||
const val TRMNL_ANDROID_APP_GITHUB_URL = "https://github.com/usetrmnl/trmnl-android"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
package ink.trmnl.android.ui.aboutapp
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.slack.circuit.codegen.annotations.CircuitInject
|
||||
import com.slack.circuit.runtime.CircuitUiState
|
||||
import com.slack.circuit.runtime.Navigator
|
||||
import com.slack.circuit.runtime.presenter.Presenter
|
||||
import com.slack.circuit.runtime.screen.Screen
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import ink.trmnl.android.BuildConfig
|
||||
import ink.trmnl.android.R
|
||||
import ink.trmnl.android.data.AppConfig.TRMNL_ANDROID_APP_GITHUB_URL
|
||||
import ink.trmnl.android.di.AppScope
|
||||
import ink.trmnl.android.ui.aboutapp.AppInfoScreen.Event
|
||||
import ink.trmnl.android.ui.aboutapp.AppInfoScreen.State
|
||||
import ink.trmnl.android.ui.theme.TrmnlDisplayAppTheme
|
||||
import ink.trmnl.android.ui.theme.TrmnlOrange
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* Screen for displaying app information and links.
|
||||
*/
|
||||
@Parcelize
|
||||
data object AppInfoScreen : Screen {
|
||||
data class State(
|
||||
val appVersion: String,
|
||||
val buildType: String,
|
||||
val eventSink: (Event) -> Unit,
|
||||
) : CircuitUiState
|
||||
|
||||
sealed class Event {
|
||||
data object BackPressed : Event()
|
||||
|
||||
data object OpenGithub : Event()
|
||||
}
|
||||
}
|
||||
|
||||
class AppInfoPresenter
|
||||
@AssistedInject
|
||||
constructor(
|
||||
@Assisted private val navigator: Navigator,
|
||||
) : Presenter<AppInfoScreen.State> {
|
||||
@Composable
|
||||
override fun present(): AppInfoScreen.State {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val appVersion = BuildConfig.VERSION_NAME
|
||||
val buildType = BuildConfig.BUILD_TYPE
|
||||
|
||||
return State(
|
||||
appVersion = appVersion,
|
||||
buildType = buildType,
|
||||
eventSink = { event ->
|
||||
when (event) {
|
||||
Event.BackPressed -> navigator.pop()
|
||||
Event.OpenGithub -> {
|
||||
// Handled in the UI
|
||||
uriHandler.openUri(TRMNL_ANDROID_APP_GITHUB_URL)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@CircuitInject(AppInfoScreen::class, AppScope::class)
|
||||
@AssistedFactory
|
||||
fun interface Factory {
|
||||
fun create(navigator: Navigator): AppInfoPresenter
|
||||
}
|
||||
}
|
||||
|
||||
@CircuitInject(AppInfoScreen::class, AppScope::class)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AppInfoContent(
|
||||
state: State,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("App Info") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = { state.eventSink(Event.BackPressed) }) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back",
|
||||
)
|
||||
}
|
||||
},
|
||||
windowInsets = WindowInsets.statusBars,
|
||||
)
|
||||
},
|
||||
contentWindowInsets = WindowInsets.safeDrawing,
|
||||
) { innerPadding ->
|
||||
Column(
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(innerPadding)
|
||||
.padding(horizontal = 32.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
.fillMaxWidth()
|
||||
.navigationBarsPadding(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.trmnl_logo_plain),
|
||||
contentDescription = null,
|
||||
tint = TrmnlOrange,
|
||||
modifier = Modifier.height(64.dp),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.app_name),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = "Version: ${state.appVersion}",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
Text(
|
||||
text = "Build Type: ${state.buildType}",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
|
||||
Button(
|
||||
onClick = { state.eventSink(Event.OpenGithub) },
|
||||
modifier = Modifier.fillMaxWidth(0.7f),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.code_24dp),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
)
|
||||
Text("View Project on GitHub")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun AppInfoScreenPreview() {
|
||||
TrmnlDisplayAppTheme {
|
||||
AppInfoContent(
|
||||
state =
|
||||
State(
|
||||
appVersion = "1.0.0",
|
||||
buildType = "debug",
|
||||
eventSink = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -91,6 +91,7 @@ import ink.trmnl.android.data.TrmnlDisplayRepository
|
||||
import ink.trmnl.android.di.AppScope
|
||||
import ink.trmnl.android.model.TrmnlDeviceConfig
|
||||
import ink.trmnl.android.model.TrmnlDeviceType
|
||||
import ink.trmnl.android.ui.aboutapp.AppInfoScreen
|
||||
import ink.trmnl.android.ui.display.TrmnlMirrorDisplayScreen
|
||||
import ink.trmnl.android.ui.settings.AppSettingsScreen.ValidationResult
|
||||
import ink.trmnl.android.ui.settings.AppSettingsScreen.ValidationResult.Failure
|
||||
@@ -193,6 +194,11 @@ data class AppSettingsScreen(
|
||||
data class ServerUrlChanged(
|
||||
val url: String,
|
||||
) : Event()
|
||||
|
||||
/**
|
||||
* Event triggered when the info icon is clicked.
|
||||
*/
|
||||
data object AppInfoPressed : Event()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +364,11 @@ class AppSettingsPresenter
|
||||
validationResult = null
|
||||
}
|
||||
}
|
||||
|
||||
AppSettingsScreen.Event.AppInfoPressed -> {
|
||||
// Navigate to AppInfoScreen
|
||||
navigator.goTo(AppInfoScreen)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -439,6 +450,15 @@ fun AppSettingsContent(
|
||||
}
|
||||
}
|
||||
},
|
||||
// Add the info action button to navigate to AppInfoScreen
|
||||
actions = {
|
||||
IconButton(onClick = { state.eventSink(AppSettingsScreen.Event.AppInfoPressed) }) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.info_24dp),
|
||||
contentDescription = "App Info",
|
||||
)
|
||||
}
|
||||
},
|
||||
// Configure the TopAppBar to handle status bar insets
|
||||
windowInsets = WindowInsets.statusBars,
|
||||
)
|
||||
|
||||
@@ -14,3 +14,6 @@ val Grey80 = Color(0xFFECEFF1)
|
||||
val Blue40 = Color(0xFF2236B0)
|
||||
val BlueGrey40 = Color(0xFF546E7A)
|
||||
val Grey40 = Color(0xFF47676F)
|
||||
|
||||
// Add TRMNL color - #F8654B
|
||||
val TrmnlOrange = Color(0xFFF8654B)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M320,720 L80,480l240,-240 57,57 -184,184 183,183 -56,56ZM640,720 L583,663 767,479 584,296 640,240 880,480 640,720Z"
|
||||
android:fillColor="#e8eaed"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M440,680h80v-240h-80v240ZM480,360q17,0 28.5,-11.5T520,320q0,-17 -11.5,-28.5T480,280q-17,0 -28.5,11.5T440,320q0,17 11.5,28.5T480,360ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"
|
||||
android:fillColor="#e8eaed"/>
|
||||
</vector>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#F86527</color>
|
||||
<color name="ic_launcher_background">#F8654B</color>
|
||||
</resources>
|
||||
@@ -1,2 +1,2 @@
|
||||
F86527
|
||||
F8654B
|
||||
|
||||
|
||||
Reference in New Issue
Block a user