Skip to content

Commit

Permalink
Adding categories by search from wiktionary. Making simple to add for…
Browse files Browse the repository at this point in the history
… any language.

Done #91
  • Loading branch information
manimaran96 committed May 4, 2024
1 parent dd75f91 commit fc4aaba
Show file tree
Hide file tree
Showing 11 changed files with 468 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ interface ApiInterface {
@Query("cmdir") sortDirection: String?
): Call<WikiWordsWithoutAudio?>

// Fetch Categories list - Wiktionary - https://www.mediawiki.org/wiki/API:allpages
@GET("w/api.php?action=query&format=json&list=allpages&apnamespace=14&utf8=1")
fun fetchCategoryList(
@Query("apfrom") categorySearchTerm: String?,
@Query("apprefix") apPrefix: String?,
@Query("aplimit") limit: Int?,
@Query("apcontinue") apContinue: String?,
): Call<WikiCategoryListItemResponse?>

// Edit Token - Commons
@GET("w/api.php?action=query&meta=tokens&format=json&type=csrf")
fun getCsrfEditToken(): Call<WikiToken?>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.manimarank.spell4wiki.data.model

import com.google.gson.annotations.SerializedName

data class WikiCategoryListItemResponse(
var batchcomplete: String?,
@SerializedName("continue")
var continue_field: Continue?,
var query: QueryRes?,
)

data class Continue(
var apcontinue: String?,
@SerializedName("continue")
var continue_field: String?,
)

data class QueryRes(
var allpages: List<CategoryItem>?,
)

data class CategoryItem(
var pageid: Long?,
var ns: Long?,
var title: String?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ class PrefManager(private val mContext: Context?) {
editor.apply()
}

fun getSelectedWordsCategory(langCode: String?): String? {
return pref.getString(String.format(SELECTED_WORDS_CATEGORY_FOR_LANG, langCode ?: "ta"), null)
}

fun setSelectedWordsCategory(langCode: String?, category: String?) {
editor.putString(String.format(SELECTED_WORDS_CATEGORY_FOR_LANG, langCode ?: "ta"), category)
editor.apply()
}

companion object {
// shared pref
private const val PREF_NAME = "spell4wiki_pref"
Expand All @@ -134,6 +143,7 @@ class PrefManager(private val mContext: Context?) {
private const val UPLOAD_AUDIO_LICENSE = "upload_audio_license"
private const val RUN_FILTER_NO_OF_WORDS_TO_CHECK = "run_filter_no_of_words_to_check"
private const val WORDS_CATEGORY_FOR_LANG = "words_category_for_%s"
private const val SELECTED_WORDS_CATEGORY_FOR_LANG = "selected_words_category_for_%s"
private const val CSRF_TOKEN = "csrf_token"
private const val COOKIE = "cookie"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.manimarank.spell4wiki.ui.categoryselector

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.manimarank.spell4wiki.R
import com.manimarank.spell4wiki.data.model.CategoryItem
import com.manimarank.spell4wiki.ui.listerners.OnCategorySelectionListener
import java.util.*

class CategoryAdapter(private var mList: ArrayList<CategoryItem>, listener: OnCategorySelectionListener?) : RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
private val mListener: OnCategorySelectionListener? = listener
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pos = holder.adapterPosition
val model = mList[pos]
holder.txtCategory.text = model.title ?: ""
holder.txtCategory.setOnClickListener {
mListener?.onCallBackListener(model.title)
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_category_row, parent, false)
return ViewHolder(view)
}

override fun getItemCount(): Int {
return mList.size
}

/* adapter view holder */
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val txtCategory: TextView = itemView.findViewById(R.id.txtCategory)
}

@SuppressLint("NotifyDataSetChanged")
fun loadData(mResData: List<CategoryItem>,) {
mList.clear()
mList.addAll(mResData)
notifyDataSetChanged()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package com.manimarank.spell4wiki.ui.categoryselector

import android.app.Activity
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.DisplayMetrics
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.manimarank.spell4wiki.R
import com.manimarank.spell4wiki.data.apis.ApiClient
import com.manimarank.spell4wiki.data.apis.ApiInterface
import com.manimarank.spell4wiki.data.model.CategoryItem
import com.manimarank.spell4wiki.data.model.WikiCategoryListItemResponse
import com.manimarank.spell4wiki.data.prefs.PrefManager
import com.manimarank.spell4wiki.ui.listerners.OnCategorySelectionListener
import com.manimarank.spell4wiki.utils.constants.AppConstants
import com.manimarank.spell4wiki.utils.constants.ListMode.Companion.EnumListMode
import com.manimarank.spell4wiki.utils.makeGone
import com.manimarank.spell4wiki.utils.makeVisible
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class CategorySelectionFragment(private val mActivity: Activity) : BottomSheetDialogFragment() {
private lateinit var pref: PrefManager
private var callback: OnCategorySelectionListener? = null
private var categoryList = ArrayList<CategoryItem>()
private var adapter: CategoryAdapter? = null

@EnumListMode
private var listMode = 0
private var preSelectedLanguageCode: String? = null

var recyclerView: RecyclerView? = null
var loaderView: ProgressBar? = null
var txtCategoryResInfo: TextView? = null

@JvmOverloads
fun init(callback: OnCategorySelectionListener?, @EnumListMode mode: Int, preSelectedLanguageCode: String? = null) {
this.callback = callback
listMode = mode
this.preSelectedLanguageCode = preSelectedLanguageCode
isCancelable = true
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
pref = PrefManager(context)
val dialog = BottomSheetDialog(mActivity, R.style.AppTheme)
dialog.setContentView(R.layout.bottom_sheet_category_selection)
val txtTitle = dialog.findViewById<TextView>(R.id.text_select_category_sub_title)
if (!TextUtils.isEmpty(subTitleInfo) && txtTitle != null) {
txtTitle.makeVisible()
txtTitle.text = subTitleInfo
}
recyclerView = dialog.findViewById(R.id.recyclerView)
loaderView = dialog.findViewById(R.id.progressBar)
txtCategoryResInfo = dialog.findViewById(R.id.txtCategorySearchInfo)
val btnClose = dialog.findViewById<ImageView>(R.id.btn_close)
val searchView = dialog.findViewById<SearchView>(R.id.search_view)

categoryList.clear()

val categorySelectionListener = object : OnCategorySelectionListener {
override fun onCallBackListener(category: String?) {
callback?.onCallBackListener(category)
dismiss()
}
}

adapter = CategoryAdapter(arrayListOf(), categorySelectionListener, preSelectedLanguageCode)
recyclerView?.adapter = adapter
btnClose?.setOnClickListener { dismiss() }
dialog.setOnShowListener { dialog1: DialogInterface ->
val d = dialog1 as BottomSheetDialog
val bottomSheet = d.findViewById<FrameLayout>(R.id.design_bottom_sheet)
if (bottomSheet != null) {
val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet)
behavior.isHideable = false
behavior.state = BottomSheetBehavior.STATE_EXPANDED

// Full screen mode no collapse
val displayMetrics = DisplayMetrics()
mActivity.windowManager.defaultDisplay.getMetrics(displayMetrics)
val screenHeight = displayMetrics.heightPixels
behavior.peekHeight = screenHeight
}
}

searchView?.queryHint = getString(R.string.search)
searchView?.isQueryRefinementEnabled = true
val handler = Handler(Looper.getMainLooper())
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
return false
}

override fun onQueryTextChange(newText: String): Boolean {
showLoader(null)
handler.removeCallbacksAndMessages(null)
handler.postDelayed({
fetchCategory(newText)
}, 400)
return false
}
})

return dialog
}

fun fetchCategory(searchTerm: String?) {
if (searchTerm == null) {
showLoader(null, "Not valid search term")
return
}

//Wiktionary Categories list
val api = ApiClient.getWiktionaryApi(mActivity, pref.languageCodeSpell4WikiAll ?: AppConstants.DEFAULT_LANGUAGE_CODE).create(ApiInterface::class.java)
val call = api.fetchCategoryList(
searchTerm,
searchTerm,
100,
null
)

showLoader(true)

call.enqueue(object : Callback<WikiCategoryListItemResponse?> {
override fun onResponse(call: Call<WikiCategoryListItemResponse?>, response: Response<WikiCategoryListItemResponse?>) {
var resList: List<CategoryItem> = listOf()
if (response.isSuccessful && response.body() != null) {
resList = response.body()?.query?.allpages ?: listOf()
}

if (resList.isNotEmpty()) {
showLoader(false)
adapter?.loadData(resList)
} else {
showLoader(null, mActivity.getString(R.string.result_not_found))
}
}

override fun onFailure(call: Call<WikiCategoryListItemResponse?>, t: Throwable) {
showLoader(false, t.message ?: "")
t.printStackTrace()

}
})
}
fun showLoader(show: Boolean?, resInfo: String? = null) {
recyclerView.makeGone()
loaderView.makeGone()
txtCategoryResInfo.makeGone()

if (resInfo != null) {
txtCategoryResInfo?.text = resInfo
txtCategoryResInfo.makeVisible()
} else if (show == true) {
loaderView.makeVisible()
} else {
recyclerView.makeVisible()
}
}
private val subTitleInfo: String?
get() {
return "Search Category by known key words"
}

fun show(fragmentManager: FragmentManager) {
try {
if (fragmentManager.findFragmentByTag(tagValue) != null) return
} catch (ignore: Exception) {
}
show(fragmentManager, tagValue)
}

private val tagValue: String
get() = "CATEGORY_SELECTION_FRAGMENT"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.manimarank.spell4wiki.ui.listerners

interface OnCategorySelectionListener {
fun onCallBackListener(category: String?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import com.manimarank.spell4wiki.utils.constants.ListMode
import com.manimarank.spell4wiki.utils.constants.ListMode.Companion.EnumListMode
import com.manimarank.spell4wiki.utils.constants.Urls
import com.manimarank.spell4wiki.utils.makeVisible
import java.util.*
import kotlin.collections.ArrayList

class EndlessRecyclerAdapter(
private val mContext: Context,
Expand Down Expand Up @@ -85,7 +83,10 @@ class EndlessRecyclerAdapter(

fun addItems(postItems: MutableList<String>) {
if (postItems.isNotEmpty()) {
mItems.addAll(postItems)
postItems.forEach {item ->
if (!mItems.contains(item))
mItems.add(item)
}
notifyDataSetChanged()
}
}
Expand Down
Loading

0 comments on commit fc4aaba

Please sign in to comment.