mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Refactor and convert to Kotlin base classes. Fix FAB behavior
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
| } | ||||
| @@ -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() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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()); | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
|  | ||||
| } | ||||
| @@ -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); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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) | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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); | ||||
| } | ||||
| @@ -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) | ||||
| } | ||||
| @@ -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); | ||||
| } | ||||
| @@ -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) | ||||
| } | ||||
| @@ -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()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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) | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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 | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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) | ||||
| } | ||||
| @@ -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) | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
|  | ||||
| } | ||||
| } | ||||
| @@ -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()); | ||||
|     } | ||||
| } | ||||
| @@ -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) | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
| } | ||||
| @@ -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) | ||||
|     } | ||||
|   | ||||
| @@ -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,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) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user