Skip to content

Commit

Permalink
CATROID-1196 Brick Search History
Browse files Browse the repository at this point in the history
  • Loading branch information
Walcho1125 committed Jun 22, 2022
1 parent 645120b commit c9eccec
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import android.view.inputmethod.InputMethodManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.clearText
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.pressKey
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
Expand Down Expand Up @@ -118,28 +119,52 @@ class BrickSearchTest {
Espresso.onView(withId(R.id.search_src_text)).perform(
replaceText("if")
).perform(pressKey(KeyEvent.KEYCODE_ENTER))
val searchAutoComplete = Espresso.onView(
Matchers.allOf(
withId(R.id.search_src_text),
ViewMatchers.withText("if"), childAtPosition(
Matchers.allOf(
withId(R.id.search_plate),
childAtPosition(withId(R.id.search_edit_frame), 1)
), 0
), isDisplayed()
)
)
searchAutoComplete.perform(ViewActions.pressImeActionButton())
val linearLayout = Espresso.onData(Matchers.anything()).inAdapterView(
Matchers.allOf(
withId(android.R.id.list),
childAtPosition(withId(R.id.fragment_brick_search), 0)
Espresso.onData(Matchers.anything())
.inAdapterView(
Matchers.allOf(
withId(android.R.id.list),
childAtPosition(
withId(R.id.fragment_brick_search),
1
)
)
)
).atPosition(0)
linearLayout.perform(click())
.atPosition(0).perform(click())
Assert.assertFalse(isKeyboardVisible())
}

@Test
fun testSearchHistory() {
Espresso.onView(withId(R.id.button_add)).perform(click())
Espresso.onView(withId(R.id.search)).perform(click())
Espresso.onView(withId(R.id.search_src_text)).perform(clearText(), ViewActions.typeText
("test")).perform(pressKey(KeyEvent.KEYCODE_ENTER))
Espresso.onData(Matchers.anything())
.inAdapterView(
Matchers.allOf(
withId(android.R.id.list),
childAtPosition(
withId(R.id.fragment_brick_search),
1
)
)
)
.atPosition(0).perform(click())
Espresso.onView(withId(R.id.button_add)).perform(click())
Espresso.onView(withId(R.id.search)).perform(click())
Espresso.onData(Matchers.anything())
.inAdapterView(
Matchers.allOf(
withId(android.R.id.list),
childAtPosition(
withId(R.id.fragment_brick_search),
1
)
)
)
.atPosition(0).check(matches(isDisplayed()))
}

@Test
fun testCloseKeyboardAfterSearching() {
ensureKeyboardIsClosed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

package org.catrobat.catroid.ui.fragment

import android.app.SearchManager
import android.content.Context
import android.os.Bundle
import android.os.CountDownTimer
import android.preference.PreferenceManager
Expand All @@ -33,7 +31,6 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AbsListView
import android.widget.AdapterView
import android.widget.ProgressBar
import android.widget.TextView
Expand All @@ -53,25 +50,35 @@ import org.catrobat.catroid.ui.settingsfragments.AccessibilityProfile
import org.catrobat.catroid.ui.settingsfragments.SettingsFragment
import org.catrobat.catroid.utils.ToastUtil
import java.util.Locale
import android.widget.AbsListView
import android.database.Cursor
import org.catrobat.catroid.utils.setVisibleOrGone

class BrickSearchFragment : ListFragment() {

private var previousActionBarTitle: CharSequence? = null

private var searchView: SearchView? = null
private var recentlyUsedTitle: TextView? = null
private var queryTextListener: SearchView.OnQueryTextListener? = null
private var suggestionListener: SearchView.OnSuggestionListener? = null
private var availableBricks: MutableList<Brick> = mutableListOf()
private var recentlyUsedBricks: MutableList<Brick> = mutableListOf()
private var searchResults = mutableListOf<Brick>()
private var addBrickListener: AddBrickFragment.OnAddBrickListener? = null
private var category: String? = null
private var adapter: PrototypeBrickAdapter? = null
@Volatile private var emptyQuery: Boolean = true
@Volatile private var previousQuery: String = ""

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_brick_search, container, false)
val actionBar = (activity as? AppCompatActivity)?.supportActionBar
previousActionBarTitle = actionBar?.title
recentlyUsedTitle = view.findViewById(R.id.recent_used_header)
hideBottomBar(activity)
setHasOptionsMenu(true)
getRecentlyUsedBricks()
category?.let { prepareBrickList(it) }
return view
}
Expand Down Expand Up @@ -105,12 +112,13 @@ class BrickSearchFragment : ListFragment() {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_search, menu)
val searchItem = menu.findItem(R.id.search_bar).actionView
val searchManager: SearchManager = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager
(searchItem as SearchView).apply {
setSearchableInfo(searchManager.getSearchableInfo(activity?.componentName))
isIconified = false
queryHint = context.getString(R.string.search_hint)
}
searchResults.addAll(recentlyUsedBricks)
adapter = PrototypeBrickAdapter(searchResults)
listAdapter = adapter
listView.setOnScrollListener(object : AbsListView.OnScrollListener {
override fun onScrollStateChanged(
view: AbsListView,
Expand All @@ -133,9 +141,10 @@ class BrickSearchFragment : ListFragment() {
var countDownTimer: CountDownTimer
adapter = PrototypeBrickAdapter(searchResults)
listAdapter = adapter
searchView?.setSearchableInfo(searchManager.getSearchableInfo(activity?.componentName))
queryTextListener = object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(query: String): Boolean {
previousQuery = query
recentlyUsedTitle?.setVisibleOrGone(query.isEmpty())
countDownTimer = object : CountDownTimer(
PROGESSIVE_INPUT_DELAY,
PROGESSIVE_INPUT_COUNTDOWN_INTERVALL
Expand All @@ -145,24 +154,22 @@ class BrickSearchFragment : ListFragment() {
}

override fun onFinish() {
setShowProgressBar(false)
searchResults.clear()
adapter?.replaceList(searchResults)
searchBrick(query)
if (searchResults.isEmpty()) {
ToastUtil.showError(
context,
context?.getString(R.string.no_results_found)
)
}
if (query.isEmpty()) {
searchResults.clear()
}
adapter?.replaceList(searchResults)
when (query) {
previousQuery -> searchAndFillBrickList(query)
}
}
}
countDownTimer.start()
setShowProgressBar(true)
emptyQuery = query.isEmpty()
if (query.isEmpty()) {
searchResults.clear()
searchResults.addAll(recentlyUsedBricks)
adapter?.replaceList(searchResults)
countDownTimer.cancel()
setShowProgressBar(false)
} else {
countDownTimer.start()
setShowProgressBar(true)
}
return true
}

Expand All @@ -172,15 +179,32 @@ class BrickSearchFragment : ListFragment() {
adapter?.replaceList(searchResults)
if (searchResults.isEmpty()) {
ToastUtil.showError(context, context?.getString(R.string.no_results_found))
} else searchView?.clearFocus()
} else {
searchView?.clearFocus()
}
return true
}
}
suggestionListener = object : SearchView.OnSuggestionListener {
override fun onSuggestionSelect(position: Int): Boolean {
return false
}

override fun onSuggestionClick(position: Int): Boolean {
val cursor: Cursor? = searchView?.suggestionsAdapter?.cursor
cursor?.moveToPosition(position)
val suggestion: String? = cursor?.getString(2)
searchView?.setQuery(suggestion, true)
return true
}
}
searchView?.setOnQueryTextListener(queryTextListener)
searchView?.requestFocus()
}
searchView?.setOnQueryTextListener(queryTextListener)
searchView?.setOnSuggestionListener(suggestionListener)
searchView?.requestFocus()
super.onCreateOptionsMenu(menu, inflater)
}

private fun setShowProgressBar(visible: Boolean) {
if (visible) {
view?.findViewById<ProgressBar>(R.id.progress_bar)?.visibility = View.VISIBLE
Expand All @@ -199,6 +223,26 @@ class BrickSearchFragment : ListFragment() {

private fun onlyBeginnerBricks(): Boolean = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(AccessibilityProfile.BEGINNER_BRICKS, false)

private fun searchAndFillBrickList(query: String) {
searchResults.clear()
if (emptyQuery) {
return
}
adapter?.replaceList(searchResults)
searchBrick(query)
if (searchResults.isEmpty()) {
ToastUtil.showError(
context,
context?.getString(R.string.no_results_found)
)
}
if (emptyQuery) {
return
}
adapter?.replaceList(searchResults)
setShowProgressBar(false)
}

private fun searchBrick(query: String) {
availableBricks.forEach { brick ->
val regexQuery = (".*" + query.toLowerCase(Locale.ROOT).replace("\\s".toRegex(), ".*") + ".*").toRegex()
Expand Down Expand Up @@ -229,6 +273,16 @@ class BrickSearchFragment : ListFragment() {
return wholeStringFoundInBrick
}

fun getRecentlyUsedBricks() {
val categoryBricksFactory: CategoryBricksFactory = when {
onlyBeginnerBricks() -> CategoryBeginnerBricksFactory()
else -> CategoryBricksFactory()
}
val backgroundSprite = ProjectManager.getInstance().currentlyEditedScene.backgroundSprite
val sprite = ProjectManager.getInstance().currentSprite
recentlyUsedBricks.addAll(categoryBricksFactory.getBricks(requireContext().getString(R.string.category_recently_used), backgroundSprite.equals(sprite), requireContext()))
}

@SuppressWarnings("ComplexMethod")
fun prepareBrickList(category: String = "") {
val categoryBricksFactory: CategoryBricksFactory = when {
Expand Down
29 changes: 22 additions & 7 deletions catroid/src/main/res/layout/fragment_brick_search.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,34 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_background">
<ListView
android:id="@android:id/list"
<TextView
android:id="@+id/recent_used_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:divider="@android:color/transparent">
</ListView>
android:text="@string/category_recently_used"
android:textColor="@color/view_holder_item_title"
android:padding="@dimen/view_holder_padding"
android:textSize="?attr/large"
android:visibility="visible"/>
<TextView
android:id="@+id/no_recently_used"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:text="">

</TextView>
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/recent_used_header"
android:cacheColorHint="#00000000"
android:divider="@android:color/transparent"/>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true"
android:visibility="invisible"
/>
android:visibility="invisible"/>
</RelativeLayout>
4 changes: 2 additions & 2 deletions catroid/src/main/res/xml/searchable.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Catroid: An on-device visual programming system for Android devices
~ Copyright (C) 2010-2021 The Catrobat Team
~ Copyright (C) 2010-2022 The Catrobat Team
~ (<http://developer.catrobat.org/credits>)
~
~ This program is free software: you can redistribute it and/or modify
Expand All @@ -24,4 +24,4 @@

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint" />
android:hint="@string/search_hint"/>

0 comments on commit c9eccec

Please sign in to comment.