diff --git a/README.md b/README.md
index e9753cf..fffb953 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,14 @@
# trending-git
Trending Git App
+
+- MVVM (KOTLIN)
+- ViewModel
+- LiveData
+- Navigation Component
+- Data binding
+
+Screen Shots
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index f401ea6..d49fceb 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,7 +8,7 @@ android {
compileSdkVersion 28
defaultConfig {
applicationId "com.ankit.trendinggit"
- minSdkVersion 16
+ minSdkVersion 17
targetSdkVersion 28
versionCode 1
versionName "1.0"
@@ -50,6 +50,9 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
+ // Picasso
+ implementation 'com.squareup.picasso:picasso:2.71828'
+
// Databinding compiler
kapt 'com.android.databinding:compiler:3.2.0-alpha10'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4ce38f9..c1dc4dc 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
Unit) {
- ApiClient.instance.getRepo().enqueue(object :Callback {
+ ApiClient.instance.getRepo().enqueue(object : Callback {
override fun onResponse(call: Call?, response: Response?) {
if (response != null && response.isSuccessful)
onResult(true, response.body()!!)
else
onResult(false, null)
- }
+ }
override fun onFailure(call: Call?, t: Throwable?) {
onResult(false, null)
@@ -27,8 +27,9 @@ class RepoRepository {
companion object {
private var INSTANCE: RepoRepository? = null
- fun getInstance() = INSTANCE ?: RepoRepository().also {
- INSTANCE = it
- }
+ fun getInstance() = INSTANCE
+ ?: RepoRepository().also {
+ INSTANCE = it
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ankit/trendinggit/model/api/ApiService.kt b/app/src/main/java/com/ankit/trendinggit/model/api/ApiService.kt
index 5e61c31..d8b8092 100644
--- a/app/src/main/java/com/ankit/trendinggit/model/api/ApiService.kt
+++ b/app/src/main/java/com/ankit/trendinggit/model/api/ApiService.kt
@@ -8,5 +8,5 @@ import retrofit2.http.Query
interface ApiService {
@GET("search/repositories")
- fun getRepo(@Query("q") search: String = "trending"): Call
+ fun getRepo(@Query("q") search: String = "trending", @Query("sort") sort: String = "stars"): Call
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ankit/trendinggit/view/adapter/viewHolders/RepoListViewHolder.kt b/app/src/main/java/com/ankit/trendinggit/view/adapter/viewHolders/RepoListViewHolder.kt
index af3796e..ee75297 100644
--- a/app/src/main/java/com/ankit/trendinggit/view/adapter/viewHolders/RepoListViewHolder.kt
+++ b/app/src/main/java/com/ankit/trendinggit/view/adapter/viewHolders/RepoListViewHolder.kt
@@ -1,16 +1,30 @@
package com.ankit.trendinggit.view.adapter.viewHolders
import androidx.databinding.ViewDataBinding
+import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.ankit.trendinggit.BR
+import com.ankit.trendinggit.R
import com.ankit.trendinggit.model.Item
import com.ankit.trendinggit.view.ui.repolist.RepoListViewModel
+import com.squareup.picasso.Picasso
+import kotlinx.android.synthetic.main.view_repo_list_item.view.*
+import org.jetbrains.anko.bundleOf
+import org.jetbrains.anko.sdk25.coroutines.onClick
class RepoListViewHolder constructor(private val dataBinding: ViewDataBinding, private val repoListViewModel: RepoListViewModel)
: RecyclerView.ViewHolder(dataBinding.root) {
+ val avatarImage = itemView.item_avatar
fun setup(itemData: Item) {
dataBinding.setVariable(BR.itemData, itemData)
dataBinding.executePendingBindings()
+
+ Picasso.get().load(itemData.owner.avatar_url).into(avatarImage);
+
+ itemView.onClick {
+ val bundle = bundleOf("url" to itemData.html_url)
+ itemView.findNavController().navigate(R.id.action_repoListFragment_to_repoDetailFragment, bundle)
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ankit/trendinggit/view/base/BaseViewModel.kt b/app/src/main/java/com/ankit/trendinggit/view/base/BaseViewModel.kt
index c5323c4..1575f82 100644
--- a/app/src/main/java/com/ankit/trendinggit/view/base/BaseViewModel.kt
+++ b/app/src/main/java/com/ankit/trendinggit/view/base/BaseViewModel.kt
@@ -11,6 +11,4 @@ open class BaseViewModel : ViewModel() {
val dataLoading = MutableLiveData().apply { value = false }
val toastMessage = MutableLiveData()
-
- val appContext get() = TrendingGitApp.instance
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ankit/trendinggit/view/ui/repodetail/RepoDetailFragment.kt b/app/src/main/java/com/ankit/trendinggit/view/ui/repodetail/RepoDetailFragment.kt
new file mode 100644
index 0000000..a2eb78e
--- /dev/null
+++ b/app/src/main/java/com/ankit/trendinggit/view/ui/repodetail/RepoDetailFragment.kt
@@ -0,0 +1,82 @@
+package com.ankit.trendinggit.view.ui.repodetail
+
+import android.graphics.Bitmap
+import android.os.Build
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.fragment.app.Fragment
+import com.ankit.trendinggit.R
+import kotlinx.android.synthetic.main.fragment_repo_detail.*
+import org.jetbrains.anko.sdk25.coroutines.onClick
+
+
+class RepoDetailFragment : Fragment() {
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.fragment_repo_detail, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ val url = RepoDetailFragmentArgs.fromBundle(arguments).url
+
+ setupWebView()
+ setClickListeners()
+
+ repo_web_view.loadUrl(url)
+ }
+
+ private fun setClickListeners() {
+ repo_back_button.onClick {
+ repo_web_view.goBack()
+ }
+
+ repo_forward_button.onClick {
+ repo_web_view.goForward()
+ }
+
+ repo_refresh_button.onClick {
+ repo_web_view.reload()
+ }
+ }
+
+ private fun setupWebView() {
+ repo_web_view.setInitialScale(1)
+ val webSettings = repo_web_view.settings
+ webSettings.setAppCacheEnabled(false)
+ webSettings.builtInZoomControls = true
+ webSettings.displayZoomControls = false
+ webSettings.javaScriptEnabled = true
+ webSettings.useWideViewPort = true
+ webSettings.domStorageEnabled = true
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW;
+ }
+
+ repo_web_view.webViewClient = object : WebViewClient() {
+ override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
+ super.onPageStarted(view, url, favicon)
+ if (repo_back_button != null && repo_forward_button != null && repo_web_view != null && repo_progress_view != null) {
+ repo_back_button.isEnabled = repo_web_view.canGoBack()
+ repo_forward_button.isEnabled = repo_web_view.canGoForward()
+ repo_progress_view.visibility = View.VISIBLE
+ }
+ }
+
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ if (repo_back_button != null && repo_forward_button != null && repo_web_view != null && repo_progress_view != null) {
+ repo_back_button.isEnabled = repo_web_view.canGoBack()
+ repo_forward_button.isEnabled = repo_web_view.canGoForward()
+ repo_progress_view.visibility = View.GONE
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListFragment.kt b/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListFragment.kt
index c456829..b8dab3d 100644
--- a/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListFragment.kt
+++ b/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListFragment.kt
@@ -12,6 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.ankit.trendinggit.databinding.FragmentRepoListBinding
import com.ankit.trendinggit.view.adapter.RepoListAdapter
import kotlinx.android.synthetic.main.fragment_repo_list.*
+import org.jetbrains.anko.longToast
class RepoListFragment : Fragment() {
@@ -33,10 +34,15 @@ class RepoListFragment : Fragment() {
setupAdapter()
setupObservers()
}
+
private fun setupObservers() {
viewDataBinding.viewmodel?.repoListLive?.observe(viewLifecycleOwner, Observer {
adapter.updateRepoList(it)
})
+
+ viewDataBinding.viewmodel?.toastMessage?.observe(viewLifecycleOwner, Observer {
+ activity?.longToast(it)
+ })
}
private fun setupAdapter() {
diff --git a/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListViewModel.kt b/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListViewModel.kt
index 91056e4..7f0dac3 100644
--- a/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListViewModel.kt
+++ b/app/src/main/java/com/ankit/trendinggit/view/ui/repolist/RepoListViewModel.kt
@@ -2,7 +2,7 @@ package com.ankit.trendinggit.view.ui.repolist
import androidx.lifecycle.MutableLiveData
import com.ankit.trendinggit.model.Item
-import com.ankit.trendinggit.model.api.RepoRepository
+import com.ankit.trendinggit.model.RepoRepository
import com.ankit.trendinggit.view.base.BaseViewModel
class RepoListViewModel : BaseViewModel() {
@@ -12,7 +12,7 @@ class RepoListViewModel : BaseViewModel() {
dataLoading.value = true
RepoRepository.getInstance().getRepoList { isSuccess, response ->
dataLoading.value = false
- if(isSuccess) {
+ if (isSuccess) {
repoListLive.value = response?.items
empty.value = false
} else {
diff --git a/app/src/main/res/drawable/ic_arrow_backward.xml b/app/src/main/res/drawable/ic_arrow_backward.xml
new file mode 100644
index 0000000..81600ea
--- /dev/null
+++ b/app/src/main/res/drawable/ic_arrow_backward.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_arrow_forward.xml b/app/src/main/res/drawable/ic_arrow_forward.xml
new file mode 100644
index 0000000..c0c90d5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_arrow_forward.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_fork.png b/app/src/main/res/drawable/ic_fork.png
new file mode 100644
index 0000000..1f12132
Binary files /dev/null and b/app/src/main/res/drawable/ic_fork.png differ
diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml
new file mode 100644
index 0000000..84720c3
--- /dev/null
+++ b/app/src/main/res/drawable/ic_refresh.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_star_black.xml b/app/src/main/res/drawable/ic_star_black.xml
new file mode 100644
index 0000000..a87ca09
--- /dev/null
+++ b/app/src/main/res/drawable/ic_star_black.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/fragment_repo_detail.xml b/app/src/main/res/layout/fragment_repo_detail.xml
new file mode 100644
index 0000000..d021dbb
--- /dev/null
+++ b/app/src/main/res/layout/fragment_repo_detail.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_repo_list_item.xml b/app/src/main/res/layout/view_repo_list_item.xml
index a9ce5f8..c21c65a 100644
--- a/app/src/main/res/layout/view_repo_list_item.xml
+++ b/app/src/main/res/layout/view_repo_list_item.xml
@@ -14,9 +14,99 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/_20dp">
+
+
+
+
+
+
+
+
-
+ android:layout_below="@id/item_header_container"
+ android:layout_marginTop="@dimen/_10dp"
+ android:layout_marginBottom="@dimen/_10dp"
+ android:text="@{itemData.description}"
+ android:textSize="@dimen/_16sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
index 6182538..d15ea88 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -8,5 +8,18 @@
android:id="@+id/repoListFragment"
android:name="com.ankit.trendinggit.view.ui.repolist.RepoListFragment"
android:label="Trending List"
- tools:layout="@layout/fragment_repo_list"/>
+ tools:layout="@layout/fragment_repo_list">
+
+
+
+
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 5644d09..ba361ce 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -1,5 +1,14 @@
+ 30dp
+
+
+ 25dp
20dp
+ 10dp
+ 5dp
+
+ 20sp
18sp
+ 16sp
diff --git a/screenshot/s1.png b/screenshot/s1.png
new file mode 100644
index 0000000..79b1dbf
Binary files /dev/null and b/screenshot/s1.png differ
diff --git a/screenshot/s2.png b/screenshot/s2.png
new file mode 100644
index 0000000..5ebd06d
Binary files /dev/null and b/screenshot/s2.png differ
diff --git a/screenshot/s3.png b/screenshot/s3.png
new file mode 100644
index 0000000..eb12c1f
Binary files /dev/null and b/screenshot/s3.png differ