diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index f4d6d06e..4c7eefc2 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -1,17 +1,17 @@
-
+
-
+
-
-
+
+
-
-
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index bebf3976..1e273c91 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -74,7 +74,7 @@ dependencies {
implementation("androidx.compose.runtime:runtime-livedata:1.0.2")
implementation("androidx.compose.material:material-icons-extended:1.0.2")
implementation("androidx.activity:activity-compose:1.3.1")
- implementation("androidx.navigation:navigation-compose:2.4.0-alpha08")
+ implementation("androidx.navigation:navigation-compose:2.4.0-alpha09")
implementation("com.google.accompanist:accompanist-flowlayout:0.16.1")
implementation("com.google.accompanist:accompanist-appcompat-theme:0.16.0")
diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/Pupil.kt
index bd4fa425..b2d061a4 100644
--- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt
+++ b/app/src/main/java/xyz/quaver/pupil/Pupil.kt
@@ -44,6 +44,8 @@ import io.ktor.client.features.json.*
import io.ktor.client.features.json.serializer.*
import org.kodein.di.*
import org.kodein.di.android.x.androidXModule
+import org.kodein.log.LoggerFactory
+import org.kodein.log.newLogger
import xyz.quaver.io.FileX
import xyz.quaver.pupil.db.databaseModule
import xyz.quaver.pupil.sources.sourceModule
diff --git a/app/src/main/java/xyz/quaver/pupil/sources/Common.kt b/app/src/main/java/xyz/quaver/pupil/sources/Common.kt
index f8a6adb5..57eefd11 100644
--- a/app/src/main/java/xyz/quaver/pupil/sources/Common.kt
+++ b/app/src/main/java/xyz/quaver/pupil/sources/Common.kt
@@ -64,7 +64,7 @@ abstract class Source {
@Composable
open fun SearchResult(itemInfo: ItemInfo, onEvent: ((SearchResultEvent) -> Unit)? = null) { }
- open fun getHeadersBuilderForImage(itemID: String, url: String): HeadersBuilder.() -> Unit = { }
+ open fun getHeadersForImage(itemID: String, url: String): Map = emptyMap()
open fun onSuggestionBind(binding: SearchSuggestionItemBinding, item: SearchSuggestion) {
binding.leftIcon.setImageResource(R.drawable.tag)
diff --git a/app/src/main/java/xyz/quaver/pupil/sources/hitomi/Hitomi.kt b/app/src/main/java/xyz/quaver/pupil/sources/hitomi/Hitomi.kt
index 7e95be63..4ab25149 100644
--- a/app/src/main/java/xyz/quaver/pupil/sources/hitomi/Hitomi.kt
+++ b/app/src/main/java/xyz/quaver/pupil/sources/hitomi/Hitomi.kt
@@ -225,9 +225,9 @@ class Hitomi(app: Application) : Source(), DIAware {
FullSearchResult(itemInfo = itemInfo)
}
- override fun getHeadersBuilderForImage(itemID: String, url: String): HeadersBuilder.() -> Unit = {
- append("Referer", getReferer(itemID.toInt()))
- }
+ override fun getHeadersForImage(itemID: String, url: String) = mapOf(
+ "Referer" to getReferer(itemID.toInt())
+ )
override fun onSuggestionBind(binding: SearchSuggestionItemBinding, item: SearchSuggestion) {
item as TagSuggestion
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
index 2bb693e4..931bfdfc 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
@@ -23,10 +23,11 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Scaffold
-import androidx.compose.material.Text
-import androidx.compose.material.TopAppBar
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Fullscreen
import androidx.compose.runtime.getValue
@@ -34,13 +35,23 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.core.view.WindowCompat
+import androidx.compose.ui.unit.dp
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
+import coil.annotation.ExperimentalCoilApi
+import coil.compose.rememberImagePainter
+import coil.request.ImageRequest
+import coil.transform.BlurTransformation
import com.google.accompanist.appcompattheme.AppCompatTheme
+import io.ktor.http.*
+import okhttp3.Headers
import org.kodein.di.DIAware
import org.kodein.di.android.closestDI
+import org.kodein.log.LoggerFactory
+import org.kodein.log.newLogger
import xyz.quaver.pupil.R
import xyz.quaver.pupil.ui.composable.FloatingActionButtonState
import xyz.quaver.pupil.ui.composable.MultipleFloatingActionButton
@@ -52,12 +63,24 @@ class ReaderActivity : ComponentActivity(), DIAware {
private val model: ReaderViewModel by viewModels()
+ private val logger = newLogger(LoggerFactory.default)
+
+ @OptIn(ExperimentalCoilApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ model.handleIntent(intent)
+ model.load()
+
setContent {
var isFABExpanded by remember { mutableStateOf(FloatingActionButtonState.COLLAPSED) }
val isFullscreen by model.isFullscreen.observeAsState(false)
+ val title by model.title.observeAsState(stringResource(R.string.reader_loading))
+ val sourceIcon by model.sourceIcon.observeAsState()
+ val images by model.images.observeAsState(emptyList())
+ val source by model.sourceInstance.observeAsState()
+
+ logger.debug { "target: ${R.drawable.hitomi} value: $sourceIcon" }
WindowInsetsControllerCompat(window, window.decorView).run {
if (isFullscreen) {
@@ -74,30 +97,69 @@ class ReaderActivity : ComponentActivity(), DIAware {
TopAppBar(
title = {
Text(
- "Reader",
+ title,
color = MaterialTheme.colors.onSecondary
)
+ },
+ actions = {
+ sourceIcon?.let { sourceIcon ->
+ Image(
+ modifier = Modifier.size(36.dp),
+ painter = painterResource(id = sourceIcon),
+ contentDescription = null
+ )
+ }
}
)
},
floatingActionButton = {
- MultipleFloatingActionButton(
- items = listOf(
- SubFabItem(
- icon = Icons.Default.Fullscreen,
- label = stringResource(id = R.string.reader_fab_fullscreen)
- ) {
- model.isFullscreen.postValue(!isFullscreen)
+ if (!isFullscreen)
+ MultipleFloatingActionButton(
+ items = listOf(
+ SubFabItem(
+ icon = Icons.Default.Fullscreen,
+ label = stringResource(id = R.string.reader_fab_fullscreen)
+ ) {
+ model.isFullscreen.postValue(!isFullscreen)
+ }
+ ),
+ targetState = isFABExpanded,
+ onStateChanged = {
+ isFABExpanded = it
}
- ),
- targetState = isFABExpanded,
- onStateChanged = {
- isFABExpanded = it
- }
- )
+ )
}
) {
-
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(32.dp)
+ ) {
+ items(images) { image ->
+ Image(
+ modifier = Modifier.fillMaxWidth().heightIn(128.dp, 1000.dp),
+ painter = rememberImagePainter(
+ ImageRequest.Builder(this@ReaderActivity)
+ .data(image)
+ .headers(
+ Headers.headersOf(
+ *(source!!.getHeadersForImage(model.itemID.value!!, image).entries.fold(arrayOf()) { acc, entry ->
+ acc + entry.key + entry.value
+ })
+ ).also {
+ logger.debug {
+ image
+ }
+ logger.debug {
+ it.toString()
+ }
+ }
+ )
+ .transformations(BlurTransformation(this@ReaderActivity, 1f))
+ .build()
+ ),
+ contentDescription = null
+ )
+ }
+ }
}
}
}
@@ -107,4 +169,11 @@ class ReaderActivity : ComponentActivity(), DIAware {
super.onNewIntent(intent)
model.handleIntent(intent)
}
+
+ override fun onBackPressed() {
+ when {
+ model.isFullscreen.value == true -> model.isFullscreen.postValue(false)
+ else -> super.onBackPressed()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/composable/MultipleFloatingActionButton.kt b/app/src/main/java/xyz/quaver/pupil/ui/composable/MultipleFloatingActionButton.kt
index f649e5d4..9bd49333 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/composable/MultipleFloatingActionButton.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/composable/MultipleFloatingActionButton.kt
@@ -74,7 +74,7 @@ fun MiniFloatingActionButton(
FloatingActionButton(
modifier = Modifier
- .size(32.dp)
+ .size(40.dp)
.scale(buttonScale),
onClick = { onClick?.invoke(item) },
elevation = elevation,
@@ -185,7 +185,7 @@ fun MultipleFloatingActionButton(
}
MiniFloatingActionButton(
- modifier = Modifier.padding(end = 12.dp),
+ modifier = Modifier.padding(end = 8.dp),
item = item,
buttonScale = buttonScale,
labelAlpha = labelAlpha,
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/viewmodel/ReaderViewModel.kt b/app/src/main/java/xyz/quaver/pupil/ui/viewmodel/ReaderViewModel.kt
index 87c6ee1e..bb1d0e1a 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/viewmodel/ReaderViewModel.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/viewmodel/ReaderViewModel.kt
@@ -28,7 +28,10 @@ import io.ktor.client.request.*
import kotlinx.coroutines.*
import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI
+import org.kodein.di.direct
import org.kodein.di.instance
+import org.kodein.log.LoggerFactory
+import org.kodein.log.newLogger
import xyz.quaver.pupil.adapters.ReaderItem
import xyz.quaver.pupil.db.AppDatabase
import xyz.quaver.pupil.db.Bookmark
@@ -42,6 +45,8 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
override val di by closestDI()
+ private val logger = newLogger(LoggerFactory.default)
+
val isFullscreen = MutableLiveData(false)
private val database: AppDatabase by instance()
@@ -72,11 +77,11 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
}
val sourceInstance = Transformations.map(source) {
- source(it)
+ direct.source(it)
}
val sourceIcon = Transformations.map(sourceInstance) {
- it.value.iconResID
+ it.iconResID
}
/**
@@ -89,18 +94,18 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
val uri = intent.data
val lastPathSegment = uri?.lastPathSegment
if (uri != null && lastPathSegment != null) {
- _source.postValue(uri.host ?: error("Source cannot be null"))
- _itemID.postValue(when (uri.host) {
+ _source.value = uri.host ?: error("Source cannot be null")
+ _itemID.value = when (uri.host) {
"hitomi.la" ->
Regex("([0-9]+).html").find(lastPathSegment)?.groupValues?.get(1) ?: error("Invalid itemID")
"hiyobi.me" -> lastPathSegment
"e-hentai.org" -> uri.pathSegments[1]
else -> error("Invalid host")
- })
+ }
}
} else {
- _source.postValue(intent.getStringExtra("source") ?: error("Invalid source"))
- _itemID.postValue(intent.getStringExtra("id") ?: error("Invalid itemID"))
+ _source.value = intent.getStringExtra("source") ?: error("Invalid source")
+ _itemID.value = intent.getStringExtra("id") ?: error("Invalid itemID")
}
}
@@ -124,7 +129,7 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
viewModelScope.launch {
_images.postValue(withContext(Dispatchers.IO) {
source.images(itemID)
- })
+ }!!)
}
}