This commit is contained in:
tom5079
2021-12-18 00:23:27 +09:00
parent 98fda1a53f
commit 338b789e62
8 changed files with 117 additions and 25 deletions

View File

@@ -1,3 +1,5 @@
import com.google.protobuf.gradle.*
plugins { plugins {
id("com.android.application") id("com.android.application")
kotlin("android") kotlin("android")
@@ -8,6 +10,7 @@ plugins {
id("com.google.gms.google-services") id("com.google.gms.google-services")
id("com.google.firebase.crashlytics") id("com.google.firebase.crashlytics")
id("com.google.firebase.firebase-perf") id("com.google.firebase.firebase-perf")
id("com.google.protobuf")
} }
android { android {
@@ -104,6 +107,7 @@ dependencies {
implementation("androidx.gridlayout:gridlayout:1.0.0") implementation("androidx.gridlayout:gridlayout:1.0.0")
implementation("androidx.biometric:biometric:1.1.0") implementation("androidx.biometric:biometric:1.1.0")
implementation("androidx.work:work-runtime-ktx:2.7.1") implementation("androidx.work:work-runtime-ktx:2.7.1")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.4.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0")
implementation("androidx.room:room-runtime:2.3.0") implementation("androidx.room:room-runtime:2.3.0")
@@ -118,10 +122,12 @@ dependencies {
implementation("com.google.android.material:material:1.4.0") implementation("com.google.android.material:material:1.4.0")
implementation(platform("com.google.firebase:firebase-bom:28.3.0")) implementation(platform("com.google.firebase:firebase-bom:29.0.3"))
implementation("com.google.firebase:firebase-analytics-ktx") implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics") implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-perf") implementation("com.google.firebase:firebase-perf-ktx")
implementation("com.google.protobuf:protobuf-javalite:3.19.1")
implementation("com.google.android.gms:play-services-oss-licenses:17.0.0") implementation("com.google.android.gms:play-services-oss-licenses:17.0.0")
@@ -147,6 +153,21 @@ dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.0.5") androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.0.5")
} }
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.19.1"
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
id("java") {
option("lite")
}
}
}
}
}
task<Exec>("clearAppCache") { task<Exec>("clearAppCache") {
commandLine("adb", "shell", "pm", "clear", "xyz.quaver.pupil.debug") commandLine("adb", "shell", "pm", "clear", "xyz.quaver.pupil.debug")
} }

View File

@@ -40,5 +40,6 @@
-keepclasseswithmembers class xyz.quaver.** { -keepclasseswithmembers class xyz.quaver.** {
kotlinx.serialization.KSerializer serializer(...); kotlinx.serialization.KSerializer serializer(...);
} }
-keep class xyz.quaver.pupil.ui.fragment.ManageFavoritesFragment -keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite {
-keep class xyz.quaver.pupil.ui.fragment.ManageStorageFragment <fields>;
}

View File

@@ -0,0 +1,47 @@
/*
* Pupil, Hitomi.la viewer for Android
* Copyright (C) 2021 tom5079
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package xyz.quaver.pupil.proto
import android.content.Context
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.DataStore
import androidx.datastore.core.Serializer
import androidx.datastore.dataStore
import com.google.protobuf.InvalidProtocolBufferException
import java.io.InputStream
import java.io.OutputStream
object SettingsSerializer : Serializer<Settings> {
override val defaultValue: Settings = Settings.getDefaultInstance()
override suspend fun readFrom(input: InputStream): Settings {
try {
return Settings.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override suspend fun writeTo(t: Settings, output: OutputStream) = t.writeTo(output)
}
val Context.settingsDataStore: DataStore<Settings> by dataStore(
fileName = "settings.proto",
serializer = SettingsSerializer
)

View File

@@ -185,6 +185,7 @@ class MainActivity : ComponentActivity(), DIAware {
} }
) { ) {
Box(Modifier.fillMaxSize()) { Box(Modifier.fillMaxSize()) {
LazyColumn( LazyColumn(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
@@ -203,6 +204,16 @@ class MainActivity : ComponentActivity(), DIAware {
return Offset.Zero return Offset.Zero
} }
override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource
): Offset {
return super.onPostScroll(consumed, available, source)
}
}), }),
contentPadding = PaddingValues(0.dp, 56.dp, 0.dp, 0.dp) contentPadding = PaddingValues(0.dp, 56.dp, 0.dp, 0.dp)
) { ) {

View File

@@ -24,23 +24,22 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI import org.kodein.di.android.x.closestDI
import org.kodein.di.direct import org.kodein.di.direct
import org.kodein.di.instance import org.kodein.di.instance
import org.kodein.log.LoggerFactory import org.kodein.log.LoggerFactory
import org.kodein.log.newLogger import org.kodein.log.newLogger
import xyz.quaver.pupil.proto.settingsDataStore
import xyz.quaver.pupil.sources.History import xyz.quaver.pupil.sources.History
import xyz.quaver.pupil.sources.ItemInfo import xyz.quaver.pupil.sources.ItemInfo
import xyz.quaver.pupil.sources.Source import xyz.quaver.pupil.sources.Source
import xyz.quaver.pupil.util.Preferences
import xyz.quaver.pupil.util.source import xyz.quaver.pupil.util.source
import kotlin.math.ceil
import kotlin.math.roundToInt
import kotlin.random.Random import kotlin.random.Random
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -51,6 +50,10 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
val searchResults = mutableStateListOf<ItemInfo>() val searchResults = mutableStateListOf<ItemInfo>()
private val resultsPerPage = app.settingsDataStore.data.map {
it.resultsPerPage
}
var loading by mutableStateOf(false) var loading by mutableStateOf(false)
private set private set
@@ -72,13 +75,8 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
var currentPage by mutableStateOf(1) var currentPage by mutableStateOf(1)
private val totalItems = MutableLiveData<Int>() var totalItems by mutableStateOf(0)
private set
val totalPages = Transformations.map(totalItems) {
val perPage = Preferences["per_page", "25"].toInt()
ceil(it / perPage.toDouble()).roundToInt()
}
fun setSourceAndReset(sourceName: String) { fun setSourceAndReset(sourceName: String) {
source = sourceFactory(sourceName) source = sourceFactory(sourceName)
@@ -112,8 +110,6 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
} }
fun query() { fun query() {
val perPage = Preferences["per_page", "25"].toInt()
suggestionJob?.cancel() suggestionJob?.cancel()
queryJob?.cancel() queryJob?.cancel()
@@ -121,13 +117,19 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
searchResults.clear() searchResults.clear()
queryJob = viewModelScope.launch { queryJob = viewModelScope.launch {
val resultsPerPage = resultsPerPage.first()
logger.info {
resultsPerPage.toString()
}
val (channel, count) = source.search( val (channel, count) = source.search(
query, query,
(currentPage - 1) * perPage until currentPage * perPage, (currentPage - 1) * resultsPerPage until currentPage * resultsPerPage,
sortModeIndex sortModeIndex
) )
totalItems.postValue(count) totalItems = count
for (result in channel) { for (result in channel) {
yield() yield()
@@ -139,15 +141,15 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
} }
fun random(callback: (ItemInfo) -> Unit) { fun random(callback: (ItemInfo) -> Unit) {
if (totalItems.value!! == 0) if (totalItems == 0)
return return
val random = Random.Default.nextInt(totalItems.value!!) val random = Random.Default.nextInt(totalItems)
viewModelScope.launch { viewModelScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
source.search( source.search(
query + Preferences["default_query", ""], query,
random .. random, random .. random,
sortModeIndex sortModeIndex
).first.receive() ).first.receive()

View File

@@ -29,6 +29,7 @@ import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.toAndroidRect import androidx.compose.ui.graphics.toAndroidRect
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.json.* import kotlinx.serialization.json.*
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.DirectDIAware import org.kodein.di.DirectDIAware

View File

@@ -0,0 +1,8 @@
syntax = "proto2";
option java_package = "xyz.quaver.pupil.proto";
option java_multiple_files = true;
message Settings {
optional int32 results_per_page = 1 [default = 25];
}

View File

@@ -13,9 +13,10 @@ buildscript {
classpath("com.google.gms:google-services:4.3.10") classpath("com.google.gms:google-services:4.3.10")
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
classpath("com.google.firebase:firebase-crashlytics-gradle:2.8.0") classpath("com.google.firebase:firebase-crashlytics-gradle:2.8.1")
classpath("com.google.firebase:perf-plugin:1.4.0") classpath("com.google.firebase:perf-plugin:1.4.0")
classpath("com.google.android.gms:oss-licenses-plugin:0.10.4") classpath("com.google.android.gms:oss-licenses-plugin:0.10.4")
classpath("com.google.protobuf:protobuf-gradle-plugin:0.8.18")
} }
} }