From 886a97ce0d7a7fed7a0f1fc13d29e9d75199e309 Mon Sep 17 00:00:00 2001
From: Gautam Shorewala <123801344+GautamCoder4019k@users.noreply.github.com>
Date: Sun, 24 Mar 2024 21:14:00 +0530
Subject: [PATCH] fix #45:Migrate home screen to compose
---
.../example/findissues/models/home/User.kt | 18 +-
.../findissues/ui/fragments/HomeFragment.kt | 121 ++++++-----
.../example/findissues/ui/home/HomeAppBar.kt | 37 ++++
.../example/findissues/ui/home/HomeScreen.kt | 202 ++++++++++++++++++
app/src/main/res/values/strings.xml | 4 +
.../core/ui/components/IconWithText.kt | 39 ++++
6 files changed, 364 insertions(+), 57 deletions(-)
create mode 100644 app/src/main/java/com/example/findissues/ui/home/HomeAppBar.kt
create mode 100644 app/src/main/java/com/example/findissues/ui/home/HomeScreen.kt
create mode 100644 core/src/main/java/com/example/core/ui/components/IconWithText.kt
diff --git a/app/src/main/java/com/example/findissues/models/home/User.kt b/app/src/main/java/com/example/findissues/models/home/User.kt
index d1a7838..5e9737a 100644
--- a/app/src/main/java/com/example/findissues/models/home/User.kt
+++ b/app/src/main/java/com/example/findissues/models/home/User.kt
@@ -1,13 +1,13 @@
package com.example.findissues.models.home
data class User(
- val login: String,
- val avatar_url: String,
- val name: String,
- val bio: String,
- val company: String,
- val location: String,
- val twitter_username: String,
- val followers: Int,
- val following: Int
+ val login: String="",
+ val avatar_url: String="",
+ val name: String="",
+ val bio: String="",
+ val company: String="",
+ val location: String="",
+ val twitter_username: String="",
+ val followers: Int=0,
+ val following: Int=0
)
diff --git a/app/src/main/java/com/example/findissues/ui/fragments/HomeFragment.kt b/app/src/main/java/com/example/findissues/ui/fragments/HomeFragment.kt
index 2604acd..3f0d3c9 100644
--- a/app/src/main/java/com/example/findissues/ui/fragments/HomeFragment.kt
+++ b/app/src/main/java/com/example/findissues/ui/fragments/HomeFragment.kt
@@ -1,18 +1,28 @@
package com.example.findissues.ui.fragments
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.material3.Button
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.findissues.R
import com.example.findissues.databinding.FragmentHomeBinding
+import com.example.findissues.models.home.User
import com.example.findissues.ui.adapters.PinnedRepoAdapter
import com.example.findissues.ui.followers.FollowersFragment
import com.example.findissues.ui.following.FollowingFragment
+import com.example.findissues.ui.home.HomeScreen
+import com.example.findissues.ui.issues.IssuesScreen
import com.example.findissues.utils.Browser
import com.example.findissues.utils.Constants.FOLLOWERS
import com.example.findissues.utils.Constants.FOLLOWING
@@ -31,8 +41,10 @@ import javax.inject.Inject
@AndroidEntryPoint
class HomeFragment : Fragment() {
- private var _binding: FragmentHomeBinding? = null
- private val binding get() = _binding!!
+// private var _binding: FragmentHomeBinding? = null
+// private val binding get() = _binding!!
+
+ private var user by mutableStateOf(User())
private lateinit var userViewModel: UserViewModel
private lateinit var pinnedRepoViewModel: PinnedRepoViewModel
@@ -43,36 +55,37 @@ class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
- _binding = FragmentHomeBinding.inflate(inflater, container, false)
- binding.toolbar.root.title = resources.getString(R.string.home)
- if(!Network.isConnected(activity)){
- Toaster.show(binding.root,"Connect to internet")
- return binding.root
- }
- binding.rvPinned.apply {
- layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
- adapter = pinnedRepoAdapter
- }
+// _binding = FragmentHomeBinding.inflate(inflater, container, false)
+// binding.toolbar.root.title = resources.getString(R.string.home)
+// if(!Network.isConnected(activity)){
+// Toaster.show(binding.root,"Connect to internet")
+// return binding.root
+// }
+// binding.rvPinned.apply {
+// layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
+// adapter = pinnedRepoAdapter
+// }
userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
pinnedRepoViewModel = ViewModelProvider(this)[PinnedRepoViewModel::class.java]
userViewModel.getUserDetail()
userViewModel.observeUserLiveData().observe(viewLifecycleOwner) {
- with(binding) {
- name.text = it.name
- githubUsername.text = it.login
- val glideLoader = GlideLoader(requireContext())
- glideLoader.loadCircularImage(it.avatar_url, profileImage)
- bio.text = it.bio.replace("\n", "")
- tvCompany.text = it.company
- tvLocation.text = it.location
- tvTwitter.text = it.twitter_username
- tvTwitter.setOnClickListener {
- Browser(requireContext()).launch(goToTwitter())
- }
- tvFollowers.text = it.followers.toString() + " " + FOLLOWERS
- tvFollowing.text = it.following.toString() + " " + FOLLOWING
- }
+// with(binding) {
+// name.text = it.name
+// githubUsername.text = it.login
+// val glideLoader = GlideLoader(requireContext())
+// glideLoader.loadCircularImage(it.avatar_url, profileImage)
+// bio.text = it.bio.replace("\n", "")
+// tvCompany.text = it.company
+// tvLocation.text = it.location
+// tvTwitter.text = it.twitter_username
+// tvTwitter.setOnClickListener {
+// Browser(requireContext()).launch(goToTwitter())
+// }
+// tvFollowers.text = it.followers.toString() + " " + FOLLOWERS
+// tvFollowing.text = it.following.toString() + " " + FOLLOWING
+// }
+ user = it
}
lifecycleScope.launch {
@@ -85,30 +98,42 @@ class HomeFragment : Fragment() {
pinnedRepoAdapter.setUpPinnedRepoList(it)
}
- with(binding) {
- tvFollowers.setOnClickListener {
- setUpFragment(FollowersFragment())
- }
- tvFollowing.setOnClickListener {
- setUpFragment(FollowingFragment())
- }
- tvRepositories.setOnClickListener {
- setUpFragment(RepositoryFragment())
- }
- tvStarred.setOnClickListener {
- setUpFragment(StarredFragment())
+// with(binding) {
+// tvFollowers.setOnClickListener {
+// setUpFragment(FollowersFragment())
+// }
+// tvFollowing.setOnClickListener {
+// setUpFragment(FollowingFragment())
+// }
+// tvRepositories.setOnClickListener {
+// setUpFragment(RepositoryFragment())
+// }
+// tvStarred.setOnClickListener {
+// setUpFragment(StarredFragment())
+// }
+// }
+
+// return binding.root
+ return ComposeView(requireContext()).apply {
+ setViewCompositionStrategy(ViewCompositionStrategy.Default)
+ setContent {
+ HomeScreen(
+ user = user,
+ onFollowersClick = { setUpFragment(FollowersFragment()) },
+ onFollowingClick = { setUpFragment(FollowingFragment()) },
+ onRepositoriesClick = { setUpFragment(RepositoryFragment()) },
+ onStarredClick = { setUpFragment(StarredFragment()) },
+ goToTwitter = { Browser(requireContext()).launch(goToTwitter(it)) }
+ )
}
}
-
- return binding.root
}
- private fun goToTwitter(): String {
- return TWITTER_BASE_URL + binding.tvTwitter.text.toString()
+ private fun goToTwitter(userName: String): String {
+ return TWITTER_BASE_URL + userName
}
private fun setUpFragment(fragment: Fragment) {
- val fragment = fragment
val fragmentManager = requireActivity().supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.nav_host_fragment_activity_dashboard, fragment)
@@ -116,8 +141,8 @@ class HomeFragment : Fragment() {
fragmentTransaction.commit()
}
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
+// override fun onDestroyView() {
+// super.onDestroyView()
+// _binding = null
+// }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/findissues/ui/home/HomeAppBar.kt b/app/src/main/java/com/example/findissues/ui/home/HomeAppBar.kt
new file mode 100644
index 0000000..d0e6c7b
--- /dev/null
+++ b/app/src/main/java/com/example/findissues/ui/home/HomeAppBar.kt
@@ -0,0 +1,37 @@
+package com.example.findissues.ui.home
+
+import androidx.compose.material.TopAppBar
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Menu
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.tooling.preview.Preview
+import com.example.findissues.R
+
+@Composable
+fun HomeAppBar() {
+ TopAppBar(
+ title = {
+ Text(
+ text = stringResource(id = R.string.home),
+ fontWeight = FontWeight.Medium,
+ color = Color.White,
+ style = MaterialTheme.typography.headlineSmall
+ )
+ },
+ backgroundColor = Color(0xFF0d1117),
+
+ )
+}
+
+@Preview( showBackground = true)
+@Composable
+fun HomeAppBarPreview() {
+ HomeAppBar()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/findissues/ui/home/HomeScreen.kt b/app/src/main/java/com/example/findissues/ui/home/HomeScreen.kt
new file mode 100644
index 0000000..f15ff37
--- /dev/null
+++ b/app/src/main/java/com/example/findissues/ui/home/HomeScreen.kt
@@ -0,0 +1,202 @@
+package com.example.findissues.ui.home
+
+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.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import coil.compose.AsyncImage
+import coil.request.ImageRequest
+import com.example.core.ui.components.IconWithText
+import com.example.findissues.R
+import com.example.findissues.models.home.User
+import com.example.findissues.utils.Constants
+
+@Composable
+fun HomeScreen(
+ user: User,
+ onFollowersClick: () -> Unit = {},
+ onFollowingClick: () -> Unit = {},
+ onRepositoriesClick: () -> Unit = {},
+ onStarredClick: () -> Unit = {},
+ goToTwitter: (String) -> Unit = {}
+) {
+ val scrollState = rememberScrollState()
+ Scaffold(topBar = { HomeAppBar() }, modifier = Modifier.fillMaxSize()) {
+ Column(
+ modifier = Modifier
+ .padding(it)
+ .fillMaxSize()
+ .verticalScroll(scrollState)
+ .background(color = Color(0xFF0d1117))
+ ) {
+ UserDetails(
+ user = user,
+ onFollowersClick = onFollowersClick,
+ onFollowingClick = onFollowingClick,
+ goToTwitter = goToTwitter,
+ modifier = Modifier
+ .fillMaxWidth()
+ )
+ Spacer(
+ modifier = Modifier
+ .height(18.dp)
+ .fillMaxWidth()
+ .background(Color(0xFF000000))
+ )
+ UserLinks(
+ onRepositoriesClick = onRepositoriesClick,
+ onStarredClick = onStarredClick,
+ modifier = Modifier
+ .fillMaxSize()
+ )
+ }
+ }
+}
+
+@Composable
+fun UserLinks(
+ modifier: Modifier = Modifier,
+ onRepositoriesClick: () -> Unit,
+ onStarredClick: () -> Unit
+) {
+ Column(modifier = modifier) {
+ IconWithText(
+ text = stringResource(R.string.pinned),
+ iconId = R.drawable.pinned,
+ modifier = Modifier.padding(8.dp)
+ )
+ IconWithText(
+ text = stringResource(R.string.repositories),
+ iconId = R.drawable.repo,
+ modifier = Modifier
+ .padding(8.dp)
+ .clickable { onRepositoriesClick() },
+ textColor = Color.White
+ )
+ IconWithText(
+ text = stringResource(R.string.starred),
+ iconId = R.drawable.star,
+ modifier = Modifier
+ .padding(8.dp)
+ .clickable { onStarredClick() },
+ textColor = Color.White
+ )
+ }
+}
+
+@Composable
+fun UserDetails(
+ user: User,
+ onFollowersClick: () -> Unit,
+ onFollowingClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ goToTwitter: (String) -> Unit
+) {
+ Column(modifier = modifier) {
+ Row {
+ AsyncImage(
+ model = ImageRequest.Builder(LocalContext.current).data(user.avatar_url).build(),
+ contentDescription = "avatar",
+ modifier = Modifier
+ .size(128.dp)
+ .padding(16.dp)
+ .clip(
+ RoundedCornerShape(100.dp)
+ )
+ )
+
+ Column(modifier = Modifier.padding(top = 16.dp, end = 16.dp)) {
+ Text(
+ text = user.name,
+ color = Color(0xFFb7b8ba),
+ fontWeight = FontWeight.Bold,
+ style = MaterialTheme.typography.headlineLarge,
+ modifier = Modifier.fillMaxWidth()
+ )
+ Text(
+ text = user.login, color = Color(0xFFb7b8ba), fontSize = 19.sp
+ )
+ }
+ }
+
+ Text(
+ text = user.bio,
+ color = Color(0xFFb7b8ba),
+ fontSize = 20.sp,
+ modifier = Modifier.padding(8.dp)
+ )
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(8.dp)
+ ) {
+ IconWithText(text = user.company, iconId = R.drawable.company)
+ Spacer(modifier = Modifier.padding(12.dp))
+ IconWithText(text = user.location, iconId = R.drawable.location)
+
+ }
+ IconWithText(
+ text = user.twitter_username,
+ iconId = R.drawable.twitter,
+ fontWeight = FontWeight.Bold,
+ modifier = Modifier
+ .padding(vertical = 16.dp, horizontal = 8.dp)
+ .clickable { goToTwitter(user.twitter_username) }
+ )
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(8.dp)
+ ) {
+ IconWithText(
+ text = stringResource(
+ R.string.number_with_string,
+ user.followers,
+ Constants.FOLLOWERS
+ ),
+ iconId = R.drawable.followers,
+ modifier = Modifier.clickable { onFollowersClick() }
+ )
+ Spacer(modifier = Modifier.padding(12.dp))
+ IconWithText(
+ text = stringResource(
+ R.string.number_with_string,
+ user.following,
+ Constants.FOLLOWING
+ ),
+ iconId = R.drawable.following,
+ modifier = Modifier.clickable { onFollowingClick() }
+ )
+
+ }
+ }
+
+}
+
+@Preview(showBackground = true)
+@Composable
+fun HomeScreenPreview() {
+ HomeScreen(User())
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bb0d829..34be4ba 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,5 +8,9 @@
Statistics
Profile
Please select a tag
+ Pinned
+ Repositories
+ Starred
+ %1$s %2$s
\ No newline at end of file
diff --git a/core/src/main/java/com/example/core/ui/components/IconWithText.kt b/core/src/main/java/com/example/core/ui/components/IconWithText.kt
new file mode 100644
index 0000000..f6beed7
--- /dev/null
+++ b/core/src/main/java/com/example/core/ui/components/IconWithText.kt
@@ -0,0 +1,39 @@
+package com.example.core.ui.components
+
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+@Composable
+fun IconWithText(
+ modifier: Modifier = Modifier,
+ text: String,
+ iconId: Int,
+ fontWeight: FontWeight = FontWeight.Normal,
+ textColor: Color = Color(0xFFb7b8ba)
+) {
+ Row(modifier = modifier) {
+ Icon(
+ painter = painterResource(id = iconId),
+ contentDescription = null,
+ tint = Color.White,
+ modifier = Modifier.size(28.dp)
+ )
+ Text(
+ text = text,
+ color = textColor,
+ fontSize = 20.sp,
+ fontWeight = fontWeight,
+ modifier = Modifier.padding(start = 12.dp, top = 4.dp),
+ )
+ }
+}
\ No newline at end of file