Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support md3 #5

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ dependencies {
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.activity:activity-compose:1.9.2")
implementation(platform("androidx.compose:compose-bom:2024.09.01"))
implementation("androidx.compose.material3:material3:1.3.1")
implementation("androidx.compose.material:material")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.compose.ui:ui")
Expand Down
212 changes: 117 additions & 95 deletions app/src/main/java/org/fcitx/fcitx5/android/updater/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.activity.viewModels
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -27,36 +25,37 @@ import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.AppBarDefaults
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.DrawerDefaults
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.ListItem
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.LibraryBooks
import androidx.compose.material.icons.filled.Book
import androidx.compose.material.icons.filled.Extension
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.SystemUpdate
import androidx.compose.material.primarySurface
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material.rememberScaffoldState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DrawerDefaults
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
Expand All @@ -66,14 +65,14 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
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.unit.dp
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
Expand Down Expand Up @@ -128,7 +127,7 @@ class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge(statusBarStyle = SystemBarStyle.dark(0))
enableEdgeToEdge()
intentLauncher = registerForActivityResult(StartActivityForResult()) {
viewModel.versions.value.forEach {
it.value.refreshIfInstalledChanged()
Expand Down Expand Up @@ -177,92 +176,106 @@ class MainActivity : ComponentActivity() {
}
}

@OptIn(ExperimentalMaterialApi::class)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(
viewModels: Map<String, VersionViewModel>,
content: @Composable (PaddingValues, NavHostController, viewModels: Map<String, VersionViewModel>) -> Unit
) {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()
val scrimColor = Color.Black.copy(DrawerDefaults.ScrimOpacity)
Scaffold(
scaffoldState = scaffoldState,
modifier = Modifier
.windowInsetsPadding(WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)),
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
backgroundColor = MaterialTheme.colors.primarySurface,
windowInsets = AppBarDefaults.topAppBarWindowInsets,
navigationIcon = {
IconButton(onClick = { scope.launch { scaffoldState.drawerState.open() } }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = null)
val scrimColor = DrawerDefaults.scrimColor
val drawerState = rememberDrawerState(DrawerValue.Closed)

ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet(
content = {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
viewModels.forEach { (name, _) ->
val selected = navBackStackEntry?.destination?.route == name
val color =
if (selected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
val icon = when {
name == "fcitx5-android" -> Icons.Default.Keyboard
name == "fcitx5-android-updater" -> Icons.Default.SystemUpdate
name.startsWith("pinyin-") -> Icons.AutoMirrored.Filled.LibraryBooks
name.startsWith("tables-") -> Icons.Default.Book
else -> Icons.Default.Extension
}
NavigationDrawerItem(
modifier = Modifier
.clickable {
scope.launch {
drawerState.close()
}
navController.navigate(name) {
popUpTo(0)
}
},

icon = {
Icon(
icon,
contentDescription = "Navigate to $name",
tint = color
)
},
label = {
Text(
text = name.removePrefix("fcitx5-android-"),
color = color,
fontWeight = FontWeight.SemiBold,
)
},
selected = selected,
onClick = {
scope.launch { drawerState.close() }
navController.navigate(name) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
// clear navigation stack before navigation
}
)
}
}
}

)
},
drawerScrimColor = scrimColor,
drawerContent = {
Box {
Box(
modifier = Modifier
.align(Alignment.TopCenter)
.fillMaxWidth()
.windowInsetsTopHeight(WindowInsets.statusBars)
.background(scrimColor)
)
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
Spacer(Modifier.windowInsetsTopHeight(WindowInsets.statusBars))
viewModels.forEach { (name, _) ->
val selected = navBackStackEntry?.destination?.route == name
val color =
if (selected) MaterialTheme.colors.primary else MaterialTheme.colors.onSurface
val icon = when {
name == "fcitx5-android" -> Icons.Default.Keyboard
name == "fcitx5-android-updater" -> Icons.Default.SystemUpdate
name.startsWith("pinyin-") -> Icons.AutoMirrored.Filled.LibraryBooks
name.startsWith("tables-") -> Icons.Default.Book
else -> Icons.Default.Extension
}
ListItem(
modifier = Modifier.clickable {
scope.launch {
scaffoldState.drawerState.close()
}
navController.navigate(name) {
// clear navigation stack before navigation
popUpTo(0)
}
},
icon = { Icon(icon, contentDescription = null, tint = color) },
text = {
Text(
text = name.removePrefix("fcitx5-android-"),
color = color,
fontWeight = FontWeight.SemiBold,
scrimColor = scrimColor,
gesturesEnabled = true,
content = {
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
windowInsets = TopAppBarDefaults.windowInsets,
navigationIcon = {
IconButton(onClick = { scope.launch { drawerState.open() } }) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = null
)
}
)
}
Spacer(
Modifier
.padding(bottom = 16.dp)
.windowInsetsBottomHeight(WindowInsets.navigationBars)
}

)
},
content = { paddingValues ->
content(paddingValues, navController, viewModels)
}
}
}
) { paddingValues ->
content(paddingValues, navController, viewModels)
}
BackHandler(enabled = scaffoldState.drawerState.isOpen) {
scope.launch {
scaffoldState.drawerState.close()

)
}
}
)
}

@Composable
Expand Down Expand Up @@ -299,7 +312,8 @@ fun NavScreen(
}
}

val LocalVersionViewModel = compositionLocalOf<VersionViewModel> { error("No view model") }
val LocalVersionViewModel =
compositionLocalOf<VersionViewModel> { error("No view model") }

@Composable
fun versionViewModel() = LocalVersionViewModel.current
Expand All @@ -314,7 +328,8 @@ fun VersionScreen(viewModel: VersionViewModel) {
}
}
val refreshing by viewModel.isRefreshing.collectAsState()
val pullRefreshState = rememberPullRefreshState(refreshing, { viewModel.refresh() })
val pullRefreshState =
rememberPullRefreshState(refreshing, { viewModel.refresh() })
val urlHandler = LocalUriHandler.current
Box(
Modifier
Expand All @@ -328,23 +343,26 @@ fun VersionScreen(viewModel: VersionViewModel) {
.clickable {
urlHandler.openUri(viewModel.url)
},
elevation = 2.dp
shadowElevation = 2.dp
) {
Row(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp),
modifier = Modifier.padding(
horizontal = 16.dp,
vertical = 14.dp
),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(R.drawable.github_mark),
contentDescription = "GitHub Logo",
modifier = Modifier.size(18.dp),
tint = MaterialTheme.colors.onSurface
tint = MaterialTheme.colorScheme.onSurface
)
Text(
text = viewModel.name,
modifier = Modifier.padding(start = 10.dp),
fontWeight = FontWeight.SemiBold,
style = MaterialTheme.typography.body1
style = MaterialTheme.typography.bodyLarge
)
}
}
Expand All @@ -362,7 +380,11 @@ fun VersionScreen(viewModel: VersionViewModel) {
.windowInsetsBottomHeight(WindowInsets.navigationBars)
)
}
PullRefreshIndicator(refreshing, pullRefreshState, Modifier.align(Alignment.TopCenter))
PullRefreshIndicator(
refreshing,
pullRefreshState,
Modifier.align(Alignment.TopCenter)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
Expand All @@ -28,7 +28,7 @@ fun VersionCard(version: VersionUi) {
val (title, size, menu, action) = createRefs()
Text(
text = version.versionName,
style = MaterialTheme.typography.body1,
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.constrainAs(title) {
top.linkTo(parent.top)
start.linkTo(parent.start)
Expand All @@ -37,7 +37,7 @@ fun VersionCard(version: VersionUi) {
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Text(
text = String.format(Locale.ROOT, "%.2f MiB", version.size),
style = MaterialTheme.typography.body2,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier
.padding(bottom = 8.dp)
.constrainAs(size) {
Expand Down
Loading