Skip to content

Commit 9be3696

Browse files
author
Róbert Nagy
committed
Merge branch 'feature/11-handle-screenshots-types' into 'master'
Resolve "Handle screenshots types" Closes #85, #84, #83, #82, and #11 See merge request halcyonmobile/android-technical/multiplatform-playground!62
2 parents aa0716c + 932a17c commit 9be3696

File tree

38 files changed

+494
-649
lines changed

38 files changed

+494
-649
lines changed

Procfile

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: java -jar ./backend/build/libs/Backend.jar

app/src/main/java/com/halcyonmobile/multiplatformplayground/ui/ApplicationDetail.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.halcyonmobile.multiplatformplayground.ui
22

33
import androidx.annotation.DrawableRes
4+
import androidx.appcompat.app.AppCompatActivity
45
import androidx.compose.foundation.Image
56
import androidx.compose.foundation.ScrollableColumn
67
import androidx.compose.foundation.layout.*
@@ -14,8 +15,12 @@ import androidx.compose.ui.res.stringResource
1415
import androidx.compose.ui.res.vectorResource
1516
import androidx.compose.ui.unit.dp
1617
import androidx.compose.runtime.remember
18+
import androidx.compose.ui.platform.AmbientContext
1719
import androidx.compose.ui.tooling.preview.Preview
20+
import androidx.core.net.toUri
1821
import com.halcyonmobile.multiplatformplayground.R
22+
import com.halcyonmobile.multiplatformplayground.shared.util.toImageFile
23+
import com.halcyonmobile.multiplatformplayground.ui.shared.Screenshots
1924
import com.halcyonmobile.multiplatformplayground.ui.theme.AppTheme
2025
import com.halcyonmobile.multiplatformplayground.util.composables.BackBar
2126
import com.halcyonmobile.multiplatformplayground.viewmodel.ApplicationDetailViewModel
@@ -28,6 +33,7 @@ fun ApplicationDetail(applicationId: Long, upPress: () -> Unit) {
2833
remember(applicationId) { ApplicationDetailViewModel(applicationId) }
2934
val applicationWithDetail by viewModel.applicationDetailUiModel.collectAsState()
3035
val state by viewModel.state.collectAsState()
36+
val contentResolver = (AmbientContext.current as AppCompatActivity).contentResolver
3137

3238
Scaffold(
3339
topBar = { BackBar(upPress = upPress) },
@@ -72,7 +78,9 @@ fun ApplicationDetail(applicationId: Long, upPress: () -> Unit) {
7278
)
7379
}
7480
Description(it.description)
75-
// TODO add screenshots
81+
Screenshots(screenshots = it.screenshots.map { screenshot ->
82+
screenshot.image.toUri().toImageFile(contentResolver)
83+
})
7684
}
7785
}
7886
ApplicationDetailViewModel.State.ERROR -> Column(

app/src/main/java/com/halcyonmobile/multiplatformplayground/ui/HomeScreen.kt

+2-19
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,8 @@
11
package com.halcyonmobile.multiplatformplayground.ui
22

3-
import androidx.compose.foundation.layout.Box
4-
import androidx.compose.foundation.layout.Column
5-
import androidx.compose.foundation.layout.PaddingValues
6-
import androidx.compose.foundation.layout.Row
7-
import androidx.compose.foundation.layout.Spacer
8-
import androidx.compose.foundation.layout.fillMaxSize
9-
import androidx.compose.foundation.layout.padding
10-
import androidx.compose.foundation.layout.size
11-
import androidx.compose.foundation.layout.wrapContentWidth
12-
import androidx.compose.material.FloatingActionButton
13-
import androidx.compose.material.Icon
14-
import androidx.compose.material.MaterialTheme
15-
import androidx.compose.material.Scaffold
16-
import androidx.compose.material.ScrollableTabRow
17-
import androidx.compose.material.Snackbar
18-
import androidx.compose.material.Surface
19-
import androidx.compose.material.Tab
20-
import androidx.compose.material.TabConstants
3+
import androidx.compose.foundation.layout.*
4+
import androidx.compose.material.*
215
import androidx.compose.material.TabConstants.defaultTabIndicatorOffset
22-
import androidx.compose.material.Text
236
import androidx.compose.runtime.Composable
247
import androidx.compose.runtime.collectAsState
258
import androidx.compose.runtime.getValue

app/src/main/java/com/halcyonmobile/multiplatformplayground/ui/UploadApplication.kt

+47-66
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,16 @@ import androidx.compose.foundation.layout.fillMaxWidth
1616
import androidx.compose.foundation.layout.padding
1717
import androidx.compose.foundation.layout.preferredSize
1818
import androidx.compose.foundation.layout.wrapContentSize
19-
import androidx.compose.foundation.lazy.LazyRowFor
2019
import androidx.compose.foundation.shape.CircleShape
2120
import androidx.compose.foundation.text.KeyboardOptions
22-
import androidx.compose.material.Card
23-
import androidx.compose.material.MaterialTheme
24-
import androidx.compose.material.Scaffold
25-
import androidx.compose.material.Surface
26-
import androidx.compose.material.Text
27-
import androidx.compose.material.TextField
21+
import androidx.compose.material.*
2822
import androidx.compose.runtime.Composable
2923
import androidx.compose.runtime.collectAsState
3024
import androidx.compose.runtime.getValue
3125
import androidx.compose.runtime.remember
3226
import androidx.compose.ui.Alignment
3327
import androidx.compose.ui.Modifier
3428
import androidx.compose.ui.graphics.ColorFilter
35-
import androidx.compose.ui.graphics.RectangleShape
3629
import androidx.compose.ui.layout.ContentScale
3730
import androidx.compose.ui.platform.AmbientContext
3831
import androidx.compose.ui.res.stringResource
@@ -44,6 +37,7 @@ import com.halcyonmobile.multiplatformplayground.model.ui.UploadApplicationUiMod
4437
import com.halcyonmobile.multiplatformplayground.model.ui.UploadApplicationUiModelChangeListener
4538
import com.halcyonmobile.multiplatformplayground.shared.util.ImageFile
4639
import com.halcyonmobile.multiplatformplayground.shared.util.toImageFile
40+
import com.halcyonmobile.multiplatformplayground.ui.shared.Screenshots
4741
import com.halcyonmobile.multiplatformplayground.ui.theme.AppTheme
4842
import com.halcyonmobile.multiplatformplayground.util.composables.BackBar
4943
import com.halcyonmobile.multiplatformplayground.util.registerForActivityResult
@@ -59,40 +53,62 @@ fun UploadApplication(initialCategoryId: Long, upPress: () -> Unit) {
5953
val uploadApplicationUiModel by viewModel.uploadApplicationUiModel.collectAsState(
6054
UploadApplicationUiModel(categoryId = initialCategoryId)
6155
)
56+
val state by viewModel.state.collectAsState()
57+
val event by viewModel.event.collectAsState(null)
58+
59+
if (event == UploadApplicationViewModel.Event.SUCCESSFUL_UPLOAD) {
60+
upPress()
61+
}
6262

6363
val getIcon = registerForGalleryResult(viewModel::onIconChanged)
6464
val getScreenshot = registerForGalleryResult(viewModel::onAddScreenshot)
6565

6666
Scaffold(
6767
topBar = { BackBar(upPress = upPress) },
6868
bodyContent = {
69-
ScrollableColumn(contentPadding = PaddingValues(16.dp)) {
70-
Card(
71-
modifier = Modifier.preferredSize(88.dp).align(Alignment.CenterHorizontally),
72-
shape = CircleShape,
73-
backgroundColor = AppTheme.colors.cardButton
69+
when (state) {
70+
UploadApplicationViewModel.State.LOADING -> Box(
71+
Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp)
7472
) {
75-
Box(Modifier.clickable { getIcon.launchAsImageResult() }) {
76-
if (uploadApplicationUiModel.icon == null) {
77-
Image(
78-
imageVector = vectorResource(id = R.drawable.ic_add_image),
79-
colorFilter = ColorFilter.tint(AppTheme.colors.secondary),
80-
modifier = Modifier.wrapContentSize().align(Alignment.Center)
81-
)
82-
} else {
83-
CoilImage(
84-
data = uploadApplicationUiModel.icon!!.uri,
85-
modifier = Modifier.matchParentSize(),
86-
contentScale = ContentScale.Crop
87-
)
73+
CircularProgressIndicator()
74+
}
75+
UploadApplicationViewModel.State.NORMAL -> ScrollableColumn(
76+
contentPadding = PaddingValues(16.dp)
77+
) {
78+
Card(
79+
modifier = Modifier.preferredSize(88.dp)
80+
.align(Alignment.CenterHorizontally),
81+
shape = CircleShape,
82+
backgroundColor = AppTheme.colors.cardButton
83+
) {
84+
Box(Modifier.clickable { getIcon.launchAsImageResult() }) {
85+
if (uploadApplicationUiModel.icon == null) {
86+
Image(
87+
imageVector = vectorResource(id = R.drawable.ic_add_image),
88+
colorFilter = ColorFilter.tint(AppTheme.colors.secondary),
89+
modifier = Modifier.wrapContentSize().align(Alignment.Center)
90+
)
91+
} else {
92+
CoilImage(
93+
data = uploadApplicationUiModel.icon!!.uri,
94+
modifier = Modifier.matchParentSize(),
95+
contentScale = ContentScale.Crop
96+
)
97+
}
8898
}
8999
}
100+
Screenshots(
101+
screenshots = uploadApplicationUiModel.screenshots,
102+
onAddScreenshot = { getScreenshot.launchAsImageResult() },
103+
showAdd = true
104+
)
105+
ApplicationDetails(uploadApplicationUiModel, viewModel)
106+
ExtendedFloatingActionButton(
107+
text = { Text(stringResource(R.string.submit)) },
108+
onClick = viewModel::submit,
109+
modifier = Modifier.fillMaxWidth().padding(16.dp)
110+
)
90111
}
91-
Screenshots(
92-
screenshots = uploadApplicationUiModel.screenshots,
93-
onAddScreenshot = { getScreenshot.launchAsImageResult() }
94-
)
95-
ApplicationDetails(uploadApplicationUiModel, viewModel)
96112
}
97113
}
98114
)
@@ -108,41 +124,6 @@ private fun registerForGalleryResult(callback: (ImageFile) -> Unit) =
108124
}
109125
}
110126

111-
@Composable
112-
private fun Screenshots(screenshots: List<ImageFile>, onAddScreenshot: () -> Unit) {
113-
Column {
114-
Text(
115-
text = stringResource(id = R.string.screenshots),
116-
style = MaterialTheme.typography.h6,
117-
modifier = Modifier.padding(16.dp)
118-
)
119-
LazyRowFor(items = screenshots + null, modifier = Modifier.padding(8.dp)) {
120-
if (it != null) {
121-
CoilImage(
122-
data = it.uri,
123-
modifier = Modifier.preferredSize(88.dp).padding(8.dp),
124-
contentScale = ContentScale.Crop
125-
)
126-
} else {
127-
Card(
128-
modifier = Modifier.preferredSize(88.dp).padding(8.dp),
129-
shape = RectangleShape,
130-
backgroundColor = AppTheme.colors.cardButton
131-
) {
132-
Box(Modifier.clickable(onClick = onAddScreenshot)) {
133-
Image(
134-
imageVector = vectorResource(id = R.drawable.ic_add_image),
135-
colorFilter = ColorFilter.tint(AppTheme.colors.secondary),
136-
modifier = Modifier.wrapContentSize().align(Alignment.Center)
137-
)
138-
}
139-
140-
}
141-
}
142-
}
143-
}
144-
}
145-
146127
@Composable
147128
private fun ApplicationDetails(
148129
uploadApplicationUiModel: UploadApplicationUiModel,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.halcyonmobile.multiplatformplayground.ui.shared
2+
3+
import androidx.compose.foundation.Image
4+
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.layout.*
6+
import androidx.compose.foundation.lazy.LazyRowFor
7+
import androidx.compose.material.Card
8+
import androidx.compose.material.MaterialTheme
9+
import androidx.compose.material.Text
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.ui.Alignment
12+
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.graphics.ColorFilter
14+
import androidx.compose.ui.graphics.RectangleShape
15+
import androidx.compose.ui.layout.ContentScale
16+
import androidx.compose.ui.res.stringResource
17+
import androidx.compose.ui.res.vectorResource
18+
import androidx.compose.ui.unit.dp
19+
import com.halcyonmobile.multiplatformplayground.R
20+
import com.halcyonmobile.multiplatformplayground.shared.util.ImageFile
21+
import com.halcyonmobile.multiplatformplayground.ui.theme.AppTheme
22+
import dev.chrisbanes.accompanist.coil.CoilImage
23+
24+
@Composable
25+
fun Screenshots(screenshots: List<ImageFile>, onAddScreenshot: () -> Unit = {}, showAdd: Boolean = false) {
26+
Column {
27+
val items = if(showAdd) screenshots + null else screenshots
28+
Text(
29+
text = stringResource(id = R.string.screenshots),
30+
style = MaterialTheme.typography.h6,
31+
modifier = Modifier.padding(16.dp)
32+
)
33+
LazyRowFor(items = items, modifier = Modifier.padding(8.dp)) {
34+
if (it != null) {
35+
CoilImage(
36+
data = it.uri,
37+
modifier = Modifier.preferredSize(88.dp).padding(8.dp),
38+
contentScale = ContentScale.Crop
39+
)
40+
} else {
41+
Card(
42+
modifier = Modifier.preferredSize(88.dp).padding(8.dp),
43+
shape = RectangleShape,
44+
backgroundColor = AppTheme.colors.cardButton
45+
) {
46+
Box(Modifier.clickable(onClick = onAddScreenshot)) {
47+
Image(
48+
imageVector = vectorResource(id = R.drawable.ic_add_image),
49+
colorFilter = ColorFilter.tint(AppTheme.colors.secondary),
50+
modifier = Modifier.wrapContentSize().align(Alignment.Center)
51+
)
52+
}
53+
54+
}
55+
}
56+
}
57+
}
58+
}

backend/Procfile

-1
This file was deleted.

backend/app.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "Start on Heroku: AppPortfolio backend",
3-
"description": "A barebones Kotlin app, which can easily be deployed to Heroku.",
2+
"name": "Start on Heroku: Multiplatform backend",
3+
"description": "Kotlin multiplatform backend",
44
"image": "heroku/java",
55
"addons": [ "heroku-postgresql" ]
66
}

backend/build.gradle.kts

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
3+
buildscript {
4+
repositories {
5+
jcenter()
6+
}
7+
dependencies {
8+
classpath(Versions.Jvm.SHADOW_GRADLE_PLUGIN)
9+
}
10+
}
11+
12+
application {
13+
// TODO to solve deprecation checkout https://github.com/johnrengelman/shadow/issues/336
14+
mainClassName = "com.halcyonmobile.multiplatformplayground.ServerKt"
15+
}
16+
117
plugins {
218
kotlin("jvm")
319
kotlin("plugin.serialization") version Versions.KOTLIN_VERSION
420
application
21+
id("com.github.johnrengelman.shadow") version Versions.Jvm.SHADOW_JAR_VERSION
522
}
623

7-
application {
8-
mainClass.set("com.halcyonmobile.multiplatformplayground.ServerKt")
9-
}
1024

1125
dependencies {
1226
implementation(project(":commonModel"))
27+
implementation(Versions.Jvm.STANDARD_LIBRARY)
1328
implementation(Versions.Jvm.KTOR_CLIENT_APACHE)
1429
implementation(Versions.Jvm.KTOR_SERIALIZATION)
1530

@@ -24,8 +39,17 @@ dependencies {
2439
implementation(Versions.Jvm.JETBRAINS_EXPOSED_CORE)
2540
implementation(Versions.Jvm.JETBRAINS_EXPOSED_DAO)
2641
implementation(Versions.Jvm.JETBRAINS_EXPOSED_JDBC)
27-
implementation(Versions.Jvm.H2_DATABASE)
42+
implementation(Versions.Jvm.POSTGRESQL)
2843
implementation(Versions.Jvm.HIKARI_CONNECTION_POOL)
2944

3045
implementation(Versions.Jvm.LOGBACK)
46+
47+
implementation(Versions.Jvm.AWS_JAVA_SDK)
3148
}
49+
50+
tasks.withType<ShadowJar> {
51+
archiveBaseName.set("Backend")
52+
archiveClassifier.set("")
53+
archiveVersion.set("")
54+
isZip64 = true
55+
}

0 commit comments

Comments
 (0)