mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-03-26 05:20:10 +01:00
WIP - searching for strings in a given note, then highlighting and looping through the string occurrences with some arrows.
This commit is contained in:
parent
12604ac41b
commit
716953ec9d
@ -57,10 +57,10 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:5.22.19'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
|
||||
implementation 'com.simplemobiletools:commons:5.23.7'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
||||
|
||||
kapt 'androidx.room:room-compiler:2.2.2'
|
||||
implementation 'androidx.room:room-runtime:2.2.2'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.2.2'
|
||||
kapt 'androidx.room:room-compiler:2.2.4'
|
||||
implementation 'androidx.room:room-runtime:2.2.4'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.2.4'
|
||||
}
|
||||
|
@ -3,13 +3,17 @@ package com.simplemobiletools.notes.pro.activities
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.method.ArrowKeyMovementMethod
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.BackgroundColorSpan
|
||||
import android.util.TypedValue
|
||||
import android.view.ActionMode
|
||||
import android.view.Gravity
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.TextView
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog
|
||||
import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
@ -26,9 +30,13 @@ import com.simplemobiletools.notes.pro.adapters.NotesPagerAdapter
|
||||
import com.simplemobiletools.notes.pro.databases.NotesDatabase
|
||||
import com.simplemobiletools.notes.pro.dialogs.*
|
||||
import com.simplemobiletools.notes.pro.extensions.*
|
||||
import com.simplemobiletools.notes.pro.helpers.*
|
||||
import com.simplemobiletools.notes.pro.helpers.MIME_TEXT_PLAIN
|
||||
import com.simplemobiletools.notes.pro.helpers.NoteType
|
||||
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
||||
import com.simplemobiletools.notes.pro.helpers.OPEN_NOTE_ID
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.search_item.*
|
||||
import java.io.File
|
||||
import java.nio.charset.Charset
|
||||
|
||||
@ -47,6 +55,9 @@ class MainActivity : SimpleActivity() {
|
||||
private var showSaveButton = false
|
||||
private var showUndoButton = false
|
||||
private var showRedoButton = false
|
||||
private var searchIndex = 0
|
||||
private var searchMatches = emptyList<Int>()
|
||||
private var searchIsActive = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -65,7 +76,127 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
wasInit = true
|
||||
|
||||
checkAppOnSDCard()
|
||||
searchListeners()
|
||||
}
|
||||
|
||||
private fun searchListeners() {
|
||||
search_query.onTextChangeListener { query ->
|
||||
currentNotesView()?.let { noteView ->
|
||||
noteView.setText(noteView.value)
|
||||
|
||||
if (query.isNotBlank() && query.length > 1) {
|
||||
searchMatches = searchMatches(query, noteView.value)
|
||||
searchHighLightText(noteView, query)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
search_previous.setOnClickListener {
|
||||
currentNotesView()?.let { noteView ->
|
||||
if (searchIndex > 0) {
|
||||
searchIndex--
|
||||
}
|
||||
else {
|
||||
searchIndex = searchMatches.lastIndex
|
||||
}
|
||||
|
||||
selectMatch(noteView)
|
||||
}
|
||||
}
|
||||
|
||||
search_next.setOnClickListener {
|
||||
currentNotesView()?.let { noteView ->
|
||||
if (searchIndex < searchMatches.lastIndex) {
|
||||
searchIndex++
|
||||
}
|
||||
else {
|
||||
searchIndex = 0
|
||||
}
|
||||
|
||||
selectMatch(noteView)
|
||||
}
|
||||
}
|
||||
|
||||
search_clear.setOnClickListener {
|
||||
if (search_query.value.isNotBlank())
|
||||
search_query.text?.clear()
|
||||
else
|
||||
searchHide()
|
||||
}
|
||||
|
||||
view_pager.onPageChangeListener {
|
||||
if (searchIsActive) searchHide()
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectMatch(noteView: MyEditText) {
|
||||
if (searchMatches.isNotEmpty()) {
|
||||
noteView.requestFocus()
|
||||
noteView.setSelection(searchMatches.getOrNull(searchIndex) ?: 0)
|
||||
} else {
|
||||
hideKeyboard()
|
||||
//toast("No matches")//TODO
|
||||
}
|
||||
}
|
||||
|
||||
private fun searchMatches(textToHighlight: String, content: String): ArrayList<Int> {
|
||||
val indexes = arrayListOf<Int>()
|
||||
var indexOf = content.indexOf(textToHighlight, 0, ignoreCase = true)
|
||||
|
||||
var offset = 0
|
||||
while (offset < content.length && indexOf != -1) {
|
||||
indexOf = content.indexOf(textToHighlight, offset, ignoreCase = true)
|
||||
|
||||
if (indexOf == -1)
|
||||
break
|
||||
else
|
||||
indexes.add(indexOf)
|
||||
|
||||
offset = indexOf + 1
|
||||
}
|
||||
|
||||
return indexes
|
||||
}
|
||||
|
||||
private fun searchHighLightText(view: MyEditText, textToHighlight: String) {
|
||||
val content = view.text.toString()
|
||||
var indexOf = content.indexOf(textToHighlight, 0, true)
|
||||
val wordToSpan = SpannableString(view.text)
|
||||
|
||||
var offset = 0
|
||||
while (offset < content.length && indexOf != -1) {
|
||||
indexOf = content.indexOf(textToHighlight, offset, true)
|
||||
|
||||
if (indexOf == -1) break
|
||||
else {
|
||||
wordToSpan.setSpan(BackgroundColorSpan(color(R.color.color_accent)), indexOf, indexOf + textToHighlight.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
view.setText(wordToSpan, TextView.BufferType.SPANNABLE)
|
||||
}
|
||||
|
||||
offset = indexOf + 1
|
||||
}
|
||||
}
|
||||
|
||||
private fun searchShow() {
|
||||
searchIsActive = true
|
||||
search_root.beVisible()
|
||||
showKeyboard(search_query)
|
||||
|
||||
currentNotesView()?.let { noteView ->
|
||||
noteView.requestFocus()
|
||||
noteView.setSelection(0)
|
||||
}
|
||||
|
||||
search_query.postDelayed({
|
||||
search_query.requestFocus()
|
||||
}, 250)
|
||||
}
|
||||
|
||||
private fun searchHide() {
|
||||
searchIsActive = false
|
||||
search_root.beGone()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@ -129,6 +260,7 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
when (item.itemId) {
|
||||
R.id.open_search -> searchShow()
|
||||
R.id.open_note -> displayOpenNoteDialog()
|
||||
R.id.save_note -> saveNote()
|
||||
R.id.undo -> undo()
|
||||
@ -627,7 +759,8 @@ class MainActivity : SimpleActivity() {
|
||||
private fun saveCurrentNote(force: Boolean) {
|
||||
getPagerAdapter().saveCurrentNote(view_pager.currentItem, force)
|
||||
if (mCurrentNote.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
mCurrentNote.value = getPagerAdapter().getNoteChecklistItems(view_pager.currentItem) ?: ""
|
||||
mCurrentNote.value = getPagerAdapter().getNoteChecklistItems(view_pager.currentItem)
|
||||
?: ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -730,26 +863,28 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
fun currentNoteTextChanged(newText: String, showUndo: Boolean, showRedo: Boolean) {
|
||||
var shouldRecreateMenu = false
|
||||
if (showUndo != showUndoButton) {
|
||||
showUndoButton = showUndo
|
||||
shouldRecreateMenu = true
|
||||
}
|
||||
|
||||
if (showRedo != showRedoButton) {
|
||||
showRedoButton = showRedo
|
||||
shouldRecreateMenu = true
|
||||
}
|
||||
|
||||
if (!config.autosaveNotes) {
|
||||
showSaveButton = newText != mCurrentNote.value
|
||||
if (showSaveButton != saveNoteButton?.isVisible) {
|
||||
if (searchIsActive.not()) {
|
||||
var shouldRecreateMenu = false
|
||||
if (showUndo != showUndoButton) {
|
||||
showUndoButton = showUndo
|
||||
shouldRecreateMenu = true
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRecreateMenu) {
|
||||
invalidateOptionsMenu()
|
||||
if (showRedo != showRedoButton) {
|
||||
showRedoButton = showRedo
|
||||
shouldRecreateMenu = true
|
||||
}
|
||||
|
||||
if (!config.autosaveNotes) {
|
||||
showSaveButton = newText != mCurrentNote.value
|
||||
if (showSaveButton != saveNoteButton?.isVisible) {
|
||||
shouldRecreateMenu = true
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRecreateMenu) {
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.simplemobiletools.notes.pro.databases.NotesDatabase
|
||||
import com.simplemobiletools.notes.pro.helpers.Config
|
||||
import com.simplemobiletools.notes.pro.helpers.MyWidgetProvider
|
||||
@ -26,3 +27,5 @@ fun Context.updateWidgets() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.color(id: Int) = ContextCompat.getColor(this, id)
|
||||
|
@ -7,3 +7,4 @@ import com.simplemobiletools.notes.pro.helpers.Config
|
||||
val Fragment.config: Config? get() = if (context != null) Config.newInstance(context!!) else null
|
||||
|
||||
val Fragment.requiredActivity: FragmentActivity get() = this.activity!!
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
package com.simplemobiletools.notes.pro.extensions
|
||||
|
||||
import android.os.Build
|
||||
import android.text.Html
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.simplemobiletools.commons.helpers.isMarshmallowPlus
|
||||
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||
import com.simplemobiletools.notes.pro.models.ChecklistItem
|
||||
|
||||
fun String.parseChecklistItems(): ArrayList<ChecklistItem>? {
|
||||
@ -14,3 +19,7 @@ fun String.parseChecklistItems(): ArrayList<ChecklistItem>? {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
fun String.toHtml() = if (isNougatPlus()) Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY) else Html.fromHtml(this)
|
||||
|
||||
|
@ -1,16 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.commons.views.MyViewPager
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/view_pager"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.viewpager.widget.PagerTitleStrip
|
||||
android:id="@+id/pager_title_strip"
|
||||
<include layout="@layout/search_item" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyViewPager
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"/>
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</com.simplemobiletools.commons.views.MyViewPager>
|
||||
<androidx.viewpager.widget.PagerTitleStrip
|
||||
android:id="@+id/pager_title_strip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin" />
|
||||
|
||||
</com.simplemobiletools.commons.views.MyViewPager>
|
||||
</LinearLayout>
|
||||
|
53
app/src/main/res/layout/search_item.xml
Normal file
53
app/src/main/res/layout/search_item.xml
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/search_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/color_primary"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="@dimen/small_margin"
|
||||
android:paddingBottom="@dimen/small_margin"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyEditText
|
||||
android:id="@+id/search_query"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/normal_margin"
|
||||
android:layout_marginEnd="@dimen/normal_margin"
|
||||
android:layout_weight="1"
|
||||
android:maxLength="50"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textCursorDrawable="@null" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_previous"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/smaller_margin"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/small_margin"
|
||||
android:src="@drawable/ic_chevron_left_vector" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/smaller_margin"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/small_margin"
|
||||
android:src="@drawable/ic_chevron_right_vector" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_clear"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/medium_margin"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/small_margin"
|
||||
android:src="@drawable/ic_cross_vector" />
|
||||
</LinearLayout>
|
@ -16,6 +16,11 @@
|
||||
android:icon="@drawable/ic_redo_vector"
|
||||
android:title="@string/redo"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/open_search"
|
||||
android:icon="@drawable/ic_search_vector"
|
||||
android:title="@string/search"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/open_note"
|
||||
android:icon="@drawable/ic_folder_open_vector"
|
||||
|
Loading…
x
Reference in New Issue
Block a user