mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-10-25 22:26:00 +03:00
Some work on search
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
00bbe3eca2
commit
5370d8669a
4 changed files with 176 additions and 35 deletions
|
@ -115,6 +115,7 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
|
|||
} else {
|
||||
fragment = NotePreviewFragment.newInstance(noteId);
|
||||
}
|
||||
|
||||
if (savedState != null) {
|
||||
fragment.setInitialSavedState(savedState);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue