Browse Source

Refactor and convert to Kotlin base classes. Fix FAB behavior

len 10 năm trước cách đây
mục cha
commit
e881488bcc
25 tập tin đã thay đổi với 342 bổ sung521 xóa
  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