Skip to content

[SPIKE][Experiment] Articles by Categories #5437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions app/src/main/java/org/wikipedia/dataclient/Service.kt
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ interface Service {
@GET(MW_API_PREFIX + "action=query&prop=info&generator=categories&inprop=varianttitles|displaytitle&gclshow=!hidden&gcllimit=500")
suspend fun getCategories(@Query("titles") titles: String): MwQueryResponse

@GET(MW_API_PREFIX + "action=query&prop=categories&clshow=!hidden&cllimit=100")
suspend fun getCategoriesProps(@Query("titles") titles: String): MwQueryResponse

@GET(MW_API_PREFIX + "action=query&prop=description|pageimages|info&pilicense=any&generator=categorymembers&inprop=varianttitles|displaytitle&gcmprop=ids|title")
suspend fun getCategoryMembers(
@Query("gcmtitle") title: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class MwQueryPage {
@SerialName("pageid") val pageId = 0
@SerialName("pageprops") val pageProps: PageProps? = null
@SerialName("entityterms") val entityTerms: EntityTerms? = null
@SerialName("categories") val categoriesProps: List<Category>? = null

val ns = 0
val coordinates: List<Coordinates>? = null
Expand Down Expand Up @@ -147,4 +148,10 @@ class MwQueryPage {
val label: List<String> = emptyList()
val description: List<String> = emptyList()
}

@Serializable
class Category {
val ns = 0
val title: String = ""
}
}
33 changes: 32 additions & 1 deletion app/src/main/java/org/wikipedia/history/HistoryFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ScrollView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import androidx.core.view.updateLayoutParams
import androidx.core.view.updateMarginsRelative
import androidx.fragment.app.Fragment
Expand All @@ -38,6 +40,7 @@ import org.wikipedia.util.DimenUtil
import org.wikipedia.util.FeedbackUtil
import org.wikipedia.util.Resource
import org.wikipedia.util.ResourceUtil
import org.wikipedia.util.StringUtil
import org.wikipedia.util.log.L
import org.wikipedia.views.DefaultViewHolder
import org.wikipedia.views.PageItemView
Expand Down Expand Up @@ -91,7 +94,6 @@ class HistoryFragment : Fragment(), BackPressedHandler {
}
}
}

private fun setUpScrollListener() {
binding.historyList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
Expand Down Expand Up @@ -260,6 +262,7 @@ class HistoryFragment : Fragment(), BackPressedHandler {
init {
val searchCardView = itemView.findViewById<WikiCardView>(R.id.search_card)
val voiceSearchButton = itemView.findViewById<View>(R.id.voice_search_button)
val categoriesDialogButton = itemView.findViewById<ImageView>(R.id.categories_dialog)
historyFilterButton = itemView.findViewById(R.id.history_filter)
clearHistoryButton = itemView.findViewById(R.id.history_delete)
searchCardView.setOnClickListener { (requireParentFragment() as MainFragment).openSearchActivity(Constants.InvokeSource.NAV_MENU, null, it) }
Expand All @@ -282,6 +285,34 @@ class HistoryFragment : Fragment(), BackPressedHandler {
deleteSelectedPages()
}
}
categoriesDialogButton.setOnClickListener {
val groupData = viewModel.groupedTitles

var htmlContent = ""
groupData.forEach {
htmlContent += "${it.first} <b> (${it.second})</b> <br>"
}

val textView = TextView(requireContext()).apply {
text = StringUtil.fromHtml(htmlContent)
textSize = 14f
}

val scrollView = ScrollView(requireContext()).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
setPadding(DimenUtil.roundedDpToPx(12f))
addView(textView)
}

MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.action_item_categories)
.setView(scrollView)
.setPositiveButton(android.R.string.ok, null)
.show()
}
FeedbackUtil.setButtonTooltip(historyFilterButton, clearHistoryButton)
adjustSearchCardView(searchCardView)
}
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/org/wikipedia/history/HistoryViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.wikipedia.WikipediaApp
import org.wikipedia.database.AppDatabase
import org.wikipedia.dataclient.ServiceFactory
import org.wikipedia.dataclient.mwapi.MwQueryPage.Category
import org.wikipedia.util.Resource
import org.wikipedia.util.SingleLiveData
import org.wikipedia.util.StringUtil

class HistoryViewModel : ViewModel() {

Expand All @@ -33,6 +39,7 @@ class HistoryViewModel : ViewModel() {

val historyItems = MutableLiveData(Resource<List<Any>>())
val deleteHistoryItemsAction = SingleLiveData<Resource<Boolean>>()
var groupedTitles = emptyList<Pair<String, Int>>()

init {
reloadHistoryItems()
Expand All @@ -47,6 +54,26 @@ class HistoryViewModel : ViewModel() {
private suspend fun loadHistoryItems() {
withContext(Dispatchers.IO) {
val items = AppDatabase.instance.historyEntryWithImageDao().filterHistoryItems(searchQuery.orEmpty())
val historyEntryItems = items.filterIsInstance<HistoryEntry>()

val categories = mutableListOf<Category>()
val deferredCategories = historyEntryItems.map { item ->
async {
try {
val response = ServiceFactory.get(WikipediaApp.instance.wikiSite).getCategoriesProps(item.apiTitle)
response.query?.firstPage()?.categoriesProps ?: emptyList()
} catch (e: Exception) {
// Handle exceptions appropriately, e.g., log, return emptyList, etc.
println("Error fetching categories for ${item.apiTitle}: ${e.message}")
emptyList() // or throw e; depending on your error handling.
}
}
}

deferredCategories.awaitAll().forEach { categories.addAll(it) }

// Grouping the titles by setting in a Pair<> with its name and count
groupedTitles = categories.groupBy { it.title }.map { Pair(StringUtil.removeNamespace(it.key), it.value.size) }.sortedByDescending { it.second }
historyItems.postValue(Resource.Success(items))
}
}
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/res/layout/view_history_header_with_search.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@
android:textSize="24sp"
android:textStyle="bold" />

<ImageView
android:id="@+id/categories_dialog"
android:layout_width="48dp"
android:layout_height="48dp"
android:clickable="true"
android:contentDescription="@string/action_item_categories"
android:focusable="true"
android:background="?attr/actionBarItemBackground"
android:scaleType="centerInside"
app:srcCompat="@drawable/ic_category_black_24dp"
app:tint="?attr/progressive_color" />

<ImageView
android:id="@+id/history_filter"
android:layout_width="48dp"
Expand Down
Loading