mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-11-27 09:46:50 +03:00
#550 In-note-search doesn't jump to occurrence of searchstring
- Fix crash on pressing prev button too often - Fix scrolling behavior in preview fragment
This commit is contained in:
parent
4de492621b
commit
9b48acf182
4 changed files with 57 additions and 53 deletions
|
@ -1,7 +1,7 @@
|
||||||
package it.niedermann.owncloud.notes.android.fragment;
|
package it.niedermann.owncloud.notes.android.fragment;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ShortcutInfo;
|
import android.content.pm.ShortcutInfo;
|
||||||
|
@ -22,6 +22,7 @@ import android.widget.LinearLayout;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.SearchView;
|
import androidx.appcompat.widget.SearchView;
|
||||||
import androidx.appcompat.widget.ShareActionProvider;
|
import androidx.appcompat.widget.ShareActionProvider;
|
||||||
|
@ -30,6 +31,7 @@ import androidx.core.view.ViewCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
|
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
|
||||||
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
|
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
|
||||||
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
||||||
|
@ -131,14 +133,14 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Activity activity) {
|
public void onAttach(@NonNull Context context) {
|
||||||
super.onAttach(activity);
|
super.onAttach(context);
|
||||||
try {
|
try {
|
||||||
listener = (NoteFragmentListener) activity;
|
listener = (NoteFragmentListener) context;
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new ClassCastException(activity.getClass() + " must implement " + NoteFragmentListener.class);
|
throw new ClassCastException(context.getClass() + " must implement " + NoteFragmentListener.class);
|
||||||
}
|
}
|
||||||
db = NoteSQLiteOpenHelper.getInstance(activity);
|
db = NoteSQLiteOpenHelper.getInstance(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -160,7 +162,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
saveNote(null);
|
saveNote(null);
|
||||||
outState.putSerializable(SAVEDKEY_NOTE, note);
|
outState.putSerializable(SAVEDKEY_NOTE, note);
|
||||||
|
@ -180,10 +182,10 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.menu_note_fragment, menu);
|
inflater.inflate(R.menu.menu_note_fragment, menu);
|
||||||
|
|
||||||
if (isRequestPinShortcutSupported(getActivity()) && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (isRequestPinShortcutSupported(Objects.requireNonNull(getActivity())) && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
menu.add(Menu.NONE, MENU_ID_PIN, 110, R.string.pin_to_homescreen);
|
menu.add(Menu.NONE, MENU_ID_PIN, 110, R.string.pin_to_homescreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +193,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
private int occurence = 1;
|
private int occurence = 1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(@NonNull Menu menu) {
|
||||||
super.onPrepareOptionsMenu(menu);
|
super.onPrepareOptionsMenu(menu);
|
||||||
MenuItem itemFavorite = menu.findItem(R.id.menu_favorite);
|
MenuItem itemFavorite = menu.findItem(R.id.menu_favorite);
|
||||||
prepareFavoriteOption(itemFavorite);
|
prepareFavoriteOption(itemFavorite);
|
||||||
|
@ -234,12 +236,18 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
|
|
||||||
View next = getSearchNextButton();
|
View next = getSearchNextButton();
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
next.setOnClickListener(v -> jumpToNthNote(searchQuery, occurence, true));
|
next.setOnClickListener(v -> {
|
||||||
|
occurence++;
|
||||||
|
jumpToNthNote(searchQuery);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
View prev = getSearchPrevButton();
|
View prev = getSearchPrevButton();
|
||||||
if (prev != null) {
|
if (prev != null) {
|
||||||
prev.setOnClickListener(v -> jumpToNthNote(searchQuery, occurence, false));
|
prev.setOnClickListener(v -> {
|
||||||
|
occurence--;
|
||||||
|
jumpToNthNote(searchQuery);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||||
|
@ -250,27 +258,27 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextChange(String newText) {
|
public boolean onQueryTextChange(String newText) {
|
||||||
occurence = 1;
|
|
||||||
searchQuery = newText;
|
searchQuery = newText;
|
||||||
colorWithText(newText);
|
colorWithText(newText);
|
||||||
|
occurence = 1;
|
||||||
jumpToNthNote(newText);
|
jumpToNthNote(newText);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void jumpToNthNote(String newText) {
|
private void jumpToNthNote(String newText) {
|
||||||
jumpToNthNote(newText, 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void jumpToNthNote(String newText, int occurrence, boolean directionForward) {
|
|
||||||
if (newText == null || newText.isEmpty()) {
|
if (newText == null || newText.isEmpty()) {
|
||||||
// No search term
|
// No search term
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (occurence < 1) {
|
||||||
|
// TODO find last occurence
|
||||||
|
occurence = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
String currentContent = getContent().toLowerCase();
|
String currentContent = getContent().toLowerCase();
|
||||||
int indexOfNewText = indexOfNth(currentContent, newText.toLowerCase(), 0, occurrence);
|
int indexOfNewText = indexOfNth(currentContent, newText.toLowerCase(), 0, occurence);
|
||||||
if (indexOfNewText <= 0) {
|
if (indexOfNewText <= 0) {
|
||||||
// Search term not in text
|
// Search term not in text
|
||||||
occurence = 1;
|
occurence = 1;
|
||||||
|
@ -288,11 +296,6 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
if (numberLine >= 0) {
|
if (numberLine >= 0) {
|
||||||
getScrollView().smoothScrollTo(0, getLayout().getLineTop(numberLine));
|
getScrollView().smoothScrollTo(0, getLayout().getLineTop(numberLine));
|
||||||
}
|
}
|
||||||
if(directionForward) {
|
|
||||||
this.occurence++;
|
|
||||||
} else {
|
|
||||||
this.occurence--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int indexOfNth(String input, String value, int startIndex, int nth) {
|
private static int indexOfNth(String input, String value, int startIndex, int nth) {
|
||||||
|
@ -310,8 +313,9 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
|
||||||
|
|
||||||
protected abstract Layout getLayout();
|
protected abstract Layout getLayout();
|
||||||
|
|
||||||
protected abstract View getSearchNextButton();
|
protected abstract FloatingActionButton getSearchNextButton();
|
||||||
protected abstract View getSearchPrevButton();
|
|
||||||
|
protected abstract FloatingActionButton getSearchPrevButton();
|
||||||
|
|
||||||
private void prepareFavoriteOption(MenuItem item) {
|
private void prepareFavoriteOption(MenuItem item) {
|
||||||
item.setIcon(note.isFavorite() ? R.drawable.ic_star_white_24dp : R.drawable.ic_star_border_white_24dp);
|
item.setIcon(note.isFavorite() ? R.drawable.ic_star_white_24dp : R.drawable.ic_star_border_white_24dp);
|
||||||
|
|
|
@ -113,12 +113,12 @@ public class NoteEditFragment extends BaseNoteFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View getSearchNextButton() {
|
protected FloatingActionButton getSearchNextButton() {
|
||||||
return searchNext;
|
return searchNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View getSearchPrevButton() {
|
protected FloatingActionButton getSearchPrevButton() {
|
||||||
return searchPrev;
|
return searchPrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,12 +80,12 @@ public class NotePreviewFragment extends BaseNoteFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View getSearchNextButton() {
|
protected FloatingActionButton getSearchNextButton() {
|
||||||
return searchNext;
|
return searchNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View getSearchPrevButton() {
|
protected FloatingActionButton getSearchPrevButton() {
|
||||||
return searchPrev;
|
return searchPrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swiperefreshlayout"
|
android:id="@+id/swiperefreshlayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
@ -9,10 +13,6 @@
|
||||||
tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
|
tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
|
||||||
tools:ignore="MergeRootFrame">
|
tools:ignore="MergeRootFrame">
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/editContentContainer"
|
android:id="@+id/editContentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
android:textColor="@color/fg_default"
|
android:textColor="@color/fg_default"
|
||||||
android:textIsSelectable="true" />
|
android:textIsSelectable="true" />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/searchPrev"
|
android:id="@+id/searchPrev"
|
||||||
|
@ -46,4 +47,3 @@
|
||||||
app:fabSize="mini"
|
app:fabSize="mini"
|
||||||
app:srcCompat="@drawable/ic_keyboard_arrow_down_white_24dp" />
|
app:srcCompat="@drawable/ic_keyboard_arrow_down_white_24dp" />
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
Loading…
Reference in a new issue