Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Commit

Permalink
NodeScreen: Initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
  • Loading branch information
theimpulson committed Dec 9, 2023
1 parent 5ee1075 commit 21902e8
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ interface XenforoInterface {
@GET("threads/audapp-watched/")
suspend fun getWatchedThreads(): Response<Threads>

@GET("forums/{id}/threads/")
suspend fun getThreadsByNode(@Path("id") nodeID: Int): Response<Threads>

@POST("threads/{id}/audapp-watch")
suspend fun watchThread(@Path("id") threadID: Int): Response<ThreadWatchResponse>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ class XenforoRepository @Inject constructor(
return safeExecute { xenforoInterface.getWatchedThreads() }
}

suspend fun getThreadsByNode(nodeID: Int): Threads? {
return safeExecute { xenforoInterface.getThreadsByNode(nodeID) }
}

suspend fun watchThread(threadID: Int): ThreadWatchResponse? {
return safeExecute { xenforoInterface.watchThread(threadID) }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.aayush.relabs.ui.components

import android.os.Build
import android.text.format.DateUtils
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -29,6 +30,7 @@ import coil.request.ImageRequest
import io.aayush.relabs.R
import io.aayush.relabs.ui.extensions.shimmer
import java.text.NumberFormat
import java.util.Date
import java.util.Locale

@Composable
Expand All @@ -43,7 +45,8 @@ fun ThreadPreviewItem(
forum: String = "",
unread: Boolean = false,
onClicked: () -> Unit = {},
loading: Boolean = false
loading: Boolean = false,
lastReplyAuthor: String = ""
) {
Row(
modifier = modifier
Expand Down Expand Up @@ -104,11 +107,25 @@ fun ThreadPreviewItem(
.shimmer(loading)
)
Text(
text = forum,
text = if (forum.isNotBlank()) {
forum
} else if (lastReplyDate != 0 && lastReplyAuthor.isNotBlank()) {
stringResource(
id = R.string.last_reply,
lastReplyAuthor,
DateUtils.getRelativeTimeSpanString(
lastReplyDate.toLong() * 1000L,
Date().time,
DateUtils.MINUTE_IN_MILLIS
).toString().lowercase()
)
} else {
String()
},
fontSize = 13.sp,
fontWeight = FontWeight.Light,
modifier = Modifier
.fillMaxWidth(if (forum.isBlank()) 0.5F else 1F)
.fillMaxWidth(if (loading) 0.5F else 1F)
.shimmer(loading)
)
}
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/io/aayush/relabs/ui/navigation/NavArg.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.aayush.relabs.ui.navigation

enum class NavArg {
THREAD_ID
THREAD_ID,
NODE_ID,
NODE_TITLE
}
18 changes: 18 additions & 0 deletions app/src/main/java/io/aayush/relabs/ui/navigation/NavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import io.aayush.relabs.ui.screens.forumpreview.ForumPreviewScreen
import io.aayush.relabs.ui.screens.login.LoginScreen
import io.aayush.relabs.ui.screens.more.MoreScreen
import io.aayush.relabs.ui.screens.news.NewsScreen
import io.aayush.relabs.ui.screens.node.NodeScreen
import io.aayush.relabs.ui.screens.reply.ReplyScreen
import io.aayush.relabs.ui.screens.thread.ThreadScreen
import io.aayush.relabs.ui.screens.threadpreview.ThreadPreviewScreen
Expand Down Expand Up @@ -77,6 +78,23 @@ fun SetupNavGraph(
viewModel = it.sharedThreadViewModel(navController = navHostController)
)
}
composable(
route = Screen.Node.route,
arguments = listOf(
navArgument(NavArg.NODE_ID.name) {
type = NavType.IntType
},
navArgument(NavArg.NODE_TITLE.name) {
type = NavType.StringType
}
)
) {
NodeScreen(
navHostController = navHostController,
nodeID = it.arguments!!.getInt(NavArg.NODE_ID.name),
nodeTitle = it.arguments!!.getString(NavArg.NODE_TITLE.name) ?: String()
)
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/io/aayush/relabs/ui/navigation/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.aayush.relabs.ui.navigation

import android.net.Uri
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import io.aayush.relabs.R
Expand Down Expand Up @@ -60,6 +61,17 @@ sealed class Screen(val route: String, @StringRes val title: Int, @DrawableRes v
}
}

data object Node : Screen(
route = "node_screen/{${NavArg.NODE_ID.name}}/{${NavArg.NODE_TITLE.name}}=",
title = R.string.node,
icon = R.drawable.ic_phone
) {
fun withIDAndTitle(id: Int, title: String): String {
return this.route.replace("{${NavArg.NODE_ID.name}}", id.toString())
.replace("{${NavArg.NODE_TITLE.name}}", Uri.encode(title))
}
}

data object ForumPreview : Screen(
route = "forum_preview_screen",
title = R.string.forum_preview,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.navigation.NavHostController
import io.aayush.relabs.R
import io.aayush.relabs.network.data.node.Node
import io.aayush.relabs.ui.components.NodePreviewItem
import io.aayush.relabs.ui.navigation.Screen
import kotlinx.coroutines.launch

@Composable
Expand Down Expand Up @@ -104,7 +105,15 @@ fun ForumPreviewScreen(
lastUpdated = node.type_data.last_post_date,
lastThreadTitle = node.type_data.last_thread_title,
unread = node.type_data.is_unread,
threads = node.type_data.discussion_count
threads = node.type_data.discussion_count,
onClicked = {
navHostController.navigate(
Screen.Node.withIDAndTitle(
node.node_id,
node.title
)
)
}
)
}
}
Expand Down
91 changes: 91 additions & 0 deletions app/src/main/java/io/aayush/relabs/ui/screens/node/NodeScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.aayush.relabs.ui.screens.node

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import io.aayush.relabs.network.data.thread.Thread
import io.aayush.relabs.ui.components.ThreadPreviewItem
import io.aayush.relabs.ui.navigation.Screen

@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun NodeScreen(
navHostController: NavHostController,
nodeID: Int,
nodeTitle: String = String(),
viewModel: NodeViewModel = hiltViewModel()
) {
val loading: Boolean by viewModel.loading.collectAsStateWithLifecycle()
val threads: List<Thread>? by viewModel.threads.collectAsStateWithLifecycle()

LaunchedEffect(key1 = Unit) {
viewModel.getThreads(nodeID)
}

Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(
title = {
Text(
text = nodeTitle,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium
)
},
navigationIcon = {
IconButton(onClick = { navHostController.navigateUp() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = ""
)
}
}
)
}
) {
Column(modifier = Modifier.padding(it)) {
LazyColumn(modifier = Modifier.fillMaxHeight()) {
items(items = threads ?: emptyList(), key = { t -> t.thread_id }) { thread ->
ThreadPreviewItem(
modifier = Modifier.padding(10.dp),
avatarURL = thread.User?.avatar_urls?.values?.first() ?: "",
title = thread.title,
author = thread.username,
totalReplies = thread.reply_count,
views = thread.view_count,
lastReplyDate = thread.last_post_date,
lastReplyAuthor = thread.last_post_username,
forum = thread.Forum.title,
unread = thread.is_unread,
onClicked = {
navHostController.navigate(Screen.Thread.withID(thread.thread_id))
}
)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.aayush.relabs.ui.screens.node

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import io.aayush.relabs.network.XenforoRepository
import io.aayush.relabs.network.data.thread.Thread
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class NodeViewModel @Inject constructor(
private val xenforoRepository: XenforoRepository
) : ViewModel() {

private val _loading = MutableStateFlow(false)
val loading = _loading.asStateFlow()

private val _threads = MutableStateFlow<List<Thread>?>(emptyList())
val threads = _threads.asStateFlow()

fun getThreads(nodeID: Int) {
if (!threads.value.isNullOrEmpty()) return
viewModelScope.launch(Dispatchers.IO) {
fetch { _threads.value = xenforoRepository.getThreadsByNode(nodeID)?.threads }
}
}

private inline fun <T> fetch(block: () -> T): T? {
return try {
_loading.value = true
block()
} finally {
_loading.value = false
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,8 @@
<string name="inventory">Inventory</string>
<string name="company_threads_lastPostDate"><xliff:g id="company">%1$s</xliff:g> &#8226; <xliff:g id="threads">%2$s</xliff:g> threads &#8226; last updated <xliff:g id="lastPostDate">%3$s</xliff:g></string>
<string name="last_thread">Last thread: <xliff:g id="lastThreadTitle">%1$s</xliff:g></string>

<!-- NodeScreen -->
<string name="node">Node</string>
<string name="last_reply">Last reply: <xliff:g id="lastThreadTitle">%1$s</xliff:g> (<xliff:g id="lastPostDate">%2$s</xliff:g>)</string>
</resources>

0 comments on commit 21902e8

Please sign in to comment.