Skip to content

Commit

Permalink
Merge pull request #101 from shockbytes/reactive-book-entity-dao
Browse files Browse the repository at this point in the history
Reactive `BookEntityDao`
  • Loading branch information
shockbytes authored Nov 22, 2020
2 parents 9a9603e + 48ff8d3 commit 1111ec6
Show file tree
Hide file tree
Showing 30 changed files with 431 additions and 343 deletions.
3 changes: 1 addition & 2 deletions app/src/main/java/at/shockbytes/dante/DanteApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ class DanteApp : MultiDexApplication(), CoreComponentProvider {
.coreModule(
CoreModule(
app = this,
// TODO Set to false once DAO is reactive
config = CoreModule.CoreModuleConfig(allowRealmExecutionOnUiThread = true)
config = CoreModule.CoreModuleConfig(allowRealmExecutionOnUiThread = false)
)
)
.networkModule(NetworkModule())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@ import java.lang.Exception
import java.util.Collections
import java.util.concurrent.Executors

/**
* TODO Explain [selectedStorageProvider] necessity!
*/
class DriveRestClient(
private val signInManager: GoogleFirebaseSignInManager,
private val selectedStorageProvider: BackupStorageProvider = BackupStorageProvider.GOOGLE_DRIVE
private val signInManager: GoogleFirebaseSignInManager
) : DriveClient {

private lateinit var drive: Drive
Expand Down Expand Up @@ -137,8 +133,7 @@ class DriveRestClient(
val data = fileName.split("_".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val storageProvider = BackupStorageProvider.byAcronym(data[0])

if (storageProvider == selectedStorageProvider) {
log(file.toPrettyString())
if (isCorrectStorageProvider(storageProvider)) {

val device = fileName.substring(
fileName.indexOf(data[4]),
Expand Down Expand Up @@ -166,6 +161,15 @@ class DriveRestClient(
}
}

/**
* This call is necessary because there is a Google Drive legacy implementation, which may
* reside next to the new GOOGLE_DRIVE format. For simplicity, the old format got fully
* discarded since it stored the data obfuscated.
*/
private fun isCorrectStorageProvider(storageProvider: BackupStorageProvider): Boolean {
return storageProvider == BackupStorageProvider.GOOGLE_DRIVE
}

private fun log(msg: String) {
Timber.d(msg)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ class GoogleDriveBackupProvider(

override fun mapBackupToBackupContent(entry: BackupMetadata): Single<BackupContent> {
return driveClient.readFileAsString(entry.id)
.map { content ->
content // TODO Remove later
}
.flatMap(contentTransform::createBackupContentFromBackupData)
.subscribeOn(schedulers.io)
.observeOn(schedulers.ui)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import timber.log.Timber
/**
* Author: Martin Macheiner
* Date: 09.05.2019
*
* IMPORTANT: Work in progress... Do not put in production!
*/
class ShockbytesHerokuServerBackupProvider(
private val signInManager: SignInManager,
Expand All @@ -30,7 +32,6 @@ class ShockbytesHerokuServerBackupProvider(
override val backupStorageProvider = BackupStorageProvider.SHOCKBYTES_SERVER

override fun initialize(activity: FragmentActivity?): Completable {
// TODO: Initialize provider
return Completable.complete()
}

Expand All @@ -40,7 +41,6 @@ class ShockbytesHerokuServerBackupProvider(
shockbytesHerokuApi.makeBackup(token, backupContent)
.flatMapCompletable { entry ->
Timber.d(entry.toString())
// TODO What to do with entry? Store in UI?
Completable.complete()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package at.shockbytes.dante.importer
import at.shockbytes.dante.core.book.BookEntity
import at.shockbytes.dante.core.book.BookState
import at.shockbytes.dante.core.data.BookRepository
import at.shockbytes.dante.util.merge
import at.shockbytes.dante.util.scheduler.SchedulerFacade
import io.reactivex.Completable
import io.reactivex.Single
Expand Down Expand Up @@ -41,15 +42,10 @@ class DefaultImportRepository(
}

override fun import(): Completable {
return Completable.create { emitter ->

if (parsedBooks != null) {
parsedBooks?.forEach(bookRepository::create)
emitter.onComplete()
} else {
emitter.onError(IllegalStateException("No books parsed!"))
}
}
return parsedBooks
?.map(bookRepository::create)
?.merge()
?: Completable.error(IllegalStateException("No books parsed!"))
}

private fun cacheBooks(books: List<BookEntity>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class LoginActivity : BaseActivity() {
viewModel.getLoginState().observe(this, Observer { state ->
when (state) {
is LoginViewModel.LoginState.FirstAppOpen -> {
// TODO Maybe offer instant sign-on solution later
// NOTE: Offer instant sign-on solution later
ActivityNavigator.navigateTo(this, Destination.Main())
}
is LoginViewModel.LoginState.LoggedIn -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class MainActivity : BaseActivity(), ViewPager.OnPageChangeListener {
// ---------------------------------------------------

private fun bindViewModel() {

viewModel.queryAnnouncements()
viewModel.hasActiveAnnouncement()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ hasAnnouncement ->
Expand All @@ -196,8 +196,6 @@ class MainActivity : BaseActivity(), ViewPager.OnPageChangeListener {
when (event) {

is MainViewModel.UserEvent.SuccessEvent -> {
// Only show announcements once the user is logged in
viewModel.queryAnnouncements()
// Only show onboarding hints after the user login state is resolved
checkForOnboardingHints()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ class BackupRestoreFragment : BaseFragment(), BaseAdapter.OnItemClickListener<Ba
}

/**
* TODO This implementation does not work on all devices...
* Use FileProvider instead
* IMPORTANT: This implementation does not work on all devices...
* TODO: Use FileProvider implementation instead
*/
private fun openFile(content: BackupMetadata.WithLocalFile) {
with(requireContext()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,18 @@ import at.shockbytes.dante.ui.adapter.main.BookAdapterEntity
import at.shockbytes.dante.ui.adapter.main.RandomPickCallback
import at.shockbytes.dante.ui.fragment.BookDetailFragment.Companion.ACTION_BOOK_CHANGED
import at.shockbytes.dante.ui.viewmodel.BookListViewModel
import at.shockbytes.dante.core.Constants.ACTION_BOOK_CREATED
import at.shockbytes.dante.core.Constants.EXTRA_BOOK_CREATED_STATE
import at.shockbytes.dante.util.DanteUtils
import at.shockbytes.dante.util.addTo
import at.shockbytes.dante.util.runDelayed
import at.shockbytes.dante.util.viewModelOf
import at.shockbytes.util.AppUtils
import at.shockbytes.util.adapter.BaseAdapter
import at.shockbytes.util.adapter.BaseItemTouchHelper
import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.android.synthetic.main.fragment_book_main.*
import timber.log.Timber
import javax.inject.Inject

class MainBookFragment : BaseFragment(),
Expand Down Expand Up @@ -87,11 +91,29 @@ class MainBookFragment : BaseFragment(),

private val bookUpdatedReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, data: Intent?) {
when (data?.action) {
ACTION_BOOK_CHANGED -> handleBookUpdatedBroadcast(data)
ACTION_BOOK_CREATED -> handleBookCreatedBroadcast(data)
}
}
}

(data?.getSerializableExtra(EXTRA_UPDATED_BOOK_STATE) as? BookState)?.let { updatedBookState ->
private fun handleBookUpdatedBroadcast(data: Intent) {
(data.getSerializableExtra(EXTRA_UPDATED_BOOK_STATE) as? BookState)
?.let { updatedBookState ->
viewModel.onBookUpdatedEvent(updatedBookState)
}
}
}

private fun handleBookCreatedBroadcast(data: Intent) {
(data.getSerializableExtra(EXTRA_BOOK_CREATED_STATE) as? BookState)
?.let { createdBookState ->
if (viewModel.state == createdBookState) {
runDelayed(500) {
fragment_book_main_rv.smoothScrollToPosition(0)
}
}
}
}

private val rvLayoutManager: RecyclerView.LayoutManager
Expand All @@ -118,8 +140,14 @@ class MainBookFragment : BaseFragment(),
}

private fun registerBookUpdatedBroadcastReceiver() {

val intentFilter = IntentFilter().apply {
addAction(ACTION_BOOK_CREATED)
addAction(ACTION_BOOK_CHANGED)
}

LocalBroadcastManager.getInstance(requireContext())
.registerReceiver(bookUpdatedReceiver, IntentFilter(ACTION_BOOK_CHANGED))
.registerReceiver(bookUpdatedReceiver, intentFilter)
}

override fun injectToGraph(appComponent: AppComponent) {
Expand All @@ -145,8 +173,8 @@ class MainBookFragment : BaseFragment(),
viewModel.getBooks().observe(this, Observer(::handleBookLoadingState))

viewModel.onPickRandomBookEvent
.subscribe(::handleRandomPickEvent)
.addTo(compositeDisposable)
.subscribe(::handleRandomPickEvent)
.addTo(compositeDisposable)
}

private fun handleBookLoadingState(state: BookListViewModel.BookLoadingState) {
Expand All @@ -155,7 +183,6 @@ class MainBookFragment : BaseFragment(),
is BookListViewModel.BookLoadingState.Success -> {
updateEmptyView(hide = true, animate = false)
bookAdapter.updateData(state.books)
fragment_book_main_rv.smoothScrollToPosition(0)
}

is BookListViewModel.BookLoadingState.Empty -> {
Expand All @@ -174,21 +201,21 @@ class MainBookFragment : BaseFragment(),
is BookListViewModel.RandomPickEvent.RandomPick -> {

PickRandomBookFragment
.newInstance(event.book.title, event.book.normalizedThumbnailUrl)
.setOnPickClickListener {
viewModel.moveBookToCurrentList(event.book)
}
.let { fragment ->
DanteUtils.addFragmentToActivity(
parentFragmentManager,
fragment,
android.R.id.content,
true
)
}
.newInstance(event.book.title, event.book.normalizedThumbnailUrl)
.setOnPickClickListener {
viewModel.moveBookToCurrentList(event.book)
}
.let { fragment ->
DanteUtils.addFragmentToActivity(
parentFragmentManager,
fragment,
android.R.id.content,
true
)
}
}
BookListViewModel.RandomPickEvent.NoBookAvailable -> {
// TODO
Timber.e(IllegalStateException("No book available in random pick event! Should never happen!"))
}
}
}
Expand All @@ -200,13 +227,13 @@ class MainBookFragment : BaseFragment(),
fragment_book_main_empty_view.text = resources.getStringArray(R.array.empty_indicators)[bookState.ordinal]

bookAdapter = BookAdapter(
requireContext(),
imageLoader,
onOverflowActionClickedListener = onBookOverflowClickedListener,
onItemClickListener = this,
onItemMoveListener = this,
onLabelClickedListener = onLabelClickedListener,
randomPickCallback = randomPickCallback
requireContext(),
imageLoader,
onOverflowActionClickedListener = onBookOverflowClickedListener,
onItemClickListener = this,
onItemMoveListener = this,
onLabelClickedListener = onLabelClickedListener,
randomPickCallback = randomPickCallback
)

fragment_book_main_rv.apply {
Expand All @@ -227,9 +254,9 @@ class MainBookFragment : BaseFragment(),
when (content) {
is BookAdapterEntity.Book -> {
ActivityNavigator.navigateTo(
context,
Destination.BookDetail(BookDetailInfo(content.id, content.title)),
getTransitionBundle(v)
context,
Destination.BookDetail(BookDetailInfo(content.id, content.title)),
getTransitionBundle(v)
)
}
BookAdapterEntity.RandomPick -> Unit // Do nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import at.shockbytes.dante.core.image.ImageLoadingCallback
import at.shockbytes.dante.ui.activity.ManualAddActivity
import at.shockbytes.dante.ui.fragment.dialog.SimpleRequestDialogFragment
import at.shockbytes.dante.ui.viewmodel.ManualAddViewModel
import at.shockbytes.dante.core.Constants.ACTION_BOOK_CREATED
import at.shockbytes.dante.core.Constants.EXTRA_BOOK_CREATED_STATE
import at.shockbytes.dante.util.addTo
import at.shockbytes.dante.util.setVisible
import at.shockbytes.dante.util.viewModelOf
Expand Down Expand Up @@ -192,6 +194,7 @@ class ManualAddFragment : BaseFragment(), ImageLoadingCallback {
when (event) {
is ManualAddViewModel.AddEvent.Success -> {
activity?.onBackPressed()
sendBookCreatedBroadcast(event.createdBookState)
}
is ManualAddViewModel.AddEvent.Error -> {
showSnackbar(getString(R.string.manual_add_error),
Expand All @@ -206,12 +209,22 @@ class ManualAddFragment : BaseFragment(), ImageLoadingCallback {
.addTo(compositeDisposable)
}

private fun sendBookCreatedBroadcast(createdBookState: BookState) {
sendBroadcast(
Intent(ACTION_BOOK_CREATED).putExtra(EXTRA_BOOK_CREATED_STATE, createdBookState)
)
}

private fun sendBookUpdatedBroadcast(bookState: BookState) {
sendBroadcast(
Intent(BookDetailFragment.ACTION_BOOK_CHANGED)
.putExtra(ManualAddActivity.EXTRA_UPDATED_BOOK_STATE, bookState)
)
}

private fun sendBroadcast(intent: Intent) {
LocalBroadcastManager.getInstance(requireContext())
.sendBroadcast(
Intent(BookDetailFragment.ACTION_BOOK_CHANGED)
.putExtra(ManualAddActivity.EXTRA_UPDATED_BOOK_STATE, bookState)
)
.sendBroadcast(intent)
}

private fun populateBookDataViews(bookEntity: BookEntity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class GoogleWelcomeScreenDialogFragment : BaseDialogFragment() {
.setView(welcomeView)
.setPositiveButton(getString(R.string.welcome_acknowledge)) { _, _ ->
listener?.invoke()
dismiss()
}
.create()
.also { it.requestWindowFeature(Window.FEATURE_NO_TITLE) }
Expand All @@ -62,8 +63,9 @@ class GoogleWelcomeScreenDialogFragment : BaseDialogFragment() {
}

fun setOnAcknowledgedListener(listener: () -> Unit): GoogleWelcomeScreenDialogFragment {
this.listener = listener
return this
return apply {
this.listener = listener
}
}

private fun setupViews() {
Expand All @@ -72,9 +74,7 @@ class GoogleWelcomeScreenDialogFragment : BaseDialogFragment() {
txtName.text = str

photoUrlString?.let { url ->
context?.let { ctx ->
imageLoader.loadImageUri(ctx, Uri.parse(url), imgView, circular = true)
}
imageLoader.loadImageUri(requireContext(), Uri.parse(url), imgView, circular = true)
}
}

Expand Down
Loading

0 comments on commit 1111ec6

Please sign in to comment.