Skip to content
This repository was archived by the owner on Jul 29, 2022. It is now read-only.

Commit 0f33b47

Browse files
authored
Rewrite the reading part with Fragments (#398)
1 parent f99fdd6 commit 0f33b47

File tree

69 files changed

+3605
-3202
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+3605
-3202
lines changed

r2-testapp/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ android {
5252
sourceCompatibility JavaVersion.VERSION_1_8
5353
targetCompatibility JavaVersion.VERSION_1_8
5454
}
55+
kotlinOptions {
56+
jvmTarget = "1.8"
57+
}
5558
buildTypes {
5659
release {
5760
minifyEnabled false
@@ -126,7 +129,7 @@ dependencies {
126129
}
127130
implementation "com.github.kittinunf.fuel:fuel:2.2.2"
128131
implementation "com.github.kittinunf.fuel:fuel-android:2.2.2"
129-
implementation "com.google.android.material:material:1.4.0-alpha01"
132+
implementation "com.google.android.material:material:1.3.0"
130133
implementation "com.google.code.gson:gson:2.8.6"
131134
implementation "com.jakewharton.timber:timber:4.7.1"
132135
implementation("com.mcxiaoke.koi:core:0.5.5") {

r2-testapp/src/main/AndroidManifest.xml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,20 +194,12 @@
194194
<activity
195195
android:name=".epub.EpubActivity"
196196
android:label="@string/title_activity_epub" />
197-
<activity android:name=".pdf.PdfActivity" />
198197
<activity
199-
android:name=".comic.DiViNaActivity"
200-
android:label="@string/title_activity_epub" />
201-
<activity
202-
android:name=".comic.ComicActivity"
203-
android:label="@string/title_activity_epub" />
204-
<activity
205-
android:name=".drm.DRMManagementActivity"
206-
android:label="DRM Management"
207-
android:theme="@style/AppTheme" />
198+
android:name=".reader.ReaderActivity"
199+
android:label="Reader" />
208200
<activity
209-
android:name=".outline.R2OutlineActivity"
210-
android:label="@string/title_activity_outline" />
201+
android:name=".reader.VisualReaderActivity"
202+
android:label="Reader" />
211203
<activity
212204
android:name=".opds.OPDSListActivity"
213205
android:label="@string/title_activity_opds_list" />
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2021 Readium Foundation. All rights reserved.
3+
* Use of this source code is governed by the BSD-style license
4+
* available in the top-level LICENSE file of the project.
5+
*/
6+
7+
package org.readium.r2.testapp.audiobook
8+
9+
import android.os.Bundle
10+
import android.view.View
11+
import androidx.fragment.app.Fragment
12+
import androidx.fragment.app.FragmentFactory
13+
import androidx.lifecycle.lifecycleScope
14+
import kotlinx.android.synthetic.main.fragment_audiobook.*
15+
import kotlinx.coroutines.flow.StateFlow
16+
import kotlinx.coroutines.launch
17+
import org.jetbrains.anko.support.v4.indeterminateProgressDialog
18+
import org.readium.r2.navigator.Navigator
19+
import org.readium.r2.testapp.utils.createFragmentFactory
20+
import org.readium.r2.shared.publication.Link
21+
import org.readium.r2.shared.publication.Locator
22+
import org.readium.r2.shared.publication.Publication
23+
import org.readium.r2.shared.publication.services.cover
24+
import org.readium.r2.testapp.R
25+
26+
class AudioNavigatorFragment(
27+
val publication: Publication,
28+
private var initialLocator: Locator? = null,
29+
internal val listener: Listener? = null
30+
) : Fragment(R.layout.fragment_audiobook), Navigator {
31+
32+
interface Listener : Navigator.Listener
33+
34+
private lateinit var activity: AudiobookActivity
35+
36+
override fun onCreate(savedInstanceState: Bundle?) {
37+
super.onCreate(savedInstanceState)
38+
39+
savedInstanceState?.getParcelable<Locator>("locator")?.let {
40+
initialLocator = it
41+
}
42+
}
43+
44+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
45+
super.onViewCreated(view, savedInstanceState)
46+
47+
activity = requireActivity() as AudiobookActivity
48+
49+
// Setting cover
50+
viewLifecycleOwner.lifecycleScope.launch {
51+
publication.cover()?.let {
52+
imageView.setImageBitmap(it)
53+
}
54+
}
55+
56+
activity.mediaPlayer.progress = indeterminateProgressDialog(getString(R.string.progress_wait_while_preparing_audiobook))
57+
initialLocator?.let { go(it) }
58+
}
59+
60+
override fun onDestroyView() {
61+
super.onDestroyView()
62+
activity.mediaPlayer.progress!!.dismiss()
63+
}
64+
65+
override val currentLocator: StateFlow<Locator>
66+
get() = activity.currentLocator
67+
68+
override fun go(locator: Locator, animated: Boolean, completion: () -> Unit): Boolean =
69+
activity.go(locator, animated, completion)
70+
71+
override fun go(link: Link, animated: Boolean, completion: () -> Unit): Boolean =
72+
activity.go(link, animated, completion)
73+
74+
override fun goForward(animated: Boolean, completion: () -> Unit): Boolean =
75+
activity.goForward(animated, completion)
76+
77+
override fun goBackward(animated: Boolean, completion: () -> Unit): Boolean =
78+
activity.goBackward(animated, completion)
79+
80+
companion object {
81+
82+
fun createFactory(publication: Publication, initialLocator: Locator? = null, listener: Listener? = null): FragmentFactory =
83+
createFragmentFactory { AudioNavigatorFragment(publication, initialLocator, listener) }
84+
}
85+
}

r2-testapp/src/main/java/org/readium/r2/testapp/audiobook/AudiobookActivity.kt

Lines changed: 77 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,112 @@
11
package org.readium.r2.testapp.audiobook
22

3-
4-
import android.app.ProgressDialog
5-
import android.content.Intent
6-
import android.graphics.BitmapFactory
73
import android.os.Bundle
8-
import android.view.Menu
9-
import android.view.MenuItem
10-
import android.widget.ImageView
11-
import kotlinx.coroutines.delay
12-
import kotlinx.coroutines.launch
13-
import org.jetbrains.anko.indeterminateProgressDialog
14-
import org.jetbrains.anko.intentFor
15-
import org.jetbrains.anko.toast
16-
import org.readium.r2.navigator.Navigator
17-
import org.readium.r2.navigator.NavigatorDelegate
4+
import androidx.fragment.app.FragmentResultListener
5+
import androidx.fragment.app.commit
6+
import androidx.fragment.app.commitNow
7+
import androidx.lifecycle.ViewModelProvider
188
import org.readium.r2.navigator.audiobook.R2AudiobookActivity
19-
import org.readium.r2.shared.extensions.putPublicationFrom
209
import org.readium.r2.shared.publication.Locator
21-
import org.readium.r2.shared.publication.services.isProtected
2210
import org.readium.r2.testapp.R
23-
import org.readium.r2.testapp.db.Bookmark
24-
import org.readium.r2.testapp.db.BookmarksDatabase
25-
import org.readium.r2.testapp.db.BooksDatabase
26-
import org.readium.r2.testapp.drm.DRMManagementActivity
27-
import org.readium.r2.testapp.library.LibraryActivity
28-
import org.readium.r2.testapp.library.activitiesLaunched
29-
import org.readium.r2.testapp.outline.R2OutlineActivity
30-
import timber.log.Timber
31-
32-
33-
class AudiobookActivity : R2AudiobookActivity(), NavigatorDelegate {
11+
import org.readium.r2.testapp.drm.DrmManagementContract
12+
import org.readium.r2.testapp.drm.DrmManagementFragment
13+
import org.readium.r2.testapp.outline.OutlineContract
14+
import org.readium.r2.testapp.outline.OutlineFragment
15+
import org.readium.r2.testapp.reader.AudioReaderFragment
16+
import org.readium.r2.testapp.reader.ReaderActivity
17+
import org.readium.r2.testapp.reader.ReaderViewModel
18+
import org.readium.r2.testapp.reader.ReaderContract
3419

35-
override fun locationDidChange(navigator: Navigator?, locator: Locator) {
36-
Timber.d("locationDidChange $locator")
37-
booksDB.books.saveProgression(locator, bookId)
38-
}
39-
40-
private lateinit var booksDB: BooksDatabase
20+
class AudiobookActivity : R2AudiobookActivity() {
4121

42-
private lateinit var bookmarksDB: BookmarksDatabase
43-
private lateinit var progressDialog: ProgressDialog
22+
private lateinit var modelFactory: ReaderViewModel.Factory
23+
private lateinit var readerFragment: AudioReaderFragment
4424

4525
override fun onCreate(savedInstanceState: Bundle?) {
46-
if (activitiesLaunched.incrementAndGet() > 1 || !LibraryActivity.isServerStarted) {
47-
finish()
48-
}
26+
val inputData = ReaderContract.parseIntent(this)
27+
modelFactory = ReaderViewModel.Factory(applicationContext, inputData)
4928
super.onCreate(savedInstanceState)
5029

51-
booksDB = BooksDatabase(this)
52-
bookmarksDB = BookmarksDatabase(this)
30+
ViewModelProvider(this).get(ReaderViewModel::class.java)
31+
.channel.receive(this) {handleReaderFragmentEvent(it) }
5332

54-
navigatorDelegate = this
33+
if (savedInstanceState == null) {
34+
supportFragmentManager.commitNow {
35+
add(R.id.activity_container, AudioReaderFragment::class.java, Bundle(), ReaderActivity.READER_FRAGMENT_TAG)
36+
}
5537

56-
bookId = intent.getLongExtra("bookId", -1)
38+
}
5739

58-
progressDialog = indeterminateProgressDialog(getString(R.string.progress_wait_while_preparing_audiobook))
40+
readerFragment = supportFragmentManager.findFragmentByTag(ReaderActivity.READER_FRAGMENT_TAG) as AudioReaderFragment
5941

60-
//Setting cover
61-
launch {
62-
delay(100)
63-
if (intent.hasExtra("cover")) {
64-
val byteArray = intent.getByteArrayExtra("cover")
65-
byteArray?.let {
66-
val bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
67-
findViewById<ImageView>(R.id.imageView).setImageBitmap(bmp)
68-
}
42+
supportFragmentManager.setFragmentResultListener(
43+
OutlineContract.REQUEST_KEY,
44+
this,
45+
FragmentResultListener { _, result ->
46+
val locator = OutlineContract.parseResult(result).destination
47+
closeOutlineFragment(locator)
6948
}
70-
menuDrm?.isVisible = publication.isProtected
71-
}
72-
mediaPlayer?.progress = progressDialog
73-
49+
)
50+
51+
supportFragmentManager.setFragmentResultListener(
52+
DrmManagementContract.REQUEST_KEY,
53+
this,
54+
FragmentResultListener { _, result ->
55+
if (DrmManagementContract.parseResult(result).hasReturned)
56+
finish()
57+
}
58+
)
7459

75-
// Loads the last read location
76-
booksDB.books.currentLocator(bookId)?.let {
77-
go(it, false, {})
60+
supportFragmentManager.addOnBackStackChangedListener {
61+
updateActivityTitle()
7862
}
7963
}
8064

81-
private var menuDrm: MenuItem? = null
82-
private var menuToc: MenuItem? = null
83-
private var menuBmk: MenuItem? = null
84-
private var menuSettings: MenuItem? = null
85-
86-
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
87-
menuInflater.inflate(R.menu.menu_audio, menu)
88-
menuDrm = menu?.findItem(R.id.drm)
89-
menuToc = menu?.findItem(R.id.toc)
90-
menuBmk = menu?.findItem(R.id.bookmark)
91-
menuSettings = menu?.findItem(R.id.settings)
92-
93-
menuSettings?.isVisible = false
94-
menuDrm?.isVisible = false
95-
return true
65+
override fun onStart() {
66+
super.onStart()
67+
updateActivityTitle()
9668
}
9769

98-
override fun onOptionsItemSelected(item: MenuItem): Boolean {
99-
when (item.itemId) {
10070

101-
R.id.toc -> {
102-
val intent = Intent(this, R2OutlineActivity::class.java).apply {
103-
putPublicationFrom(this@AudiobookActivity)
104-
putExtra("bookId", bookId)
105-
}
106-
startActivityForResult(intent, 2)
107-
return true
108-
}
109-
R.id.settings -> {
110-
// TODO do we need any settings ?
111-
return true
112-
}
113-
R.id.bookmark -> {
114-
val locator = currentLocator.value
115-
116-
val bookmark = Bookmark(bookId, publicationIdentifier, resourceIndex = currentResource.toLong(), locator = locator)
117-
bookmarksDB.bookmarks.insert(bookmark)?.let {
118-
launch {
119-
toast("Bookmark added")
120-
}
121-
} ?: run {
122-
launch {
123-
toast("Bookmark already exists")
124-
}
125-
}
126-
127-
return true
128-
}
129-
R.id.drm -> {
130-
startActivityForResult(intentFor<DRMManagementActivity>("publication" to publicationPath), 1)
131-
return true
132-
}
133-
134-
else -> return false
71+
private fun updateActivityTitle() {
72+
title = when (supportFragmentManager.fragments.last()) {
73+
is OutlineFragment -> publication.metadata.title
74+
is DrmManagementFragment -> getString(R.string.title_fragment_drm_management)
75+
else -> null
13576
}
77+
}
13678

79+
override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory {
80+
return modelFactory
13781
}
13882

139-
override fun onDestroy() {
140-
super.onDestroy()
141-
activitiesLaunched.getAndDecrement()
83+
private fun handleReaderFragmentEvent(event: ReaderViewModel.Event) {
84+
when(event) {
85+
is ReaderViewModel.Event.OpenOutlineRequested -> showOutlineFragment()
86+
is ReaderViewModel.Event.OpenDrmManagementRequested -> showDrmManagementFragment()
87+
}
14288
}
14389

144-
override fun onStop() {
145-
super.onStop()
146-
progressDialog.dismiss()
90+
private fun showOutlineFragment() {
91+
supportFragmentManager.commit {
92+
add(R.id.activity_container, OutlineFragment::class.java, Bundle(), ReaderActivity.OUTLINE_FRAGMENT_TAG)
93+
hide(readerFragment)
94+
addToBackStack(null)
95+
}
96+
}
97+
98+
private fun closeOutlineFragment(locator: Locator) {
99+
go(locator)
100+
supportFragmentManager.popBackStack()
147101
}
148102

103+
private fun showDrmManagementFragment() {
104+
supportFragmentManager.commit {
105+
add(R.id.activity_container, DrmManagementFragment::class.java, Bundle(), ReaderActivity.DRM_FRAGMENT_TAG)
106+
hide(readerFragment)
107+
addToBackStack(null)
108+
}
109+
}
149110
}
150111

151112

0 commit comments

Comments
 (0)