package com.h.pixeldroid.fragments.feeds import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.ProgressBar import android.widget.TextView import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout import androidx.fragment.app.Fragment import androidx.lifecycle.MutableLiveData import androidx.paging.DataSource import androidx.paging.ItemKeyedDataSource import androidx.paging.PagedListAdapter import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.h.pixeldroid.Pixeldroid import com.h.pixeldroid.R import com.h.pixeldroid.api.PixelfedAPI import com.h.pixeldroid.db.AppDatabase import com.h.pixeldroid.db.UserDatabaseEntity import com.h.pixeldroid.di.PixelfedAPIHolder import com.h.pixeldroid.objects.FeedContent import kotlinx.android.synthetic.main.fragment_feed.* import kotlinx.android.synthetic.main.fragment_feed.view.* import org.w3c.dom.Text import retrofit2.Call import javax.inject.Inject open class FeedFragment: Fragment() { protected var accessToken: String? = null @Inject lateinit var apiHolder: PixelfedAPIHolder protected lateinit var pixelfedAPI: PixelfedAPI protected lateinit var list : RecyclerView protected lateinit var swipeRefreshLayout: SwipeRefreshLayout internal lateinit var loadingIndicator: ProgressBar var user: UserDatabaseEntity? = null @Inject lateinit var db: AppDatabase override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_feed, container, false) (requireActivity().application as Pixeldroid).getAppComponent().inject(this) //Initialize lateinit fields that are needed as soon as the view is created swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout) loadingIndicator = view.findViewById(R.id.progressBar) list = swipeRefreshLayout.list list.layoutManager = LinearLayoutManager(context) user = db.userDao().getActiveUser() pixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db) accessToken = user?.accessToken.orEmpty() return view } fun showError(@StringRes errorText: Int = R.string.loading_toast, show: Boolean = true){ val errorLayout = view?.findViewById(R.id.errorLayout) val progressBar = view?.findViewById(R.id.progressBar) if(show){ view?.findViewById(R.id.error_text)?.setText(errorText) errorLayout?.visibility = VISIBLE progressBar?.visibility = GONE } else { errorLayout?.visibility = GONE progressBar?.visibility = VISIBLE } } open inner class FeedDataSourceFactory( private val dataSource: FeedDataSource ): DataSource.Factory() { internal lateinit var liveData: MutableLiveData> override fun create(): DataSource { val dataSource = dataSource.newSource() liveData = MutableLiveData() liveData.postValue(dataSource) return dataSource } } abstract inner class FeedDataSource: ItemKeyedDataSource(){ /** * Used in the initial call to initialize the list [loadInitial]. * @param requestedLoadSize number of objects requested in a call * @return [Call] that gets the list of [APIObject] */ abstract fun makeInitialCall(requestedLoadSize: Int): Call> /** * Used in the subsequent calls to get more objects. * @param requestedLoadSize number of objects requested in a call * @param key of the last object we already have * @return [Call] that gets the list of [APIObject] */ abstract fun makeAfterCall(requestedLoadSize: Int, key: ObjectId): Call> /** * This is called to initialize the list, so we want some of the most recent objects. * @param params holds the requestedLoadSize * @param callback to call after network request completes */ override fun loadInitial( params: LoadInitialParams, callback: LoadInitialCallback ) { enqueueCall(makeInitialCall(params.requestedLoadSize), callback) } /** * This is called to when we get to the bottom of the loaded content, so we want objects * older than the given key (params.key). * @param params holds the requestedLoadSize * @param callback to call after network request completes */ override fun loadAfter(params: LoadParams, callback: LoadCallback) { enqueueCall(makeAfterCall(params.requestedLoadSize, params.key), callback) } /** * Do nothing here, it is expected to pull to refresh to load newer items */ override fun loadBefore(params: LoadParams, callback: LoadCallback) {} abstract fun enqueueCall(call: Call>, callback: LoadCallback) abstract fun newSource(): FeedDataSource } } abstract class FeedsRecyclerViewAdapter: PagedListAdapter( object : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: T, newItem: T): Boolean { return oldItem.id === newItem.id } override fun areContentsTheSame(oldItem: T, newItem: T): Boolean { return oldItem.equals(newItem) } } ){ protected lateinit var context: Context }