Browse Source

Refactor and convert to Kotlin base classes. Fix FAB behavior

len 9 years ago
parent
commit
e881488bcc
25 changed files with 342 additions and 521 deletions
  1. 4 1
      app/build.gradle
  2. 75 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/ActivityMixin.kt
  3. 2 69
      app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
  4. 0 94
      app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.java
  5. 24 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt
  6. 0 48
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.java
  7. 39 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.kt
  8. 0 57
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.java
  9. 36 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.kt
  10. 0 13
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.java
  11. 13 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.kt
  12. 0 44
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.java
  13. 28 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.kt
  14. 0 48
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.java
  15. 41 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.kt
  16. 11 9
      app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationBase.kt
  17. 18 22
      app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationUpDown.kt
  18. 2 14
      app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseFragment.kt
  19. 0 97
      app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java
  20. 21 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.kt
  21. 22 0
      app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/FragmentMixin.kt
  22. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt
  23. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt
  24. 2 1
      app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt
  25. 1 1
      build.gradle

+ 4 - 1
app/build.gradle

@@ -92,6 +92,7 @@ dependencies {
     final DAGGER_VERSION = '2.2'
     final OKHTTP_VERSION = '3.2.0'
     final RETROFIT_VERSION = '2.0.1'
+    final NUCLEUS_VERSION = '3.0.0-beta'
     final STORIO_VERSION = '1.8.0'
     final MOCKITO_VERSION = '1.10.19'
 
@@ -142,7 +143,9 @@ dependencies {
     kapt "com.pushtorefresh.storio:sqlite-annotations-processor:$STORIO_VERSION"
 
     // Model View Presenter
-    compile 'info.android15.nucleus:nucleus:3.0.0-beta'
+    compile "info.android15.nucleus:nucleus:$NUCLEUS_VERSION"
+    compile "info.android15.nucleus:nucleus-support-v4:$NUCLEUS_VERSION"
+    compile "info.android15.nucleus:nucleus-support-v7:$NUCLEUS_VERSION"
 
     // Dependency injection
     compile "com.google.dagger:dagger:$DAGGER_VERSION"

+ 75 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/ActivityMixin.kt

@@ -0,0 +1,75 @@
+package eu.kanade.tachiyomi.ui.base.activity
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Build
+import android.support.v4.app.ActivityCompat
+import android.support.v4.content.ContextCompat
+import android.support.v7.app.ActionBar
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.Toolbar
+import eu.kanade.tachiyomi.App
+import eu.kanade.tachiyomi.R
+
+interface ActivityMixin {
+
+    fun setupToolbar(toolbar: Toolbar, backNavigation: Boolean = true) {
+        setSupportActionBar(toolbar)
+        getSupportActionBar()?.setDisplayHomeAsUpEnabled(true)
+        if (backNavigation) {
+            toolbar.setNavigationOnClickListener { onBackPressed() }
+        }
+    }
+
+    fun setAppTheme() {
+        setTheme(when (App.get(getActivity()).appTheme) {
+            2 -> R.style.Theme_Tachiyomi_Dark
+            else -> R.style.Theme_Tachiyomi
+        })
+    }
+
+    fun setToolbarTitle(title: String) {
+        getSupportActionBar()?.title = title
+    }
+
+    fun setToolbarTitle(titleResource: Int) {
+        getSupportActionBar()?.title = getString(titleResource)
+    }
+
+    fun setToolbarSubtitle(title: String) {
+        getSupportActionBar()?.subtitle = title
+    }
+
+    fun setToolbarSubtitle(titleResource: Int) {
+        getSupportActionBar()?.subtitle = getString(titleResource)
+    }
+
+    /**
+     * Requests read and write permissions on Android M and higher.
+     */
+    fun requestPermissionsOnMarshmallow() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (ContextCompat.checkSelfPermission(getActivity(),
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+
+                ActivityCompat.requestPermissions(getActivity(),
+                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
+                        1)
+
+            }
+        }
+    }
+
+    fun getActivity(): AppCompatActivity
+
+    fun onBackPressed()
+
+    fun getSupportActionBar(): ActionBar?
+
+    fun setSupportActionBar(toolbar: Toolbar?)
+
+    fun setTheme(resource: Int)
+
+    fun getString(resource: Int): String
+
+}

+ 2 - 69
app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt

@@ -1,76 +1,9 @@
 package eu.kanade.tachiyomi.ui.base.activity
 
-import android.Manifest
-import android.content.pm.PackageManager
-import android.graphics.Color
-import android.os.Build
-import android.support.design.widget.Snackbar
-import android.support.v4.app.ActivityCompat
-import android.support.v4.content.ContextCompat
 import android.support.v7.app.AppCompatActivity
-import android.support.v7.widget.Toolbar
-import android.view.View
-import android.widget.TextView
-import eu.kanade.tachiyomi.App
-import eu.kanade.tachiyomi.R
 
-open class BaseActivity : AppCompatActivity() {
+abstract class BaseActivity : AppCompatActivity(), ActivityMixin {
 
-    protected fun setupToolbar(toolbar: Toolbar, backNavigation: Boolean = true) {
-        setSupportActionBar(toolbar)
-        supportActionBar?.setDisplayHomeAsUpEnabled(true)
-        if (backNavigation) {
-            toolbar.setNavigationOnClickListener { onBackPressed() }
-        }
-    }
+    override fun getActivity() = this
 
-    fun setAppTheme() {
-        when (app.appTheme) {
-            2 -> setTheme(R.style.Theme_Tachiyomi_Dark)
-            else -> setTheme(R.style.Theme_Tachiyomi)
-        }
-    }
-
-    fun setToolbarTitle(title: String) {
-        supportActionBar?.title = title
-    }
-
-    fun setToolbarTitle(titleResource: Int) {
-        supportActionBar?.title = getString(titleResource)
-    }
-
-    fun setToolbarSubtitle(title: String) {
-        supportActionBar?.subtitle = title
-    }
-
-    fun setToolbarSubtitle(titleResource: Int) {
-        supportActionBar?.subtitle = getString(titleResource)
-    }
-
-    /**
-     * Requests read and write permissions on Android M and higher.
-     */
-    fun requestPermissionsOnMarshmallow() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            if (ContextCompat.checkSelfPermission(this,
-                    Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
-
-                ActivityCompat.requestPermissions(this,
-                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
-                        1)
-
-            }
-        }
-    }
-
-    protected val app: App
-        get() = App.get(this)
-
-    inline fun View.snack(message: String, length: Int = Snackbar.LENGTH_LONG, f: Snackbar.() -> Unit) {
-        val snack = Snackbar.make(this, message, length)
-        val textView = snack.view.findViewById(android.support.design.R.id.snackbar_text) as TextView
-        textView.setTextColor(Color.WHITE)
-        snack.f()
-        snack.show()
-    }
 }

+ 0 - 94
app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.java

@@ -1,94 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.activity;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-
-import eu.kanade.tachiyomi.App;
-import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter;
-import nucleus.factory.PresenterFactory;
-import nucleus.factory.ReflectionPresenterFactory;
-import nucleus.presenter.Presenter;
-import nucleus.view.PresenterLifecycleDelegate;
-import nucleus.view.ViewWithPresenter;
-
-/**
- * This class is an example of how an activity could controls it's presenter.
- * You can inherit from this class or copy/paste this class's code to
- * create your own view implementation.
- *
- * @param <P> a type of presenter to return with {@link #getPresenter}.
- */
-public abstract class BaseRxActivity<P extends Presenter> extends BaseActivity implements ViewWithPresenter<P> {
-
-    private static final String PRESENTER_STATE_KEY = "presenter_state";
-
-    private final PresenterLifecycleDelegate<P> presenterDelegate =
-            new PresenterLifecycleDelegate<>(ReflectionPresenterFactory.<P>fromViewClass(getClass()));
-
-    /**
-     * Returns a current presenter factory.
-     */
-    public PresenterFactory<P> getPresenterFactory() {
-        return presenterDelegate.getPresenterFactory();
-    }
-
-    /**
-     * Sets a presenter factory.
-     * Call this method before onCreate/onFinishInflate to override default {@link ReflectionPresenterFactory} presenter factory.
-     * Use this method for presenter dependency injection.
-     */
-    @Override
-    public void setPresenterFactory(PresenterFactory<P> presenterFactory) {
-        presenterDelegate.setPresenterFactory(presenterFactory);
-    }
-
-    /**
-     * Returns a current attached presenter.
-     * This method is guaranteed to return a non-null value between
-     * onResume/onPause and onAttachedToWindow/onDetachedFromWindow calls
-     * if the presenter factory returns a non-null value.
-     *
-     * @return a currently attached presenter or null.
-     */
-    public P getPresenter() {
-        return presenterDelegate.getPresenter();
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        final PresenterFactory<P> superFactory = getPresenterFactory();
-        setPresenterFactory(new PresenterFactory<P>() {
-            @Override
-            public P createPresenter() {
-                P presenter = superFactory.createPresenter();
-                App app = (App) getApplication();
-                app.getComponentReflection().inject(presenter);
-                ((BasePresenter) presenter).setContext(app.getApplicationContext());
-                return presenter;
-            }
-        });
-
-        super.onCreate(savedInstanceState);
-        if (savedInstanceState != null)
-            presenterDelegate.onRestoreInstanceState(savedInstanceState.getBundle(PRESENTER_STATE_KEY));
-    }
-
-    @Override
-    protected void onSaveInstanceState(@NonNull Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putBundle(PRESENTER_STATE_KEY, presenterDelegate.onSaveInstanceState());
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        presenterDelegate.onResume(this);
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        presenterDelegate.onDropView();
-        presenterDelegate.onDestroy(!isChangingConfigurations());
-    }
-}

+ 24 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt

@@ -0,0 +1,24 @@
+package eu.kanade.tachiyomi.ui.base.activity
+
+import android.os.Bundle
+import eu.kanade.tachiyomi.App
+import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import nucleus.view.NucleusAppCompatActivity
+
+abstract class BaseRxActivity<P : BasePresenter<*>> : NucleusAppCompatActivity<P>(), ActivityMixin {
+
+    override fun onCreate(savedState: Bundle?) {
+        val superFactory = presenterFactory
+        setPresenterFactory {
+            superFactory.createPresenter().apply {
+                val app = application as App
+                app.componentReflection.inject(this)
+                context = app.applicationContext
+            }
+        }
+        super.onCreate(savedState)
+    }
+
+    override fun getActivity() = this
+
+}

+ 0 - 48
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.java

@@ -1,48 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.adapter;
-
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-
-import eu.davidea.flexibleadapter.FlexibleAdapter;
-
-public abstract class FlexibleViewHolder extends RecyclerView.ViewHolder
-        implements View.OnClickListener, View.OnLongClickListener {
-
-    private final FlexibleAdapter adapter;
-    private final OnListItemClickListener onListItemClickListener;
-
-    public FlexibleViewHolder(View itemView,FlexibleAdapter adapter,
-                              OnListItemClickListener onListItemClickListener) {
-        super(itemView);
-        this.adapter = adapter;
-
-        this.onListItemClickListener = onListItemClickListener;
-
-        this.itemView.setOnClickListener(this);
-        this.itemView.setOnLongClickListener(this);
-    }
-
-    @Override
-    public void onClick(View view) {
-        if (onListItemClickListener.onListItemClick(getAdapterPosition())) {
-            toggleActivation();
-        }
-    }
-
-    @Override
-    public boolean onLongClick(View view) {
-        onListItemClickListener.onListItemLongClick(getAdapterPosition());
-        toggleActivation();
-        return true;
-    }
-
-    protected void toggleActivation() {
-        itemView.setActivated(adapter.isSelected(getAdapterPosition()));
-    }
-
-    public interface OnListItemClickListener {
-        boolean onListItemClick(int position);
-        void onListItemLongClick(int position);
-    }
-
-}

+ 39 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.kt

@@ -0,0 +1,39 @@
+package eu.kanade.tachiyomi.ui.base.adapter
+
+import android.support.v7.widget.RecyclerView
+import android.view.View
+
+import eu.davidea.flexibleadapter.FlexibleAdapter
+
+abstract class FlexibleViewHolder(view: View,
+                                  private val adapter: FlexibleAdapter<*, *>,
+                                  private val itemClickListener: FlexibleViewHolder.OnListItemClickListener) :
+        RecyclerView.ViewHolder(view), View.OnClickListener, View.OnLongClickListener {
+
+    init {
+        view.setOnClickListener(this)
+        view.setOnLongClickListener(this)
+    }
+
+    override fun onClick(view: View) {
+        if (itemClickListener.onListItemClick(adapterPosition)) {
+            toggleActivation()
+        }
+    }
+
+    override fun onLongClick(view: View): Boolean {
+        itemClickListener.onListItemLongClick(adapterPosition)
+        toggleActivation()
+        return true
+    }
+
+    protected fun toggleActivation() {
+        itemView.isActivated = adapter.isSelected(adapterPosition)
+    }
+
+    interface OnListItemClickListener {
+        fun onListItemClick(position: Int): Boolean
+        fun onListItemLongClick(position: Int)
+    }
+
+}

+ 0 - 57
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.java

@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2015 Paul Burke
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package eu.kanade.tachiyomi.ui.base.adapter;
-
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
-
-/**
- * Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}.
- *
- * @author Paul Burke (ipaulpro)
- */
-public interface ItemTouchHelperAdapter {
-
-    /**
-     * Called when an item has been dragged far enough to trigger a move. This is called every time
-     * an item is shifted, and <strong>not</strong> at the end of a "drop" event.<br/>
-     * <br/>
-     * Implementations should call {@link RecyclerView.Adapter#notifyItemMoved(int, int)} after
-     * adjusting the underlying data to reflect this move.
-     *
-     * @param fromPosition The start position of the moved item.
-     * @param toPosition   Then resolved position of the moved item.
-     *
-     * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
-     * @see RecyclerView.ViewHolder#getAdapterPosition()
-     */
-    void onItemMove(int fromPosition, int toPosition);
-
-
-    /**
-     * Called when an item has been dismissed by a swipe.<br/>
-     * <br/>
-     * Implementations should call {@link RecyclerView.Adapter#notifyItemRemoved(int)} after
-     * adjusting the underlying data to reflect this removal.
-     *
-     * @param position The position of the item dismissed.
-     *
-     * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
-     * @see RecyclerView.ViewHolder#getAdapterPosition()
-     */
-    void onItemDismiss(int position);
-}

+ 36 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.kt

@@ -0,0 +1,36 @@
+package eu.kanade.tachiyomi.ui.base.adapter
+
+/**
+ * Interface to listen for a move or dismissal event from a [ItemTouchHelper.Callback].
+ *
+ * @author Paul Burke (ipaulpro)
+ */
+interface ItemTouchHelperAdapter {
+
+    /**
+     * Called when an item has been dragged far enough to trigger a move. This is called every time
+     * an item is shifted, and **not** at the end of a "drop" event.
+     *
+     * Implementations should call [RecyclerView.Adapter.notifyItemMoved] after
+     * adjusting the underlying data to reflect this move.
+     *
+     * @param fromPosition The start position of the moved item.
+     * @param toPosition   Then resolved position of the moved item.
+     * @see [RecyclerView.getAdapterPositionFor]
+     * @see [RecyclerView.ViewHolder.getAdapterPosition]
+     */
+    fun onItemMove(fromPosition: Int, toPosition: Int)
+
+
+    /**
+     * Called when an item has been dismissed by a swipe.
+     *
+     * Implementations should call [RecyclerView.Adapter.notifyItemRemoved] after
+     * adjusting the underlying data to reflect this removal.
+     *
+     * @param position The position of the item dismissed.
+     * @see RecyclerView.getAdapterPositionFor
+     * @see RecyclerView.ViewHolder.getAdapterPosition
+     */
+    fun onItemDismiss(position: Int)
+}

+ 0 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.java

@@ -1,13 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.adapter;
-
-import android.support.v7.widget.RecyclerView;
-
-public interface OnStartDragListener {
-
-    /**
-     * Called when a view is requesting a start of a drag.
-     *
-     * @param viewHolder The holder of the view to drag.
-     */
-    void onStartDrag(RecyclerView.ViewHolder viewHolder);
-}

+ 13 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.kt

@@ -0,0 +1,13 @@
+package eu.kanade.tachiyomi.ui.base.adapter
+
+import android.support.v7.widget.RecyclerView
+
+interface OnStartDragListener {
+
+    /**
+     * Called when a view is requesting a start of a drag.
+     *
+     * @param viewHolder The holder of the view to drag.
+     */
+    fun onStartDrag(viewHolder: RecyclerView.ViewHolder)
+}

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

@@ -1,44 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.adapter;
-
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
-
-public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
-
-    private final ItemTouchHelperAdapter adapter;
-
-    public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
-        this.adapter = adapter;
-    }
-
-    @Override
-    public boolean isLongPressDragEnabled() {
-        return true;
-    }
-
-    @Override
-    public boolean isItemViewSwipeEnabled() {
-        return true;
-    }
-
-    @Override
-    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
-        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
-        int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
-        return makeMovementFlags(dragFlags, swipeFlags);
-    }
-
-
-    @Override
-    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
-                          RecyclerView.ViewHolder target) {
-        adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
-        return true;
-    }
-
-    @Override
-    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
-        adapter.onItemDismiss(viewHolder.getAdapterPosition());
-    }
-
-}

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

@@ -0,0 +1,28 @@
+package eu.kanade.tachiyomi.ui.base.adapter
+
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.helper.ItemTouchHelper
+
+open class SimpleItemTouchHelperCallback(private val adapter: ItemTouchHelperAdapter) : ItemTouchHelper.Callback() {
+
+    override fun isLongPressDragEnabled() = true
+
+    override fun isItemViewSwipeEnabled() = true
+
+    override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
+        val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
+        val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END
+        return ItemTouchHelper.Callback.makeMovementFlags(dragFlags, swipeFlags)
+    }
+
+    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
+                        target: RecyclerView.ViewHolder): Boolean {
+        adapter.onItemMove(viewHolder.adapterPosition, target.adapterPosition)
+        return true
+    }
+
+    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+        adapter.onItemDismiss(viewHolder.adapterPosition)
+    }
+
+}

+ 0 - 48
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.java

@@ -1,48 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.adapter;
-
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentStatePagerAdapter;
-import android.util.SparseArray;
-import android.view.ViewGroup;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
-    // Sparse array to keep track of registered fragments in memory
-    private final SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
-
-    public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
-        super(fragmentManager);
-    }
-
-    // Register the fragment when the item is instantiated
-    @Override
-    public Object instantiateItem(ViewGroup container, int position) {
-        Fragment fragment = (Fragment) super.instantiateItem(container, position);
-        registeredFragments.put(position, fragment);
-        return fragment;
-    }
-
-    // Unregister when the item is inactive
-    @Override
-    public void destroyItem(ViewGroup container, int position, Object object) {
-        registeredFragments.remove(position);
-        super.destroyItem(container, position, object);
-    }
-
-    // Returns the fragment for the position (if instantiated)
-    public Fragment getRegisteredFragment(int position) {
-        return registeredFragments.get(position);
-    }
-
-    public List<Fragment> getRegisteredFragments() {
-        ArrayList<Fragment> fragments = new ArrayList<>();
-        for (int i = 0; i < registeredFragments.size(); i++) {
-            fragments.add(registeredFragments.valueAt(i));
-        }
-        return fragments;
-    }
-
-}

+ 41 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.kt

@@ -0,0 +1,41 @@
+package eu.kanade.tachiyomi.ui.base.adapter
+
+import android.support.v4.app.Fragment
+import android.support.v4.app.FragmentManager
+import android.support.v4.app.FragmentStatePagerAdapter
+import android.util.SparseArray
+import android.view.ViewGroup
+import java.util.*
+
+abstract class SmartFragmentStatePagerAdapter(fragmentManager: FragmentManager) :
+        FragmentStatePagerAdapter(fragmentManager) {
+    // Sparse array to keep track of registered fragments in memory
+    private val registeredFragments = SparseArray<Fragment>()
+
+    // Register the fragment when the item is instantiated
+    override fun instantiateItem(container: ViewGroup, position: Int): Any {
+        val fragment = super.instantiateItem(container, position) as Fragment
+        registeredFragments.put(position, fragment)
+        return fragment
+    }
+
+    // Unregister when the item is inactive
+    override fun destroyItem(container: ViewGroup?, position: Int, `object`: Any) {
+        registeredFragments.remove(position)
+        super.destroyItem(container, position, `object`)
+    }
+
+    // Returns the fragment for the position (if instantiated)
+    fun getRegisteredFragment(position: Int): Fragment {
+        return registeredFragments.get(position)
+    }
+
+    fun getRegisteredFragments(): List<Fragment> {
+        val fragments = ArrayList<Fragment>()
+        for (i in 0..registeredFragments.size() - 1) {
+            fragments.add(registeredFragments.valueAt(i))
+        }
+        return fragments
+    }
+
+}

+ 11 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationBase.kt

@@ -5,27 +5,29 @@ import android.support.design.widget.FloatingActionButton
 import android.support.v4.view.ViewCompat
 import android.view.View
 
-open class FABAnimationBase() : FloatingActionButton.Behavior()
-{
-    open val mIsAnimatingOut = false;
+abstract class FABAnimationBase() : FloatingActionButton.Behavior() {
 
-    override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout?, child: FloatingActionButton?, directTargetChild: View?, target: View?, nestedScrollAxes: Int): Boolean {
+    var isAnimatingOut = false
+
+    override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: FloatingActionButton,
+                                     directTargetChild: View, target: View, nestedScrollAxes: Int): Boolean {
         // Ensure we react to vertical scrolling
         return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
                 super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes)
     }
 
-    override fun onNestedScroll(coordinatorLayout: CoordinatorLayout?, child: FloatingActionButton?, target: View?, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
+    override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: FloatingActionButton, target: View,
+                                dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
         super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
-        if (dyConsumed > 0 && !this.mIsAnimatingOut && child!!.visibility == View.VISIBLE) {
+        if (dyConsumed > 0 && !isAnimatingOut && child.visibility == View.VISIBLE) {
             // User scrolled down and the FAB is currently visible -> hide the FAB
             animateOut(child)
-        } else if (dyConsumed < 0 && child!!.visibility != View.VISIBLE) {
+        } else if (dyConsumed < 0 && child.visibility != View.VISIBLE) {
             // User scrolled up and the FAB is currently not visible -> show the FAB
             animateIn(child)
         }
     }
 
-    open fun animateOut(button : FloatingActionButton) {}
-    open fun animateIn(button : FloatingActionButton) {}
+    abstract fun animateOut(button: FloatingActionButton)
+    abstract fun animateIn(button: FloatingActionButton)
 }

+ 18 - 22
app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationUpDown.kt

@@ -9,46 +9,42 @@ import android.view.animation.Animation
 import android.view.animation.AnimationUtils
 import eu.kanade.tachiyomi.R
 
-class FABAnimationUpDown() : FABAnimationBase()
-{
-    override var mIsAnimatingOut: Boolean = false
-        get() = super.mIsAnimatingOut
+class FABAnimationUpDown @JvmOverloads constructor(ctx: Context, attrs: AttributeSet? = null) : FABAnimationBase() {
 
     private val INTERPOLATOR = FastOutSlowInInterpolator()
 
-    /**
-     * Needed to prevent NoSuchMethodException
-     */
-    constructor(ctx: Context, attrs: AttributeSet) : this() { }
+    private val outAnimation by lazy {
+        AnimationUtils.loadAnimation(ctx, R.anim.fab_hide_to_bottom).apply {
+            duration = 200
+            interpolator = INTERPOLATOR
+        }
+    }
+    private val inAnimation by lazy {
+        AnimationUtils.loadAnimation(ctx, R.anim.fab_show_from_bottom).apply {
+            duration = 200
+            interpolator = INTERPOLATOR
+        }
+    }
 
     override fun animateOut(button: FloatingActionButton) {
-        super.animateIn(button)
-        val anim = AnimationUtils.loadAnimation(button.context, R.anim.fab_hide_to_bottom)
-        anim.interpolator = INTERPOLATOR
-        anim.duration = 200L
-        anim.setAnimationListener(object : Animation.AnimationListener {
+        outAnimation.setAnimationListener(object : Animation.AnimationListener {
             override fun onAnimationStart(animation: Animation) {
-                mIsAnimatingOut = true
+                isAnimatingOut = true
             }
 
             override fun onAnimationEnd(animation: Animation) {
-                mIsAnimatingOut = false
+                isAnimatingOut = false
                 button.visibility = View.GONE
             }
 
             override fun onAnimationRepeat(animation: Animation) {
             }
         })
-        button.startAnimation(anim)
-
+        button.startAnimation(outAnimation)
     }
 
     override fun animateIn(button: FloatingActionButton) {
-        super.animateOut(button)
         button.visibility = View.VISIBLE
-        val anim = AnimationUtils.loadAnimation(button.context, R.anim.fab_show_from_bottom)
-        anim.duration = 200L
-        anim.interpolator = INTERPOLATOR
-        button.startAnimation(anim)
+        button.startAnimation(inAnimation)
     }
 }

+ 2 - 14
app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseFragment.kt

@@ -1,19 +1,7 @@
 package eu.kanade.tachiyomi.ui.base.fragment
 
 import android.support.v4.app.Fragment
-import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
 
-open class BaseFragment : Fragment() {
+abstract class BaseFragment : Fragment(), FragmentMixin {
 
-    fun setToolbarTitle(title: String) {
-        baseActivity.setToolbarTitle(title)
-    }
-
-    fun setToolbarTitle(resourceId: Int) {
-        baseActivity.setToolbarTitle(getString(resourceId))
-    }
-
-    val baseActivity: BaseActivity
-        get() = activity as BaseActivity
-
-}
+}

+ 0 - 97
app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java

@@ -1,97 +0,0 @@
-package eu.kanade.tachiyomi.ui.base.fragment;
-
-import android.os.Bundle;
-
-import eu.kanade.tachiyomi.App;
-import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter;
-import nucleus.factory.PresenterFactory;
-import nucleus.factory.ReflectionPresenterFactory;
-import nucleus.presenter.Presenter;
-import nucleus.view.PresenterLifecycleDelegate;
-import nucleus.view.ViewWithPresenter;
-
-/**
- * This view is an example of how a view should control it's presenter.
- * You can inherit from this class or copy/paste this class's code to
- * create your own view implementation.
- *
- * @param <P> a type of presenter to return with {@link #getPresenter}.
- */
-public abstract class BaseRxFragment<P extends Presenter> extends BaseFragment implements ViewWithPresenter<P> {
-
-    private static final String PRESENTER_STATE_KEY = "presenter_state";
-    private final PresenterLifecycleDelegate<P> presenterDelegate =
-            new PresenterLifecycleDelegate<>(ReflectionPresenterFactory.<P>fromViewClass(getClass()));
-
-    /**
-     * Returns a current presenter factory.
-     */
-    public PresenterFactory<P> getPresenterFactory() {
-        return presenterDelegate.getPresenterFactory();
-    }
-
-    /**
-     * Sets a presenter factory.
-     * Call this method before onCreate/onFinishInflate to override default {@link ReflectionPresenterFactory} presenter factory.
-     * Use this method for presenter dependency injection.
-     */
-    @Override
-    public void setPresenterFactory(PresenterFactory<P> presenterFactory) {
-        presenterDelegate.setPresenterFactory(presenterFactory);
-    }
-
-    /**
-     * Returns a current attached presenter.
-     * This method is guaranteed to return a non-null value between
-     * onResume/onPause and onAttachedToWindow/onDetachedFromWindow calls
-     * if the presenter factory returns a non-null value.
-     *
-     * @return a currently attached presenter or null.
-     */
-    public P getPresenter() {
-        return presenterDelegate.getPresenter();
-    }
-
-    @Override
-    public void onCreate(Bundle bundle) {
-        final PresenterFactory<P> superFactory = getPresenterFactory();
-        setPresenterFactory(new PresenterFactory<P>() {
-            @Override
-            public P createPresenter() {
-                P presenter = superFactory.createPresenter();
-                App app = (App) getActivity().getApplication();
-                app.getComponentReflection().inject(presenter);
-                ((BasePresenter) presenter).setContext(app.getApplicationContext());
-                return presenter;
-            }
-        });
-
-        super.onCreate(bundle);
-        if (bundle != null)
-            presenterDelegate.onRestoreInstanceState(bundle.getBundle(PRESENTER_STATE_KEY));
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle bundle) {
-        super.onSaveInstanceState(bundle);
-        bundle.putBundle(PRESENTER_STATE_KEY, presenterDelegate.onSaveInstanceState());
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        presenterDelegate.onResume(this);
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        presenterDelegate.onDropView();
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        presenterDelegate.onDestroy(!getActivity().isChangingConfigurations());
-    }
-}

+ 21 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.kt

@@ -0,0 +1,21 @@
+package eu.kanade.tachiyomi.ui.base.fragment
+
+import android.os.Bundle
+import eu.kanade.tachiyomi.App
+import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import nucleus.view.NucleusSupportFragment
+
+abstract class BaseRxFragment<P : BasePresenter<*>> : NucleusSupportFragment<P>(), FragmentMixin {
+
+    override fun onCreate(savedState: Bundle?) {
+        val superFactory = presenterFactory
+        setPresenterFactory {
+            superFactory.createPresenter().apply {
+                val app = activity.application as App
+                app.componentReflection.inject(this)
+                context = app.applicationContext
+            }
+        }
+        super.onCreate(savedState)
+    }
+}

+ 22 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/FragmentMixin.kt

@@ -0,0 +1,22 @@
+package eu.kanade.tachiyomi.ui.base.fragment
+
+import android.support.v4.app.FragmentActivity
+import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
+
+interface FragmentMixin {
+
+    fun setToolbarTitle(title: String) {
+        baseActivity.setToolbarTitle(title)
+    }
+
+    fun setToolbarTitle(resourceId: Int) {
+        baseActivity.setToolbarTitle(getString(resourceId))
+    }
+
+    val baseActivity: BaseActivity
+        get() = getActivity() as BaseActivity
+
+    fun getActivity(): FragmentActivity
+
+    fun getString(resource: Int): String
+}

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

@@ -260,7 +260,7 @@ class CategoryActivity : BaseRxActivity<CategoryPresenter>(), ActionMode.Callbac
      *
      * @param viewHolder view that contains dragged item
      */
-    override fun onStartDrag(viewHolder: RecyclerView.ViewHolder?) {
+    override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
         // Notify touchHelper
         touchHelper.startDrag(viewHolder)
     }

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt

@@ -62,7 +62,7 @@ class LibraryAdapter(fm: FragmentManager) : SmartFragmentStatePagerAdapter(fm) {
      * @param mode the mode to set.
      */
     fun setSelectionMode(mode: Int) {
-        for (fragment in registeredFragments) {
+        for (fragment in getRegisteredFragments()) {
             (fragment as LibraryCategoryFragment).setSelectionMode(mode)
         }
     }
@@ -71,7 +71,7 @@ class LibraryAdapter(fm: FragmentManager) : SmartFragmentStatePagerAdapter(fm) {
      * Notifies the adapters in all the registered fragments to refresh their content.
      */
     fun refreshRegisteredAdapters() {
-        for (fragment in registeredFragments) {
+        for (fragment in getRegisteredFragments()) {
             (fragment as LibraryCategoryFragment).adapter.notifyDataSetChanged()
         }
     }

+ 2 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt

@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.setting
 
 import android.os.Bundle
 import android.support.v14.preference.PreferenceFragment
+import eu.kanade.tachiyomi.App
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.cache.ChapterCache
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
@@ -24,7 +25,7 @@ class SettingsActivity : BaseActivity() {
         setAppTheme()
         super.onCreate(savedState)
         setContentView(R.layout.activity_preferences)
-        app.component.inject(this)
+        App.get(this).component.inject(this)
 
         setupToolbar(toolbar)
 

+ 1 - 1
build.gradle

@@ -6,7 +6,7 @@ buildscript {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.0.0'
+        classpath 'com.android.tools.build:gradle:2.1.0'
         classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0'
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files