diff --git a/app/build.gradle b/app/build.gradle index b0fb411..6fed333 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -72,7 +72,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.1.0-alpha02' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3' - implementation 'androidx.core:core-ktx:1.0.1' + implementation 'androidx.core:core-ktx:1.1.0-alpha04' implementation 'androidx.fragment:fragment-ktx:1.1.0-alpha04' implementation 'com.google.android.material:material:1.1.0-alpha04' @@ -80,8 +80,8 @@ dependencies { implementation 'com.auth0.android:auth0:1.15.1' // Butter Knife - implementation 'com.jakewharton:butterknife:10.0.0' - kapt 'com.jakewharton:butterknife-compiler:10.0.0' + implementation 'com.jakewharton:butterknife:10.1.0' + kapt 'com.jakewharton:butterknife-compiler:10.1.0' // Dagger implementation 'com.google.dagger:dagger:2.21' diff --git a/app/src/main/java/com/branhamplayer/android/base/ui/BindableViewHolder.kt b/app/src/main/java/com/branhamplayer/android/base/ui/BindableViewHolder.kt new file mode 100644 index 0000000..6264c7b --- /dev/null +++ b/app/src/main/java/com/branhamplayer/android/base/ui/BindableViewHolder.kt @@ -0,0 +1,9 @@ +package com.branhamplayer.android.base.ui + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.branhamplayer.android.base.models.Model + +abstract class BindableViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + abstract fun bind(model: BindingModel) +} diff --git a/build.gradle b/build.gradle index 6622770..0547617 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ buildscript { classpath 'io.fabric.tools:gradle:1.26.1' // Gradle - classpath 'com.android.tools.build:gradle:3.5.0-alpha06' + classpath 'com.android.tools.build:gradle:3.5.0-alpha07' // Kotlin classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" diff --git a/sermons/build.gradle b/sermons/build.gradle index 5cd3e0a..005101e 100644 --- a/sermons/build.gradle +++ b/sermons/build.gradle @@ -16,6 +16,8 @@ android { minSdkVersion min_sdk_version targetSdkVersion target_sdk_version + + vectorDrawables.useSupportLibrary = true } buildTypes { @@ -32,7 +34,7 @@ dependencies { implementation 'androidx.annotation:annotation:1.1.0-alpha01' implementation 'androidx.appcompat:appcompat:1.1.0-alpha02' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3' - implementation 'androidx.core:core-ktx:1.0.1' + implementation 'androidx.core:core-ktx:1.1.0-alpha04' implementation 'androidx.fragment:fragment-ktx:1.1.0-alpha04' implementation 'androidx.media:media:1.1.0-alpha01' implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha02' @@ -42,13 +44,19 @@ dependencies { implementation 'com.auth0.android:auth0:1.15.1' // Butter Knife - implementation 'com.jakewharton:butterknife:10.0.0' - kapt 'com.jakewharton:butterknife-compiler:10.0.0' + implementation 'com.jakewharton:butterknife:10.1.0' + kapt 'com.jakewharton:butterknife-compiler:10.1.0' // Dagger implementation 'com.google.dagger:dagger:2.21' kapt 'com.google.dagger:dagger-compiler:2.21' + // Glide + implementation 'com.github.bumptech.glide:glide:4.9.0' + + // CircleImageView + implementation 'de.hdodenhof:circleimageview:3.0.0' + // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" @@ -61,6 +69,6 @@ dependencies { kapt 'androidx.room:room-compiler:2.1.0-alpha04' // RxJava - implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' - implementation 'io.reactivex.rxjava2:rxjava:2.2.6' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' + implementation 'io.reactivex.rxjava2:rxjava:2.2.7' } diff --git a/sermons/src/main/AndroidManifest.xml b/sermons/src/main/AndroidManifest.xml index 6329002..df0268b 100644 --- a/sermons/src/main/AndroidManifest.xml +++ b/sermons/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ + diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/ProfileAction.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/AuthAction.kt similarity index 54% rename from sermons/src/main/java/com/branhamplayer/android/sermons/actions/ProfileAction.kt rename to sermons/src/main/java/com/branhamplayer/android/sermons/actions/AuthAction.kt index 4a8ffa2..42659d9 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/ProfileAction.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/AuthAction.kt @@ -1,9 +1,8 @@ package com.branhamplayer.android.sermons.actions import com.auth0.android.result.UserProfile -import org.rekotlin.Action -sealed class ProfileAction : Action { - object GetUserProfileAction : ProfileAction() - data class SaveUserProfileAction(val userProfile: UserProfile) : ProfileAction() +sealed class AuthAction : SermonsAction { + object GetUserProfileAction : AuthAction() + data class SaveUserProfileAction(val userProfile: UserProfile) : AuthAction() } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/DataAction.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/DataAction.kt deleted file mode 100644 index d4c1664..0000000 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/DataAction.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.branhamplayer.android.sermons.actions - -import androidx.annotation.StringRes -import org.rekotlin.Action - -sealed class DataAction : Action { - object FetchSermonListAction : DataAction() - data class SetTitleAction(@StringRes val title: Int) : DataAction() -} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/PermissionAction.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/PermissionAction.kt deleted file mode 100644 index 5d8ae11..0000000 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/PermissionAction.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.branhamplayer.android.sermons.actions - -import org.rekotlin.Action - -sealed class PermissionAction : Action { - object GetFileReadPermissionAction : PermissionAction() - object ShowPermissionDeniedErrorAction : PermissionAction() -} \ No newline at end of file diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/PlayerAction.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/PlayerAction.kt new file mode 100644 index 0000000..3ddbf86 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/PlayerAction.kt @@ -0,0 +1,10 @@ +package com.branhamplayer.android.sermons.actions + +import com.branhamplayer.android.sermons.models.SermonModel + +sealed class PlayerAction : SermonsAction { + object HidePhoneActionBarAction : PlayerAction() + object NavigateToNoSelectionAction : PlayerAction() + data class NavigateToPlayerAction(val selectedSermon: SermonModel) : PlayerAction() + data class ShowBackButtonAction(val showButton: Boolean) : PlayerAction() +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/SermonListAction.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/SermonListAction.kt new file mode 100644 index 0000000..bf98724 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/SermonListAction.kt @@ -0,0 +1,9 @@ +package com.branhamplayer.android.sermons.actions + +sealed class SermonListAction : SermonsAction { + object FetchSermonListAction : SermonListAction() + object GetFileReadPermissionAction : SermonListAction() + data class SetTitleAction(val title: String) : SermonListAction() + object ShowPhoneActionBarAction : SermonListAction() + object ShowPermissionDeniedErrorAction : SermonListAction() +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/actions/SermonsAction.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/SermonsAction.kt new file mode 100644 index 0000000..9a5d3c4 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/actions/SermonsAction.kt @@ -0,0 +1,5 @@ +package com.branhamplayer.android.sermons.actions + +import org.rekotlin.Action + +interface SermonsAction : Action diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonViewHolder.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonViewHolder.kt index cb41b5c..3c9b792 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonViewHolder.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonViewHolder.kt @@ -2,19 +2,41 @@ package com.branhamplayer.android.sermons.adapters import android.view.View import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView +import com.branhamplayer.android.base.ui.BindableViewHolder import com.branhamplayer.android.sermons.R +import com.branhamplayer.android.sermons.actions.PlayerAction import com.branhamplayer.android.sermons.models.SermonModel +import com.branhamplayer.android.sermons.store.sermonsStore -class SermonViewHolder( - itemView: View -) : RecyclerView.ViewHolder(itemView) { +class SermonViewHolder(itemView: View) : BindableViewHolder(itemView), View.OnClickListener { private val date: TextView = itemView.findViewById(R.id.sermon_date) private val name: TextView = itemView.findViewById(R.id.sermon_name) - fun bind(sermon: SermonModel) { - date.text = sermon.formattedDate - name.text = sermon.name + private var sermonModel: SermonModel? = null + + init { + itemView.setOnClickListener(this) + } + + // region BindableViewHolder + + override fun bind(model: SermonModel) { + date.text = model.formattedDate + name.text = model.name + + sermonModel = model } + + // endregion + + // region View.OnClickListener + + override fun onClick(view: View?) { + sermonModel?.let { + sermonsStore.dispatch(PlayerAction.NavigateToPlayerAction(it)) + } + } + + // endregion } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonsAdapter.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonsAdapter.kt index 01e9278..d54f168 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonsAdapter.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/adapters/SermonsAdapter.kt @@ -8,8 +8,8 @@ import com.branhamplayer.android.sermons.R import com.branhamplayer.android.sermons.models.SermonModel class SermonsAdapter( - context: Context?, - private val inflater: LayoutInflater = LayoutInflater.from(context) + context: Context?, + private val inflater: LayoutInflater = LayoutInflater.from(context) ) : RecyclerView.Adapter() { private var sermons: List = emptyList() @@ -25,10 +25,8 @@ class SermonsAdapter( } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SermonViewHolder { - val view = inflater.inflate(R.layout.sermon_list_item_fragment, parent, false) - return SermonViewHolder(view) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + SermonViewHolder(inflater.inflate(R.layout.sermon_list_item_fragment, parent, false)) override fun getItemCount() = sermons.size diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/AuthModule.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/AuthModule.kt new file mode 100644 index 0000000..a3ee574 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/AuthModule.kt @@ -0,0 +1,23 @@ +package com.branhamplayer.android.sermons.di + +import com.branhamplayer.android.sermons.middleware.AuthMiddleware +import com.branhamplayer.android.sermons.reducers.AuthReducer +import com.branhamplayer.android.services.auth0.Auth0Service +import dagger.Module +import dagger.Provides +import io.reactivex.Scheduler +import javax.inject.Named + +@Module +class AuthModule { + + @Provides + fun provideProfileMiddleware( + auth0Service: Auth0Service, + @Named(RxJavaModule.BG) bg: Scheduler, + @Named(RxJavaModule.UI) ui: Scheduler + ) = AuthMiddleware(auth0Service, bg, ui) + + @Provides + fun provideProfileReducer() = AuthReducer() +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/DaggerInjector.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/DaggerInjector.kt index b836e6a..10931b2 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/di/DaggerInjector.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/DaggerInjector.kt @@ -1,22 +1,35 @@ package com.branhamplayer.android.sermons.di -import androidx.appcompat.app.AppCompatActivity -import com.branhamplayer.android.di.AuthenticationModule +import com.branhamplayer.android.sermons.ui.SermonsActivity object DaggerInjector { + // region Player + + // This component needs to be rebuilt every time. Since rotating the device + // destroys the given activity, a new one must be available on each rotate + fun buildPlayerComponent(activity: SermonsActivity): PlayerComponent = DaggerPlayerComponent + .builder() + .playerModule(PlayerModule(activity)) + .build() + + // endregion + + // region Activity & Module-wide Injections + var sermonsComponent: SermonsComponent? = null private set - fun buildSermonsComponent(activity: AppCompatActivity): SermonsComponent { + fun buildSermonsComponent(activity: SermonsActivity): SermonsComponent { val component = sermonsComponent ?: DaggerSermonsComponent .builder() - .authenticationModule(AuthenticationModule()) - .rxJavaModule(RxJavaModule()) + .playerModule(PlayerModule(activity)) .sermonsModule(SermonsModule(activity)) .build() sermonsComponent = component return component } + + // endregion } \ No newline at end of file diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/DataModule.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/DataModule.kt deleted file mode 100644 index 6a27850..0000000 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/di/DataModule.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.branhamplayer.android.sermons.di - -import android.content.Context -import com.branhamplayer.android.sermons.mappers.SermonMapper -import com.branhamplayer.android.sermons.reducers.DataReducer -import com.branhamplayer.android.sermons.repositories.SermonsRepository -import dagger.Module -import dagger.Provides - -@Module -class DataModule { - - @Provides - fun provideDataReducer(context: Context, mapper: SermonMapper, repository: SermonsRepository) = - DataReducer(context, mapper, repository) - - @Provides - fun provideSermonMapper() = SermonMapper() - - @Provides - fun provideSermonsRepository() = SermonsRepository() -} \ No newline at end of file diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/PlayerComponent.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/PlayerComponent.kt new file mode 100644 index 0000000..e2a5d7f --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/PlayerComponent.kt @@ -0,0 +1,9 @@ +package com.branhamplayer.android.sermons.di + +import com.branhamplayer.android.sermons.ui.PlayerFragment +import dagger.Component + +@Component(modules = [PlayerModule::class]) +interface PlayerComponent { + fun inject(fragment: PlayerFragment) +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/PlayerModule.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/PlayerModule.kt new file mode 100644 index 0000000..a536858 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/PlayerModule.kt @@ -0,0 +1,32 @@ +package com.branhamplayer.android.sermons.di + +import com.branhamplayer.android.sermons.reducers.PlayerReducer +import com.branhamplayer.android.sermons.ui.NoSelectionFragment +import com.branhamplayer.android.sermons.ui.PlayerFragment +import com.branhamplayer.android.sermons.ui.SermonsActivity +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import dagger.Module +import dagger.Provides + +@Module +class PlayerModule(private val activity: SermonsActivity) { + + @Provides + fun provideDrawableTransitionOptions() = DrawableTransitionOptions.withCrossFade() + + @Provides + fun provideNoSelectionFragment() = NoSelectionFragment() + + @Provides + fun providePlayerFragment() = PlayerFragment() + + @Provides + fun providesRoutingReducer( + noSelectionFragment: NoSelectionFragment, + playerFragment: PlayerFragment + ) = PlayerReducer(activity, noSelectionFragment, playerFragment) + + @Provides + fun provideRequestManager() = Glide.with(activity) +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/ProfileModule.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/ProfileModule.kt deleted file mode 100644 index 72990fb..0000000 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/di/ProfileModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.branhamplayer.android.sermons.di - -import com.branhamplayer.android.sermons.middleware.ProfileMiddleware -import com.branhamplayer.android.sermons.reducers.ProfileReducer -import com.branhamplayer.android.services.auth0.Auth0Service -import dagger.Module -import dagger.Provides -import io.reactivex.Scheduler -import javax.inject.Named - -@Module -class ProfileModule { - - @Provides - fun provideProfileMiddleware( - auth0Service: Auth0Service, @Named(RxJavaModule.BG) bg: Scheduler, @Named(RxJavaModule.UI) ui: Scheduler - ) = ProfileMiddleware(auth0Service, bg, ui) - - @Provides - fun provideProfileReducer() = ProfileReducer() -} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonListModule.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonListModule.kt new file mode 100644 index 0000000..9a48979 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonListModule.kt @@ -0,0 +1,43 @@ +package com.branhamplayer.android.sermons.di + +import android.content.Context +import com.branhamplayer.android.sermons.adapters.SermonsAdapter +import com.branhamplayer.android.sermons.mappers.SermonMapper +import com.branhamplayer.android.sermons.middleware.SermonsListMiddleware +import com.branhamplayer.android.sermons.reducers.SermonListReducer +import com.branhamplayer.android.sermons.repositories.SermonsRepository +import com.branhamplayer.android.sermons.ui.SermonListFragment +import com.branhamplayer.android.sermons.ui.SermonsActivity +import dagger.Module +import dagger.Provides +import io.reactivex.Scheduler +import javax.inject.Named + +@Module +class SermonListModule { + + @Provides + fun provideSermonsAdapter(context: Context) = SermonsAdapter(context) + + @Provides + fun provideSermonListFragment() = SermonListFragment() + + @Provides + fun provideSermonListMiddleware( + activity: SermonsActivity, + @Named(RxJavaModule.BG) bg: Scheduler, + @Named(RxJavaModule.UI) ui: Scheduler + ) = SermonsListMiddleware( + activity, bg, ui + ) + + @Provides + fun provideSermonListReducer(mapper: SermonMapper, repository: SermonsRepository) = + SermonListReducer(mapper, repository) + + @Provides + fun provideSermonMapper() = SermonMapper() + + @Provides + fun provideSermonsRepository() = SermonsRepository() +} \ No newline at end of file diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsComponent.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsComponent.kt index 7341c0e..15264cb 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsComponent.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsComponent.kt @@ -7,7 +7,7 @@ import com.branhamplayer.android.sermons.ui.SermonListFragment import com.branhamplayer.android.sermons.ui.SermonsActivity import dagger.Component -@Component(modules = [AuthenticationModule::class, DataModule::class, DrawerModule::class, ProfileModule::class, RxJavaModule::class, SermonsModule::class]) +@Component(modules = [AuthenticationModule::class, AuthModule::class, DrawerModule::class, PlayerModule::class, RxJavaModule::class, SermonListModule::class, SermonsModule::class]) interface SermonsComponent { fun inject(activity: SermonsActivity) fun inject(fragment: SermonListFragment) diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsModule.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsModule.kt index c27291f..e3d28b9 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsModule.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/di/SermonsModule.kt @@ -1,28 +1,22 @@ package com.branhamplayer.android.sermons.di import android.content.Context -import androidx.appcompat.app.AppCompatActivity import com.branhamplayer.android.sermons.adapters.SermonsAdapter import com.branhamplayer.android.sermons.ui.SermonListFragment +import com.branhamplayer.android.sermons.ui.SermonsActivity import com.branhamplayer.android.ui.DrawerHeaderViewBinder import dagger.Module import dagger.Provides @Module -class SermonsModule(private val activity: AppCompatActivity) { +class SermonsModule(private val activity: SermonsActivity) { @Provides fun provideActivity() = activity @Provides - fun provideContext(): Context = activity.applicationContext + fun provideContext(): Context = activity @Provides fun provideDrawerHeaderViewBinder() = DrawerHeaderViewBinder() - - @Provides - fun provideListFragment() = SermonListFragment() - - @Provides - fun provideSermonsAdapter(context: Context) = SermonsAdapter(context) } \ No newline at end of file diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/ProfileMiddleware.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/AuthMiddleware.kt similarity index 69% rename from sermons/src/main/java/com/branhamplayer/android/sermons/middleware/ProfileMiddleware.kt rename to sermons/src/main/java/com/branhamplayer/android/sermons/middleware/AuthMiddleware.kt index 0e987bc..d29a5ce 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/ProfileMiddleware.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/AuthMiddleware.kt @@ -1,7 +1,7 @@ package com.branhamplayer.android.sermons.middleware import com.branhamplayer.android.base.redux.TypedMiddleware -import com.branhamplayer.android.sermons.actions.ProfileAction +import com.branhamplayer.android.sermons.actions.AuthAction import com.branhamplayer.android.sermons.di.RxJavaModule import com.branhamplayer.android.sermons.states.SermonsState import com.branhamplayer.android.services.auth0.Auth0Service @@ -10,15 +10,15 @@ import org.rekotlin.DispatchFunction import javax.inject.Inject import javax.inject.Named -class ProfileMiddleware @Inject constructor( +class AuthMiddleware @Inject constructor( private val auth0Service: Auth0Service, @Named(RxJavaModule.BG) private val bg: Scheduler, @Named(RxJavaModule.UI) private val ui: Scheduler -) : TypedMiddleware { +) : TypedMiddleware { - override fun invoke(dispatch: DispatchFunction, action: ProfileAction, oldState: SermonsState?) { + override fun invoke(dispatch: DispatchFunction, action: AuthAction, oldState: SermonsState?) { when (action) { - is ProfileAction.GetUserProfileAction -> getUserProfile(dispatch) + is AuthAction.GetUserProfileAction -> getUserProfile(dispatch) } } @@ -28,7 +28,7 @@ class ProfileMiddleware @Inject constructor( .subscribeOn(bg) .observeOn(ui) .subscribe({ profile -> - dispatch(ProfileAction.SaveUserProfileAction(profile)) + dispatch(AuthAction.SaveUserProfileAction(profile)) }, { // TODO: Do nothing? }) diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/PermissionMiddleware.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsListMiddleware.kt similarity index 67% rename from sermons/src/main/java/com/branhamplayer/android/sermons/middleware/PermissionMiddleware.kt rename to sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsListMiddleware.kt index 878d9fa..e035143 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/PermissionMiddleware.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsListMiddleware.kt @@ -1,11 +1,10 @@ package com.branhamplayer.android.sermons.middleware -import androidx.appcompat.app.AppCompatActivity import com.branhamplayer.android.base.redux.TypedMiddleware -import com.branhamplayer.android.sermons.actions.DataAction -import com.branhamplayer.android.sermons.actions.PermissionAction +import com.branhamplayer.android.sermons.actions.SermonListAction import com.branhamplayer.android.sermons.di.RxJavaModule import com.branhamplayer.android.sermons.states.SermonsState +import com.branhamplayer.android.sermons.ui.SermonsActivity import com.branhamplayer.android.sermons.utils.permissions.PermissionConstants import com.branhamplayer.android.sermons.utils.permissions.PermissionManager import io.reactivex.Scheduler @@ -13,16 +12,16 @@ import org.rekotlin.DispatchFunction import javax.inject.Inject import javax.inject.Named -class PermissionMiddleware @Inject constructor( - private val activity: AppCompatActivity, +class SermonsListMiddleware @Inject constructor( + private val activity: SermonsActivity, @Named(RxJavaModule.BG) private val bg: Scheduler, @Named(RxJavaModule.UI) private val ui: Scheduler -) : TypedMiddleware { +) : TypedMiddleware { - override fun invoke(dispatch: DispatchFunction, action: PermissionAction, oldState: SermonsState?) { + override fun invoke(dispatch: DispatchFunction, action: SermonListAction, oldState: SermonsState?) { when (action) { - is PermissionAction.GetFileReadPermissionAction -> getFileReadPermission(dispatch) - is PermissionAction.ShowPermissionDeniedErrorAction -> showPermissionDeniedError() + is SermonListAction.GetFileReadPermissionAction -> getFileReadPermission(dispatch) + is SermonListAction.ShowPermissionDeniedErrorAction -> showPermissionDeniedError() } } @@ -34,12 +33,12 @@ class PermissionMiddleware @Inject constructor( .observeOn(ui) .subscribe({ hasPermission -> if (hasPermission) { - dispatcher(DataAction.FetchSermonListAction) + dispatcher(SermonListAction.FetchSermonListAction) } else { - dispatcher(PermissionAction.ShowPermissionDeniedErrorAction) + dispatcher(SermonListAction.ShowPermissionDeniedErrorAction) } }, { - dispatcher(PermissionAction.ShowPermissionDeniedErrorAction) + dispatcher(SermonListAction.ShowPermissionDeniedErrorAction) }) } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsMiddleware.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsMiddleware.kt index 5d838e2..ac67598 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsMiddleware.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/middleware/SermonsMiddleware.kt @@ -1,7 +1,7 @@ package com.branhamplayer.android.sermons.middleware -import com.branhamplayer.android.sermons.actions.PermissionAction -import com.branhamplayer.android.sermons.actions.ProfileAction +import com.branhamplayer.android.sermons.actions.AuthAction +import com.branhamplayer.android.sermons.actions.SermonListAction import com.branhamplayer.android.sermons.di.DaggerInjector import com.branhamplayer.android.sermons.states.SermonsState import org.rekotlin.DispatchFunction @@ -10,11 +10,17 @@ import javax.inject.Inject class SermonsMiddleware : Middleware { + // region DI + @Inject - lateinit var permissionMiddleware: PermissionMiddleware + lateinit var authMiddleware: AuthMiddleware @Inject - lateinit var profileMiddleware: ProfileMiddleware + lateinit var sermonsListMiddleware: SermonsListMiddleware + + // endregion + + // region Middleware override fun invoke( dispatch: DispatchFunction, @@ -22,14 +28,14 @@ class SermonsMiddleware : Middleware { ): (DispatchFunction) -> DispatchFunction = { next -> { action -> when (action) { - is PermissionAction -> { + is AuthAction -> { inject() - permissionMiddleware.invoke(dispatch, action, getState()) + authMiddleware.invoke(dispatch, action, getState()) } - is ProfileAction -> { + is SermonListAction -> { inject() - profileMiddleware.invoke(dispatch, action, getState()) + sermonsListMiddleware.invoke(dispatch, action, getState()) } } @@ -37,7 +43,9 @@ class SermonsMiddleware : Middleware { } } + // endregion + private fun inject() { DaggerInjector.sermonsComponent?.inject(this) } -} \ No newline at end of file +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/AuthReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/AuthReducer.kt new file mode 100644 index 0000000..8f1b67e --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/AuthReducer.kt @@ -0,0 +1,16 @@ +package com.branhamplayer.android.sermons.reducers + +import com.branhamplayer.android.base.redux.TypedReducer +import com.branhamplayer.android.sermons.actions.AuthAction +import com.branhamplayer.android.sermons.states.SermonsState + +class AuthReducer : TypedReducer { + override fun invoke(action: AuthAction, oldState: SermonsState) = when (action) { + is AuthAction.SaveUserProfileAction -> saveUserProfile(oldState, action) + else -> oldState + } + + private fun saveUserProfile(oldState: SermonsState, action: AuthAction.SaveUserProfileAction) = oldState.copy( + profile = action.userProfile + ) +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DataReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DataReducer.kt deleted file mode 100644 index 171554a..0000000 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DataReducer.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.branhamplayer.android.sermons.reducers - -import android.content.Context -import androidx.annotation.StringRes -import com.branhamplayer.android.base.redux.TypedReducer -import com.branhamplayer.android.sermons.actions.DataAction -import com.branhamplayer.android.sermons.mappers.SermonMapper -import com.branhamplayer.android.sermons.repositories.SermonsRepository -import com.branhamplayer.android.sermons.states.SermonsState -import javax.inject.Inject - -class DataReducer @Inject constructor( - private val context: Context, - private val mapper: SermonMapper, - private val repository: SermonsRepository -) : TypedReducer { - - override fun invoke(action: DataAction, oldState: SermonsState) = when (action) { - is DataAction.FetchSermonListAction -> fetchSermonList(oldState) - is DataAction.SetTitleAction -> setTitle(oldState, action.title) - } - - private fun fetchSermonList(state: SermonsState): SermonsState { - val filesOnDisk = repository.getSermons().value - val sermons = mapper.map(filesOnDisk) - - return state.copy( - sermonList = sermons?.value - ) - } - - private fun setTitle(state: SermonsState, @StringRes title: Int) = state.copy( - title = context.getString(title) - ) -} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DrawerReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DrawerReducer.kt index 91b1741..eee72ad 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DrawerReducer.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/DrawerReducer.kt @@ -11,7 +11,6 @@ class DrawerReducer @Inject constructor() : TypedReducer setSelectedItem(oldState, action) } - private fun setSelectedItem(oldState: SermonsState, action: DrawerAction.SetSelectedItemAction) = oldState.copy( - drawerItemSelectedIndex = action.index - ) + private fun setSelectedItem(oldState: SermonsState, action: DrawerAction.SetSelectedItemAction) = + oldState.copy(drawerItemSelectedIndex = action.index) } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/PlayerReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/PlayerReducer.kt new file mode 100644 index 0000000..ccb9389 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/PlayerReducer.kt @@ -0,0 +1,55 @@ +package com.branhamplayer.android.sermons.reducers + +import com.branhamplayer.android.base.redux.TypedReducer +import com.branhamplayer.android.sermons.actions.PlayerAction +import com.branhamplayer.android.R as RBase +import com.branhamplayer.android.sermons.states.SermonsState +import com.branhamplayer.android.sermons.ui.NoSelectionFragment +import com.branhamplayer.android.sermons.ui.PlayerFragment +import com.branhamplayer.android.sermons.ui.SermonsActivity +import javax.inject.Inject + +class PlayerReducer @Inject constructor( + private val sermonsActivity: SermonsActivity, + private val noSelectionFragment: NoSelectionFragment, + private val playerFragment: PlayerFragment +) : TypedReducer { + + // region TypedReducer + + override fun invoke(action: PlayerAction, oldState: SermonsState) = when (action) { + is PlayerAction.HidePhoneActionBarAction -> hidePhoneActionBar(oldState) + is PlayerAction.NavigateToNoSelectionAction -> navigateToNoSelection(oldState) + is PlayerAction.NavigateToPlayerAction -> navigateToPlayer(oldState, action) + is PlayerAction.ShowBackButtonAction -> showBackButton(oldState, action) + } + + // endregion + + private fun hidePhoneActionBar(oldState: SermonsState) = oldState.copy( + phoneActionBarVisible = false + ) + + private fun navigateToNoSelection(oldState: SermonsState): SermonsState { + sermonsActivity.setDetailFragment(noSelectionFragment) + return oldState + } + + private fun navigateToPlayer(oldState: SermonsState, action: PlayerAction.NavigateToPlayerAction): SermonsState { + val isLargeTablet = sermonsActivity.resources.getBoolean(RBase.bool.is_large_tablet) + + if (isLargeTablet) { + sermonsActivity.setDetailFragment(playerFragment) + } else { + sermonsActivity.setMasterFragment(playerFragment) + } + + return oldState.copy( + selectedSermon = action.selectedSermon + ) + } + + private fun showBackButton(oldState: SermonsState, action: PlayerAction.ShowBackButtonAction) = oldState.copy( + showPlayerBackButton = action.showButton + ) +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/ProfileReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/ProfileReducer.kt deleted file mode 100644 index 818e9fd..0000000 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/ProfileReducer.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.branhamplayer.android.sermons.reducers - -import com.auth0.android.result.UserProfile -import com.branhamplayer.android.base.redux.TypedReducer -import com.branhamplayer.android.sermons.actions.ProfileAction -import com.branhamplayer.android.sermons.states.SermonsState -import javax.inject.Inject - -class ProfileReducer @Inject constructor() : TypedReducer { - - override fun invoke(action: ProfileAction, oldState: SermonsState) = when (action) { - is ProfileAction.GetUserProfileAction -> oldState - is ProfileAction.SaveUserProfileAction -> saveUserProfile(action.userProfile, oldState) - } - - private fun saveUserProfile(userProfile: UserProfile, oldState: SermonsState) = oldState.copy( - profile = userProfile - ) -} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonListReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonListReducer.kt new file mode 100644 index 0000000..3c1ff96 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonListReducer.kt @@ -0,0 +1,42 @@ +package com.branhamplayer.android.sermons.reducers + +import com.branhamplayer.android.base.redux.TypedReducer +import com.branhamplayer.android.sermons.actions.SermonListAction +import com.branhamplayer.android.sermons.mappers.SermonMapper +import com.branhamplayer.android.sermons.repositories.SermonsRepository +import com.branhamplayer.android.sermons.states.SermonsState +import javax.inject.Inject + +class SermonListReducer @Inject constructor( + private val mapper: SermonMapper, + private val repository: SermonsRepository +) : TypedReducer { + + // region TypedReducer + + override fun invoke(action: SermonListAction, oldState: SermonsState) = when (action) { + is SermonListAction.FetchSermonListAction -> fetchSermonList(oldState) + is SermonListAction.SetTitleAction -> setTitle(oldState, action) + is SermonListAction.ShowPhoneActionBarAction -> showPhoneActionBar(oldState) + else -> oldState + } + + // endregion + + private fun fetchSermonList(state: SermonsState): SermonsState { + val filesOnDisk = repository.getSermons().value + val sermons = mapper.map(filesOnDisk) + + return state.copy( + sermons = sermons?.value + ) + } + + private fun setTitle(state: SermonsState, action: SermonListAction.SetTitleAction) = state.copy( + title = action.title + ) + + private fun showPhoneActionBar(oldState: SermonsState) = oldState.copy( + phoneActionBarVisible = true + ) +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonsReducer.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonsReducer.kt index 395ac7f..5767818 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonsReducer.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/reducers/SermonsReducer.kt @@ -1,8 +1,9 @@ package com.branhamplayer.android.sermons.reducers -import com.branhamplayer.android.sermons.actions.DataAction +import com.branhamplayer.android.sermons.actions.AuthAction +import com.branhamplayer.android.sermons.actions.SermonListAction import com.branhamplayer.android.sermons.actions.DrawerAction -import com.branhamplayer.android.sermons.actions.ProfileAction +import com.branhamplayer.android.sermons.actions.PlayerAction import com.branhamplayer.android.sermons.di.DaggerInjector import com.branhamplayer.android.sermons.states.SermonsState import org.rekotlin.Action @@ -11,22 +12,31 @@ import javax.inject.Inject class SermonsReducer : Reducer { + // region DI + @Inject - lateinit var dataReducer: DataReducer + lateinit var authReducer: AuthReducer @Inject lateinit var drawerReducer: DrawerReducer @Inject - lateinit var profileReducer: ProfileReducer + lateinit var playerReducer: PlayerReducer + + @Inject + lateinit var sermonListReducer: SermonListReducer + + // endregion + + // region Reducer override fun invoke(action: Action, sermonsState: SermonsState?): SermonsState { val oldState = sermonsState ?: SermonsState() return when (action) { - is DataAction -> { + is AuthAction -> { inject() - dataReducer.invoke(action, oldState) + authReducer.invoke(action, oldState) } is DrawerAction -> { @@ -34,15 +44,22 @@ class SermonsReducer : Reducer { drawerReducer.invoke(action, oldState) } - is ProfileAction -> { + is PlayerAction -> { inject() - profileReducer.invoke(action, oldState) + playerReducer.invoke(action, oldState) + } + + is SermonListAction -> { + inject() + sermonListReducer.invoke(action, oldState) } else -> oldState } } + // endregion + private fun inject() { DaggerInjector.sermonsComponent?.inject(this) } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/states/SermonsState.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/states/SermonsState.kt index 8663499..94cc500 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/states/SermonsState.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/states/SermonsState.kt @@ -5,8 +5,23 @@ import com.branhamplayer.android.sermons.models.SermonModel import org.rekotlin.StateType data class SermonsState( - val drawerItemSelectedIndex: Int = 0, + val phoneActionBarVisible: Boolean = true, + + // region Auth val profile: UserProfile? = null, - val sermonList: List? = null, + // endregion + + // region Drawer + val drawerItemSelectedIndex: Int = 0, + // endregion + + // region Player + val selectedSermon: SermonModel? = null, + val showPlayerBackButton: Boolean = true, + // endregion + + // region SermonList + val sermons: List? = null, val title: String? = null + // endregion ) : StateType diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/ui/NoSelectionFragment.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/NoSelectionFragment.kt new file mode 100644 index 0000000..cb52ad0 --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/NoSelectionFragment.kt @@ -0,0 +1,14 @@ +package com.branhamplayer.android.sermons.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.branhamplayer.android.sermons.R + +class NoSelectionFragment : Fragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = + inflater.inflate(R.layout.no_selection_fragment, container, false) +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/ui/PlayerFragment.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/PlayerFragment.kt new file mode 100644 index 0000000..5bceecc --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/PlayerFragment.kt @@ -0,0 +1,174 @@ +package com.branhamplayer.android.sermons.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.widget.AppCompatImageView +import androidx.appcompat.widget.AppCompatTextView +import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.Fragment +import butterknife.BindView +import butterknife.ButterKnife +import butterknife.Unbinder +import com.branhamplayer.android.R as RBase +import com.branhamplayer.android.sermons.R +import com.branhamplayer.android.sermons.actions.PlayerAction +import com.branhamplayer.android.sermons.di.DaggerInjector +import com.branhamplayer.android.sermons.states.SermonsState +import com.branhamplayer.android.sermons.store.sermonsStore +import com.branhamplayer.android.sermons.utils.DisplayUtility +import com.bumptech.glide.RequestManager +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.google.android.material.appbar.AppBarLayout +import de.hdodenhof.circleimageview.CircleImageView +import org.rekotlin.StoreSubscriber +import javax.inject.Inject + +class PlayerFragment : Fragment(), AppBarLayout.OnOffsetChangedListener, StoreSubscriber { + + private var showingArtwork = true + private var unbinder: Unbinder? = null + + // region DI + + @Inject + lateinit var artworkLoader: RequestManager + + @Inject + lateinit var backgroundLoader: RequestManager + + @Inject + lateinit var crossFade: DrawableTransitionOptions + + // endregion + + // region UI + + @BindView(R.id.player_app_bar) + lateinit var appBar: AppBarLayout + + @BindView(R.id.player_artwork) + lateinit var artwork: CircleImageView + + @BindView(R.id.player_background) + lateinit var background: AppCompatImageView + + @BindView(R.id.player_date) + lateinit var date: AppCompatTextView + + @BindView(R.id.player_title) + lateinit var title: AppCompatTextView + + @BindView(R.id.player_toolbar) + lateinit var toolbar: Toolbar + + // endregion + + // region Fragment + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val view = inflater.inflate(R.layout.player_fragment, container, false) + unbinder = ButterKnife.bind(this, view) + + val isLargeTablet = resources.getBoolean(RBase.bool.is_tablet) + val sermonsActivity = activity as? SermonsActivity + + sermonsActivity?.let { + DaggerInjector.buildPlayerComponent(it).inject(this) + } + + sermonsStore.subscribe(this) + + if (isLargeTablet) { + sermonsStore.dispatch(PlayerAction.ShowBackButtonAction(false)) + } else { + sermonsStore.dispatch(PlayerAction.HidePhoneActionBarAction) + sermonsStore.dispatch(PlayerAction.ShowBackButtonAction(true)) + } + + appBar.addOnOffsetChangedListener(this) + + return view + } + + override fun onDestroyView() { + super.onDestroyView() + + appBar.removeOnOffsetChangedListener(this) + sermonsStore.unsubscribe(this) + unbinder?.unbind() + } + + // endregion + + // region AppBarLayout.OnOffsetChangedListener + + override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) { + context?.let { + val verticalOffsetInDp = DisplayUtility.convertPxToDp(Math.abs(verticalOffset), it) + + if (verticalOffsetInDp >= 125 && showingArtwork) { + showingArtwork = false + + artwork.animate() + .scaleX(0F) + .scaleY(0F) + .setDuration(200L) + .start() + } else if (verticalOffsetInDp < 125 && !showingArtwork) { + showingArtwork = true + + artwork.animate() + .scaleX(1F) + .scaleY(1F) + .setDuration(200L) + .start() + } + } + } + + // endregion + + // region StoreSubscriber + + override fun newState(state: SermonsState) { + state.selectedSermon?.let { + date.text = it.formattedDate + title.text = it.name + toolbar.title = "" // Don't use the default toolbar, since we extend it with a collapsing toolbar + } + + setUpToolbar(state.showPlayerBackButton) + + // TODO, replace with real album artwork + artworkLoader + .load("https://cloudinary-a.akamaihd.net/branham-player/image/upload/c_scale,w_421/samples/landscapes/beach-boat.jpg") + .timeout(5000) + .dontAnimate() + .error(RBase.drawable.ic_sermons) + .placeholder(RBase.drawable.ic_sermons) + .into(artwork) + + backgroundLoader + .load("https://cloudinary-a.akamaihd.net/branham-player/image/upload/c_scale,w_421/samples/landscapes/beach-boat.jpg") + .timeout(5000) + .transition(crossFade) + .error(RBase.drawable.ic_sermons) + .placeholder(RBase.drawable.ic_sermons) + .into(background) + } + + // endregion + + private fun setUpToolbar(showBackButton: Boolean) { + val sermonsActivity = activity as? SermonsActivity? + sermonsActivity?.setSupportActionBar(toolbar) + sermonsActivity?.supportActionBar?.setHomeButtonEnabled(showBackButton) + sermonsActivity?.supportActionBar?.setDisplayHomeAsUpEnabled(showBackButton) + + toolbar.setNavigationOnClickListener { + sermonsActivity?.onBackPressed() + } + } +} diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonListFragment.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonListFragment.kt index dfc71ba..2aa95d0 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonListFragment.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonListFragment.kt @@ -12,14 +12,15 @@ import butterknife.ButterKnife import butterknife.Unbinder import com.branhamplayer.android.R as RBase import com.branhamplayer.android.sermons.R +import com.branhamplayer.android.sermons.actions.SermonListAction import com.branhamplayer.android.sermons.adapters.SermonsAdapter import com.branhamplayer.android.sermons.di.DaggerInjector +import com.branhamplayer.android.sermons.models.SermonModel import com.branhamplayer.android.sermons.store.sermonsStore -import com.branhamplayer.android.sermons.states.SermonsState import org.rekotlin.StoreSubscriber import javax.inject.Inject -class SermonListFragment : Fragment(), StoreSubscriber { +class SermonListFragment : Fragment(), StoreSubscriber?> { private var unbinder: Unbinder? = null @@ -44,9 +45,15 @@ class SermonListFragment : Fragment(), StoreSubscriber { val view = inflater.inflate(R.layout.sermon_list_fragment, container, false) DaggerInjector.sermonsComponent?.inject(this) - unbinder = ButterKnife.bind(this, view) - sermonsStore.subscribe(this) + + sermonsStore.subscribe(this) { + it.select { state -> + state.sermons + }.skipRepeats() + } + + sermonsStore.dispatch(SermonListAction.ShowPhoneActionBarAction) sermonsRecyclerView?.adapter = sermonAdapter sermonsRecyclerView?.layoutManager = LinearLayoutManager(context) @@ -63,8 +70,8 @@ class SermonListFragment : Fragment(), StoreSubscriber { // region StoreSubscriber - override fun newState(state: SermonsState) { - state.sermonList?.let { + override fun newState(state: List?) { + state?.let { sermonAdapter.setSermons(it) sermonsRecyclerView?.adapter?.notifyDataSetChanged() } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonsActivity.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonsActivity.kt index 9a2f3cb..12c0c7b 100644 --- a/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonsActivity.kt +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/ui/SermonsActivity.kt @@ -1,20 +1,22 @@ package com.branhamplayer.android.sermons.ui import android.os.Bundle +import android.view.View import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.drawerlayout.widget.DrawerLayout +import androidx.fragment.app.Fragment import androidx.fragment.app.commit import butterknife.BindView import butterknife.ButterKnife import butterknife.Unbinder import com.branhamplayer.android.R as RBase import com.branhamplayer.android.sermons.R -import com.branhamplayer.android.sermons.actions.DataAction +import com.branhamplayer.android.sermons.actions.AuthAction +import com.branhamplayer.android.sermons.actions.SermonListAction import com.branhamplayer.android.sermons.actions.DrawerAction -import com.branhamplayer.android.sermons.actions.PermissionAction -import com.branhamplayer.android.sermons.actions.ProfileAction +import com.branhamplayer.android.sermons.actions.PlayerAction import com.branhamplayer.android.sermons.di.DaggerInjector import com.branhamplayer.android.sermons.store.sermonsStore import com.branhamplayer.android.sermons.states.SermonsState @@ -28,7 +30,17 @@ class SermonsActivity : AppCompatActivity(), StoreSubscriber { private var activityUnbinder: Unbinder? = null private var drawerToggle: ActionBarDrawerToggle? = null - // region Components + // region DI + + @Inject + lateinit var drawerHeaderBinder: DrawerHeaderViewBinder + + @Inject + lateinit var sermonListFragment: SermonListFragment + + // endregion + + // region UI @JvmField @BindView(R.id.navigation_drawer) @@ -42,19 +54,8 @@ class SermonsActivity : AppCompatActivity(), StoreSubscriber { @BindView(R.id.primary_toolbar) var primaryToolbar: Toolbar? = null - @JvmField @BindView(R.id.sermon_list_toolbar) - var sermonsListToolbar: Toolbar? = null - - // endregion - - // region DI - - @Inject - lateinit var drawerHeaderBinder: DrawerHeaderViewBinder - - @Inject - lateinit var sermonListFragment: SermonListFragment + lateinit var sermonsListToolbar: Toolbar // endregion @@ -76,8 +77,8 @@ class SermonsActivity : AppCompatActivity(), StoreSubscriber { replace(R.id.sermon_list_container, sermonListFragment) } - sermonsStore.dispatch(DataAction.SetTitleAction(RBase.string.navigation_sermons)) - sermonsStore.dispatch(PermissionAction.GetFileReadPermissionAction) + sermonsStore.dispatch(SermonListAction.GetFileReadPermissionAction) + sermonsStore.dispatch(SermonListAction.SetTitleAction(getString(RBase.string.navigation_sermons))) val isTablet = resources.getBoolean(RBase.bool.is_tablet) @@ -91,6 +92,7 @@ class SermonsActivity : AppCompatActivity(), StoreSubscriber { drawerHeaderBinder.unbind() activityUnbinder?.unbind() + sermonsStore.unsubscribe(this) } // endregion @@ -100,19 +102,43 @@ class SermonsActivity : AppCompatActivity(), StoreSubscriber { override fun newState(state: SermonsState) { drawer?.menu?.getItem(state.drawerItemSelectedIndex)?.isChecked = true + sermonsListToolbar.visibility = if (state.phoneActionBarVisible) View.VISIBLE else View.GONE state.profile?.let { drawerHeaderBinder.email?.text = it.email drawerHeaderBinder.name?.text = it.name } + if (!state.sermons.isNullOrEmpty() && state.selectedSermon == null) { + sermonsStore.dispatch(PlayerAction.NavigateToNoSelectionAction) + } + state.title?.let { - sermonsListToolbar?.title = it + sermonsListToolbar.title = it } } // endregion + fun setDetailFragment(fragment: Fragment) { + val isLargeTablet = resources.getBoolean(RBase.bool.is_large_tablet) + if (!isLargeTablet) return + + supportFragmentManager.commit(allowStateLoss = true) { + replace(R.id.sermons_details_container, fragment) + } + } + + fun setMasterFragment(fragment: Fragment, addToBackStack: Boolean = true) { + supportFragmentManager.commit(allowStateLoss = true) { + replace(R.id.sermon_list_container, fragment) + + if (addToBackStack) { + addToBackStack(fragment::class.java.simpleName) + } + } + } + private fun setUpDrawer() { drawerToggle = ActionBarDrawerToggle( @@ -135,7 +161,7 @@ class SermonsActivity : AppCompatActivity(), StoreSubscriber { } } + sermonsStore.dispatch(AuthAction.GetUserProfileAction) sermonsStore.dispatch(DrawerAction.SetSelectedItemAction(0)) - sermonsStore.dispatch(ProfileAction.GetUserProfileAction) } } diff --git a/sermons/src/main/java/com/branhamplayer/android/sermons/utils/DisplayUtility.kt b/sermons/src/main/java/com/branhamplayer/android/sermons/utils/DisplayUtility.kt new file mode 100644 index 0000000..5e8dbed --- /dev/null +++ b/sermons/src/main/java/com/branhamplayer/android/sermons/utils/DisplayUtility.kt @@ -0,0 +1,11 @@ +package com.branhamplayer.android.sermons.utils + +import android.content.Context +import android.util.DisplayMetrics + +object DisplayUtility { + + // Thank you: https://stackoverflow.com/a/9563438/663604 + fun convertPxToDp(pixels: Int, context: Context) = + pixels / (context.resources.displayMetrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT) +} diff --git a/sermons/src/main/res/drawable/ic_backward_30.xml b/sermons/src/main/res/drawable/ic_backward_30.xml new file mode 100644 index 0000000..477ed41 --- /dev/null +++ b/sermons/src/main/res/drawable/ic_backward_30.xml @@ -0,0 +1,10 @@ + + + diff --git a/sermons/src/main/res/drawable/ic_forward_30.xml b/sermons/src/main/res/drawable/ic_forward_30.xml new file mode 100644 index 0000000..2689367 --- /dev/null +++ b/sermons/src/main/res/drawable/ic_forward_30.xml @@ -0,0 +1,10 @@ + + + diff --git a/sermons/src/main/res/drawable/ic_next.xml b/sermons/src/main/res/drawable/ic_next.xml new file mode 100644 index 0000000..666691b --- /dev/null +++ b/sermons/src/main/res/drawable/ic_next.xml @@ -0,0 +1,10 @@ + + + diff --git a/sermons/src/main/res/drawable/ic_pause.xml b/sermons/src/main/res/drawable/ic_pause.xml new file mode 100644 index 0000000..c907560 --- /dev/null +++ b/sermons/src/main/res/drawable/ic_pause.xml @@ -0,0 +1,10 @@ + + + diff --git a/sermons/src/main/res/drawable/ic_play.xml b/sermons/src/main/res/drawable/ic_play.xml new file mode 100644 index 0000000..3d12280 --- /dev/null +++ b/sermons/src/main/res/drawable/ic_play.xml @@ -0,0 +1,10 @@ + + + diff --git a/sermons/src/main/res/drawable/ic_previous.xml b/sermons/src/main/res/drawable/ic_previous.xml new file mode 100644 index 0000000..1f63b36 --- /dev/null +++ b/sermons/src/main/res/drawable/ic_previous.xml @@ -0,0 +1,10 @@ + + + diff --git a/sermons/src/main/res/drawable/no_selection.xml b/sermons/src/main/res/drawable/no_selection.xml new file mode 100644 index 0000000..cc95d56 --- /dev/null +++ b/sermons/src/main/res/drawable/no_selection.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sermons/src/main/res/layout-w840dp/sermons_activity.xml b/sermons/src/main/res/layout-w840dp/sermons_activity.xml index d29c543..e119ed4 100644 --- a/sermons/src/main/res/layout-w840dp/sermons_activity.xml +++ b/sermons/src/main/res/layout-w840dp/sermons_activity.xml @@ -83,23 +83,10 @@ app:layout_constraintStart_toEndOf="@+id/sermon_list_card" app:layout_constraintTop_toTopOf="@+id/primary_toolbar_spacer"> - - - - - - + android:layout_width="match_parent"/> diff --git a/sermons/src/main/res/layout/no_selection_fragment.xml b/sermons/src/main/res/layout/no_selection_fragment.xml new file mode 100644 index 0000000..8cfb03e --- /dev/null +++ b/sermons/src/main/res/layout/no_selection_fragment.xml @@ -0,0 +1,34 @@ + + + + + + + diff --git a/sermons/src/main/res/layout/player_fragment.xml b/sermons/src/main/res/layout/player_fragment.xml new file mode 100644 index 0000000..8bf6628 --- /dev/null +++ b/sermons/src/main/res/layout/player_fragment.xml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sermons/src/main/res/values/strings.xml b/sermons/src/main/res/values/strings.xml index 10ebb75..61f39c0 100644 --- a/sermons/src/main/res/values/strings.xml +++ b/sermons/src/main/res/values/strings.xml @@ -28,4 +28,10 @@ This permission is necessary for the Branham Player to work properly + + + + Select a sermon from the list + + diff --git a/sermons/src/main/res/values/styles.xml b/sermons/src/main/res/values/styles.xml index c2cc003..e9c9421 100644 --- a/sermons/src/main/res/values/styles.xml +++ b/sermons/src/main/res/values/styles.xml @@ -2,9 +2,9 @@ -