diff --git a/app/build.gradle b/app/build.gradle index 2ae628d2..041c1d28 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,4 +119,5 @@ dependencies { testImplementation 'org.powermock:powermock-module-junit4:2.0.2' testImplementation 'org.powermock:powermock-api-mockito2:2.0.2' testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1' + implementation 'com.github.woxthebox:draglistview:1.7.2' } diff --git a/app/src/main/assets/images/draggable_icon.png b/app/src/main/assets/images/draggable_icon.png new file mode 100644 index 00000000..ef8638bd Binary files /dev/null and b/app/src/main/assets/images/draggable_icon.png differ diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java index 7fbdf746..28d06dfe 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java @@ -77,6 +77,12 @@ public class BookmarksActivity extends BaseActivity { return false; } + + public void updateBookmarks(ArrayList update_bookmarks) + { + this.updateBookmarksOnReorder(update_bookmarks); + } + private boolean onTopicInteractionListener(String interactionType, Bookmark bookmarkedTopic) { switch (interactionType) { case BookmarksFragment.INTERACTION_CLICK_TOPIC_BOOKMARK: diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksAdapter.java new file mode 100644 index 00000000..4fb82c25 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksAdapter.java @@ -0,0 +1,189 @@ +package gr.thmmy.mthmmy.activities.bookmarks; + +import android.app.Activity; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; + +import com.woxthebox.draglistview.DragItemAdapter; + +import java.util.ArrayList; + +import gr.thmmy.mthmmy.R; +import gr.thmmy.mthmmy.model.Bookmark; + + + + +public class BookmarksAdapter extends DragItemAdapter, BookmarksAdapter.BookmarksViewHolder> +{ + private final BookmarksFragment m_fragment; + private final Drawable m_notificationsEnabled; + private final Drawable m_notificationsDisabled; + + public BookmarksAdapter(BookmarksFragment fragment, Drawable noteEnabled, Drawable noteDisabled) + { + this.m_fragment = fragment; + this.m_notificationsEnabled = noteEnabled; + this.m_notificationsDisabled = noteDisabled; + } + + @Override + public long getUniqueItemId(int position) + { + return m_fragment.bookmarks.get(position).getId().hashCode(); + } + + @NonNull + @Override + public BookmarksAdapter.BookmarksViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_bookmarks_row, parent, false); + return new BookmarksViewHolder(view, view.findViewById(R.id.bookmark_dragable).getId(), true); + } + + @Override + public void onBindViewHolder(@NonNull BookmarksViewHolder holder, int position) + { + super.onBindViewHolder(holder, position); + + //If this is a drop indicator, use the dashed corner background. + if (m_fragment.bookmarks.get(position).getId().equals("-1")) + { + holder.itemView.findViewById(R.id.bookmark_dragable).setBackgroundResource(R.drawable.bookmark_row_dashed_bg); + holder.itemView.findViewById(R.id.bookmark_drag_icon).setVisibility(View.GONE); + holder.itemView.findViewById(R.id.toggle_notification).setVisibility(View.GONE); + holder.itemView.findViewById(R.id.remove_bookmark).setVisibility(View.GONE); + } + + //Check if bookMarks ArrayList Exists and is not empty. + if(m_fragment.bookmarks != null && !m_fragment.bookmarks.isEmpty()) + { + //Check if the current bookmark exists and has a title. + if (m_fragment.bookmarks.get(position) != null && m_fragment.bookmarks.get(position).getTitle() != null) + { + + //Set the title. + holder.m_textView.setText(m_fragment.bookmarks.get(position).getTitle()); + + //Set Notifications Enabled Image Indicator. + if (m_fragment.bookmarks.get(position).isNotificationsEnabled()) + holder.m_noteView.setImageDrawable(m_notificationsEnabled); + + //Set Notifications Disabled Image Indicator. + else + holder.m_noteView.setImageDrawable(m_notificationsDisabled); + + + //On Bookmark Click. + holder.mGrabView.setOnClickListener(v -> { + + //Get the activity. + Activity activity = m_fragment.getActivity(); + + //Go to the bookmarked activity. + if (activity instanceof BookmarksActivity) + ((BookmarksActivity) activity).onFragmentRowInteractionListener( + m_fragment.type, + m_fragment.interactionClick, + m_fragment.bookmarks.get(position)); + }); + + + //On Notifications Toggle. + holder.m_noteView.setOnClickListener(v -> { + + //Toggle the current local instance. + m_fragment.bookmarks.get(position).toggleNotificationsEnabled(); + + //Get the fragment activity. + Activity activity = m_fragment.getActivity(); + + //Check if it is indeed the fragment activity. + if (activity instanceof BookmarksActivity) + { + + //Trigger the toggle functionality and set the Enabled notifications image. + if (((BookmarksActivity) activity).onFragmentRowInteractionListener( + m_fragment.type, + m_fragment.interactionToggle, + m_fragment.bookmarks.get(position))) + { + holder.m_noteView.setImageDrawable(m_notificationsEnabled); + } + + //Trigger returned false, so set the notifications disabled image. + else + holder.m_noteView.setImageDrawable(m_notificationsDisabled); + } + }); + + + //Remove Item. + //TODO: AFTER DELETION, UPDATE THE ORDER IN THE PREFERENCES OF ALL + // ALL THE BOOKMARKS UNDER THIS ONE THAT HAS BEEN DELETED! + holder.m_removeView.setOnClickListener(v -> { + + //Get fragment's activity. + Activity activity = m_fragment.getActivity(); + + if (activity instanceof BookmarksActivity) + { + + //Trigger the bookmark remove functionality. + ((BookmarksActivity) activity).onFragmentRowInteractionListener( + m_fragment.type, + m_fragment.interactionRemove, + m_fragment.bookmarks.get(position)); + { + notifyItemRemoved(position); + notifyItemRangeChanged(position, m_fragment.bookmarks.size()); + m_fragment.bookmarks.remove(m_fragment.bookmarks.get(position)); + } + } + + //If the bookmarks are empty then show nothing marked. + if (m_fragment.bookmarks.isEmpty()) + { + m_fragment.showNothingBookmarked(); + } + + }); + } + } + } + + @Override + public int getItemCount() + { + if (m_fragment.bookmarks != null) + return m_fragment.bookmarks.size(); + + return 0; + } + + //View Holder. + static class BookmarksViewHolder extends DragItemAdapter.ViewHolder + { + + public final TextView m_textView; + public final ImageView m_noteView; + public final ImageView m_removeView; + public final View m_thisView; + + public BookmarksViewHolder(View itemView, int handleResId, boolean dragOnLongPress) + { + super(itemView, handleResId, dragOnLongPress); + this.m_textView = itemView.findViewById(R.id.bookmark_title); + this.m_noteView = itemView.findViewById(R.id.toggle_notification); + this.m_removeView = itemView.findViewById(R.id.remove_bookmark); + this.m_thisView = itemView; + } + } +} diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java index 12b70d89..3194e17c 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java @@ -1,5 +1,6 @@ package gr.thmmy.mthmmy.activities.bookmarks; + import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Build; @@ -7,14 +8,16 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; +import com.woxthebox.draglistview.DragListView; + import java.util.ArrayList; import gr.thmmy.mthmmy.R; @@ -37,9 +40,9 @@ public class BookmarksFragment extends Fragment { private TextView nothingBookmarkedTextView; - private ArrayList bookmarks = null; - private Type type; - private String interactionClick, interactionToggle, interactionRemove; + public ArrayList bookmarks = null; + public Type type; + public String interactionClick, interactionToggle, interactionRemove; private Drawable notificationsEnabledButtonImage; private Drawable notificationsDisabledButtonImage; @@ -101,68 +104,156 @@ public class BookmarksFragment extends Fragment { Bundle savedInstanceState) { // Inflates the layout for this fragment final View rootView = layoutInflater.inflate(R.layout.fragment_bookmarks, container, false); - //bookmarks container - final LinearLayout bookmarksLinearView = rootView.findViewById(R.id.bookmarks_container); + + //Get the nothing bookmarked text view. nothingBookmarkedTextView = rootView.findViewById(R.id.nothing_bookmarked); - if (this.bookmarks != null && !this.bookmarks.isEmpty()) { - hideNothingBookmarked(); - for (final Bookmark bookmark : bookmarks) { - if (bookmark != null && bookmark.getTitle() != null) { - final LinearLayout row = (LinearLayout) layoutInflater.inflate( - R.layout.fragment_bookmarks_row, bookmarksLinearView, false); - row.setOnClickListener(view -> { - Activity activity = getActivity(); - if (activity instanceof BookmarksActivity) - ((BookmarksActivity) activity).onFragmentRowInteractionListener(type, interactionClick, bookmark); - }); - ((TextView) row.findViewById(R.id.bookmark_title)).setText(bookmark.getTitle()); - - final ImageButton notificationsEnabledButton = row.findViewById(R.id.toggle_notification); - if (!bookmark.isNotificationsEnabled()) { - notificationsEnabledButton.setImageDrawable(notificationsDisabledButtonImage); - } - notificationsEnabledButton.setOnClickListener(view -> { - Activity activity = getActivity(); - if (activity instanceof BookmarksActivity) { - if (((BookmarksActivity) activity).onFragmentRowInteractionListener(type, interactionToggle, bookmark)) - notificationsEnabledButton.setImageDrawable(notificationsEnabledButtonImage); - else - notificationsEnabledButton.setImageDrawable(notificationsDisabledButtonImage); - } - }); + //Create the adapter. + BookmarksAdapter adapter = new BookmarksAdapter(this, notificationsEnabledButtonImage, notificationsDisabledButtonImage); - (row.findViewById(R.id.remove_bookmark)).setOnClickListener(view -> { - Activity activity = getActivity(); - if (activity instanceof BookmarksActivity) { - ((BookmarksActivity) activity).onFragmentRowInteractionListener(type, interactionRemove, bookmark); - bookmarks.remove(bookmark); - } - row.setVisibility(View.GONE); + //Get the drag list view. + DragListView mDragListView = (DragListView) rootView.findViewById(R.id.fragment_bookmarks_dragList); + + + //Set the Drag List Listener. + mDragListView.setDragListListener(new DragListView.DragListListener() + { + @Override + public void onItemDragStarted(int position) + { + //Create a new array of bookmarks. + ArrayList new_bookmarks = new ArrayList(); + + //For each bookmark in the current bookmarks array. + for (int i = 0; i < bookmarks.size(); i++) + { + //Create an indicator bookmark. + Bookmark indicator = new Bookmark("Drop Here", "-1", true); + + //Add the indicator followed by the current actual bookmark. + if (position != i-1 && position != i) + new_bookmarks.add(indicator); + + new_bookmarks.add(bookmarks.get(i)); + } + + //Add one last indicator. + if (position != bookmarks.size() - 1) + new_bookmarks.add(new Bookmark("Drop Here", "-1", true)); + + //Replace the bookmarks with the new bookmarks that contains the indicators. + bookmarks = new_bookmarks; + + //Notify the adapter that the bookmarks array has changed! + adapter.notifyDataSetChanged(); + } + + @Override + public void onItemDragging(int itemPosition, float x, float y) + { + + } + + @Override + public void onItemDragEnded(int fromPosition, int toPosition) + { + //It's hard to explain what this does. + int actualPos = fromPosition; + + //It's hard to explain what this does. + if (fromPosition != 0) + actualPos = 2 * fromPosition; + + //If the drag and drop is not the same item. + if (actualPos != toPosition) + { + + //Get the from bookmark. + Bookmark from = bookmarks.get(actualPos); + Bookmark to = bookmarks.get(toPosition); - if (bookmarks.isEmpty()) { - showNothingBookmarked(); + //You can only drop items in the indicator boxes!!! + //Indicator boxes are Bookmark objects with id "-1". + if (to.getId().equals("-1")) + { + //Swap the indicator with the actual. + bookmarks.set(actualPos, to); + bookmarks.set(toPosition, from); + + //Get the fragments activity. + Activity unknownActivity = getActivity(); + + //Update the order of the bookmarks in the preferences. + if (unknownActivity instanceof BookmarksActivity) + { + //Cast to BookmarksActivity. + BookmarksActivity activity = (BookmarksActivity)unknownActivity; + + //Update the preferences. + activity.updateBookmarks(bookmarks); } - }); - bookmarksLinearView.addView(row); + } + + //------------------------Clean up the indicator boxes------------------------// + } + + //Find all the indicator boxes in the bookmarks array. + ArrayList books_to_delete = new ArrayList(); + for (int i = 0; i < bookmarks.size(); i++) + { + Bookmark book = bookmarks.get(i); + + if (book.getId().equals("-1")) + books_to_delete.add(book); + } + + + //Remove all the indicators. + for (int i = 0; i < books_to_delete.size(); i++) + { + bookmarks.remove(books_to_delete.get(i)); } + + //------------------------Clean up the indicator boxes------------------------// + + //Notify the adapter, because I made changes to the bookmarks array. + adapter.notifyDataSetChanged(); } + + }); + + //====================================This is the code for the Drag and Drop Functionality====================================// + mDragListView.setLayoutManager(new LinearLayoutManager(getActivity())); + mDragListView.setAdapter(adapter, false); + mDragListView.setCanDragHorizontally(false); + //====================================This is the code for the Drag and Drop Functionality====================================// + + //Hide Nothing Bookmarked. + if(this.bookmarks != null && !this.bookmarks.isEmpty()) + { + hideNothingBookmarked(); } - else + + //Show Nothing Bookmarked. + else { showNothingBookmarked(); + } + return rootView; } - private void showNothingBookmarked() { - if (nothingBookmarkedTextView != null) + + public void showNothingBookmarked() { + if(nothingBookmarkedTextView!=null) nothingBookmarkedTextView.setVisibility(View.VISIBLE); } - private void hideNothingBookmarked() { - if (nothingBookmarkedTextView != null) + public void hideNothingBookmarked(){ + if(nothingBookmarkedTextView!=null) + nothingBookmarkedTextView.setVisibility(View.INVISIBLE); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java index ee377c83..d503478e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -48,6 +48,7 @@ import net.gotev.uploadservice.UploadService; import java.io.File; import java.util.ArrayList; +import gr.thmmy.mthmmy.BuildConfig; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.AboutActivity; import gr.thmmy.mthmmy.activities.LoginActivity; @@ -709,6 +710,46 @@ public abstract class BaseActivity extends AppCompatActivity { Timber.w("No bookmark match exists!"); return false; } + + + /* + * This method should only be called after reordering the bookmarks. + * It Re-creates the topicsBookmarked and boardsBookmarked arrays + * with the reordered bookmarks. + * */ + protected void updateBookmarksOnReorder(ArrayList updated_bookmarks) + { + //Define to empty arrays. + ArrayList newTopicBookmarks = new ArrayList(); + ArrayList newBoardBookmarks = new ArrayList(); + + //For each bookmark in updated_bookmarks. + for (int i = 0; i < updated_bookmarks.size(); i++) + { + //Get the current updated bookamrk. + Bookmark book = updated_bookmarks.get(i); + + //Is it a topics bookmark? + if ( book.matchExists(topicsBookmarked) ) + newTopicBookmarks.add(book); + + + //Is it a board bookmark? + else if ( book.matchExists(boardsBookmarked) ) + newBoardBookmarks.add(book); + } + + + if (newTopicBookmarks.size() > 0) + topicsBookmarked = newTopicBookmarks; + + if (newBoardBookmarks.size() > 0) + boardsBookmarked = newBoardBookmarks; + + //Update the bookmarks. + updateTopicBookmarks(); + updateBoardBookmarks(); + } //-------------------------------------------BOOKMARKS END------------------------------------------ //-------PERMS--------- diff --git a/app/src/main/res/drawable-hdpi/draggable_icon.png b/app/src/main/res/drawable-hdpi/draggable_icon.png new file mode 100644 index 00000000..d30285ec Binary files /dev/null and b/app/src/main/res/drawable-hdpi/draggable_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/draggable_icon.png b/app/src/main/res/drawable-mdpi/draggable_icon.png new file mode 100644 index 00000000..e59f5013 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/draggable_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/draggable_icon.png b/app/src/main/res/drawable-xhdpi/draggable_icon.png new file mode 100644 index 00000000..bd8c3a1d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/draggable_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/draggable_icon.png b/app/src/main/res/drawable-xxhdpi/draggable_icon.png new file mode 100644 index 00000000..f5ee0e30 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/draggable_icon.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/draggable_icon.png b/app/src/main/res/drawable-xxxhdpi/draggable_icon.png new file mode 100644 index 00000000..3fe3ba1d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/draggable_icon.png differ diff --git a/app/src/main/res/drawable/bookmark_row_bg.xml b/app/src/main/res/drawable/bookmark_row_bg.xml new file mode 100644 index 00000000..acac08e0 --- /dev/null +++ b/app/src/main/res/drawable/bookmark_row_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bookmark_row_dashed_bg.xml b/app/src/main/res/drawable/bookmark_row_dashed_bg.xml new file mode 100644 index 00000000..7eb0a45c --- /dev/null +++ b/app/src/main/res/drawable/bookmark_row_dashed_bg.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bookmarks.xml b/app/src/main/res/layout/fragment_bookmarks.xml index e672fab8..f71e9800 100644 --- a/app/src/main/res/layout/fragment_bookmarks.xml +++ b/app/src/main/res/layout/fragment_bookmarks.xml @@ -1,36 +1,36 @@ - + android:layout_height="match_parent" + android:orientation="vertical" + > + + - - - - \ No newline at end of file + + android:textIsSelectable="false" + android:textSize="@dimen/medium_text" + android:visibility="invisible" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bookmarks_row.xml b/app/src/main/res/layout/fragment_bookmarks_row.xml index eafe5ef1..3eab93e2 100644 --- a/app/src/main/res/layout/fragment_bookmarks_row.xml +++ b/app/src/main/res/layout/fragment_bookmarks_row.xml @@ -1,49 +1,72 @@ - - - + + - - - - - \ No newline at end of file + + android:background="@drawable/bookmark_row_bg" + android:clickable="true" + android:focusable="true" + android:gravity="center_vertical" + android:orientation="horizontal" + android:layout_marginTop="24dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + > + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5f3d866c..1815148b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ buildscript { repositories { google() jcenter() + mavenCentral() maven { url "https://jitpack.io" } } dependencies { @@ -21,6 +22,7 @@ allprojects { maven { url "https://maven.google.com" } google() jcenter() + mavenCentral() maven { url "https://jitpack.io" } } }