diff --git a/app/build.gradle b/app/build.gradle index 171248d09..78e4ca1e9 100644 --- a/app/build.gradle +++ b/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" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/ActivityMixin.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/ActivityMixin.kt new file mode 100644 index 000000000..41773a9d5 --- /dev/null +++ b/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 + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt index efe2218df..999b64ba1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt +++ b/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() - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.java deleted file mode 100644 index 910697d8d..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.java +++ /dev/null @@ -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

a type of presenter to return with {@link #getPresenter}. - */ -public abstract class BaseRxActivity

extends BaseActivity implements ViewWithPresenter

{ - - private static final String PRESENTER_STATE_KEY = "presenter_state"; - - private final PresenterLifecycleDelegate

presenterDelegate = - new PresenterLifecycleDelegate<>(ReflectionPresenterFactory.

fromViewClass(getClass())); - - /** - * Returns a current presenter factory. - */ - public PresenterFactory

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

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

superFactory = getPresenterFactory(); - setPresenterFactory(new PresenterFactory

() { - @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()); - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt new file mode 100644 index 000000000..6f83dfdec --- /dev/null +++ b/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

> : NucleusAppCompatActivity

(), 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 + +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.java deleted file mode 100644 index 8ca4d3b13..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.java +++ /dev/null @@ -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); - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.kt new file mode 100644 index 000000000..ed5e39e65 --- /dev/null +++ b/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) + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.java deleted file mode 100644 index 7f335bd86..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.java +++ /dev/null @@ -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 not at the end of a "drop" event.
- *
- * 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.
- *
- * 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); -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/ItemTouchHelperAdapter.kt new file mode 100644 index 000000000..8fbb68fc3 --- /dev/null +++ b/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) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.java deleted file mode 100644 index 26bfcb4ce..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.java +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/OnStartDragListener.kt new file mode 100644 index 000000000..3589c1201 --- /dev/null +++ b/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) +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.java deleted file mode 100644 index 2091e5c0f..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.java +++ /dev/null @@ -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()); - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SimpleItemTouchHelperCallback.kt new file mode 100644 index 000000000..bfbbecc08 --- /dev/null +++ b/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) + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.java deleted file mode 100644 index 3756df15e..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.java +++ /dev/null @@ -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 registeredFragments = new SparseArray(); - - 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 getRegisteredFragments() { - ArrayList fragments = new ArrayList<>(); - for (int i = 0; i < registeredFragments.size(); i++) { - fragments.add(registeredFragments.valueAt(i)); - } - return fragments; - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.kt new file mode 100644 index 000000000..2169b603c --- /dev/null +++ b/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() + + // 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 { + val fragments = ArrayList() + for (i in 0..registeredFragments.size() - 1) { + fragments.add(registeredFragments.valueAt(i)) + } + return fragments + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationBase.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationBase.kt index c32fc9909..0ad485ff9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationBase.kt +++ b/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) } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationUpDown.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationUpDown.kt index 347f9792c..7ff12b7c8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fab/FABAnimationUpDown.kt +++ b/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) } } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseFragment.kt index 888d4b1a2..ee466c536 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseFragment.kt +++ b/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 - -} +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java deleted file mode 100644 index a0cb91798..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java +++ /dev/null @@ -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

a type of presenter to return with {@link #getPresenter}. - */ -public abstract class BaseRxFragment

extends BaseFragment implements ViewWithPresenter

{ - - private static final String PRESENTER_STATE_KEY = "presenter_state"; - private final PresenterLifecycleDelegate

presenterDelegate = - new PresenterLifecycleDelegate<>(ReflectionPresenterFactory.

fromViewClass(getClass())); - - /** - * Returns a current presenter factory. - */ - public PresenterFactory

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

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

superFactory = getPresenterFactory(); - setPresenterFactory(new PresenterFactory

() { - @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()); - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.kt new file mode 100644 index 000000000..03f20d5f1 --- /dev/null +++ b/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

> : NucleusSupportFragment

(), 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) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/FragmentMixin.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/FragmentMixin.kt new file mode 100644 index 000000000..4d7fcc8cd --- /dev/null +++ b/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 +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt index f86d1a5cd..2f25572c3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt @@ -260,7 +260,7 @@ class CategoryActivity : BaseRxActivity(), 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) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt index 258f65a61..dcfc8539e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt +++ b/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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt index 17d22ff80..73ae0d0b1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt +++ b/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) diff --git a/build.gradle b/build.gradle index 52a83784e..1cc9f13db 100644 --- a/build.gradle +++ b/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