mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-10-25 14:15:48 +03:00
#378 Enhance category handling
This commit is contained in:
parent
97c622d255
commit
d12eab5b51
8 changed files with 190 additions and 135 deletions
|
@ -11,7 +11,7 @@ import android.view.WindowManager;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.appcompat.app.AppCompatDialogFragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -24,7 +24,7 @@ import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.Accou
|
|||
import it.niedermann.owncloud.notes.model.LocalAccount;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
|
||||
|
||||
public class AccountChooserDialogFragment extends DialogFragment implements AccountChooserListener {
|
||||
public class AccountChooserDialogFragment extends AppCompatDialogFragment implements AccountChooserListener {
|
||||
private AccountChooserListener accountChooserListener;
|
||||
@BindView(R.id.accounts_list)
|
||||
RecyclerView accountRecyclerView;
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package it.niedermann.owncloud.notes.android.fragment;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.android.fragment.CategoryDialogFragment.CategoryDialogListener;
|
||||
import it.niedermann.owncloud.notes.model.NavigationAdapter;
|
||||
import it.niedermann.owncloud.notes.util.NoteUtil;
|
||||
|
||||
public class CategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
@NonNull
|
||||
private List<NavigationAdapter.NavigationItem> categories = new ArrayList<>();
|
||||
@NonNull
|
||||
private CategoryDialogListener categoryListener;
|
||||
|
||||
CategoryAdapter(@NonNull CategoryDialogListener categoryListener) {
|
||||
this.categoryListener = categoryListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_category, parent, false);
|
||||
return new CategoryViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
NavigationAdapter.NavigationItem category = categories.get(position);
|
||||
CategoryViewHolder categoryViewHolder = (CategoryViewHolder) holder;
|
||||
categoryViewHolder.category.setOnClickListener((v) -> categoryListener.onCategoryChosen(NoteUtil.extendCategory(category.label)));
|
||||
categoryViewHolder.category.setText(category.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return categories.size();
|
||||
}
|
||||
|
||||
static class CategoryViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.category)
|
||||
TextView category;
|
||||
|
||||
private CategoryViewHolder(View view) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
}
|
||||
|
||||
void setCategoryList(List<NavigationAdapter.NavigationItem> categories) {
|
||||
this.categories = categories;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
|
@ -6,22 +6,24 @@ import android.app.DialogFragment;
|
|||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.model.CategoryAdapter;
|
||||
import it.niedermann.owncloud.notes.model.NavigationAdapter;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
|
||||
|
||||
|
@ -30,9 +32,12 @@ import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
|
|||
* It targetFragment is set it must implement the interface {@link CategoryDialogListener}.
|
||||
* The calling Activity must implement the interface {@link CategoryDialogListener}.
|
||||
*/
|
||||
public class CategoryDialogFragment extends DialogFragment {
|
||||
public class CategoryDialogFragment extends AppCompatDialogFragment {
|
||||
|
||||
private static final String TAG = CategoryDialogFragment.class.getSimpleName();
|
||||
private static final String STATE_CATEGORY = "category";
|
||||
|
||||
private CategoryDialogListener listener;
|
||||
|
||||
/**
|
||||
* Interface that must be implemented by the calling Activity.
|
||||
|
@ -53,6 +58,7 @@ public class CategoryDialogFragment extends DialogFragment {
|
|||
|
||||
@BindView(R.id.search)
|
||||
EditText editCategory;
|
||||
|
||||
@BindView(R.id.recycler_view)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
|
@ -66,6 +72,14 @@ public class CategoryDialogFragment extends DialogFragment {
|
|||
} else {
|
||||
throw new IllegalArgumentException("Provide at least \"" + PARAM_ACCOUNT_ID + "\"");
|
||||
}
|
||||
Fragment target = getTargetFragment();
|
||||
if (target instanceof CategoryDialogListener) {
|
||||
listener = (CategoryDialogListener) target;
|
||||
} else if (getActivity() instanceof CategoryDialogListener) {
|
||||
listener = (CategoryDialogListener) getActivity();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Calling activity or target fragment must implement " + CategoryDialogListener.class.getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -73,36 +87,54 @@ public class CategoryDialogFragment extends DialogFragment {
|
|||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
View dialogView = Objects.requireNonNull(getActivity()).getLayoutInflater().inflate(R.layout.dialog_change_category, null);
|
||||
ButterKnife.bind(this, dialogView);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
if (getArguments() != null && getArguments().containsKey(PARAM_CATEGORY)) {
|
||||
editCategory.setText(getArguments().getString(PARAM_CATEGORY));
|
||||
}
|
||||
} else if (savedInstanceState.containsKey(STATE_CATEGORY)) {
|
||||
editCategory.setText(savedInstanceState.getString(STATE_CATEGORY));
|
||||
}
|
||||
adapter = new CategoryAdapter();
|
||||
|
||||
adapter = new CategoryAdapter((String category) -> {
|
||||
listener.onCategoryChosen(category);
|
||||
dismiss();
|
||||
});
|
||||
|
||||
recyclerView.setAdapter(adapter);
|
||||
new LoadCategoriesTask().execute();
|
||||
new LoadCategoriesTask().execute("");
|
||||
editCategory.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// Nothing to do here...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
new LoadCategoriesTask().execute(editCategory.getText().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
// Nothing to do here....
|
||||
}
|
||||
});
|
||||
|
||||
return new AlertDialog.Builder(getActivity(), R.style.ncAlertDialog)
|
||||
.setTitle(R.string.change_category_title)
|
||||
.setView(dialogView)
|
||||
.setCancelable(true)
|
||||
|
||||
// @Override
|
||||
// public void onClick(DialogInterface dialog, int which) {
|
||||
// CategoryDialogListener listener;
|
||||
// Fragment target = getTargetFragment();
|
||||
// if (target instanceof CategoryDialogListener) {
|
||||
// listener = (CategoryDialogListener) target;
|
||||
// } else {
|
||||
// listener = (CategoryDialogListener) getActivity();
|
||||
// }
|
||||
//// listener.onCategoryChosen(textCategory.getText().toString());
|
||||
// }
|
||||
.setNegativeButton(R.string.simple_cancel, (dialog, which) -> {
|
||||
// do nothing
|
||||
})
|
||||
.setPositiveButton(R.string.action_edit_save, (dialog, which) -> listener.onCategoryChosen(editCategory.getText().toString()))
|
||||
.setNegativeButton(R.string.simple_cancel, null)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(STATE_CATEGORY, editCategory.getText().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
@ -114,29 +146,18 @@ public class CategoryDialogFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
|
||||
private class LoadCategoriesTask extends AsyncTask<Void, Void, List<String>> {
|
||||
private class LoadCategoriesTask extends AsyncTask<String, Void, List<NavigationAdapter.NavigationItem>> {
|
||||
@Override
|
||||
protected List<String> doInBackground(Void... voids) {
|
||||
protected List<NavigationAdapter.NavigationItem> doInBackground(String... searchText) {
|
||||
NoteSQLiteOpenHelper db = NoteSQLiteOpenHelper.getInstance(getActivity());
|
||||
List<NavigationAdapter.NavigationItem> items = db.getCategories(accountId);
|
||||
List<String> categories = new ArrayList<>();
|
||||
for (NavigationAdapter.NavigationItem item : items) {
|
||||
if (!item.label.isEmpty()) {
|
||||
categories.add(item.label);
|
||||
}
|
||||
}
|
||||
return categories;
|
||||
return (searchText[0] == null || searchText[0].length() == 0)
|
||||
? db.getCategories(accountId)
|
||||
: db.searchCategories(accountId, searchText[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> categories) {
|
||||
protected void onPostExecute(List<NavigationAdapter.NavigationItem> categories) {
|
||||
adapter.setCategoryList(categories);
|
||||
//TODO show creation entry
|
||||
// if (textCategory.getText().length() == 0) {
|
||||
// textCategory.showFullDropDown();
|
||||
// } else {
|
||||
// textCategory.dismissDropDown();
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
package it.niedermann.owncloud.notes.model;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
|
||||
public class CategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private List<String> categoryList;
|
||||
|
||||
public CategoryAdapter() {
|
||||
this.categoryList = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the item list and notifies respective view to update.
|
||||
*
|
||||
* @param categoryList List of items to be set
|
||||
*/
|
||||
public void setCategoryList(@NonNull List<String> categoryList) {
|
||||
this.categoryList = categoryList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given note to the top of the list.
|
||||
*
|
||||
* @param category Category that should be added.
|
||||
*/
|
||||
public void add(@NonNull String category) {
|
||||
categoryList.add(0, category);
|
||||
notifyItemInserted(0);
|
||||
notifyItemChanged(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new CategoryViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.dialog_change_category_single, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
|
||||
((CategoryViewHolder) holder).title.setText(categoryList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return categoryList.size();
|
||||
}
|
||||
|
||||
static class CategoryViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.title)
|
||||
TextView title;
|
||||
|
||||
CategoryViewHolder(View view) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -626,6 +626,38 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||
return categories;
|
||||
}
|
||||
|
||||
// TODO merge with getCategories(long accountId)
|
||||
@NonNull
|
||||
@WorkerThread
|
||||
public List<NavigationAdapter.NavigationItem> searchCategories(long accountId, String search) {
|
||||
validateAccountId(accountId);
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor cursor = db.query(
|
||||
table_notes,
|
||||
new String[]{key_category, "COUNT(*)"},
|
||||
key_status + " != ? AND " + key_account_id + " = ? AND " + key_category + " LIKE ?",
|
||||
new String[]{DBStatus.LOCAL_DELETED.getTitle(), "" + accountId, "%" + search + "%"},
|
||||
key_category,
|
||||
null,
|
||||
key_category);
|
||||
List<NavigationAdapter.NavigationItem> categories = new ArrayList<>(cursor.getCount());
|
||||
while (cursor.moveToNext()) {
|
||||
Resources res = context.getResources();
|
||||
String category = cursor.getString(0).toLowerCase();
|
||||
int icon = NavigationAdapter.ICON_FOLDER;
|
||||
if (category.equals(res.getString(R.string.category_music).toLowerCase())) {
|
||||
icon = R.drawable.ic_library_music_grey600_24dp;
|
||||
} else if (category.equals(res.getString(R.string.category_movies).toLowerCase()) || category.equals(res.getString(R.string.category_movie).toLowerCase())) {
|
||||
icon = R.drawable.ic_local_movies_grey600_24dp;
|
||||
} else if (category.equals(res.getString(R.string.category_work).toLowerCase())) {
|
||||
icon = R.drawable.ic_work_grey600_24dp;
|
||||
}
|
||||
categories.add(new NavigationAdapter.NavigationItem("category:" + cursor.getString(0), cursor.getString(0), cursor.getInt(1), icon));
|
||||
}
|
||||
cursor.close();
|
||||
return categories;
|
||||
}
|
||||
|
||||
public void toggleFavorite(@NonNull DBNote note, @Nullable ICallback callback) {
|
||||
note.setFavorite(!note.isFavorite());
|
||||
note.setStatus(DBStatus.LOCAL_EDITED);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/editCategoryLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -9,10 +11,15 @@
|
|||
<EditText
|
||||
android:id="@+id/search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAutofill="no" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:scrollbars="vertical" />
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:scrollbars="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_category" />
|
||||
</LinearLayout>
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:padding="36dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Category" />
|
||||
</LinearLayout>
|
11
app/src/main/res/layout/item_category.xml
Normal file
11
app/src/main/res/layout/item_category.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/category"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:ellipsize="middle"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/NavigationItem"
|
||||
android:textColor="@color/fg_default"
|
||||
tools:hint="Username" />
|
Loading…
Reference in a new issue