mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-17 23:47:02 +05:30
app: implement first draft of lobste.rs UI
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
parent
6e4a9c6a73
commit
63f5bea155
6 changed files with 147 additions and 20 deletions
|
@ -38,6 +38,7 @@ dependencies {
|
||||||
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
implementation(project(":data"))
|
implementation(project(":data"))
|
||||||
implementation(project(":lobsters-api"))
|
implementation(project(":lobsters-api"))
|
||||||
|
implementation(project(":model"))
|
||||||
implementation 'androidx.core:core-ktx:1.5.0-alpha03'
|
implementation 'androidx.core:core-ktx:1.5.0-alpha03'
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
|
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
|
||||||
implementation "androidx.compose.foundation:foundation:$compose_version"
|
implementation "androidx.compose.foundation:foundation:$compose_version"
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="dev.msfjarvis.lobsters">
|
package="dev.msfjarvis.lobsters">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".Application"
|
android:name=".Application"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.foundation.Text
|
import androidx.compose.foundation.Text
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumnFor
|
||||||
import androidx.compose.material.AlertDialog
|
import androidx.compose.material.AlertDialog
|
||||||
import androidx.compose.material.Button
|
import androidx.compose.material.Button
|
||||||
import androidx.compose.material.FloatingActionButton
|
import androidx.compose.material.FloatingActionButton
|
||||||
|
@ -16,8 +17,8 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.Providers
|
import androidx.compose.runtime.Providers
|
||||||
import androidx.compose.runtime.ambientOf
|
import androidx.compose.runtime.ambientOf
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
@ -28,15 +29,20 @@ import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.ui.tooling.preview.Preview
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import dev.msfjarvis.lobsters.api.LobstersApi
|
||||||
import dev.msfjarvis.lobsters.compose.utils.IconResource
|
import dev.msfjarvis.lobsters.compose.utils.IconResource
|
||||||
import dev.msfjarvis.lobsters.data.model.TodoItem
|
import dev.msfjarvis.lobsters.data.model.TodoItem
|
||||||
import dev.msfjarvis.lobsters.data.source.TodoDatabase
|
import dev.msfjarvis.lobsters.data.source.TodoDatabase
|
||||||
|
import dev.msfjarvis.lobsters.model.LobstersPost
|
||||||
import dev.msfjarvis.lobsters.ui.ListContent
|
import dev.msfjarvis.lobsters.ui.ListContent
|
||||||
|
import dev.msfjarvis.lobsters.ui.LobstersItem
|
||||||
import dev.msfjarvis.lobsters.ui.LobstersTheme
|
import dev.msfjarvis.lobsters.ui.LobstersTheme
|
||||||
import dev.msfjarvis.lobsters.urllauncher.UrlLauncher
|
import dev.msfjarvis.lobsters.urllauncher.UrlLauncher
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
val UrlLauncherAmbient = ambientOf<UrlLauncher> { error("Needs to be provided") }
|
val UrlLauncherAmbient = ambientOf<UrlLauncher> { error("Needs to be provided") }
|
||||||
|
@ -45,6 +51,7 @@ val UrlLauncherAmbient = ambientOf<UrlLauncher> { error("Needs to be provided")
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
@Inject lateinit var database: TodoDatabase
|
@Inject lateinit var database: TodoDatabase
|
||||||
@Inject lateinit var urlLauncher: UrlLauncher
|
@Inject lateinit var urlLauncher: UrlLauncher
|
||||||
|
@Inject lateinit var apiClient: LobstersApi
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -52,6 +59,25 @@ class MainActivity : AppCompatActivity() {
|
||||||
Providers(UrlLauncherAmbient provides urlLauncher) {
|
Providers(UrlLauncherAmbient provides urlLauncher) {
|
||||||
LobstersTheme {
|
LobstersTheme {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val posts = mutableStateListOf<LobstersPost>()
|
||||||
|
coroutineScope.launch {
|
||||||
|
apiClient.getHottestPosts().enqueue(object : Callback<List<LobstersPost>> {
|
||||||
|
override fun onResponse(
|
||||||
|
call: Call<List<LobstersPost>>,
|
||||||
|
response: Response<List<LobstersPost>>
|
||||||
|
) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body()?.let { posts.addAll(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<List<LobstersPost>>, t: Throwable) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
LobstersApp(posts)
|
||||||
|
/*
|
||||||
val itemsDao = database.todoItemsDao()
|
val itemsDao = database.todoItemsDao()
|
||||||
val items by itemsDao.getAllItems().collectAsState(initial = emptyList())
|
val items by itemsDao.getAllItems().collectAsState(initial = emptyList())
|
||||||
TodoApp(
|
TodoApp(
|
||||||
|
@ -59,12 +85,31 @@ class MainActivity : AppCompatActivity() {
|
||||||
{ item -> coroutineScope.launch { itemsDao.insert(item) } },
|
{ item -> coroutineScope.launch { itemsDao.insert(item) } },
|
||||||
{ item -> coroutineScope.launch { itemsDao.delete(item) } },
|
{ item -> coroutineScope.launch { itemsDao.delete(item) } },
|
||||||
)
|
)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LobstersApp(
|
||||||
|
items: List<LobstersPost>,
|
||||||
|
) {
|
||||||
|
val urlLauncher = UrlLauncherAmbient.current
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { TopAppBar({ Text(text = stringResource(R.string.app_name)) }) },
|
||||||
|
bodyContent = {
|
||||||
|
LazyColumnFor(items) { item ->
|
||||||
|
LobstersItem(item) { post ->
|
||||||
|
urlLauncher.launch(post.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TodoApp(
|
fun TodoApp(
|
||||||
items: List<TodoItem>,
|
items: List<TodoItem>,
|
||||||
|
@ -145,6 +190,7 @@ fun ItemAddDialog(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun PreviewApp() {
|
fun PreviewApp() {
|
||||||
|
@ -157,3 +203,4 @@ fun PreviewApp() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
90
app/src/main/java/dev/msfjarvis/lobsters/ui/LobstersItem.kt
Normal file
90
app/src/main/java/dev/msfjarvis/lobsters/ui/LobstersItem.kt
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package dev.msfjarvis.lobsters.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Text
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumnFor
|
||||||
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.ListItem
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.msfjarvis.lobsters.model.LobstersPost
|
||||||
|
import dev.msfjarvis.lobsters.model.Submitter
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LazyItemScope.LobstersItem(
|
||||||
|
post: LobstersPost,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: (LobstersPost) -> Unit,
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
modifier = modifier.padding(horizontal = 8.dp)
|
||||||
|
.fillParentMaxWidth()
|
||||||
|
.clickable(onClick = { onClick.invoke(post) }),
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = post.title,
|
||||||
|
color = Color(0xFF7395D9),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(top = 8.dp)
|
||||||
|
)
|
||||||
|
Row {
|
||||||
|
post.tags.forEach { tag ->
|
||||||
|
Text(
|
||||||
|
text = tag,
|
||||||
|
modifier = Modifier
|
||||||
|
.background(Color(0xFFE2E0C5), RoundedCornerShape(4.dp)),
|
||||||
|
color = Color.DarkGray,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = "authored by ${post.submitterUser.username}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PreviewLobstersItem() {
|
||||||
|
val post = LobstersPost(
|
||||||
|
"zqyydb",
|
||||||
|
"https://lobste.rs/s/zqyydb",
|
||||||
|
"2020-09-21T07:11:14.000-05:00",
|
||||||
|
"k2k20 hackathon report: Bob Beck on LibreSSL progress",
|
||||||
|
"https://undeadly.org/cgi?action=article;sid=20200921105847",
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"https://lobste.rs/s/zqyydb/k2k20_hackathon_report_bob_beck_on",
|
||||||
|
Submitter(
|
||||||
|
"Vigdis",
|
||||||
|
"2017-02-27T21:08:14.000-06:00",
|
||||||
|
false,
|
||||||
|
"Alleycat for the fun, sys/net admin for a living and OpenBSD contributions for the pleasure. (Not so) French dude in Montreal\r\n\r\nhttps://chown.me",
|
||||||
|
false,
|
||||||
|
76,
|
||||||
|
"/avatars/Vigdis-100.png",
|
||||||
|
"sevan",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
listOf("openbsd")
|
||||||
|
)
|
||||||
|
LobstersTheme {
|
||||||
|
LazyColumnFor(items = listOf(post)) { item ->
|
||||||
|
LobstersItem(post = item, onClick = {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,38 +1,25 @@
|
||||||
package dev.msfjarvis.lobsters.ui
|
package dev.msfjarvis.lobsters.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.darkColors
|
|
||||||
import androidx.compose.material.lightColors
|
import androidx.compose.material.lightColors
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
val lightColors = lightColors(
|
val lightColors = lightColors(
|
||||||
primary = Color.White,
|
primary = Color.White,
|
||||||
secondary = Color(0xFFAC130D),
|
secondary = Color(0xFF6C0000),
|
||||||
background = Color(0xFFFEFEFE),
|
background = Color.White,
|
||||||
surface = Color.White,
|
surface = Color.White,
|
||||||
onPrimary = Color(0x7395D9),
|
onPrimary = Color.DarkGray,
|
||||||
onSecondary = Color.White,
|
onSecondary = Color.White,
|
||||||
onBackground = Color.Black,
|
onBackground = Color.Black,
|
||||||
onSurface = Color.Black,
|
onSurface = Color.Black,
|
||||||
)
|
)
|
||||||
|
|
||||||
val darkColors = darkColors(
|
|
||||||
primary = Color(0xFF121212),
|
|
||||||
secondary = Color(0xFFAC130D),
|
|
||||||
background = Color.Black,
|
|
||||||
surface = Color(0xFF121212),
|
|
||||||
onPrimary = Color(0x7395D9),
|
|
||||||
onSecondary = Color.White,
|
|
||||||
onBackground = Color.White,
|
|
||||||
onSurface = Color.White,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LobstersTheme(children: @Composable () -> Unit) {
|
fun LobstersTheme(children: @Composable () -> Unit) {
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colors = if (isSystemInDarkTheme()) darkColors else lightColors,
|
colors = lightColors,
|
||||||
content = children,
|
content = children,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ dependencies {
|
||||||
def moshi_version = "1.9.3"
|
def moshi_version = "1.9.3"
|
||||||
def retrofit_version = "2.9.0"
|
def retrofit_version = "2.9.0"
|
||||||
implementation project(":model")
|
implementation project(":model")
|
||||||
|
api "com.squareup.retrofit2:retrofit:$retrofit_version"
|
||||||
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
|
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
|
||||||
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
|
|
||||||
kaptTest "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
kaptTest "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13'
|
||||||
// retrofit uses 3.14.9, so shall we.
|
// retrofit uses 3.14.9, so shall we.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue