Skip to content

Commit

Permalink
Mono theme
Browse files Browse the repository at this point in the history
Signed-off-by: Lucchetto <[email protected]>
  • Loading branch information
Lucchetto committed Jan 21, 2023
1 parent c76d869 commit cf0be0f
Show file tree
Hide file tree
Showing 20 changed files with 575 additions and 94 deletions.
41 changes: 41 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ dependencies {
implementation 'androidx.compose.material3:material3:1.1.0-alpha04'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation "androidx.work:work-runtime-ktx:2.7.1"
implementation "io.coil-kt:coil-compose:2.2.2"

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/zhenxiang/superimage/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.lifecycle.viewmodel.compose.viewModel
import com.zhenxiang.superimage.home.HomePage
import com.zhenxiang.superimage.ui.theme.SuperImageTheme
import com.zhenxiang.superimage.ui.theme.MonoTheme

class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SuperImageTheme {
MonoTheme {
HomePage(viewModel())
}
}
Expand Down
175 changes: 150 additions & 25 deletions app/src/main/java/com/zhenxiang/superimage/home/HomePage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,46 @@ package com.zhenxiang.superimage.home

import android.Manifest
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.zhenxiang.realesrgan.UpscalingModel
import com.zhenxiang.superimage.R
import com.zhenxiang.superimage.model.DataState
import com.zhenxiang.superimage.model.InputImage
import com.zhenxiang.superimage.ui.form.DropDownMenu
import com.zhenxiang.superimage.ui.mono.MonoAppBar
import com.zhenxiang.superimage.ui.mono.MonoButton
import com.zhenxiang.superimage.ui.mono.MonoButtonDefaults
import com.zhenxiang.superimage.ui.mono.drawTopBorder
import com.zhenxiang.superimage.ui.theme.MonoTheme
import com.zhenxiang.superimage.ui.theme.border
import com.zhenxiang.superimage.ui.theme.spacing
import kotlinx.coroutines.flow.MutableStateFlow

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomePage(viewModel: HomePageViewModel) = Scaffold { padding ->
fun HomePage(viewModel: HomePageViewModel) = Scaffold(
topBar = { TopBar() }
) { padding ->

val imagePicker = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
it?.let { viewModel.loadImage(it) }
Expand All @@ -52,34 +65,97 @@ fun HomePage(viewModel: HomePageViewModel) = Scaffold { padding ->
Column(modifier = Modifier.padding(padding)) {

val selectedImageState by viewModel.selectedImageFlow.collectAsStateWithLifecycle()
val selectedImage = selectedImageState as? DataState.Success

ModelSelection(flow = viewModel.selectedUpscalingModelFlow)
ImagePreview(
modifier = Modifier
.weight(1f, true)
.fillMaxWidth(),
selectedImageState = selectedImageState
) { imagePicker.launch(HomePageViewModel.IMAGE_MIME_TYPE) }

selectedImage?.data?.let {
Image(bitmap = it.preview.asImageBitmap(), contentDescription = it.fileName)
}

Button(
onClick = { imagePicker.launch(HomePageViewModel.IMAGE_MIME_TYPE) },
Options(
flow = viewModel.selectedUpscalingModelFlow,
selectedImageState = selectedImageState
) {
Text(stringResource(id = R.string.select_image))
viewModel.upscale()
}
}
}

Button(
enabled = selectedImage != null,
onClick = { viewModel.upscale() },
) {
Text(stringResource(id = R.string.upscale_label))
@Composable
private fun TopBar() {
MonoAppBar(
title = { Text(stringResource(id = R.string.app_name)) }
)
}

@Composable
private fun ImagePreview(
modifier: Modifier,
selectedImageState: DataState<InputImage, Unit>?,
onSelectedImage: () -> Unit
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
when (selectedImageState) {
is DataState.Success -> selectedImageState.data.let {
Box(
modifier = Modifier
.weight(1f, fill = false)
.padding(
horizontal = MaterialTheme.spacing.level3,
vertical = MaterialTheme.spacing.level5,
)
,
contentAlignment = Alignment.Center
) {
AsyncImage(
modifier = Modifier
.clip(MaterialTheme.shapes.large),
model = ImageRequest.Builder(LocalContext.current).data(it.fileUri).build(),
contentDescription = it.fileName
)
}

Row(
modifier = Modifier.padding(
horizontal = MaterialTheme.spacing.level5,
vertical = MaterialTheme.spacing.level5,
)
) {
MonoButton(
onClick = onSelectedImage
) {
Icon(
painterResource(id = R.drawable.ic_image_24),
contentDescription = null,
modifier = Modifier
.padding(end = MaterialTheme.spacing.level3)
.size(MonoButtonDefaults.IconSize)
)
Text(stringResource(id = R.string.change_image_label))
}
}
}
else -> {
MonoButton(
onClick = onSelectedImage,
) {
Text(stringResource(id = R.string.select_image_label))
}
}
}
}
}

@Composable
private fun ModelSelection(flow: MutableStateFlow<UpscalingModel>) {

val selected by flow.collectAsStateWithLifecycle()

DropDownMenu(
value = selected,
label = { Text(stringResource(id = R.string.selected_mode_label)) },
Expand All @@ -89,3 +165,52 @@ private fun ModelSelection(flow: MutableStateFlow<UpscalingModel>) {
flow.tryEmit(it)
}
}

@Composable
private fun Options(
flow: MutableStateFlow<UpscalingModel>,
selectedImageState: DataState<InputImage, Unit>?,
onUpscaleClick: () -> Unit
) {
Column(
modifier = Modifier
.drawTopBorder(MaterialTheme.border.regular)
.padding(
horizontal = MaterialTheme.spacing.level3,
vertical = MaterialTheme.spacing.level4
)
) {
Text(
modifier = Modifier.padding(
start = MaterialTheme.spacing.level3,
end = MaterialTheme.spacing.level3,
bottom = MaterialTheme.spacing.level4
),
text = stringResource(id = R.string.upscaling_options_title),
style = MaterialTheme.typography.headlineSmall
)

ModelSelection(flow = flow)

MonoButton(
modifier = Modifier.padding(top = MaterialTheme.spacing.level5),
enabled = selectedImageState is DataState.Success,
onClick = onUpscaleClick,
) {
Text(stringResource(id = R.string.upscale_label))
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun OptionsPreview() = MonoTheme {
Scaffold {
Options(
flow = MutableStateFlow(UpscalingModel.X4_PLUS),
selectedImageState = DataState.Success(InputImage("", "".toUri()))
) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ class HomePageViewModel(application: Application): AndroidViewModel(application)
viewModelScope.launch(Dispatchers.IO) {
val application = getApplication<Application>()
DocumentFile.fromSingleUri(application, imageUri)?.name?.let { fileName ->
BitmapUtils.loadImageFromUri(application.contentResolver, imageUri)?.let { bitmap ->
emit(DataState.Success(InputImage(fileName, imageUri, bitmap)))
} ?: emit(DataState.Error(Unit))
emit(
DataState.Success(
InputImage(fileName, imageUri)
)
)
} ?: emit(DataState.Error(Unit))
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.zhenxiang.superimage.model

import android.graphics.Bitmap
import android.net.Uri

data class InputImage(
val fileName: String,
val fileUri: Uri,
val preview: Bitmap
val fileUri: Uri
)
50 changes: 50 additions & 0 deletions app/src/main/java/com/zhenxiang/superimage/ui/mono/AppBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.zhenxiang.superimage.ui.mono

import android.annotation.SuppressLint
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.zhenxiang.superimage.ui.theme.MonoTheme
import com.zhenxiang.superimage.ui.theme.border
import com.zhenxiang.superimage.ui.theme.spacing

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MonoAppBar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
) {
Row(
modifier = modifier
.fillMaxWidth()
.windowInsetsPadding(windowInsets)
.background(MaterialTheme.colorScheme.primaryContainer)
.drawBottomBorder(MaterialTheme.border.regular)
.padding(MaterialTheme.spacing.level5)
) {
ProvideTextStyle(
value = MaterialTheme.typography.displayMedium,
content = title
)
}
}

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Preview(showBackground = true, showSystemUi = true)
@Preview(showBackground = true, showSystemUi = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun MonoAppBarPreview() = MonoTheme {
Scaffold(
topBar = {
MonoAppBar(
title = { Text("AppBar") }
)
}
) {}
}
Loading

0 comments on commit cf0be0f

Please sign in to comment.