From 8384792d2793bc2e65d44f3711f7493178a3322e Mon Sep 17 00:00:00 2001 From: korelstar Date: Sun, 6 Nov 2016 20:39:34 +0100 Subject: [PATCH] New Feature: set note as favorite; refactoring NotesListViewActivity.refreshList (#151) Fix #118 Every touch brings to the top Fix #92 Option to change sort method --- .../owncloud/notes/model/NoteTest.java | 2 +- .../android/activity/EditNoteActivity.java | 12 + .../activity/NotesListViewActivity.java | 216 ++++++++++-------- .../activity/SelectSingleNoteActivity.java | 8 +- .../notes/android/widget/AllNotesWidget.java | 4 +- .../owncloud/notes/model/DBNote.java | 6 +- .../owncloud/notes/model/ItemAdapter.java | 79 +++---- .../owncloud/notes/model/OwnCloudNote.java | 14 +- .../persistence/NoteSQLiteOpenHelper.java | 59 +++-- .../persistence/NoteServerSyncHelper.java | 8 +- .../owncloud/notes/util/NotesClient.java | 11 +- .../drawable-hdpi/ic_star_grey600_24dp.png | Bin 0 -> 840 bytes .../ic_star_outline_grey600_24dp.png | Bin 0 -> 1178 bytes .../ic_star_outline_white_24dp.png | Bin 0 -> 732 bytes .../res/drawable-hdpi/ic_star_white_24dp.png | Bin 0 -> 547 bytes .../ic_sync_alert_grey600_18dp.png | Bin 0 -> 829 bytes .../drawable-mdpi/ic_star_grey600_24dp.png | Bin 0 -> 576 bytes .../ic_star_outline_grey600_24dp.png | Bin 0 -> 730 bytes .../ic_star_outline_white_24dp.png | Bin 0 -> 495 bytes .../res/drawable-mdpi/ic_star_white_24dp.png | Bin 0 -> 397 bytes .../ic_sync_alert_grey600_18dp.png | Bin 0 -> 522 bytes .../drawable-xhdpi/ic_star_grey600_24dp.png | Bin 0 -> 1111 bytes .../ic_star_outline_grey600_24dp.png | Bin 0 -> 1589 bytes .../ic_star_outline_white_24dp.png | Bin 0 -> 953 bytes .../res/drawable-xhdpi/ic_star_white_24dp.png | Bin 0 -> 712 bytes .../ic_sync_alert_grey600_18dp.png | Bin 0 -> 933 bytes .../drawable-xxhdpi/ic_star_grey600_24dp.png | Bin 0 -> 1638 bytes .../ic_star_outline_grey600_24dp.png | Bin 0 -> 2292 bytes .../ic_star_outline_white_24dp.png | Bin 0 -> 1412 bytes .../drawable-xxhdpi/ic_star_white_24dp.png | Bin 0 -> 1139 bytes .../ic_sync_alert_grey600_18dp.png | Bin 0 -> 1328 bytes .../drawable-xxxhdpi/ic_star_grey600_24dp.png | Bin 0 -> 2191 bytes .../ic_star_outline_grey600_24dp.png | Bin 0 -> 3090 bytes .../ic_star_outline_white_24dp.png | Bin 0 -> 1970 bytes .../drawable-xxxhdpi/ic_star_white_24dp.png | Bin 0 -> 1584 bytes .../ic_sync_alert_grey600_18dp.png | Bin 0 -> 1525 bytes .../layout/fragment_notes_list_note_item.xml | 104 +++++---- .../fragment_notes_list_section_item.xml | 3 +- app/src/main/res/menu/menu_note_list_view.xml | 6 + app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 41 files changed, 308 insertions(+), 226 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_star_outline_grey600_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_star_outline_white_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_star_white_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_sync_alert_grey600_18dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_star_outline_grey600_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_star_outline_white_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_star_white_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_sync_alert_grey600_18dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_star_outline_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_star_outline_white_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_star_white_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_sync_alert_grey600_18dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_star_outline_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_star_outline_white_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_star_white_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_sync_alert_grey600_18dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_star_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_star_outline_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_star_outline_white_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_star_white_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_sync_alert_grey600_18dp.png diff --git a/app/src/androidTest/java/it/niedermann/owncloud/notes/model/NoteTest.java b/app/src/androidTest/java/it/niedermann/owncloud/notes/model/NoteTest.java index c98281312..03aa63806 100644 --- a/app/src/androidTest/java/it/niedermann/owncloud/notes/model/NoteTest.java +++ b/app/src/androidTest/java/it/niedermann/owncloud/notes/model/NoteTest.java @@ -11,7 +11,7 @@ public class NoteTest extends TestCase { public void testMarkDownStrip() { - OwnCloudNote note = new OwnCloudNote(0, Calendar.getInstance(), "#Title", ""); + OwnCloudNote note = new OwnCloudNote(0, Calendar.getInstance(), "#Title", "", false); assertTrue("Title".equals(note.getTitle())); note.setTitle("* Aufzählung"); assertTrue("Aufzählung".equals(note.getTitle())); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java index 91a604f94..e42f61d89 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java @@ -124,6 +124,14 @@ public boolean onCreateOptionsMenu(Menu menu) { return true; } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + MenuItem itemFavorite = menu.findItem(R.id.menu_favorite); + itemFavorite.setIcon(note.isFavorite() ? R.drawable.ic_star_white_24dp : R.drawable.ic_star_outline_white_24dp); + itemFavorite.setChecked(note.isFavorite()); + return super.onPrepareOptionsMenu(menu); + } + /** * Main-Menu-Handler */ @@ -146,6 +154,10 @@ public boolean onOptionsItemSelected(MenuItem item) { setResult(RESULT_FIRST_USER, data); finish(); return true; + case R.id.menu_favorite: + db.toggleFavorite(note, null); + invalidateOptionsMenu(); + return true; case R.id.menu_preview: saveData(null); Intent previewIntent = new Intent(getApplicationContext(), NoteActivity.class); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index 7b1c1e702..7a60c5337 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -5,6 +5,7 @@ import android.app.SearchManager; import android.content.Intent; import android.content.SharedPreferences; +import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.view.MenuItemCompat; @@ -61,8 +62,7 @@ public void onFinish() { if (mActionMode != null) { mActionMode.finish(); } - // adapter.checkForUpdates(db.getNotes()); // FIXME deactivated, since it doesn't remove remotely deleted notes - setListView(db.getNotes()); + refreshList(); swipeRefreshLayout.setRefreshing(false); } }; @@ -82,7 +82,8 @@ protected void onCreate(Bundle savedInstanceState) { // Display Data db = new NoteSQLiteOpenHelper(this); - setListView(db.getNotes()); + initList(); + refreshList(); // Pull to Refresh swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swiperefreshlayout); @@ -144,6 +145,8 @@ protected void onResume() { checkNotificationSetting(); if (db.getNoteServerSyncHelper().isSyncPossible()) { synchronize(); + } else { + refreshList(); } super.onResume(); } @@ -162,79 +165,110 @@ public void onClick(View v) { } /** - * Allows other classes to set a List of Notes. - * - * @param noteList List<Note> + * Allows other classes to refresh the List of Notes. Starts an AsyncTask which loads the data in the background. */ - @SuppressWarnings("WeakerAccess") - public void setListView(List noteList) { - final List itemList = new ArrayList<>(); - // #12 Create Sections depending on Time - // TODO Move to ItemAdapter? - boolean todaySet, yesterdaySet, weekSet, monthSet, earlierSet; - todaySet = yesterdaySet = weekSet = monthSet = earlierSet = false; - Calendar recent = Calendar.getInstance(); - Calendar today = Calendar.getInstance(); - today.set(Calendar.HOUR_OF_DAY, 0); - today.set(Calendar.MINUTE, 0); - today.set(Calendar.SECOND, 0); - today.set(Calendar.MILLISECOND, 0); - Calendar yesterday = Calendar.getInstance(); - yesterday.set(Calendar.DAY_OF_YEAR, yesterday.get(Calendar.DAY_OF_YEAR) - 1); - yesterday.set(Calendar.HOUR_OF_DAY, 0); - yesterday.set(Calendar.MINUTE, 0); - yesterday.set(Calendar.SECOND, 0); - yesterday.set(Calendar.MILLISECOND, 0); - Calendar week = Calendar.getInstance(); - week.set(Calendar.DAY_OF_WEEK, week.getFirstDayOfWeek()); - week.set(Calendar.HOUR_OF_DAY, 0); - week.set(Calendar.MINUTE, 0); - week.set(Calendar.SECOND, 0); - week.set(Calendar.MILLISECOND, 0); - Calendar month = Calendar.getInstance(); - month.set(Calendar.DAY_OF_MONTH, 0); - month.set(Calendar.HOUR_OF_DAY, 0); - month.set(Calendar.MINUTE, 0); - month.set(Calendar.SECOND, 0); - month.set(Calendar.MILLISECOND, 0); - for (int i = 0; i < noteList.size(); i++) { - DBNote currentNote = noteList.get(i); - if (!todaySet && recent.getTimeInMillis() - currentNote.getModified().getTimeInMillis() >= 600000 && currentNote.getModified().getTimeInMillis() >= today.getTimeInMillis()) { - // < 10 minutes but after 00:00 today - //if (i > 0) { - //itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_today))); - //} - todaySet = true; - } else if (!yesterdaySet && currentNote.getModified().getTimeInMillis() < today.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= yesterday.getTimeInMillis()) { - // between today 00:00 and yesterday 00:00 - if (i > 0) { - itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_yesterday))); - } - yesterdaySet = true; - } else if (!weekSet && currentNote.getModified().getTimeInMillis() < yesterday.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= week.getTimeInMillis()) { - // between yesterday 00:00 and start of the week 00:00 - if (i > 0) { - itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_this_week))); - } - weekSet = true; - } else if (!monthSet && currentNote.getModified().getTimeInMillis() < week.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= month.getTimeInMillis()) { - // between start of the week 00:00 and start of the month 00:00 - if (i > 0) { - itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_this_month))); - } - monthSet = true; - } else if (!earlierSet && currentNote.getModified().getTimeInMillis() < month.getTimeInMillis()) { - // before start of the month 00:00 - if (i > 0) { - itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_earlier))); + public void refreshList() { + new RefreshListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private class RefreshListTask extends AsyncTask> { + + private CharSequence query = null; + + @Override + protected void onPreExecute() { + if(searchView != null && !searchView.isIconified() && searchView.getQuery().length() != 0) { + query = searchView.getQuery(); + } + } + + @Override + protected List doInBackground(Void... voids) { + List noteList; + if (query==null) { + noteList = db.getNotes(); + } else { + noteList = db.searchNotes(query); + } + + final List itemList = new ArrayList<>(); + // #12 Create Sections depending on Time + // TODO Move to ItemAdapter? + boolean todaySet, yesterdaySet, weekSet, monthSet, earlierSet; + todaySet = yesterdaySet = weekSet = monthSet = earlierSet = false; + Calendar recent = Calendar.getInstance(); + Calendar today = Calendar.getInstance(); + today.set(Calendar.HOUR_OF_DAY, 0); + today.set(Calendar.MINUTE, 0); + today.set(Calendar.SECOND, 0); + today.set(Calendar.MILLISECOND, 0); + Calendar yesterday = Calendar.getInstance(); + yesterday.set(Calendar.DAY_OF_YEAR, yesterday.get(Calendar.DAY_OF_YEAR) - 1); + yesterday.set(Calendar.HOUR_OF_DAY, 0); + yesterday.set(Calendar.MINUTE, 0); + yesterday.set(Calendar.SECOND, 0); + yesterday.set(Calendar.MILLISECOND, 0); + Calendar week = Calendar.getInstance(); + week.set(Calendar.DAY_OF_WEEK, week.getFirstDayOfWeek()); + week.set(Calendar.HOUR_OF_DAY, 0); + week.set(Calendar.MINUTE, 0); + week.set(Calendar.SECOND, 0); + week.set(Calendar.MILLISECOND, 0); + Calendar month = Calendar.getInstance(); + month.set(Calendar.DAY_OF_MONTH, 0); + month.set(Calendar.HOUR_OF_DAY, 0); + month.set(Calendar.MINUTE, 0); + month.set(Calendar.SECOND, 0); + month.set(Calendar.MILLISECOND, 0); + for (int i = 0; i < noteList.size(); i++) { + DBNote currentNote = noteList.get(i); + if (currentNote.isFavorite()) { + // don't show as new section + } else if (!todaySet && currentNote.getModified().getTimeInMillis() >= today.getTimeInMillis()) { + // after 00:00 today + if (i > 0) { + itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_today))); + } + todaySet = true; + } else if (!yesterdaySet && currentNote.getModified().getTimeInMillis() < today.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= yesterday.getTimeInMillis()) { + // between today 00:00 and yesterday 00:00 + if (i > 0) { + itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_yesterday))); + } + yesterdaySet = true; + } else if (!weekSet && currentNote.getModified().getTimeInMillis() < yesterday.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= week.getTimeInMillis()) { + // between yesterday 00:00 and start of the week 00:00 + if (i > 0) { + itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_this_week))); + } + weekSet = true; + } else if (!monthSet && currentNote.getModified().getTimeInMillis() < week.getTimeInMillis() && currentNote.getModified().getTimeInMillis() >= month.getTimeInMillis()) { + // between start of the week 00:00 and start of the month 00:00 + if (i > 0) { + itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_this_month))); + } + monthSet = true; + } else if (!earlierSet && currentNote.getModified().getTimeInMillis() < month.getTimeInMillis()) { + // before start of the month 00:00 + if (i > 0) { + itemList.add(new SectionItem(getResources().getString(R.string.listview_updated_earlier))); + } + earlierSet = true; } - earlierSet = true; + itemList.add(currentNote); } - itemList.add(currentNote); + + return itemList; } - adapter = new ItemAdapter(itemList); - ItemAdapter.setNoteClickListener(this); + @Override + protected void onPostExecute(List items) { + adapter.setItemList(items); + } + } + + public void initList() { + adapter = new ItemAdapter(this); listView = (RecyclerView) findViewById(R.id.recycler_view); listView.setAdapter(adapter); listView.setLayoutManager(new LinearLayoutManager(this)); @@ -296,31 +330,17 @@ public boolean onQueryTextSubmit(String query) { @Override public boolean onQueryTextChange(String newText) { - search(newText.trim()); + refreshList(); return true; } }); return true; } - private void search(final String query) { - new Thread() { - @Override - public void run() { - if (query.length() > 0) { - setListView(db.searchNotes(query)); - } else { - setListView(db.getNotes()); - } - listView.scrollToPosition(0); - } - }.run(); - } - @Override protected void onNewIntent(Intent intent) { if (Intent.ACTION_SEARCH.equals(intent.getAction())) { - search(intent.getStringExtra(SearchManager.QUERY)); + searchView.setQuery(intent.getStringExtra(SearchManager.QUERY), true); } super.onNewIntent(intent); } @@ -377,12 +397,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } if (resultCode == RESULT_OK) { DBNote editedNote = (DBNote) data.getExtras().getSerializable(EditNoteActivity.PARAM_NOTE); - if(oldItem instanceof DBNote && !editedNote.getModified().after(((DBNote)oldItem).getModified())) { - adapter.replace(editedNote, notePosition); - } else { - adapter.remove(oldItem); - adapter.add(editedNote); - } + adapter.replace(editedNote, notePosition); + refreshList(); } } } else if (requestCode == server_settings) { @@ -435,6 +451,15 @@ public void onNoteClick(int position, View v) { } } + @Override + public void onNoteFavoriteClick(int position, View view) { + DBNote note = (DBNote) adapter.getItem(position); + NoteSQLiteOpenHelper db = new NoteSQLiteOpenHelper(view.getContext()); + db.toggleFavorite(note, syncCallBack); + adapter.notifyItemChanged(position); + refreshList(); + } + @Override public boolean onNoteLongClick(int position, View v) { boolean selected = adapter.select(position); @@ -464,8 +489,7 @@ private void synchronize() { /** * Handler for the MultiSelect Actions */ - private class MultiSelectedActionModeCallback implements - ActionMode.Callback { + private class MultiSelectedActionModeCallback implements ActionMode.Callback { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { @@ -499,7 +523,7 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) { mode.finish(); // Action picked, so close the CAB //after delete selection has to be cleared searchView.setIconified(true); - setListView(db.getNotes()); + refreshList(); return true; default: return false; diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java index 0b171f1d1..412c98078 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java @@ -64,11 +64,11 @@ public void onCreate(Bundle savedInstanceState) { private void setListView(List noteList) { List itemList = new ArrayList<>(); itemList.addAll(noteList); - adapter = new ItemAdapter(itemList); + adapter = new ItemAdapter(this); + adapter.setItemList(itemList); listView = (RecyclerView) findViewById(R.id.select_single_note_list_view); listView.setAdapter(adapter); listView.setLayoutManager(new LinearLayoutManager(this)); - ItemAdapter.setNoteClickListener(this); } @Override @@ -87,6 +87,10 @@ public void onNoteClick(int position, View v) { finish(); } + @Override + public void onNoteFavoriteClick(int position, View v) { + } + @Override public boolean onNoteLongClick(int position, View v) { return false; diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/widget/AllNotesWidget.java b/app/src/main/java/it/niedermann/owncloud/notes/android/widget/AllNotesWidget.java index fe4d06a8f..4aa320b19 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/widget/AllNotesWidget.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/widget/AllNotesWidget.java @@ -63,11 +63,11 @@ public StackRemoteViewsFactory(Context context, Intent intent) { NoteSQLiteOpenHelper db = new NoteSQLiteOpenHelper(mContext); db.getNoteServerSyncHelper().scheduleSync(false); mWidgetItems = db.getNotes(); - mWidgetItems.add(new DBNote(0, 0, Calendar.getInstance(), "Test-Titel", "Test-Beschreibung", DBStatus.VOID)); + mWidgetItems.add(new DBNote(0, 0, Calendar.getInstance(), "Test-Titel", "Test-Beschreibung", false, DBStatus.VOID)); } public void onCreate() { - mWidgetItems.add(new DBNote(0, 0, Calendar.getInstance(), "Test-Titel", "Test-Beschreibung", DBStatus.VOID)); + mWidgetItems.add(new DBNote(0, 0, Calendar.getInstance(), "Test-Titel", "Test-Beschreibung", false, DBStatus.VOID)); } @Override diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/DBNote.java b/app/src/main/java/it/niedermann/owncloud/notes/model/DBNote.java index f25105b86..7ced944fb 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/DBNote.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/DBNote.java @@ -16,8 +16,8 @@ public class DBNote extends OwnCloudNote implements Item, Serializable { private DBStatus status; private String excerpt = ""; - public DBNote(long id, long remoteId, Calendar modified, String title, String content, DBStatus status) { - super(remoteId, modified, title, content); + public DBNote(long id, long remoteId, Calendar modified, String title, String content, boolean favorite, DBStatus status) { + super(remoteId, modified, title, content, favorite); this.id = id; setExcerpt(content); this.status = status; @@ -60,6 +60,6 @@ public boolean isSection() { @Override public String toString() { - return "#" + getId() + "/R"+getRemoteId()+" " + getTitle() + " (" + getModified(NoteSQLiteOpenHelper.DATE_FORMAT) + ") " + getStatus(); + return "#" + getId() + "/R"+getRemoteId()+" " + (isFavorite() ? " (*) " : " ") + getTitle() + " (" + getModified(NoteSQLiteOpenHelper.DATE_FORMAT) + ") " + getStatus(); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java index 01d7ad2ef..3242d7a32 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java @@ -16,22 +16,23 @@ public class ItemAdapter extends RecyclerView.Adapter { private static final int section_type = 0; private static final int note_type = 1; - private static NoteClickListener noteClickListener; + private final NoteClickListener noteClickListener; private List itemList = null; private List selected = null; - public ItemAdapter(List itemList) { - //super(context, android.R.layout.simple_list_item_1, itemList); - super(); - this.itemList = itemList; + + public ItemAdapter(NoteClickListener noteClickListener) { + this.itemList = new ArrayList<>(); this.selected = new ArrayList<>(); + this.noteClickListener = noteClickListener; } /** - * Sets the given NoteClickListener that should be notified on clicks - * @param noteClickListener NoteClickListener + * Updates the item list and notifies respective view to update. + * @param itemList */ - public static void setNoteClickListener(NoteClickListener noteClickListener) { - ItemAdapter.noteClickListener = noteClickListener; + public void setItemList(List itemList) { + this.itemList = itemList; + notifyDataSetChanged(); } /** @@ -62,42 +63,9 @@ public void removeAll() { notifyDataSetChanged(); } - /** - * Compares the given List of notes to the current internal holded notes and updates the list if necessairy - * @param newNotes List of more up to date notes - */ - public void checkForUpdates(List newNotes) { - for(DBNote newNote : newNotes) { - boolean foundNewNoteInOldList = false; - for(Item oldItem : itemList) { - if(!oldItem.isSection()) { - DBNote oldNote = (DBNote) oldItem; - if(newNote.getId() == oldNote.getId()) { - // Notes have the same id, check which is newer - if(newNote.getModified().after(oldNote.getModified())) { - // Replace old note with new note because new note has been edited more recently - int indexOfOldNote = itemList.indexOf(oldNote); - itemList.remove(indexOfOldNote); - itemList.add(indexOfOldNote, newNote); - this.notifyItemChanged(indexOfOldNote); - } - foundNewNoteInOldList = true; - break; - } - } - } - if(!foundNewNoteInOldList) { - // Add new note because it could not be found in the itemList - add(newNote); - } - } - //TODO check if a note has been deleted on server?? - } - // Create new views (invoked by the layout manager) @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, - int viewType) { + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; if (viewType == section_type) { v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_notes_list_section_item, parent, false); @@ -111,7 +79,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, // Replace the contents of a view (invoked by the layout manager) @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { // - get element from your dataset at this position // - replace the contents of the view with that element Item item = itemList.get(position); @@ -120,11 +88,19 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ((SectionViewHolder) holder).sectionTitle.setText(section.geTitle()); ((SectionViewHolder) holder).setPosition(position); } else { - DBNote note = (DBNote) item; - ((NoteViewHolder) holder).noteTitle.setText(note.getTitle()); - ((NoteViewHolder) holder).noteExcerpt.setText(note.getExcerpt()); - ((NoteViewHolder) holder).noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.GONE : View.VISIBLE); - ((NoteViewHolder) holder).setPosition(position); + final DBNote note = (DBNote) item; + final NoteViewHolder nvHolder = ((NoteViewHolder) holder); + nvHolder.noteTitle.setText(note.getTitle()); + nvHolder.noteExcerpt.setText(note.getExcerpt()); + nvHolder.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.GONE : View.VISIBLE); + nvHolder.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_grey600_24dp : R.drawable.ic_star_outline_grey600_24dp); + nvHolder.noteFavorite.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + noteClickListener.onNoteFavoriteClick(position, view); + } + }); + nvHolder.setPosition(position); } } @@ -173,14 +149,16 @@ public int getItemViewType(int position) { public interface NoteClickListener { void onNoteClick(int position, View v); + void onNoteFavoriteClick(int position, View v); boolean onNoteLongClick(int position, View v); } - public static class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { + public class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { // each data item is just a string in this case public TextView noteTitle; public TextView noteExcerpt; public ImageView noteStatus; + public ImageView noteFavorite; public int position = -1; private NoteViewHolder(View v) { @@ -188,6 +166,7 @@ private NoteViewHolder(View v) { this.noteTitle = (TextView) v.findViewById(R.id.noteTitle); this.noteExcerpt = (TextView) v.findViewById(R.id.noteExcerpt); this.noteStatus = (ImageView) v.findViewById(R.id.noteStatus); + this.noteFavorite = (ImageView) v.findViewById(R.id.noteFavorite); v.setOnClickListener(this); v.setOnLongClickListener(this); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/OwnCloudNote.java b/app/src/main/java/it/niedermann/owncloud/notes/model/OwnCloudNote.java index b9a31865c..9c228d336 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/OwnCloudNote.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/OwnCloudNote.java @@ -17,13 +17,15 @@ public class OwnCloudNote implements Serializable { private String title = ""; private Calendar modified = null; private String content = ""; + private boolean favorite = false; - public OwnCloudNote(long remoteId, Calendar modified, String title, String content) { + public OwnCloudNote(long remoteId, Calendar modified, String title, String content, boolean favorite) { this.remoteId = remoteId; if (title != null) setTitle(title); setTitle(title); setContent(content); + setFavorite(favorite); this.modified = modified; } @@ -65,8 +67,16 @@ public void setContent(String content) { this.content = content; } + public boolean isFavorite() { + return favorite; + } + + public void setFavorite(boolean favorite) { + this.favorite = favorite; + } + @Override public String toString() { - return "#" + getRemoteId() + " " + getTitle() + " (" + getModified(NoteSQLiteOpenHelper.DATE_FORMAT) + ")"; + return "#" + getRemoteId() + " " + (isFavorite() ? " (*) " : " ") + getTitle() + " (" + getModified(NoteSQLiteOpenHelper.DATE_FORMAT) + ")"; } } \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java index 7286534d6..50a1ae85b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java @@ -28,7 +28,7 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper { public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; - private static final int database_version = 5; + private static final int database_version = 6; private static final String database_name = "OWNCLOUD_NOTES"; private static final String table_notes = "NOTES"; private static final String key_id = "ID"; @@ -37,7 +37,9 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper { private static final String key_title = "TITLE"; private static final String key_modified = "MODIFIED"; private static final String key_content = "CONTENT"; - private static final String[] columns = {key_id, key_remote_id, key_status, key_title, key_modified, key_content}; + private static final String key_favorite = "FAVORITE"; + private static final String[] columns = {key_id, key_remote_id, key_status, key_title, key_modified, key_content, key_favorite}; + private static final String default_order = key_favorite + " DESC, " + key_modified + " DESC"; private NoteServerSyncHelper serverSyncHelper = null; private Context context = null; @@ -65,7 +67,8 @@ public void onCreate(SQLiteDatabase db) { key_status + "' VARCHAR(50), '" + key_title + "' TEXT, '" + key_modified + "' TEXT, '" + - key_content + "' TEXT)"); + key_content + "' TEXT, '" + + key_favorite + "' INTEGER DEFAULT 0)"); // FIXME create index for status and remote_id } @@ -79,6 +82,9 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("UPDATE "+table_notes+" SET "+key_remote_id+"="+key_id+" WHERE ("+key_remote_id+" IS NULL OR "+key_remote_id+"=0) AND "+key_status+"!=?", new String[]{DBStatus.LOCAL_CREATED.getTitle()}); db.execSQL("UPDATE "+table_notes+" SET "+key_remote_id+"=0, "+key_status+"=? WHERE "+key_status+"=?", new String[]{DBStatus.LOCAL_EDITED.getTitle(), DBStatus.LOCAL_CREATED.getTitle()}); } + if(oldVersion<6) { + db.execSQL("ALTER TABLE "+table_notes+" ADD COLUMN "+key_favorite+" INTEGER DEFAULT 0"); + } } private void clearDatabase(SQLiteDatabase db) { @@ -96,7 +102,7 @@ public Context getContext() { */ @SuppressWarnings("UnusedReturnValue") public long addNoteAndSync(String content) { - DBNote note = new DBNote(0, 0, Calendar.getInstance(), NoteUtil.generateNoteTitle(content), content, DBStatus.LOCAL_EDITED); + DBNote note = new DBNote(0, 0, Calendar.getInstance(), NoteUtil.generateNoteTitle(content), content, false, DBStatus.LOCAL_EDITED); long id = addNote(note); getNoteServerSyncHelper().scheduleSync(true); return id; @@ -126,6 +132,7 @@ long addNote(OwnCloudNote note) { values.put(key_title, note.getTitle()); values.put(key_modified, note.getModified(NoteSQLiteOpenHelper.DATE_FORMAT)); values.put(key_content, note.getContent()); + values.put(key_favorite, note.isFavorite()); long id = db.insert(table_notes, null, values); db.close(); return id; @@ -192,11 +199,11 @@ private DBNote getNoteFromCursor(Cursor cursor) { } catch (ParseException e) { e.printStackTrace(); } - return new DBNote(cursor.getLong(0), cursor.getLong(1), modified, cursor.getString(3), cursor.getString(5), DBStatus.parse(cursor.getString(2))); + return new DBNote(cursor.getLong(0), cursor.getLong(1), modified, cursor.getString(3), cursor.getString(5), cursor.getInt(6)>0, DBStatus.parse(cursor.getString(2))); } public void debugPrintFullDB() { - List notes = getNotesCustom("", new String[]{}, key_modified + " DESC"); + List notes = getNotesCustom("", new String[]{}, default_order); Log.d(getClass().getSimpleName(), "Full Database:"); for (DBNote note : notes) { Log.d(getClass().getSimpleName(), " "+note); @@ -209,7 +216,7 @@ public void debugPrintFullDB() { * @return List<Note> */ public List getNotes() { - return getNotesCustom(key_status + " != ?", new String[]{DBStatus.LOCAL_DELETED.getTitle()}, key_modified + " DESC"); + return getNotesCustom(key_status + " != ?", new String[]{DBStatus.LOCAL_DELETED.getTitle()}, default_order); } /** @@ -217,8 +224,8 @@ public List getNotes() { * * @return List<Note> */ - public List searchNotes(String query) { - return getNotesCustom(key_status + " != ? AND " + key_content + " LIKE ?", new String[]{DBStatus.LOCAL_DELETED.getTitle(), "%" + query + "%"}, key_modified + " DESC"); + public List searchNotes(CharSequence query) { + return getNotesCustom(key_status + " != ? AND " + key_content + " LIKE ?", new String[]{DBStatus.LOCAL_DELETED.getTitle(), "%" + query + "%"}, default_order); } /** @@ -238,6 +245,22 @@ public List getLocalModifiedNotes() { return getNotesCustom(key_status + " != ?", new String[]{DBStatus.VOID.getTitle()}, null); } + + public void toggleFavorite(DBNote note, ICallback callback) { + note.setFavorite(!note.isFavorite()); + note.setStatus(DBStatus.LOCAL_EDITED); + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(key_status, note.getStatus().getTitle()); + values.put(key_favorite, note.isFavorite()?"1":"0"); + db.update(table_notes, values, key_id + " = ?", new String[]{String.valueOf(note.getId())}); + db.close(); + if(callback!=null) { + serverSyncHelper.addCallbackPush(callback); + } + serverSyncHelper.scheduleSync(true); + } + /** * Updates a single Note with a new content. * The title is derived from the new content automatically, and modified date as well as DBStatus are updated, too -- if the content differs to the state in the database. @@ -251,9 +274,9 @@ public DBNote updateNoteAndSync(DBNote oldNote, String newContent, ICallback cal debugPrintFullDB(); DBNote newNote; if(newContent==null) { - newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), DBStatus.LOCAL_EDITED); + newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.isFavorite(), DBStatus.LOCAL_EDITED); } else { - newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), NoteUtil.generateNoteTitle(newContent), newContent, DBStatus.LOCAL_EDITED); + newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), NoteUtil.generateNoteTitle(newContent), newContent, oldNote.isFavorite(), DBStatus.LOCAL_EDITED); } SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); @@ -304,19 +327,21 @@ int updateNote(long id, OwnCloudNote remoteNote, DBNote forceUnchangedDBNoteStat values.put(key_title, remoteNote.getTitle()); values.put(key_modified, remoteNote.getModified(DATE_FORMAT)); values.put(key_content, remoteNote.getContent()); + values.put(key_favorite, remoteNote.isFavorite()); String whereClause; String[] whereArgs; if(forceUnchangedDBNoteState!=null) { // used by: NoteServerSyncHelper.SyncTask.pushLocalChanges() - // update only, if not modified locally during the synchronization, + // update only, if not modified locally during the synchronization + // (i.e. all (!) user changeable columns (content, favorite) should still have the same value), // uses reference value gathered at start of synchronization - whereClause = key_id + " = ? AND " + key_content + " = ?"; - whereArgs = new String[]{String.valueOf(id), forceUnchangedDBNoteState.getContent()}; + whereClause = key_id + " = ? AND " + key_content + " = ? AND " + key_favorite + " = ?"; + whereArgs = new String[]{String.valueOf(id), forceUnchangedDBNoteState.getContent(), forceUnchangedDBNoteState.isFavorite()?"1":"0"}; } else { // used by: NoteServerSyncHelper.SyncTask.pullRemoteChanges() - // update only, if not modified locally - whereClause = key_id + " = ? AND " + key_status + " = ? AND ("+key_modified+"!=? OR "+key_content+"!=?)"; - whereArgs = new String[]{String.valueOf(id), DBStatus.VOID.getTitle(), remoteNote.getModified(DATE_FORMAT), remoteNote.getContent()}; + // update only, if not modified locally (i.e. STATUS="") and if modified remotely (i.e. any (!) column has changed) + whereClause = key_id + " = ? AND " + key_status + " = ? AND ("+key_modified+"!=? OR "+key_content+"!=? OR "+key_favorite+"!=?)"; + whereArgs = new String[]{String.valueOf(id), DBStatus.VOID.getTitle(), remoteNote.getModified(DATE_FORMAT), remoteNote.getContent(), remoteNote.isFavorite()?"1":"0"}; } int i = db.update(table_notes, values, whereClause, whereArgs); db.close(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java index 0ae7d6195..6090f9163 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java @@ -229,10 +229,8 @@ private void pushLocalChanges() { if (remoteNote == null) { Log.d(getClass().getSimpleName(), " ...Note does not exist on server -> (re)create"); remoteNote = client.createNote(note); - dbHelper.updateNote(note.getId(), remoteNote, note); - } else { - dbHelper.updateNote(note.getId(), remoteNote, note); } + dbHelper.updateNote(note.getId(), remoteNote, note); break; case LOCAL_DELETED: if(note.getRemoteId()>0) { @@ -252,8 +250,8 @@ private void pushLocalChanges() { throw new IllegalStateException("Unknown State of Note: "+note); } } catch (IOException | JSONException e) { - // FIXME make some errors visible in the UI - e.printStackTrace(); + Log.e(getClass().getSimpleName(), "Exception", e); + exceptions.add(e); } } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java b/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java index c3068bc06..613cff013 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java @@ -30,6 +30,7 @@ public class NotesClient { private static final String key_id = "id"; private static final String key_title = "title"; private static final String key_content = "content"; + private static final String key_favorite = "favorite"; private static final String key_modified = "modified"; private static final String application_json = "application/json"; private String url = ""; @@ -47,6 +48,7 @@ private OwnCloudNote getNoteFromJSON(JSONObject json) throws JSONException { String noteTitle = ""; String noteContent = ""; Calendar noteModified = null; + boolean noteFavorite = false; if (!json.isNull(key_id)) { noteId = json.getLong(key_id); } @@ -58,10 +60,12 @@ private OwnCloudNote getNoteFromJSON(JSONObject json) throws JSONException { } if (!json.isNull(key_modified)) { noteModified = GregorianCalendar.getInstance(); - noteModified - .setTimeInMillis(json.getLong(key_modified) * 1000); + noteModified.setTimeInMillis(json.getLong(key_modified) * 1000); } - return new OwnCloudNote(noteId, noteModified, noteTitle, noteContent); + if (!json.isNull(key_favorite)) { + noteFavorite = json.getBoolean(key_favorite); + } + return new OwnCloudNote(noteId, noteModified, noteTitle, noteContent, noteFavorite); } public List getNotes() throws JSONException, IOException { @@ -92,6 +96,7 @@ private OwnCloudNote putNote(OwnCloudNote note, String path, String method) thr JSONObject paramObject = new JSONObject(); paramObject.accumulate(key_content, note.getContent()); paramObject.accumulate(key_modified, note.getModified().getTimeInMillis()/1000); + paramObject.accumulate(key_favorite, note.isFavorite()); JSONObject json = new JSONObject(requestServer(path, method, paramObject)); return getNoteFromJSON(json); } diff --git a/app/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png b/app/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..57be19b9311d71f3f8b019d7aef927cfdbd88c70 GIT binary patch literal 840 zcmV-O1GoH%P)1vJb`_ivf=DqfG(3e!2C1NS^-y%_6kWng2RpcjaaJ!m&_PE> z5GguzDFTV=R@b6~3PO?>kAV@DXorN=ZJXWsx=gX_VH?9VJ5 z>3@`In%$;pc2~kHUI`PW)L^h&D%-1E1Jg9?l~Nx8MC7#Vx*O&AX%$H4CQuDj2kXO2 z$hPhH_V)G~&=izD8HUkf+jjO)5=x~~SMy*1nu1znl?9adFqf?D%QNcW@bGX4@UF=A z`KhU?l_%dnL*$mbjnx<_68%n9qj^nKU8u;U+7LisFnF9=^%04p* zz*~Zgd`}Sp*aofxzkzmrs%2RhMC3(~#zAUbDRpIXa`J6{v0w}%BO@)jT<#^%c0e$z zzVBb2o}T{j_eQ~A*~G-eS}Yd32)sT3m{*#n^%jBwh!vZfpP&EU-{1el^Sox@T!mmB zZf$K{o1LBADb^6?$yJtRjfu$Zko|=uA~NQ>?w!3FV`1DD78c(0_4Ta*m%`5E>4%66 zxUPFQOmpayTG#c*KsrJ?soL7wxv)X}285SuE8bfDR;+$p^mg-vc^CBve9ser2|8*8Je%ZN}n_ysIptI3vTms1F z^WB4kgOkh2XO=6d(P+F3tO3^8@y+W{5Cr*ZwfYOtZJ|q!Qe5Pzi#dA|fMJ6BUk77 z5$OcFRJBu8JAhk7WCO6?hNy@fYsQPnF;(3M6pS&GrBdlnRhMk zX_`*ta=FW47+#!HkgDD#A}3YVu|6%u=9i^zK5?%DZN z6%nbb>a)Pyf}$w;%=i6=RP}S9%fboprJdOXa0Qsk<#Lntdi_5ecV=eh#kFhK_9RKt z3AA>#3wR93S?aimJP}3Fx2^GWPP<$#-;pHA7rOifTt{U zF-_CQhlhuMoz0#1u`id)ZAp@x0v@r@H^7sJ4jmf59xJqz^#qps`Tn^lbEj<$$-XL@>i$9!TI>`*Jm_x*#a`iA9S6_K4$ z6n(u=knj5stLn!<8=$IsFplFl7b}+K9MUL?0uk8_Tm#xv_4P%A{^qm+*HrcSEMl?> z0-#VRybsi@JDMS+$*B~J#gkd3h95SU7(@{)+WrK;^# z#M7SVy;dw1PXs|QT`H9>06ikI9e6uSo$GnIHU*t=UAMPdt)3H+<3Kx*+N)hej#sPI zbFS<5^3Squ%UUGU_mJ=V-KzSVb;p2vnv)Tc@6t5gYddsQRUfdt6!;m~WO=toQS|$Y zbSO>J?Je#m8}|pWr%)*L#c_N-j^p!%LZJ`XWAB-!m^pIHYgzYDYs(dQH=ob@v;Xo0 zL68E+1_lOBH5!cwc%iup#+YruhbtmTL>{!m?~O5g!!TU%9I`@p_xJaoNYnHvaKEZ% z>d>M~76d^N*r=-e9mnZiOiZhVVL0kIPOqx&2R7PV%j;0RUSBseGqdIJ;lr1+3Yj&b s25{uSfde1a>-BX&Whr@9ZPl{cUsd9@;YhTodH?_b07*qoM6N<$f-3Yg)Bpeg literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_star_outline_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_star_outline_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..61133a2f6c802dbe7d7630cbd0e9132b5225e148 GIT binary patch literal 732 zcmV<20wev2P)+a@* zk_wWFl1gq1lFoVTR1zX-AcXMV@qLokBHkTIpCo;jv@Pk2q%F7G9@`8dtQ|JffQLZUq~Cy%6mcW=#jy{LB&0!tyVQ;t0JAClljYtA?&K=Q2|9ou zPBNLof6~5Rfz-#GEa#ysl9J8%CWU|Eb5>H{aR|EZwkl~pszd>JVv9c)^Y)db8yWJX z1MtF2u;S+qpzI|fTAp&UM8JyspC5;yk0zf6t^tdYkONzSMf*%AuZz6JT#S;f*Ck)V z*C79nMXpEB7xENzyTOO?J1`#qgS?F69;-)wM_b@=L|pY7xA+JDqJ64S+@m}NEt~W$ zFq|Q7*f9Xhd5P%(wt)$nxZ+T|DovQ9Cl5hIYG<6I^7N9!&9;p;{)V60JCx(IGDi>q O0000|k1|%Oc%$NbB*pj^6U4S$Y{B+)352QE?JR*yM zvQ&rUPlPeufHm>3#+V#&w=9jv*0;-%da1<>V;R_Fpht&`~7zBuAFC z;0}SNSCUa)-3wv^y6-8x5M9JR;ojl}xf8Z*H1FWyzTNTQ*!os=q2S%+GQ|t+dA=9C zpJ{ym%$%9l%D$$ZOl1vo1vXx4oN?~WPlI`iF9jwr&I&U+e9W6Q!D^yO_S2L*izlb9F9A7&!4NycWJ)YPv-= zGc?F8DCNB9=ILk8dCcmT+^@J&>!t6d_9f+;SEq%m?zMV8@Aua~3@bj@uVQAe_jQ+B z@rT)m^~CYB6L}ZdIL$EHFwdk=ym7bSfjdmxcAWYNVmmlFf?3k`Bv>twDd61F#*oP< z?%eo=!FpNk5sy`B1tQyJ#jgu`c&_sFvifi8Ik9-1=yA)F>yvLYyG@#=l6$Pwk7>(u z#?Nd2cCu$hO1h@kaYsmR=#tx*J>llxEmA@+Hn=m-Kd^G`zWn`D_WpkJQ2t#8cT9P1 zk*k8#1NoW$&(o?zg;u0E&TqKO^0jO&pM$2z8JiD`a~>BSU054xwO!(~VuO-R|Kixf iP0hn+R!=ra_IgU@smN?XBp4;K3gBAXK4x5iAH68k%lQq3~2_ z>^30>1z}4)h=LaMBIF|Y2UNTjsRu6=Qni&dO_oqM`^G~zl3%+`kA==oAd{1m{eHiHmYHu? ztJMnt)>~tGdV2b#lutTre-RFc*BTwJu<7aP5dg0N^bvK{fF@8d7`!Wlko&?kO}om> z?*XU)Hi_s_u~^&yfJ7n@^Z9(CTCG;eWHP^9U~gMN0HCxwlF8&CGrt0$644iC9@2IF znPC_f01#2mw(ajklDyZ8_xsNQC;*5^DIa^n zG))@-a2)`c`9V6J-aN>R=H}*p0Z2K%v8k!46JC{F#@-x@p-^bK8%nWQ+-STE!C>$W zfD!;zQIru^7&8w!dPN9P>jq{RhShi(oVWPdG0%Ec)(Zec^ry@Axk-J_O>Jzw`df~U zxn*JIPefE<<`s{aPilWR)DX#$-uq%DO{5pV9$7};Jb6i!`Gt3+ZfbsEhzou#TiD;FXhXL3`bj!)p zByE*BGrHkcfitK7vx-Ke{Zh)Oj=2qBOxN{%r@cxCP}7XM5oWFccy3wN`GtjryjxsT zW#w{tn20t3%(n*a?(Xh%N)QMHewIq5ST2{V9^`;WayaB4PZ%j$jp;Nl00000NkvXX Hu0mjf3n*&J literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png b/app/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..3e05c1154bcfa9b4dfe0ad10c748297bef08fa81 GIT binary patch literal 576 zcmV-G0>AxYpa|UsX(3mfMVwr^Itf}RA>1X<#hWU*_i~Ga zIMvm?;NYax13{>Nf*^&`xQNLh~yPOJmD9==b|qRJA1{%_K>hBC-eESt$Fgs{6*6k*bbFA^2iDpze@o_WLli~Fsu~xKE+QZE$j=o>o41MtRQ24NTmjGXZUL<#0btd2-J8oe za2Ecjz>DEeY5Wy6tR)}IDh+VJ~1IC!#Zn#1@Y|eaN z?nDK#Q*1 zQmG8CXQs3su$he(>1@|C-2$uCYG0OR?*K}rQh&W(U+88o>Q*4jvQxkYU_+7rJqNW~ zt<-9@UISl>(x!5`yuDVdWq-xN;^N{lpkLBeNmqgXqV{JF(lqVOvTRFFPtWE&&-=`* z3hXYI%Uc0jt=3!Mg`|2M#|ukKOP@=n(nsgq*Ny^dnpP!^0)4>7HoBL+_Y(j~k~D#H zZ7|<}1v9(uoU8w`BIn#CNp}kJ05r^OB!n;w?2~kU8C&H0LI}fVHUcz?nT?X}IOi^P zTv3uFr-5t0hbW2;Pft(JueRf-mL6TPEKx%qUa^?2{_`tf8LI#<1=kG zn{$$$0pELjd*A=wFKXY->}eFc2s!6&#&J9#>2WdhKh_^V0H7obAk#(}6TtKSPDj(q#+`j8&d4jv*e$-%j4>#q221_J3-Ea0`o1qN1bD z8m41v`2roTr%D8aJg%5~WU6|2C~ExTNSdwW>&5-sB&;b=CuyOZO4gIj1ud@U3d%E< zG9P|>=FjKzZ{GHNS_*NKy3PP`MI zq^ELsrnYM4K}++0EAIzCbiU@xsI@Vl;f%+u$tK#G$}1H!JumHX{59#E>RS&fk6lws z9?y~Xd$o!2OQYbyOP@BZ%{NefoWUYma9|zd{RXuFR<8qG6TWQl{5+NC@)nt%!@j#t zsu{59HO6#&KPmZ5^ajW86{`;j>|pN_E^s|;!>}~qNnDZK4z{?490!~1joJy8LOb1y zm~3vz)%2?Bl*x48@yKgfmp;95Q+j#h>m5(J%|vgPW{&%bex`03g2gZUndykKNrAhyL~+YHmgUlvVT-oUIN%QTzqTVu$R e=s(>mdzq78yeWEZ_aPS;B@CXfelF{r5}E*S+{Zfr literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_star_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_star_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb2edb8f0be3416248308b8a2c1e2633823c7dc GIT binary patch literal 397 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE(}6TtKSPDj(q#+`j1rzMjv*e$-%c^~JM19f`d_Jg+7g9Dt}zVZ znh%%?8op#IE%2YLyu?+(g6WZr$d{dreGXo%CXO4wXw2ZywzzhVNwg+2<)-!Le?8Z; zU;1;tV2btkefGs-^XtF)CHEQc=~!(nmFDYjT;kh((7${>BkO!EhWD>?OhO3M@4*Zb*u=JQi#;hkI8o~#- zAE=ZC_cw;K|6#TGRA*^v(Ayw>U>|p!;m%%z9iC0I4<@%9G!fnR{6_QL(mBiOFCIKq ztNHTIqL@f)pP3JKU3w@xA^ciV^|mXaT?biaFxF=A@yWAq&bJiS-@_Wi^tR)USpnmg gJHdavC*5OQDw=rv?w|I1zyM?LboFyt=akR{0I;8#?*IS* literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_sync_alert_grey600_18dp.png b/app/src/main/res/drawable-mdpi/ic_sync_alert_grey600_18dp.png new file mode 100644 index 0000000000000000000000000000000000000000..e8152118c9ba1d19171077b2589258c6bd0d311b GIT binary patch literal 522 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|wj^(N7a$D;Kb?2i11Zh|kH}&m z?E%JaC$sH9f@KAc=|CE+pF!Co&x?V9ajK__V~EA+rxR_vg#$&}<{Mw{oMh7U|G=T7 zn{F4*`E?(4+b+O#Eoo_5@-sEZ$Tm^WBK?%+=#>#UiaHT1dUF!fwR0Z2CqA?n$WeP^ zbjQ+cw!t&!YTLWD=Pmi)SL^-RtlE7fY;~z_*P`xoJKK$au?y}j`D4R!ZSVKr4C<$v zGiQYzd;D?Ts%xQN@5cMwnc={&s7U?vCfU%n-6s}Dt=-0#u=eh@YkAX;^)axnn^L~K zZ`Rpol@F$M*c6`2_4~3&L(k{ELJ>y{yB_n|vfY1^3?yoPot@8EaD`dknV& z?Wvq+&-O{+&{@}uVU78FJqlz_{Vj55ovMg878L=T*? z47$30)vj9^CVtE%R&zHqoZHF!{Epkq3vbKLGdyoNU#yUP##^E9@ejvID%pxH%f0J* z1rDhRvWbLMb7jfkAK zmu+3wiMXv%dxPWVG)+>8WRCmTE;O-uk;c5r_xC^jzoH-beUjP5XW`7i*kbT>^>bP0 Hl+XkKiXz>& literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png b/app/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..0b13a35816622193e3ca2e070a693484bece0ff5 GIT binary patch literal 1111 zcmV-d1gQIoP)wGb2$#DHmpLR0NqABw*C1NBi65kbgqW@ZV6 zGDRU|X4oXu2f;ik($e)sRD^;dB7yi&6hz;I#Q4)@MU?E)xU)OQ2dA=bv%53XJE;%* z!G+m7=brO@=iHy!8DM|`21pHtVH`IM<9M1eWSY*2==JdOtJGqo<=8Nc5hB_K0A@bw zdEQPMaYSmFA$k=+7C<(%=)XQkA*ZQD)Vu~Ml(tyX)sjXVGx z3H!7o6#;FFw`ZT0Sh^jWrujI4ue;oybY1rwo$<6+pjW2TsDjoC6bgm=q?A7a80unj zv)ODuu(-JRyRMj8DKyhXITbQJ$Gc0gM2c0&p~mS7Zca^2U6N8h2w>tai@1dk_V)H( zSYBSPb>8T;2FS9kH<|g|T_*pQ>$>OBWj*wq*X!%+tJBld+W^k=vrPd$fLC1CUF>BP zX%{k0^E7}8fO`&z{GUYhoZ~p3_cM%qkd;cMi696*Mf9yQDSi|}oLN{{_%4cZtdrQX ztT6zeF!N*@%!%k4Ge7OR?)9i+Vx7c}krkiJpZjl}bwp@tzLy03d{Tzf!5R5{*q7Gzfx| zx&$!ubYk&$5I1qqeFP*c`py4c07a$LF{RWo0L8GcE0XR+vH#T1&CTVT&1Tm(%|vv$(P$Kx zmX>~P@1L2Oxj&oDmYMl%Hw{wC(fRrLY8*bXzYqAnf0Afl-QP3w8?NiF?sqd3^rB%H z?-J2P0FQQR_kI5afREzvi9Lln7ceu|0F;zclb+|T_8aec-l|e+5&+wME|I!N+` z=3fEK{9zCT#d5j49mj!f+YJCtu~@t$geViy^PRpUCp3<6p->o-QvN|io8ff1njitU z!8Fa&M0Amv$CXm|+P1wHb!@CDB!qYjz=d2cH=&C>0JyGuHJ8gx0JyNbyZe86kubmj d0}K!We*@q;JsbcKsCEDV002ovPDHLkV1iC*0S^EG literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_star_outline_grey600_24dp.png b/app/src/main/res/drawable-xhdpi/ic_star_outline_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..3e7873f3c290163bdba23306eeae763620c01a1a GIT binary patch literal 1589 zcmV-52Fm$~P)I0hiBne`y>Cen; z8xu1`W4Aj?-B=PeCXz@*V@U`gArh@VutgqxP$E2tv?*wTEwQGvT06UQeCXXelr8Km zvpn^CnS0N@=bZ1{-!m6jzycOfHE5c)TGO=E)$|dnrg0*AO%{(=%}2EicXxM3^ZEQa z00@Ob4LvZM<}84V04@;G(PT3Dq1WgY zOUQAYFEMkAJ^^4QGcN_8_?XpERaN)T6-wEt4?BwVy;5>%klZdq$sufQZM~_sw)PVM zFO_JXB%(3bb;pS)3m{8G7nnKA%-NcnniIXfy(dc9jmP6ng+if;h@x_4>j6ZWIVyyx zlZ0)YL2e{r&%z6+p4gFpRgE`Av_k0HD>ftPgyQWZBSleH(y&05u-*JC<5gfQ>CJE$YzF&^G~cCr#6mMD#BHU)BzQEtX}ycU8qQ zM`k^M0RXoYWz4*H@#4iVo2EH+JHxa$y5&uO*&nJ_~Z?747xsKxTc$4e8 zhXCB;5g&71_n93#c8pg-zO%ElP6%-Tz#|^w!OKQi-EmSvqU*N(57IGIfT5s5?|C8EO~@p1sibX{-u zLB1KlF)w)l2VK{F%ny0r0RVt$n)dMU@Y4W3@`#tXu3KNO4cT`|vChmpM@B|ArBbP! zUp^J(LIVQ>1tG+zUQUXl{7|mG?CZ{w5MuYhz(AoAE)^$puIsMxR8J-ni9gHLm3>bZ z>&zUhl*jdCqh6<(QXNdwjF_ewnMZ$CN9JBPGynq7;vsN!ZU@6Kp3UWQr*gU6DZ?F z->B$q)H`BCG?qvt&a}6;FH#gGUMLg{0EkPw4I*!wuNF>e}hA}1+IACT; z`npSiYve-nAr_0h0pMW(VCJu5vDiQIM%{$VQ|}X)$>objtO8)I5MpyI7CXbtw-eC{ zIS`jJnalydTq;^ZMAYIbKMvp^F29r}0d%OU+N`Q-GiF{VCOz%T0UVUNkONWCKJfjl zB43>^UM09Mrl+Sn(&_Y=SKijvwlo|L_c8P4c~m(R3f234#rC}i9LHHR&#&Z3W^T1C zYp_(K4CqBo(>^AmegG@x#_l*y3xNIb0pCk#?vW?oeB!FAu1cj+gV)kerBZ{cs;&YM z_q-PsZTr3tDmjH_17PO8uIqO6_4S?gW56`cX#mNNj*icT5PhD10pI(;*B)qZZ(kG& zg(iq-L@t*j6%4=?&~<%15%n|ky{f9->gOlP*Afy!JP2TWBob)~iaY>VmUSc&i8KM& nJ~=tr6qMZsEMNf(s6PG!X~#YP?Z!qg00000NkvXXu0mjfX7kla literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_star_outline_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_star_outline_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..d609a927d34e00161f1718c7e1b79582bb5a86c7 GIT binary patch literal 953 zcmV;q14jIbP)y5zny3-95CtK`LePMw@BslqQBf?cL<=9-2x4I+Xr*>G z3Zj)*sEwd)Qusg+3q^yNMg?C{d<2E~`Ydu5598fr@7;TME%t}uPUg({|NqRrvv+nQ zHPAog_8{0euMt^wrx}rRJAW9?SC9D`FELbp1hVNwNPAKr8Uot@t5pC42>1 z>+N%_0uDQ~!&XqM^-DNhZ=dDNPXL}dqvu@goEv`z6#4$iT)?Ji!*;q@XB69%mu^U5 zaJHm&*XG%^P10OR-I5mC^!^aS+9}CB1g5Gi0k%>OTr0JSxN6C8-zKR;(u{=EOOp145JoD# ze?S0EM62)<*q`DtNCjZOX?Pq5D&DI}q`QId5$VaQNRt=qWTf#O*p-(+FYq}MxB^Vc zfqRN^d3*xa=e0m3p)TM>Byg1*2KIsvC0|v14@MJ~1&xWT`;0W5a&7De&YAH~%au*V6%vauH681Rkq_-1oj zEa#Pr?W$z~7oG4GU}M5d3E-i%7=xDMj}Yf;S-?{#{2{^M7e;@LXtH+5#$x!~fm)ew zXKY*sIui0aELIM`DezZpZ)9s31CN1q738n8xk=buivmtZqQk%upg9Fcv*ip&T&HSL zz};vAFQ|fRL9~(Y6m7nR(f_zS1$uMj?KRF3a`=)ome2~|Xqv|*1$VP?uPCg51{!Ff bf!y&2a8R;5Z6kRZ00000NkvXXu0mjfZ^EWr literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_star_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_star_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..624b2288c33f2ae052d618cf4b6ca3b8d5e17d1a GIT binary patch literal 712 zcmV;(0yq7MP)3_Tj*Ev@hj&SYlwu)5Kw`ijO@wQMO=?LIB%O_gt#;bk@2Jg1VvDr5F}MlQ<%g;69^=rkHya668G+Q_rBS+*awE2Wp=*reP?EOcK4);ii%(W z^T2$_9JRn6R{ih0z*g)zrWe|FTrJ zt}F(+2?n}l>q;wrmj29I=L>NWujXtkAD{^w4w!*MplO-YdIpvyH3qad{5k(0z!G$pC+k0*WovZR@mdA~~fAZb_9j-)+b|0e0X zKi+fBk=X!nN79X$u%7U7t5HkIubz>Z(bvwowPB;(?6VP-O*i!&4443(m903&Q(z*~ z`~ePlShjND0ns&>4`3NME%FTZkmXXnYaXeDM0*Z;G(Jcn2B@1 z$AIGB15-i7$4s07UIh^U5;z@He9Xi+ux2R!2~g}t30yTaa3!yfQJxB~8;-}dG7RKS znn3Qs$hE@}?TovMo=h#+an9ws`{bR03x?t)X%aYJqyfw2Gg8dF2GXwCbzdxFjt;On zj-CB8L8$a7#iq2IJ`>&I`PRfK_CeFSU(3n}_9_;Zsmd)Xf( z;PHv12f#g`o*_ov_c=Hb>roK~-o_HX0MdSmNQyP%WAu0vT6}}(AD2y_V;HyNV;%vg uLK>I@?q^vp8DiIc?73hDDk>@}%=rUKk_xHKP%$O|0000J!lj`6vzK>Cy}tR5JW_aTnZbpOCf$?{Aw%|L{2QMYy>TgxSQL6nu!S6 zV^+k%TI@7IM6s|?G@>YicA`a!B!w0tSh!o5%sh+i#o=ym_wJ(D+`rm+`)1}hZ|2P# zpsTLB`nRHXoXh31D3waXM6^aJ^(4>N_x%9CWRA<65MqBAhI6*jX%*b_ypyF;=`#^M z12DYGKxD!IKu=N6k&%&gy}iA6032N}dT0$?Km0pLKABv$}j%9=OxPzOP<1;9nibRmkODRibeA;fNb zJZ8RFsZ<792GUyl>1qJrsZ#3JDq!}9VK}Fhx=BPYQ+uD*y3!I*xm*?iPOLaM&O|39 z%-oPo%zVij_n4HjVg3fgz`(!|fOWMMR;$%lod88qbhkd6lv1y-e4fC}o023MDg<&I zXPec0-3d%y;H+(fF=k645D~4nnqU7i5NZ)hwYd<;7{eA^tEHv&5HXvT$sMPmmS){U zxhu$+;4Oe^x`3if5dbz>eZLn1IgT^S%(V`CvHT+7W}`<@^a8+(HiERf_F;_q*f4*+ z!FAmaL{vLFn|t@U#vx?A&arFF7soSgjDtY6cMF9?D`0Qb?Mh-h0K%%jD{#a($YK$9)2WfM9) zGq#v{7Qp2witZujK5Gi}7h&Eo^TGM~`I)Tr?y9S<{+E6OHV;4KU_Mj)00000NkvXX Hu0mjff!w5U literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..541bf1b1b9528c915bb8b43d8ac0dbf308fbdadf GIT binary patch literal 1638 zcmV-s2ATPZP)->n^V{!y?>Dov(^()SBqSsxBt!y+VXQF>V~uJZr9@Q=D20e#@V|bqTFZnc z)dI#b3}X=y{Q&^X+~zpWMb(-BKvOMX93t8ZU>1N`{`aP!DKbb15zXiGX8dzIOo=wt0y3G*N&r8W`SU8qtQPB%qdf4q);f_*4Ni}S(Qem85E61pF??b0AP+^M;Xd8NC=_j z^ZC;N+NY^{M%VQ_g%F+!oys!Eb=@a0y*U8T?$=d}ee5yueH|>kX;^jyr@+uK69WP^M)t#(|1ppQ>a|Zwr zP2|S;VzF3urCxTD&gF8)iKq*}PpW$sAg73^E0@b1FIS=BT`Zf;p4Bw18^9N;dlCRg zG)+rpv)QwiDn+J?a`foY(az4!4`Z=d8-SIndnE&A-a9-z{M4>pyRJ-Ex2olSCX;y$ zfT*%vGr<5}w{824nKqa5n3)d% zXjR?o8FJb4ybZZr?we{G);v`FEsH|{?oi$PX*f+p>n+RrrIyAuKa2T$Giw1HQ|&+n zzGLRKwVDIe`LJr+_5d@l1MrDzC#K*)p-@;??;(h~C))o0{;@gqRgX>_7~1U3WErn*w#^dSb5YJ`hCUpf>Hh12kjmj%ZpkkhlSfZMZ?q z9LP1L8zh9#n0amRmfS!$0=O$nH)v#JtIRQW2R|tWad5qw^tKvY-}tE;DD??NzI@t*FRU8dAqLb9h1xf z09clFP}lViX5J3qY87#%&VjPu7n`ZLBSiF~ZQB*MLWK}l0Q8!s`7SfR1>liJ8zgOE zC4`ul&*z6wd9&;sGr!_E&i-1iVHn1fMD!-EfAM891zp$Y`{ve-v?1oYZdV0!#+cdG zb$xlQ<^X`>IQw;7U(U=nfO6ZZQD2J`qzy45D))HtmFIaqvQDT9AzT1vI-Pz;)3iMR z9-5+BH-Imj${b%707*qoM6N<$g6KZ#%K!iX literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_star_outline_grey600_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_star_outline_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..080a1884b2f1e00ac8240d0d127395a24b481e98 GIT binary patch literal 2292 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 b*wK-ga90V@(9K{@?0~7EC9+1}<=+1QhzQxo literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_star_outline_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_star_outline_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..0b3ab785f0534e9fce90217fa8bfb00893bd8d42 GIT binary patch literal 1970 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 + android:layout_height="wrap_content" + android:background="@drawable/list_item_background_selector" + > - - - + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_alignParentLeft="true" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginLeft="16dp" + android:layout_marginEnd="70dp" + android:layout_marginRight="70dp" + android:ellipsize="marquee" + android:maxLines="1" + android:textColor="@drawable/list_item_color_selector" + android:textSize="16sp" /> - + - + - + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_notes_list_section_item.xml b/app/src/main/res/layout/fragment_notes_list_section_item.xml index 56c492454..a3a64667e 100644 --- a/app/src/main/res/layout/fragment_notes_list_section_item.xml +++ b/app/src/main/res/layout/fragment_notes_list_section_item.xml @@ -11,6 +11,7 @@ android:layout_alignParentEnd="false" android:layout_alignParentRight="true" android:layout_alignParentStart="true" + android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_alignWithParentIfMissing="true" android:background="@color/bg_highlighted" @@ -24,9 +25,9 @@ android:textSize="12sp" /> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_note_list_view.xml b/app/src/main/res/menu/menu_note_list_view.xml index 693c9673e..2aa6866e4 100644 --- a/app/src/main/res/menu/menu_note_list_view.xml +++ b/app/src/main/res/menu/menu_note_list_view.xml @@ -1,6 +1,12 @@ + Kopieren Bearbeiten Abbrechen + Favorit Vorschau Teilen Über diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ecbc753e1..530a9fe79 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,6 +18,7 @@ Copy Edit Cancel + Favorite Preview Share About