Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/src/main/java/in/testpress/testpress/TestpressModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
import in.testpress.testpress.ui.ProfileDetailsActivity;
import in.testpress.testpress.ui.ProfilePhotoActivity;
import in.testpress.testpress.ui.WebViewActivity;
import in.testpress.testpress.ui.fragments.DashboardFragment;
import in.testpress.testpress.ui.fragments.DashBoardFragment;
import in.testpress.testpress.ui.fragments.OTPVerificationFragment;
import in.testpress.testpress.ui.fragments.PhoneAuthenticationFragment;
import in.testpress.testpress.ui.fragments.UsernameAuthentication;
Expand Down Expand Up @@ -89,7 +89,7 @@
ForumActivity.class,
CreateForumActivity.class,
WebViewActivity.class,
DashboardFragment.class,
DashBoardFragment.class,
DoubtsActivity.class,
LoginActivityV2.class,
UsernameAuthentication.class,
Expand Down
11 changes: 10 additions & 1 deletion app/src/main/java/in/testpress/testpress/network/AppService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import `in`.testpress.network.TestpressApiClient
import `in`.testpress.testpress.BuildConfig
import `in`.testpress.testpress.core.Constants
import `in`.testpress.testpress.models.InstituteSettings
import `in`.testpress.testpress.models.pojo.DashboardResponse
import `in`.testpress.testpress.models.pojo.GenerateOTPResponse
import `in`.testpress.testpress.models.pojo.OTPLoginResponse
import android.content.Context
import retrofit.http.GET
import retrofit2.http.GET
import retrofit2.http.Body
import retrofit2.http.POST
import kotlin.collections.HashMap
Expand All @@ -17,6 +18,10 @@ const val OTP_URL = "/api/v2.5/auth/generate-otp/"
const val VERIFY_OTP_URL = "/api/v2.5/auth/otp-login/"

interface AppService {

@GET("/api/v2.4/dashboard/")
fun getDashBoardData():RetrofitCall<DashboardResponse>

@GET(Constants.Http.URL_INSTITUTE_SETTINGS_FRAG)
fun getInstituteSettings(): RetrofitCall<InstituteSettings>

Expand All @@ -31,6 +36,10 @@ interface AppService {
class AppNetwork(context: Context) : TestpressApiClient(BuildConfig.BASE_URL, context) {
private fun getAppService() = retrofit.create(AppService::class.java)

fun getDashBoardData():RetrofitCall<DashboardResponse>{
return getAppService().getDashBoardData()
}

fun getInstituteSettings(): RetrofitCall<InstituteSettings> {
return getAppService().getInstituteSettings()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package `in`.testpress.testpress.repository

import `in`.testpress.network.NetworkBoundResource
import `in`.testpress.network.Resource
import `in`.testpress.network.RetrofitCall
import `in`.testpress.testpress.models.pojo.DashboardResponse
import `in`.testpress.testpress.network.AppNetwork
import `in`.testpress.testpress.util.PreferenceManager
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.gson.GsonBuilder

class DashBoardRepository(
val context: Context
) {
private val service = AppNetwork(context)

fun loadData(): LiveData<Resource<DashboardResponse>> {
return object : NetworkBoundResource<DashboardResponse, DashboardResponse>() {

override fun loadFromDb(): LiveData<DashboardResponse> {
val liveData = MutableLiveData<DashboardResponse>()
liveData.postValue(
PreferenceManager.getDashboardDataPreferences(context)
)
return liveData
}

override fun saveNetworkResponseToDB(item: DashboardResponse) {
val gson = GsonBuilder().setPrettyPrinting().create()
val json = gson.toJson(item)
PreferenceManager.setDashboardData(context, json)
}

override fun shouldFetch(data: DashboardResponse?): Boolean {
return true
}

override fun createCall(): RetrofitCall<DashboardResponse> {
return service.getDashBoardData()
}
}.asLiveData()
}

}
5 changes: 2 additions & 3 deletions app/src/main/java/in/testpress/testpress/ui/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
import in.testpress.testpress.models.InstituteSettingsDao;
import in.testpress.testpress.models.SsoUrl;
import in.testpress.testpress.models.Update;
import in.testpress.testpress.ui.fragments.DashboardFragment;
import in.testpress.testpress.ui.fragments.DashBoardFragment;
import in.testpress.testpress.ui.fragments.DiscussionFragmentv2;
import in.testpress.testpress.ui.utils.HandleMainMenu;
import in.testpress.testpress.util.CommonUtils;
Expand All @@ -75,7 +75,6 @@
import in.testpress.testpress.util.Strings;
import in.testpress.testpress.util.UIUtils;
import in.testpress.testpress.util.UpdateAppDialogManager;
import in.testpress.ui.fragments.DiscussionFragment;
import io.sentry.android.core.SentryAndroid;

import static in.testpress.testpress.BuildConfig.ALLOW_ANONYMOUS_USER;
Expand Down Expand Up @@ -335,7 +334,7 @@ private void initScreen() {
}

if (isUserAuthenticated && mInstituteSettings.getShowGameFrontend()) {
addMenuItem(R.string.dashboard, R.drawable.ic_dashboard, new DashboardFragment());
addMenuItem(R.string.dashboard, R.drawable.ic_dashboard, new DashBoardFragment());
} else {
addMenuItem(R.string.dashboard, R.drawable.profile_default, new MainMenuFragment());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package `in`.testpress.testpress.ui.fragments

import `in`.testpress.enums.Status
import `in`.testpress.network.Resource
import `in`.testpress.testpress.BuildConfig
import `in`.testpress.testpress.Injector
import `in`.testpress.testpress.R
import `in`.testpress.testpress.TestpressServiceProvider
import `in`.testpress.testpress.models.pojo.DashboardResponse
import `in`.testpress.testpress.models.pojo.DashboardSection
import `in`.testpress.testpress.repository.DashBoardRepository
import `in`.testpress.testpress.ui.adapters.DashboardAdapter
import `in`.testpress.testpress.util.PreferenceManager
import `in`.testpress.testpress.viewmodel.DashBoardViewModel
import android.accounts.AccountManager
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import butterknife.ButterKnife
import butterknife.InjectView
import com.facebook.shimmer.ShimmerFrameLayout
import io.sentry.Sentry
import io.sentry.protocol.User
import javax.inject.Inject

class DashBoardFragment : Fragment() {

@InjectView(R.id.recycler_View)
lateinit var recyclerView: RecyclerView

@InjectView(R.id.empty_container)
lateinit var emptyView: LinearLayout

@InjectView(R.id.empty_title)
lateinit var emptyTitleView: TextView

@InjectView(R.id.empty_description)
lateinit var emptyDescView: TextView

@InjectView(R.id.retry_button)
lateinit var retryButton: Button

@InjectView(R.id.swipe_container)
lateinit var swipeRefreshLayout: SwipeRefreshLayout

@InjectView(R.id.shimmer_view_container)
lateinit var loadingPlaceholder: ShimmerFrameLayout

@Inject
lateinit var serviceProvider: TestpressServiceProvider
private lateinit var adapter: DashboardAdapter
lateinit var exception: Exception
lateinit var dashboardResponse: DashboardResponse
private lateinit var viewModel: DashBoardViewModel

override fun onCreate(savedInstanceState: Bundle?) {
Injector.inject(this)
super.onCreate(savedInstanceState)

initViewModel()
setUsernameInSentry()
}

private fun initViewModel() {
viewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return DashBoardViewModel(DashBoardRepository(requireContext())) as T
}
}).get(DashBoardViewModel::class.java)
}

private fun setUsernameInSentry() {
val manager = activity!!.getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
val account = manager.getAccountsByType(BuildConfig.APPLICATION_ID)
if (account.isNotEmpty()) {
val user = User()
user.username = account[0].name
Sentry.setUser(user)
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Injector.inject(this)
activity!!.invalidateOptionsMenu()
return inflater.inflate(R.layout.dashboard_view, null)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ButterKnife.inject(this, view)

setRecycleViewAdapter()
showDataFromCacheIfAvailable()
addOnClickListeners()
}

private fun setRecycleViewAdapter() {
adapter = DashboardAdapter(context, DashboardResponse(), serviceProvider)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
swipeRefreshLayout.isEnabled = true
}

private fun showDataFromCacheIfAvailable() {
if (getSections().isNotEmpty()) {
adapter.setResponse(PreferenceManager.getDashboardDataPreferences(requireContext()))
} else {
loadData()
}
}

private fun getSections(): List<DashboardSection> {
return PreferenceManager.getDashboardDataPreferences(context).availableSections
}

private fun addOnClickListeners() {
swipeRefreshLayout.setOnRefreshListener {
swipeRefreshLayout.isEnabled = true
refresh()
}
retryButton.setOnClickListener {
swipeRefreshLayout.visibility = View.VISIBLE
swipeRefreshLayout.isRefreshing = true
emptyView.visibility = View.GONE
refresh()
}
}

fun refresh() {
if (activity != null) {
loadData()
}
}

private fun loadData() {
viewModel.loadData().observe(
viewLifecycleOwner,
Observer<Resource<DashboardResponse>> { dashBoard ->
showLoadingImage()
when (dashBoard.status) {
Status.SUCCESS -> {
swipeRefreshLayout.isRefreshing = false
adapter.setResponse(dashBoard.data)
hideShimmer()
}
Status.ERROR -> {
hideShimmer()
setEmptyText()
}
else -> {}
}
})
}

private fun showLoadingImage() {
loadingPlaceholder.visibility = View.VISIBLE
loadingPlaceholder.startShimmer()
}

private fun hideShimmer() {
loadingPlaceholder.stopShimmer()
loadingPlaceholder.visibility = View.GONE
}

private fun setEmptyText() {
setEmptyText(
R.string.no_data_available, R.string.try_after_some_time,
R.drawable.ic_error_outline_black_18dp
)
}

private fun setEmptyText(title: Int, description: Int, icon: Int) {
emptyView.visibility = View.VISIBLE
emptyTitleView.setText(title)
emptyTitleView.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0)
emptyDescView.setText(description)
retryButton.visibility = View.VISIBLE
}

override fun onResume() {
super.onResume()
refresh()
}
}
Loading