Some work on search

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2018-05-14 20:10:44 +02:00
parent 00bbe3eca2
commit 5370d8669a
4 changed files with 176 additions and 35 deletions

View file

@ -115,6 +115,7 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
} else {
fragment = NotePreviewFragment.newInstance(noteId);
}
if (savedState != null) {
fragment.setInitialSavedState(savedState);
}

View file

@ -4,14 +4,20 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.text.Editable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.yydcdut.rxmarkdown.RxMDEditText;
@ -22,6 +28,7 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.util.DisplayUtils;
import it.niedermann.owncloud.notes.util.ICallback;
import it.niedermann.owncloud.notes.util.MarkDownUtil;
import rx.Subscriber;
@ -32,12 +39,43 @@ public class NoteEditFragment extends BaseNoteFragment {
private static final long DELAY = 2000; // Wait for this time after typing before saving
private static final long DELAY_AFTER_SYNC = 5000; // Wait for this time after saving before checking for next save
private Handler handler;
private boolean saveActive, unsavedEdit;
@BindView(R.id.editContent)
RxMDEditText editContent;
private Handler handler;
private boolean saveActive, unsavedEdit;
private final Runnable runAutoSave = new Runnable() {
@Override
public void run() {
if (unsavedEdit) {
Log.d(LOG_TAG_AUTOSAVE, "runAutoSave: start AutoSave");
autoSave();
} else {
Log.d(LOG_TAG_AUTOSAVE, "runAutoSave: nothing changed");
}
}
};
private final TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(final Editable s) {
unsavedEdit = true;
if (!saveActive) {
handler.removeCallbacks(runAutoSave);
handler.postDelayed(runAutoSave, DELAY);
}
}
};
private android.support.v7.widget.SearchView searchView;
private String searchQuery = null;
private MenuItem searchMenuItem;
public static NoteEditFragment newInstance(long noteId) {
NoteEditFragment f = new NoteEditFragment();
@ -66,6 +104,51 @@ public class NoteEditFragment extends BaseNoteFragment {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.menu_edit).setVisible(false);
menu.findItem(R.id.menu_preview).setVisible(true);
searchMenuItem = menu.findItem(R.id.search);
searchMenuItem.setVisible(true);
searchView = (android.support.v7.widget.SearchView) searchMenuItem.getActionView();
final LinearLayout searchEditFrame = searchView.findViewById(android.support.v7.appcompat.R.id
.search_edit_frame);
searchEditFrame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
int oldVisibility = -1;
@Override
public void onGlobalLayout() {
int currentVisibility = searchEditFrame.getVisibility();
if (currentVisibility != oldVisibility) {
if (currentVisibility != View.VISIBLE) {
colorWithText("");
}
oldVisibility = currentVisibility;
}
}
});
searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
colorWithText(newText);
return true;
}
});
}
private void colorWithText(String newText) {
if (ViewCompat.isAttachedToWindow(editContent)) {
editContent.setText(DisplayUtils.searchAndColor(editContent.getText().toString(), new SpannableString
(editContent.getText()), newText, getResources().getColor(R.color.primary)),
TextView.BufferType.SPANNABLE);
}
}
@Nullable
@ -80,6 +163,16 @@ public class NoteEditFragment extends BaseNoteFragment {
ButterKnife.bind(this, getView());
if (savedInstanceState != null) {
searchQuery = savedInstanceState.getString("searchQuery", "");
if (!TextUtils.isEmpty(searchQuery)) {
searchMenuItem.expandActionView();
searchView.setQuery(searchQuery, true);
searchView.clearFocus();
}
}
if (note.getContent().isEmpty()) {
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
@ -110,25 +203,6 @@ public class NoteEditFragment extends BaseNoteFragment {
});
}
private final TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(final Editable s) {
unsavedEdit = true;
if (!saveActive) {
handler.removeCallbacks(runAutoSave);
handler.postDelayed(runAutoSave, DELAY);
}
}
};
@Override
public void onResume() {
super.onResume();
@ -142,18 +216,6 @@ public class NoteEditFragment extends BaseNoteFragment {
cancelTimers();
}
private final Runnable runAutoSave = new Runnable() {
@Override
public void run() {
if (unsavedEdit) {
Log.d(LOG_TAG_AUTOSAVE, "runAutoSave: start AutoSave");
autoSave();
} else {
Log.d(LOG_TAG_AUTOSAVE, "runAutoSave: nothing changed");
}
}
};
private void cancelTimers() {
handler.removeCallbacks(runAutoSave);
}
@ -202,4 +264,13 @@ public class NoteEditFragment extends BaseNoteFragment {
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (searchView != null && TextUtils.isEmpty(searchView.getQuery().toString())) {
outState.putString("searchQuery", searchView.getQuery().toString());
}
}
}

View file

@ -0,0 +1,61 @@
/*
* Nextcloud Notes application
*
* @author Mario Danic
* Copyright (C) 2018 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.niedermann.owncloud.notes.util;
import android.graphics.Typeface;
import android.support.annotation.ColorInt;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DisplayUtils {
public static Spannable searchAndColor(String text, Spannable spannable, String searchText, @ColorInt int color) {
Object spansToRemove[] = spannable.getSpans(0, text.length(), Object.class);
for(Object span: spansToRemove){
if(span instanceof CharacterStyle)
spannable.removeSpan(span);
}
if (TextUtils.isEmpty(text) || TextUtils.isEmpty(searchText)) {
return spannable;
}
Matcher m = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
.matcher(text);
while (m.find()) {
int start = text.indexOf(m.group());
int end = text.indexOf(m.group()) + m.group().length();
spannable.setSpan(new ForegroundColorSpan(color), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannable;
}
}

View file

@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:title="@string/action_search"
android:icon="@drawable/ic_search_white_24dp"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|always" />
<item
android:id="@+id/menu_favorite"
android:orderInCategory="80"