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..bf4c039 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..6be0f8c 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
@@ -4,22 +4,23 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+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.theme.FindIssueTheme
import com.example.findissues.utils.Browser
-import com.example.findissues.utils.Constants.FOLLOWERS
-import com.example.findissues.utils.Constants.FOLLOWING
import com.example.findissues.utils.Constants.TWITTER_BASE_URL
-import com.example.findissues.utils.GlideLoader
-import com.example.findissues.utils.Network
-import com.example.findissues.utils.Toaster
import com.example.findissues.viewmodels.PinnedRepoViewModel
import com.example.findissues.viewmodels.UserViewModel
import dagger.hilt.android.AndroidEntryPoint
@@ -31,8 +32,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class HomeFragment : Fragment() {
- 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 +43,12 @@ 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
- }
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
- }
+ user = it
}
lifecycleScope.launch {
@@ -85,30 +61,28 @@ class HomeFragment : Fragment() {
pinnedRepoAdapter.setUpPinnedRepoList(it)
}
- with(binding) {
- tvFollowers.setOnClickListener {
- setUpFragment(FollowersFragment())
- }
- tvFollowing.setOnClickListener {
- setUpFragment(FollowingFragment())
- }
- tvRepositories.setOnClickListener {
- setUpFragment(RepositoryFragment())
- }
- tvStarred.setOnClickListener {
- setUpFragment(StarredFragment())
+ return ComposeView(requireContext()).apply {
+ setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
+ setContent {
+ FindIssueTheme {
+ 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 +90,4 @@ class HomeFragment : Fragment() {
fragmentTransaction.commit()
}
- 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/HomeScreen.kt b/app/src/main/java/com/example/findissues/ui/home/HomeScreen.kt
new file mode 100644
index 0000000..7c3d7e1
--- /dev/null
+++ b/app/src/main/java/com/example/findissues/ui/home/HomeScreen.kt
@@ -0,0 +1,208 @@
+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.AppTopBar
+import com.example.core.ui.components.IconWithText
+import com.example.findissues.R
+import com.example.findissues.models.home.User
+import com.example.findissues.ui.theme.FindIssueTheme
+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 = { AppTopBar(title = R.string.home) }, modifier = Modifier.fillMaxSize()) {
+ Column(
+ modifier = Modifier
+ .padding(it)
+ .fillMaxSize()
+ .verticalScroll(scrollState)
+ .background(color = MaterialTheme.colorScheme.primary)
+ ) {
+ UserDetails(
+ user = user,
+ onFollowersClick = onFollowersClick,
+ onFollowingClick = onFollowingClick,
+ goToTwitter = goToTwitter,
+ modifier = Modifier
+ .fillMaxWidth()
+ )
+ Spacer(
+ modifier = Modifier
+ .height(18.dp)
+ .fillMaxWidth()
+ .background(MaterialTheme.colorScheme.secondary)
+ )
+ 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 = MaterialTheme.colorScheme.tertiary,
+ fontWeight = FontWeight.Bold,
+ style = MaterialTheme.typography.headlineLarge,
+ modifier = Modifier.fillMaxWidth()
+ )
+ Text(
+ text = user.login,
+ color = MaterialTheme.colorScheme.tertiary,
+ fontSize = 19.sp
+ )
+ }
+ }
+
+ Text(
+ text = user.bio,
+ color = MaterialTheme.colorScheme.tertiary,
+ 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() {
+ FindIssueTheme {
+ HomeScreen(User())
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/findissues/ui/theme/Color.kt b/app/src/main/java/com/example/findissues/ui/theme/Color.kt
new file mode 100644
index 0000000..3cfad5d
--- /dev/null
+++ b/app/src/main/java/com/example/findissues/ui/theme/Color.kt
@@ -0,0 +1,6 @@
+package com.example.findissues.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val GitHub_Bkg = Color(0xFF0d1117)
+val Grey40 = Color(0xFFb7b8ba)
diff --git a/app/src/main/java/com/example/findissues/ui/theme/Theme.kt b/app/src/main/java/com/example/findissues/ui/theme/Theme.kt
new file mode 100644
index 0000000..4e3b3ac
--- /dev/null
+++ b/app/src/main/java/com/example/findissues/ui/theme/Theme.kt
@@ -0,0 +1,36 @@
+package com.example.findissues.ui.theme
+
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+
+private val DarkColorScheme = darkColorScheme(
+ primary = GitHub_Bkg,
+ secondary = Color.Black,
+ tertiary = Grey40
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = GitHub_Bkg,
+ secondary = Color.Black,
+ tertiary = Grey40
+
+)
+
+@Composable
+fun FindIssueTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ content: @Composable () -> Unit
+) {
+ val colorScheme = when {
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+ MaterialTheme(
+ colorScheme = colorScheme,
+ content = content
+ )
+}
\ 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/AppTopBar.kt b/core/src/main/java/com/example/core/ui/components/AppTopBar.kt
new file mode 100644
index 0000000..e0e4378
--- /dev/null
+++ b/core/src/main/java/com/example/core/ui/components/AppTopBar.kt
@@ -0,0 +1,24 @@
+package com.example.core.ui.components
+
+import androidx.compose.material.TopAppBar
+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
+
+@Composable
+fun AppTopBar(title: Int) {
+ TopAppBar(
+ title = {
+ Text(
+ text = stringResource(id = title),
+ fontWeight = FontWeight.Medium,
+ color = Color.White,
+ style = MaterialTheme.typography.headlineSmall
+ )
+ },
+ backgroundColor = Color(0xFF0d1117),
+ )
+}
\ 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