Browse Source

- Rewrote Category to Kotlin
- Moved category to ui
- Reworked Animation (smoother)
- Updated TextDrawable

NoodleMage 9 years ago
parent
commit
9f78c8f6b4
29 changed files with 624 additions and 415 deletions
  1. 1 0
      app/build.gradle
  2. 1 2
      app/src/main/AndroidManifest.xml
  3. 3 3
      app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.java
  4. 1 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.java
  5. 276 0
      app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt
  6. 110 0
      app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryAdapter.kt
  7. 74 0
      app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryHolder.kt
  8. 26 0
      app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryItemTouchHelper.kt
  9. 106 0
      app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryPresenter.kt
  10. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.java
  11. 0 180
      app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryActivity.java
  12. 0 80
      app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryAdapter.java
  13. 0 58
      app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryHolder.java
  14. 0 16
      app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryItemTouchHelper.java
  15. 0 68
      app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryPresenter.java
  16. 15 0
      app/src/main/java/eu/kanade/tachiyomi/util/ViewGroupExtensions.kt
  17. BIN
      app/src/main/res/drawable-hdpi/ic_action_reorder.png
  18. BIN
      app/src/main/res/drawable-hdpi/ic_reorder_grey_600_24dp.png
  19. BIN
      app/src/main/res/drawable-ldpi/ic_reorder_grey_600_24dp.png
  20. BIN
      app/src/main/res/drawable-mdpi/ic_action_reorder.png
  21. BIN
      app/src/main/res/drawable-mdpi/ic_reorder_grey_600_24dp.png
  22. BIN
      app/src/main/res/drawable-xhdpi/ic_action_reorder.png
  23. BIN
      app/src/main/res/drawable-xhdpi/ic_reorder_grey_600_24dp.png
  24. BIN
      app/src/main/res/drawable-xxhdpi/ic_action_reorder.png
  25. BIN
      app/src/main/res/drawable-xxhdpi/ic_reorder_grey_600_24dp.png
  26. BIN
      app/src/main/res/drawable-xxxhdpi/ic_action_reorder.png
  27. BIN
      app/src/main/res/drawable-xxxhdpi/ic_reorder_grey_600_24dp.png
  28. 5 3
      app/src/main/res/layout/activity_edit_categories.xml
  29. 5 4
      app/src/main/res/layout/item_edit_categories.xml

+ 1 - 0
app/build.gradle

@@ -2,6 +2,7 @@ import java.text.SimpleDateFormat
 
 apply plugin: 'com.android.application'
 apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
 apply plugin: 'com.neenbedankt.android-apt'
 apply plugin: 'me.tatarka.retrolambda'
 

+ 1 - 2
app/src/main/AndroidManifest.xml

@@ -40,11 +40,10 @@
             android:parentActivityName=".ui.main.MainActivity" >
         </activity>
         <activity
-            android:name=".ui.library.category.CategoryActivity"
+            android:name=".ui.category.CategoryActivity"
             android:label="@string/label_categories"
             android:parentActivityName=".ui.main.MainActivity">
         </activity>
-
         <activity
             android:name=".ui.setting.SettingsDownloadsFragment$CustomLayoutPickerActivity"
             android:label="@string/app_name"

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.java

@@ -6,17 +6,17 @@ import javax.inject.Singleton;
 
 import dagger.Component;
 import eu.kanade.tachiyomi.data.download.DownloadService;
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService;
-import eu.kanade.tachiyomi.data.source.base.Source;
 import eu.kanade.tachiyomi.data.library.LibraryUpdateService;
 import eu.kanade.tachiyomi.data.mangasync.UpdateMangaSyncService;
+import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService;
+import eu.kanade.tachiyomi.data.source.base.Source;
 import eu.kanade.tachiyomi.data.updater.UpdateDownloader;
 import eu.kanade.tachiyomi.injection.module.AppModule;
 import eu.kanade.tachiyomi.injection.module.DataModule;
 import eu.kanade.tachiyomi.ui.catalogue.CataloguePresenter;
+import eu.kanade.tachiyomi.ui.category.CategoryPresenter;
 import eu.kanade.tachiyomi.ui.download.DownloadPresenter;
 import eu.kanade.tachiyomi.ui.library.LibraryPresenter;
-import eu.kanade.tachiyomi.ui.library.category.CategoryPresenter;
 import eu.kanade.tachiyomi.ui.manga.MangaActivity;
 import eu.kanade.tachiyomi.ui.manga.MangaPresenter;
 import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter;

+ 1 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.java

@@ -28,6 +28,7 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
         return makeMovementFlags(dragFlags, swipeFlags);
     }
 
+
     @Override
     public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                           RecyclerView.ViewHolder target) {

+ 276 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt

@@ -0,0 +1,276 @@
+package eu.kanade.tachiyomi.ui.category
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.support.v7.view.ActionMode
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.helper.ItemTouchHelper
+import android.view.Menu
+import android.view.MenuItem
+import com.afollestad.materialdialogs.MaterialDialog
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.data.database.models.Category
+import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
+import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
+import eu.kanade.tachiyomi.ui.base.adapter.OnStartDragListener
+import eu.kanade.tachiyomi.ui.library.LibraryCategoryAdapter
+import kotlinx.android.synthetic.main.activity_edit_categories.*
+import kotlinx.android.synthetic.main.toolbar.*
+import nucleus.factory.RequiresPresenter
+
+
+/**
+ * Activity that shows categories.
+ * Uses R.layout.activity_edit_categories.
+ * UI related actions should be called from here.
+ */
+@RequiresPresenter(CategoryPresenter::class)
+class CategoryActivity : BaseRxActivity<CategoryPresenter>(), ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener, OnStartDragListener {
+
+    /**
+     * Object used to show actionMode toolbar.
+     */
+    var actionMode: ActionMode? = null
+
+    /**
+     * Adapter containing category items.
+     */
+    private lateinit var adapter: CategoryAdapter
+
+    /**
+     * TouchHelper used for reorder animation and movement.
+     */
+    private lateinit var touchHelper: ItemTouchHelper
+
+    companion object {
+        /**
+         * Create new CategoryActivity intent.
+         *
+         * @param context context information.
+         */
+        @JvmStatic
+        fun newIntent(context: Context): Intent? {
+            return Intent(context, CategoryActivity::class.java)
+        }
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        // Inflate activity_edit_categories.xml.
+        setContentView(R.layout.activity_edit_categories)
+
+        // Setup the toolbar.
+        setupToolbar(toolbar)
+
+        // Get new adapter.
+        adapter = CategoryAdapter(this)
+
+        // Create view and inject category items into view
+        recycler.layoutManager = LinearLayoutManager(this)
+        recycler.setHasFixedSize(true)
+        recycler.adapter = adapter
+
+        // Touch helper to drag and reorder categories
+        touchHelper = ItemTouchHelper(CategoryItemTouchHelper(adapter))
+        touchHelper.attachToRecyclerView(recycler)
+
+        // Create OnClickListener for creating new category
+        fab.setOnClickListener({ v ->
+            MaterialDialog.Builder(this)
+                    .title(R.string.action_add_category)
+                    .negativeText(R.string.button_cancel)
+                    .input(R.string.name, 0, false)
+                    { dialog, input -> presenter.createCategory(input.toString()) }
+                    .show()
+        })
+    }
+
+    /**
+     * Finishes action mode.
+     * Call this when action mode action is finished.
+     */
+    fun destroyActionModeIfNeeded() {
+            actionMode?.finish()
+    }
+
+    /**
+     * Fill adapter with category items
+     *
+     * @param categories list containing categories
+     */
+    fun setCategories(categories: List<Category>) {
+        destroyActionModeIfNeeded()
+        adapter.setItems(categories)
+    }
+
+    /**
+     * Delete selected categories
+     *
+     * @param categories list containing categories
+     */
+    private fun deleteCategories(categories: List<Category?>?) {
+        presenter.deleteCategories(categories)
+    }
+
+    /**
+     * Returns the selected categories
+     *
+     * @return list of selected categories
+     */
+    private fun getSelectedCategories(): List<Category?>? {
+        // Create a list of the selected categories
+        return adapter.selectedItems.map { adapter.getItem(it) }
+    }
+
+    /**
+     * Show MaterialDialog which let user change category name.
+     *
+     * @param category category that will be edited.
+     */
+    private fun editCategory(category: Category?) {
+        MaterialDialog.Builder(this)
+                .title(R.string.action_rename_category)
+                .negativeText(R.string.button_cancel)
+                .onNegative { materialDialog, dialogAction -> destroyActionModeIfNeeded() }
+                .input(getString(R.string.name), category?.name, false)
+                { dialog, input -> presenter.renameCategory(category as Category, input.toString()) }
+                .show()
+    }
+
+    /**
+     * Toggle actionMode selection
+     *
+     * @param position position of selected item
+     */
+    private fun toggleSelection(position: Int) {
+        adapter.toggleSelection(position, false)
+
+        // Get selected item count
+        val count = adapter.selectedItemCount
+
+        // If no item is selected finish action mode
+        if (count == 0) {
+            actionMode?.finish()
+        } else {
+            // This block will only run if actionMode is not null
+            actionMode?.let {
+
+                // Set title equal to selected item
+                it.title = getString(R.string.label_selected, count)
+                it.invalidate()
+
+                // Show edit button only when one item is selected
+                val editItem = it.menu?.findItem(R.id.action_edit)
+                editItem?.isVisible = count == 1
+            }
+        }
+    }
+
+    /**
+     * Called each time the action mode is shown.
+     * Always called after onCreateActionMode
+     *
+     * @return false
+     */
+    override fun onPrepareActionMode(p0: ActionMode?, p1: Menu?): Boolean {
+        return false
+    }
+
+    /**
+     * Called when action mode item clicked.
+     *
+     * @param actionMode action mode toolbar.
+     * @param menuItem selected menu item.
+     *
+     * @return action mode item clicked exist status
+     */
+    override fun onActionItemClicked(actionMode: ActionMode, menuItem: MenuItem): Boolean {
+        when (menuItem.itemId) {
+            R.id.action_delete -> {
+                // Delete select categories.
+                deleteCategories(getSelectedCategories())
+                return true
+            }
+            R.id.action_edit -> {
+                // Edit selected category
+                editCategory(getSelectedCategories()?.get(0))
+                return true
+            }
+        }
+        return false
+    }
+
+    /**
+     * Inflate menu when action mode selected.
+     *
+     * @param mode ActionMode object
+     * @param menu Menu object
+     *
+     * @return true
+     */
+    override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
+        // Inflate menu.
+        mode.menuInflater.inflate(R.menu.category_selection, menu)
+        // Enable adapter multi selection.
+        adapter.mode = LibraryCategoryAdapter.MODE_MULTI
+        return true
+    }
+
+    /**
+     * Called when action mode destroyed.
+     *
+     * @param mode ActionMode object.
+     */
+    override fun onDestroyActionMode(mode: ActionMode?) {
+        // Reset adapter to single selection
+        adapter.mode = LibraryCategoryAdapter.MODE_SINGLE
+        // Clear selected items
+        adapter.clearSelection()
+        actionMode = null
+    }
+
+    /**
+     * Called when item in list is clicked.
+     *
+     * @param position position of clicked item.
+     */
+    override fun onListItemClick(position: Int): Boolean {
+        // Check if action mode is initialized and selected item exist.
+        if (actionMode != null && position != -1) {
+            // Toggle selection of clicked item.
+            toggleSelection(position)
+            return true
+        } else {
+            return false
+        }
+    }
+
+    /**
+     * Called when item long clicked
+     *
+     * @param position position of clicked item.
+     */
+    override fun onListItemLongClick(position: Int) {
+        // Check if action mode is initialized.
+        if (actionMode == null)
+        // Initialize action mode
+            actionMode = startSupportActionMode(this)
+
+        // Set item as selected
+        toggleSelection(position)
+    }
+
+    /**
+     * Called when item is dragged
+     *
+     * @param viewHolder view that contains dragged item
+     */
+    override fun onStartDrag(viewHolder: RecyclerView.ViewHolder?) {
+        // Notify touchHelper
+        touchHelper.startDrag(viewHolder)
+    }
+
+}

+ 110 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryAdapter.kt

@@ -0,0 +1,110 @@
+package eu.kanade.tachiyomi.ui.category
+
+import android.view.ViewGroup
+import com.amulyakhare.textdrawable.util.ColorGenerator
+import eu.davidea.flexibleadapter.FlexibleAdapter
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.data.database.models.Category
+import eu.kanade.tachiyomi.ui.base.adapter.ItemTouchHelperAdapter
+import eu.kanade.tachiyomi.util.inflate
+import java.util.*
+
+/**
+ * Adapter of CategoryHolder.
+ * Connection between Activity and Holder
+ * Holder updates should be called from here.
+ *
+ * @param activity activity that created adapter
+ * @constructor Creates a CategoryAdapter object
+ */
+class CategoryAdapter(private val activity: CategoryActivity) : FlexibleAdapter<CategoryHolder, Category>(), ItemTouchHelperAdapter {
+
+    /**
+     * Generator used to generate circle letter icons
+     */
+    private val generator: ColorGenerator
+
+    init {
+        // Let generator use Material Design colors.
+        // Material design is love, material design is live!
+        generator = ColorGenerator.MATERIAL
+
+        // Set unique id's
+        setHasStableIds(true)
+    }
+
+    /**
+     * Called when ViewHolder is created
+     *
+     * @param parent parent View
+     * @param viewType int containing viewType
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryHolder {
+        // Inflate layout with item_edit_categories.xml
+        val view = parent.inflate(R.layout.item_edit_categories)
+        return CategoryHolder(view, this, activity, activity)
+    }
+
+    /**
+     * Called when ViewHolder is bind
+     *
+     * @param holder bind holder
+     * @param position position of holder
+     */
+    override fun onBindViewHolder(holder: CategoryHolder, position: Int) {
+        // Update holder values.
+        val category = getItem(position)
+        holder.onSetValues(category, generator)
+
+        //When user scrolls this bind the correct selection status
+        holder.itemView.isActivated = isSelected(position)
+    }
+
+    /**
+     * Update items with list of categories
+     *
+     * @param items list of categories
+     */
+    fun setItems(items: List<Category>) {
+        mItems = ArrayList(items)
+        notifyDataSetChanged()
+    }
+
+    /**
+     * Get category by position
+     *
+     * @param position position of item
+     */
+    override fun getItemId(position: Int): Long {
+        return mItems[position].id!!.toLong()
+    }
+
+    /**
+     * Called when item is moved
+     *
+     * @param fromPosition previous position of item.
+     * @param toPosition new position of item.
+     */
+    override fun onItemMove(fromPosition: Int, toPosition: Int) {
+        // Move items and notify touch helper
+        Collections.swap(mItems, fromPosition, toPosition)
+        notifyItemMoved(fromPosition, toPosition)
+
+        // Update database
+        activity.presenter.reorderCategories(mItems)
+    }
+
+    /**
+     * Must be implemented, not used
+     */
+    override fun onItemDismiss(position: Int) {
+        // Empty method.
+    }
+
+    /**
+     * Must be implemented, not used
+     */
+    override fun updateDataSet(p0: String?) {
+        // Empty method.
+    }
+}

+ 74 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryHolder.kt

@@ -0,0 +1,74 @@
+package eu.kanade.tachiyomi.ui.category
+
+import android.graphics.Color
+import android.graphics.Typeface
+import android.support.v4.view.MotionEventCompat
+import android.view.MotionEvent
+import android.view.View
+import com.amulyakhare.textdrawable.TextDrawable
+import com.amulyakhare.textdrawable.util.ColorGenerator
+import eu.kanade.tachiyomi.data.database.models.Category
+import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
+import eu.kanade.tachiyomi.ui.base.adapter.OnStartDragListener
+import kotlinx.android.synthetic.main.item_edit_categories.view.*
+
+/**
+ * Holder that contains category item.
+ * Uses R.layout.item_edit_categories.
+ * UI related actions should be called from here.
+ *
+ * @param view view of category item.
+ * @param adapter adapter belonging to holder.
+ * @param listener called when item clicked.
+ * @param dragListener called when item dragged.
+ *
+ * @constructor Create CategoryHolder object
+ */
+class CategoryHolder(view: View, adapter: CategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener, dragListener: OnStartDragListener) : FlexibleViewHolder(view, adapter, listener) {
+
+    init {
+        // Create round letter image onclick to simulate long click
+        itemView.image.setOnClickListener({ v ->
+            // Simulate long click on this view to enter selection mode
+            onLongClick(view)
+        })
+
+        // Set on touch listener for reorder image
+        itemView.reorder.setOnTouchListener({ v, event ->
+            if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+                dragListener.onStartDrag(this)
+            }
+            false
+        })
+    }
+
+    /**
+     * Update category item values.
+     *
+     * @param category category of item.
+     * @param generator generator used to generate circle letter icons.
+     */
+    fun onSetValues(category: Category, generator: ColorGenerator) {
+        // Set capitalized title.
+        itemView.title.text = category.name.capitalize()
+
+        // Update circle letter image.
+        itemView.image.setImageDrawable(getRound(category.name.substring(0, 1).toUpperCase(), generator))
+    }
+
+    /**
+     * Returns circle letter image
+     *
+     * @param text first letter of string
+     * @param generator the generator used to generate circle letter image
+     */
+    private fun getRound(text: String, generator: ColorGenerator): TextDrawable {
+        return TextDrawable.builder()
+                .beginConfig()
+                .textColor(Color.WHITE)
+                .useFont(Typeface.DEFAULT)
+                .toUpperCase()
+                .endConfig()
+                .buildRound(text, generator.getColor(text))
+    }
+}

+ 26 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryItemTouchHelper.kt

@@ -0,0 +1,26 @@
+package eu.kanade.tachiyomi.ui.category
+
+import eu.kanade.tachiyomi.ui.base.adapter.ItemTouchHelperAdapter
+import eu.kanade.tachiyomi.ui.base.adapter.SimpleItemTouchHelperCallback
+
+class CategoryItemTouchHelper(adapter: ItemTouchHelperAdapter) : SimpleItemTouchHelperCallback(adapter) {
+
+    /**
+     * Disable items swipe remove
+     *
+     * @return false
+     */
+    override fun isItemViewSwipeEnabled(): Boolean {
+        return false
+    }
+
+    /**
+     * Disable long press item drag
+     *
+     * @return false
+     */
+    override fun isLongPressDragEnabled(): Boolean {
+        return false
+    }
+
+}

+ 106 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryPresenter.kt

@@ -0,0 +1,106 @@
+package eu.kanade.tachiyomi.ui.category
+
+import android.os.Bundle
+import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.tachiyomi.data.database.models.Category
+import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import rx.android.schedulers.AndroidSchedulers
+import javax.inject.Inject
+
+/**
+ * Presenter of CategoryActivity.
+ * Contains information and data for activity.
+ * Observable updates should be called from here.
+ */
+class CategoryPresenter : BasePresenter<CategoryActivity>() {
+
+    /**
+     * Used to connect to database
+     */
+    @Inject lateinit var db: DatabaseHelper
+
+    /**
+     * List containing categories
+     */
+    private var categories: List<Category>? = null
+
+    companion object {
+        /**
+         * The id of the restartable.
+         */
+        final private val GET_CATEGORIES = 1
+    }
+
+    override fun onCreate(savedState: Bundle?) {
+        super.onCreate(savedState)
+
+        // Get categories as list
+        restartableLatestCache(GET_CATEGORIES,
+                {
+                    db.categories.asRxObservable()
+                            .doOnNext { categories -> this.categories = categories }
+                            .observeOn(AndroidSchedulers.mainThread())
+                }, CategoryActivity::setCategories)
+
+        // Start get categories as list task
+        start(GET_CATEGORIES)
+    }
+
+
+    /**
+     * Create category and add it to database
+     *
+     * @param name name of category
+     */
+    fun createCategory(name: String) {
+        // Create category.
+        val cat = Category.create(name)
+
+        // Set the new item in the last position.
+        var max = 0
+        if (categories != null) {
+            for (cat2 in categories!!) {
+                if (cat2.order > max) {
+                    max = cat2.order + 1
+                }
+            }
+        }
+        cat.order = max
+
+        // Insert into database.
+        db.insertCategory(cat).asRxObservable().subscribe()
+    }
+
+    /**
+     * Delete category from database
+     *
+     * @param categories list of categories
+     */
+    fun deleteCategories(categories: List<Category?>?) {
+        db.deleteCategories(categories).asRxObservable().subscribe()
+    }
+
+    /**
+     * Reorder categories in database
+     *
+     * @param categories list of categories
+     */
+    fun reorderCategories(categories: List<Category>) {
+        for (i in categories.indices) {
+            categories[i].order = i
+        }
+
+        db.insertCategories(categories).asRxObservable().subscribe()
+    }
+
+    /**
+     * Rename a category
+     *
+     * @param category category that gets renamed
+     * @param name new name of category
+     */
+    fun renameCategory(category: Category, name: String) {
+        category.name = name
+        db.insertCategory(category).asRxObservable().subscribe()
+    }
+}

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.java

@@ -38,7 +38,7 @@ import eu.kanade.tachiyomi.data.io.IOHandler;
 import eu.kanade.tachiyomi.data.library.LibraryUpdateService;
 import eu.kanade.tachiyomi.event.LibraryMangasEvent;
 import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
-import eu.kanade.tachiyomi.ui.library.category.CategoryActivity;
+import eu.kanade.tachiyomi.ui.category.CategoryActivity;
 import eu.kanade.tachiyomi.ui.main.MainActivity;
 import eu.kanade.tachiyomi.util.ToastUtil;
 import icepick.State;

+ 0 - 180
app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryActivity.java

@@ -1,180 +0,0 @@
-package eu.kanade.tachiyomi.ui.library.category;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.design.widget.FloatingActionButton;
-import android.support.v4.content.res.ResourcesCompat;
-import android.support.v7.view.ActionMode;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
-import android.support.v7.widget.helper.ItemTouchHelper;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import com.afollestad.materialdialogs.MaterialDialog;
-
-import java.util.List;
-
-import butterknife.Bind;
-import butterknife.ButterKnife;
-import eu.kanade.tachiyomi.R;
-import eu.kanade.tachiyomi.data.database.models.Category;
-import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity;
-import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder;
-import eu.kanade.tachiyomi.ui.base.adapter.OnStartDragListener;
-import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration;
-import eu.kanade.tachiyomi.ui.library.LibraryCategoryAdapter;
-import nucleus.factory.RequiresPresenter;
-import rx.Observable;
-
-@RequiresPresenter(CategoryPresenter.class)
-public class CategoryActivity extends BaseRxActivity<CategoryPresenter> implements
-        ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener, OnStartDragListener {
-
-    @Bind(R.id.toolbar) Toolbar toolbar;
-    @Bind(R.id.categories_list) RecyclerView recycler;
-    @Bind(R.id.fab) FloatingActionButton fab;
-
-    private CategoryAdapter adapter;
-    private ActionMode actionMode;
-    private ItemTouchHelper touchHelper;
-
-    public static Intent newIntent(Context context) {
-        return new Intent(context, CategoryActivity.class);
-    }
-
-    @Override
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-        setContentView(R.layout.activity_edit_categories);
-        ButterKnife.bind(this);
-
-        setupToolbar(toolbar);
-
-        adapter = new CategoryAdapter(this);
-        recycler.setLayoutManager(new LinearLayoutManager(this));
-        recycler.setHasFixedSize(true);
-        recycler.setAdapter(adapter);
-        recycler.addItemDecoration(new DividerItemDecoration(
-                ResourcesCompat.getDrawable(getResources(), R.drawable.line_divider, null)));
-
-        // Touch helper to drag and reorder categories
-        touchHelper = new ItemTouchHelper(new CategoryItemTouchHelper(adapter));
-        touchHelper.attachToRecyclerView(recycler);
-
-        fab.setOnClickListener(v -> {
-            new MaterialDialog.Builder(this)
-                    .title(R.string.action_add_category)
-                    .input(R.string.name, 0, false, (dialog, input) -> {
-                        getPresenter().createCategory(input.toString());
-                    })
-                    .show();
-        });
-    }
-
-    public void setCategories(List<Category> categories) {
-        destroyActionModeIfNeeded();
-        adapter.setItems(categories);
-    }
-
-    private List<Category> getSelectedCategories() {
-        // Create a blocking copy of the selected categories
-        return Observable.from(adapter.getSelectedItems())
-                .map(adapter::getItem).toList().toBlocking().single();
-    }
-
-    @Override
-    public boolean onListItemClick(int position) {
-        if (actionMode != null && position != -1) {
-            toggleSelection(position);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public void onListItemLongClick(int position) {
-        if (actionMode == null)
-            actionMode = startSupportActionMode(this);
-
-        toggleSelection(position);
-    }
-
-    private void toggleSelection(int position) {
-        adapter.toggleSelection(position, false);
-
-        int count = adapter.getSelectedItemCount();
-        if (count == 0) {
-            actionMode.finish();
-        } else {
-            setContextTitle(count);
-            actionMode.invalidate();
-            MenuItem editItem = actionMode.getMenu().findItem(R.id.action_edit);
-            editItem.setVisible(count == 1);
-        }
-    }
-
-    private void setContextTitle(int count) {
-        actionMode.setTitle(getString(R.string.label_selected, count));
-    }
-
-    @Override
-    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-        mode.getMenuInflater().inflate(R.menu.category_selection, menu);
-        adapter.setMode(LibraryCategoryAdapter.MODE_MULTI);
-        return true;
-    }
-
-    @Override
-    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-        return false;
-    }
-
-    @Override
-    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.action_delete:
-                deleteCategories(getSelectedCategories());
-                return true;
-            case R.id.action_edit:
-                editCategory(getSelectedCategories().get(0));
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void onDestroyActionMode(ActionMode mode) {
-        adapter.setMode(LibraryCategoryAdapter.MODE_SINGLE);
-        adapter.clearSelection();
-        actionMode = null;
-    }
-
-    public void destroyActionModeIfNeeded() {
-        if (actionMode != null) {
-            actionMode.finish();
-        }
-    }
-
-    private void deleteCategories(List<Category> categories) {
-        getPresenter().deleteCategories(categories);
-    }
-
-    private void editCategory(Category category) {
-        new MaterialDialog.Builder(this)
-                .title(R.string.action_rename_category)
-                .input(getString(R.string.name), category.name, false, (dialog, input) -> {
-                    getPresenter().renameCategory(category, input.toString());
-                })
-                .show();
-    }
-
-    @Override
-    public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
-        touchHelper.startDrag(viewHolder);
-    }
-
-}

+ 0 - 80
app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryAdapter.java

@@ -1,80 +0,0 @@
-package eu.kanade.tachiyomi.ui.library.category;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.amulyakhare.textdrawable.util.ColorGenerator;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import eu.davidea.flexibleadapter.FlexibleAdapter;
-import eu.kanade.tachiyomi.R;
-import eu.kanade.tachiyomi.data.database.models.Category;
-import eu.kanade.tachiyomi.ui.base.adapter.ItemTouchHelperAdapter;
-
-public class CategoryAdapter extends FlexibleAdapter<CategoryHolder, Category> implements
-        ItemTouchHelperAdapter {
-
-    private final CategoryActivity activity;
-    private final ColorGenerator generator;
-
-    public CategoryAdapter(CategoryActivity activity) {
-        this.activity = activity;
-        generator = ColorGenerator.DEFAULT;
-        setHasStableIds(true);
-    }
-
-    public void setItems(List<Category> items) {
-        mItems = new ArrayList<>(items);
-        notifyDataSetChanged();
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return mItems.get(position).id;
-    }
-
-    @Override
-    public void updateDataSet(String param) {
-        
-    }
-
-    @Override
-    public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-        LayoutInflater inflater = activity.getLayoutInflater();
-        View v = inflater.inflate(R.layout.item_edit_categories, parent, false);
-        return new CategoryHolder(v, this, activity, activity);
-    }
-
-    @Override
-    public void onBindViewHolder(CategoryHolder holder, int position) {
-        final Category category = getItem(position);
-        holder.onSetValues(category, generator);
-
-        //When user scrolls this bind the correct selection status
-        holder.itemView.setActivated(isSelected(position));
-    }
-
-    @Override
-    public void onItemMove(int fromPosition, int toPosition) {
-        if (fromPosition < toPosition) {
-            for (int i = fromPosition; i < toPosition; i++) {
-                Collections.swap(mItems, i, i + 1);
-            }
-        } else {
-            for (int i = fromPosition; i > toPosition; i--) {
-                Collections.swap(mItems, i, i - 1);
-            }
-        }
-
-        activity.getPresenter().reorderCategories(mItems);
-    }
-
-    @Override
-    public void onItemDismiss(int position) {
-
-    }
-}

+ 0 - 58
app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryHolder.java

@@ -1,58 +0,0 @@
-package eu.kanade.tachiyomi.ui.library.category;
-
-import android.support.v4.view.MotionEventCompat;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.amulyakhare.textdrawable.TextDrawable;
-import com.amulyakhare.textdrawable.util.ColorGenerator;
-
-import butterknife.Bind;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import eu.kanade.tachiyomi.R;
-import eu.kanade.tachiyomi.data.database.models.Category;
-import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder;
-import eu.kanade.tachiyomi.ui.base.adapter.OnStartDragListener;
-
-public class CategoryHolder extends FlexibleViewHolder {
-
-    private View view;
-
-    @Bind(R.id.image) ImageView image;
-    @Bind(R.id.title) TextView title;
-    @Bind(R.id.reorder) ImageView reorder;
-
-    public CategoryHolder(View view, CategoryAdapter adapter,
-                          OnListItemClickListener listener, OnStartDragListener dragListener) {
-        super(view, adapter, listener);
-        ButterKnife.bind(this, view);
-        this.view = view;
-
-        reorder.setOnTouchListener((v, event) -> {
-            if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
-                dragListener.onStartDrag(this);
-                return true;
-            }
-            return false;
-        });
-    }
-
-    public void onSetValues(Category category, ColorGenerator generator) {
-        title.setText(category.name);
-        image.setImageDrawable(getRound(category.name.substring(0, 1), generator));
-    }
-
-    private TextDrawable getRound(String text, ColorGenerator generator) {
-        return TextDrawable.builder().buildRound(text, generator.getColor(text));
-    }
-
-    @OnClick(R.id.image)
-    void onImageClick() {
-        // Simulate long click on this view to enter selection mode
-        onLongClick(view);
-    }
-
-}

+ 0 - 16
app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryItemTouchHelper.java

@@ -1,16 +0,0 @@
-package eu.kanade.tachiyomi.ui.library.category;
-
-import eu.kanade.tachiyomi.ui.base.adapter.ItemTouchHelperAdapter;
-import eu.kanade.tachiyomi.ui.base.adapter.SimpleItemTouchHelperCallback;
-
-public class CategoryItemTouchHelper extends SimpleItemTouchHelperCallback {
-
-    public CategoryItemTouchHelper(ItemTouchHelperAdapter adapter) {
-        super(adapter);
-    }
-
-    @Override
-    public boolean isItemViewSwipeEnabled() {
-        return false;
-    }
-}

+ 0 - 68
app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryPresenter.java

@@ -1,68 +0,0 @@
-package eu.kanade.tachiyomi.ui.library.category;
-
-import android.os.Bundle;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import eu.kanade.tachiyomi.data.database.DatabaseHelper;
-import eu.kanade.tachiyomi.data.database.models.Category;
-import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter;
-import rx.android.schedulers.AndroidSchedulers;
-
-public class CategoryPresenter extends BasePresenter<CategoryActivity> {
-
-    @Inject DatabaseHelper db;
-
-    private List<Category> categories;
-
-    private static final int GET_CATEGORIES = 1;
-
-    @Override
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-
-        restartableLatestCache(GET_CATEGORIES,
-                () -> db.getCategories().asRxObservable()
-                        .doOnNext(categories -> this.categories = categories)
-                        .observeOn(AndroidSchedulers.mainThread()),
-                CategoryActivity::setCategories);
-
-        start(GET_CATEGORIES);
-    }
-
-    public void createCategory(String name) {
-        Category cat = Category.create(name);
-
-        // Set the new item in the last position
-        int max = 0;
-        if (categories != null) {
-            for (Category cat2 : categories) {
-                if (cat2.order > max) {
-                    max = cat2.order + 1;
-                }
-            }
-        }
-        cat.order = max;
-
-        db.insertCategory(cat).asRxObservable().subscribe();
-    }
-
-    public void deleteCategories(List<Category> categories) {
-        db.deleteCategories(categories).asRxObservable().subscribe();
-    }
-
-    public void reorderCategories(List<Category> categories) {
-        for (int i = 0; i < categories.size(); i++) {
-            categories.get(i).order = i;
-        }
-
-        db.insertCategories(categories).asRxObservable().subscribe();
-    }
-
-    public void renameCategory(Category category, String name) {
-        category.name = name;
-        db.insertCategory(category).asRxObservable().subscribe();
-    }
-}

+ 15 - 0
app/src/main/java/eu/kanade/tachiyomi/util/ViewGroupExtensions.kt

@@ -0,0 +1,15 @@
+package eu.kanade.tachiyomi.util
+
+import android.support.annotation.LayoutRes
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+/**
+ * Extension method to inflate a view directly from its parent.
+ * @param layout the layout to inflate.
+ * @param attachToRoot whether to attach the view to the root or not. Defaults to false.
+ */
+fun ViewGroup.inflate(@LayoutRes layout: Int, attachToRoot: Boolean = false): View {
+    return LayoutInflater.from(context).inflate(layout, this, attachToRoot)
+}

BIN
app/src/main/res/drawable-hdpi/ic_action_reorder.png


BIN
app/src/main/res/drawable-hdpi/ic_reorder_grey_600_24dp.png


BIN
app/src/main/res/drawable-ldpi/ic_reorder_grey_600_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_action_reorder.png


BIN
app/src/main/res/drawable-mdpi/ic_reorder_grey_600_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_action_reorder.png


BIN
app/src/main/res/drawable-xhdpi/ic_reorder_grey_600_24dp.png


BIN
app/src/main/res/drawable-xxhdpi/ic_action_reorder.png


BIN
app/src/main/res/drawable-xxhdpi/ic_reorder_grey_600_24dp.png


BIN
app/src/main/res/drawable-xxxhdpi/ic_action_reorder.png


BIN
app/src/main/res/drawable-xxxhdpi/ic_reorder_grey_600_24dp.png


+ 5 - 3
app/src/main/res/layout/activity_edit_categories.xml

@@ -4,6 +4,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    xmlns:tools="http://schemas.android.com/tools"
     android:gravity="center">
 
     <include layout="@layout/toolbar"/>
@@ -12,9 +13,10 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_marginTop="?attr/actionBarSize"
-        android:id="@+id/categories_list"
+        android:id="@+id/recycler"
         android:choiceMode="multipleChoice"
-        android:listSelector="@color/list_choice_pressed_bg_light" />
+        android:listSelector="@color/list_choice_pressed_bg_light"
+        tools:listitem="@layout/item_edit_categories"/>
 
     <android.support.design.widget.FloatingActionButton
         android:id="@+id/fab"
@@ -25,7 +27,7 @@
         android:scaleType="fitCenter"
         android:src="@drawable/ic_add_white_24dp"
         app:backgroundTint="@color/colorPrimary"
-        app:layout_anchor="@id/categories_list"
+        app:layout_anchor="@id/recycler"
         app:layout_anchorGravity="bottom|right|end"
         app:layout_behavior="eu.kanade.tachiyomi.ui.base.fab.FABAnimationUpDown"/>
 

+ 5 - 4
app/src/main/res/layout/item_edit_categories.xml

@@ -3,8 +3,8 @@
                 xmlns:tools="http://schemas.android.com/tools"
                 android:layout_width="match_parent"
                 android:layout_height="?android:attr/listPreferredItemHeightLarge"
-                android:paddingTop="@dimen/margin_top"
-                android:paddingBottom="@dimen/margin_bottom"
+                android:paddingTop="8dp"
+                android:paddingBottom="8dp"
                 android:background="@drawable/selector_chapter_light">
 
     <ImageView
@@ -14,7 +14,6 @@
         android:layout_alignParentLeft="true"
         android:layout_alignParentStart="true"
         android:layout_centerInParent="true"
-        android:elevation="4dp"
         android:clickable="true"
         android:layout_marginLeft="@dimen/margin_left"
         android:layout_marginStart="@dimen/margin_left"
@@ -30,8 +29,10 @@
         android:layout_marginRight="@dimen/margin_right"
         android:layout_marginEnd="@dimen/margin_right"
         android:scaleType="center"
+        android:layout_centerInParent="true"
         android:layout_alignParentRight="true"
-        android:src="@drawable/ic_reorder_grey_600_24dp"/>
+        android:layout_alignParentEnd="true"
+        android:src="@drawable/ic_action_reorder"/>
 
     <TextView
         android:id="@+id/title"