Upstream changes (#23)

This commit is contained in:
2024-07-11 02:12:32 +03:00
committed by GitHub
parent 8a6378f509
commit 3503ecffab
906 changed files with 23577 additions and 24115 deletions
+1
View File
@@ -0,0 +1 @@
/build
+55
View File
@@ -0,0 +1,55 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.org.jetbrains.kotlin.android)
alias(libs.plugins.kotlin.compose.compiler)
}
group = "com.meloda.app.fast.photoviewer"
android {
namespace = "com.meloda.app.fast.photoviewer"
compileSdk = Configs.compileSdk
defaultConfig {
minSdk = Configs.minSdk
}
buildTypes {
release {
isMinifyEnabled = false
}
}
compileOptions {
sourceCompatibility = Configs.java
targetCompatibility = Configs.java
}
kotlinOptions {
jvmTarget = Configs.java.toString()
freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn", "-Xcontext-receivers")
}
buildFeatures {
compose = true
}
composeOptions {
useLiveLiterals = true
}
}
dependencies {
implementation(projects.core.data)
implementation(projects.core.model)
implementation(projects.core.ui)
implementation(libs.nanokt.android)
implementation(libs.nanokt.jvm)
implementation(libs.nanokt)
implementation(libs.koin.android)
implementation(libs.koin.androidx.compose)
implementation(platform(libs.compose.bom))
implementation(libs.bundles.compose)
implementation(libs.coil.compose)
}
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,22 @@
package com.meloda.app.fast.photoviewer
import androidx.lifecycle.ViewModel
import com.meloda.app.fast.common.extensions.setValue
import com.meloda.app.fast.photoviewer.model.PhotoViewArguments
import com.meloda.app.fast.photoviewer.model.PhotoViewState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
interface PhotoViewViewModel {
val state: StateFlow<PhotoViewState>
fun setArguments(arguments: PhotoViewArguments)
}
class PhotoViewViewModelImpl : PhotoViewViewModel, ViewModel() {
override val state = MutableStateFlow(PhotoViewState.EMPTY)
override fun setArguments(arguments: PhotoViewArguments) {
state.setValue { old -> old.copy(images = arguments.images) }
}
}
@@ -0,0 +1,11 @@
package com.meloda.app.fast.photoviewer.di
import com.meloda.app.fast.photoviewer.PhotoViewViewModel
import com.meloda.app.fast.photoviewer.PhotoViewViewModelImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.dsl.bind
import org.koin.dsl.module
val photoViewModule = module {
viewModelOf(::PhotoViewViewModelImpl) bind PhotoViewViewModel::class
}
@@ -0,0 +1,9 @@
package com.meloda.app.fast.photoviewer.model
import androidx.compose.runtime.Immutable
import com.meloda.app.fast.common.UiImage
@Immutable
data class PhotoViewArguments(
val images: List<UiImage>
)
@@ -0,0 +1,16 @@
package com.meloda.app.fast.photoviewer.model
import androidx.compose.runtime.Immutable
import com.meloda.app.fast.common.UiImage
@Immutable
data class PhotoViewState(
val images: List<UiImage>
) {
companion object {
val EMPTY: PhotoViewState = PhotoViewState(
images = emptyList()
)
}
}
@@ -0,0 +1,180 @@
package com.meloda.app.fast.photoviewer.presentation
import android.graphics.drawable.ColorDrawable
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.rounded.MoreVert
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
import com.meloda.app.fast.common.UiImage
import com.meloda.app.fast.photoviewer.PhotoViewViewModel
import com.meloda.app.fast.photoviewer.model.PhotoViewState
@OptIn(
ExperimentalFoundationApi::class,
)
@Composable
fun PhotoViewScreenContent(
onBackClick: () -> Unit,
viewModel: PhotoViewViewModel
) {
val state by viewModel.state.collectAsStateWithLifecycle()
val images = state.images
val pagerState = rememberPagerState(pageCount = { images.size })
// TODO: 23/11/2023, Danil Nikolaev: заюзать штуку для цветов статус бара и навбара
Box(
modifier = Modifier.fillMaxSize()
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xffb00b69))
) {
Spacer(
modifier = Modifier
.statusBarsPadding()
.padding(top = 56.dp)
)
Pager(
pagerState = pagerState,
state = state
)
Spacer(modifier = Modifier.navigationBarsPadding())
}
AppBar(onBackClick = onBackClick)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppBar(onBackClick: () -> Unit) {
val context = LocalContext.current
var dropdownMenuShown by remember {
mutableStateOf(false)
}
TopAppBar(
title = {},
navigationIcon = {
IconButton(onClick = onBackClick) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Back button"
)
}
},
actions = {
IconButton(
onClick = { dropdownMenuShown = true }
) {
Icon(
imageVector = Icons.Rounded.MoreVert,
contentDescription = "Options"
)
}
DropdownMenu(
modifier = Modifier.defaultMinSize(minWidth = 140.dp),
expanded = dropdownMenuShown,
onDismissRequest = { dropdownMenuShown = false },
offset = DpOffset(x = (10).dp, y = (-60).dp)
) {
DropdownMenuItem(
onClick = {
Toast.makeText(context, "Save clicked", Toast.LENGTH_SHORT).show()
dropdownMenuShown = false
},
text = { Text(text = "Save") },
)
}
}
)
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Pager(
pagerState: PagerState,
padding: PaddingValues = PaddingValues(0.dp),
state: PhotoViewState
) {
val images = state.images
HorizontalPager(
state = pagerState,
modifier = Modifier
.fillMaxSize()
.padding(padding),
key = { index -> images[index].hashCode() }
) { page ->
val model = images[page].getImage()
if (model is Painter) {
Image(
painter = model,
contentDescription = "Image",
modifier = Modifier.fillMaxSize()
)
} else {
AsyncImage(
model = model,
contentDescription = "Image",
modifier = Modifier.fillMaxSize(),
placeholder = ColorPainter(Color.DarkGray),
error = ColorPainter(Color.Red)
)
}
}
}
@Composable
fun UiImage.getImage(): Any {
return when (this) {
is UiImage.Color -> ColorDrawable(color)
is UiImage.ColorResource -> ColorDrawable(colorResource(id = resId).toArgb())
is UiImage.Resource -> painterResource(id = resId)
is UiImage.Simple -> drawable
is UiImage.Url -> url
}
}