@@ -9,17 +9,22 @@ import android.print.PrintAttributes
99import android.print.PrintManager
1010import android.view.Menu
1111import android.view.MenuItem
12+ import android.view.inputmethod.EditorInfo
1213import android.webkit.WebResourceRequest
1314import android.webkit.WebView
1415import android.webkit.WebViewClient
16+ import android.widget.ImageView
17+ import android.widget.TextView
1518import com.simplemobiletools.commons.extensions.*
1619import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
1720import com.simplemobiletools.commons.helpers.REAL_FILE_PATH
1821import com.simplemobiletools.commons.helpers.ensureBackgroundThread
22+ import com.simplemobiletools.commons.views.MyEditText
1923import com.simplemobiletools.filemanager.pro.R
2024import com.simplemobiletools.filemanager.pro.dialogs.SaveAsDialog
2125import com.simplemobiletools.filemanager.pro.extensions.config
2226import com.simplemobiletools.filemanager.pro.extensions.openPath
27+ import com.simplemobiletools.filemanager.pro.views.GestureEditText
2328import kotlinx.android.synthetic.main.activity_read_text.*
2429import java.io.File
2530import java.io.OutputStream
@@ -29,10 +34,22 @@ class ReadTextActivity : SimpleActivity() {
2934
3035 private var filePath = " "
3136 private var originalText = " "
37+ private var searchIndex = 0
38+ private var searchMatches = emptyList<Int >()
39+ private var isSearchActive = false
40+
41+ private lateinit var searchQueryET: MyEditText
42+ private lateinit var searchPrevBtn: ImageView
43+ private lateinit var searchNextBtn: ImageView
44+ private lateinit var searchClearBtn: ImageView
3245
3346 override fun onCreate (savedInstanceState : Bundle ? ) {
3447 super .onCreate(savedInstanceState)
3548 setContentView(R .layout.activity_read_text)
49+ searchQueryET = findViewById(R .id.search_query)
50+ searchPrevBtn = findViewById(R .id.search_previous)
51+ searchNextBtn = findViewById(R .id.search_next)
52+ searchClearBtn = findViewById(R .id.search_clear)
3653
3754 if (checkAppSideloading()) {
3855 return
@@ -41,6 +58,8 @@ class ReadTextActivity : SimpleActivity() {
4158 read_text_view.onGlobalLayout {
4259 checkIntent()
4360 }
61+
62+ setupSearchButtons()
4463 }
4564
4665 override fun onCreateOptionsMenu (menu : Menu ): Boolean {
@@ -68,8 +87,26 @@ class ReadTextActivity : SimpleActivity() {
6887 }
6988 }
7089
90+ override fun onBackPressed () {
91+ if (isSearchActive) {
92+ closeSearch()
93+ } else {
94+ super .onBackPressed()
95+ }
96+ }
97+
7198 private fun openSearch () {
99+ isSearchActive = true
100+ search_wrapper.beVisible()
101+
102+ showKeyboard(searchQueryET)
72103
104+ read_text_view.requestFocus()
105+ read_text_view.setSelection(0 )
106+
107+ searchQueryET.postDelayed({
108+ searchQueryET.requestFocus()
109+ }, 250 )
73110 }
74111
75112 private fun saveText () {
@@ -129,7 +166,12 @@ class ReadTextActivity : SimpleActivity() {
129166 }
130167
131168 private fun createWebPrintJob (webView : WebView ) {
132- val jobName = if (filePath.isNotEmpty()) filePath.getFilenameFromPath() else getString(R .string.app_name)
169+ val jobName = if (filePath.isNotEmpty()) {
170+ filePath.getFilenameFromPath()
171+ } else {
172+ getString(R .string.app_name)
173+ }
174+
133175 val printAdapter = webView.createPrintDocumentAdapter(jobName)
134176
135177 (getSystemService(Context .PRINT_SERVICE ) as ? PrintManager )?.apply {
@@ -180,4 +222,90 @@ class ReadTextActivity : SimpleActivity() {
180222 }
181223 }
182224 }
225+
226+ private fun setupSearchButtons () {
227+ searchQueryET.onTextChangeListener {
228+ searchTextChanged(it)
229+ }
230+
231+ searchPrevBtn.setOnClickListener {
232+ goToPrevSearchResult()
233+ }
234+
235+ searchNextBtn.setOnClickListener {
236+ goToNextSearchResult()
237+ }
238+
239+ searchClearBtn.setOnClickListener {
240+ closeSearch()
241+ }
242+
243+ searchQueryET.setOnEditorActionListener(TextView .OnEditorActionListener { _, actionId, _ ->
244+ if (actionId == EditorInfo .IME_ACTION_SEARCH ) {
245+ searchNextBtn.performClick()
246+ return @OnEditorActionListener true
247+ }
248+
249+ false
250+ })
251+
252+ search_wrapper.setBackgroundColor(config.primaryColor)
253+ val contrastColor = config.primaryColor.getContrastColor()
254+ arrayListOf (searchPrevBtn, searchNextBtn, searchClearBtn).forEach {
255+ it.applyColorFilter(contrastColor)
256+ }
257+ }
258+
259+ private fun searchTextChanged (text : String ) {
260+ read_text_view.text?.clearSpans()
261+
262+ if (text.isNotBlank() && text.length > 1 ) {
263+ searchMatches = text.searchMatches(read_text_view.value)
264+ read_text_view.highlightText(text, config.primaryColor)
265+ }
266+
267+ if (searchMatches.isNotEmpty()) {
268+ read_text_view.requestFocus()
269+ read_text_view.setSelection(searchMatches.getOrNull(searchIndex) ? : 0 )
270+ }
271+
272+ searchQueryET.postDelayed({
273+ searchQueryET.requestFocus()
274+ }, 50 )
275+ }
276+
277+ private fun goToPrevSearchResult () {
278+ if (searchIndex > 0 ) {
279+ searchIndex--
280+ } else {
281+ searchIndex = searchMatches.lastIndex
282+ }
283+
284+ selectSearchMatch(read_text_view)
285+ }
286+
287+ private fun goToNextSearchResult () {
288+ if (searchIndex < searchMatches.lastIndex) {
289+ searchIndex++
290+ } else {
291+ searchIndex = 0
292+ }
293+
294+ selectSearchMatch(read_text_view)
295+ }
296+
297+ private fun closeSearch () {
298+ searchQueryET.text.clear()
299+ isSearchActive = false
300+ search_wrapper.beGone()
301+ }
302+
303+ private fun selectSearchMatch (editText : GestureEditText ) {
304+ if (searchMatches.isNotEmpty()) {
305+ editText.requestFocus()
306+ editText.setSelection(searchMatches.getOrNull(searchIndex) ? : 0 )
307+ } else {
308+ hideKeyboard()
309+ }
310+ }
183311}
0 commit comments