From b8a1a767544d47266b93a802585a722ecef7fa85 Mon Sep 17 00:00:00 2001 From: aalbert Date: Thu, 6 Jun 2024 17:15:58 +0200 Subject: [PATCH 1/9] migrate to Gradle Kotlin DSL, version catalog and ksp --- app/build.gradle | 222 ------------------ app/build.gradle.kts | 173 ++++++++++++++ .../infrastructure/di/OkHttpClientModule.kt | 2 +- build.gradle | 56 ----- build.gradle.kts | 17 ++ gradle.properties | 2 +- gradle/libs.versions.toml | 98 ++++++++ settings.gradle => settings.gradle.kts | 6 +- 8 files changed, 294 insertions(+), 282 deletions(-) delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 gradle/libs.versions.toml rename settings.gradle => settings.gradle.kts (81%) diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 10713b715..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,222 +0,0 @@ -plugins { - id "com.android.application" - id "org.jetbrains.kotlin.android" - id "kotlin-kapt" - id "dagger.hilt.android.plugin" - id "com.google.dagger.hilt.android" - id 'com.mikepenz.aboutlibraries.plugin' -} - -def gitCommitHash = "git rev-parse --verify --short HEAD".execute().text.trim() -def keyProps = new Properties() -def keyPropsFile = rootProject.file("signature/keystore.properties") -if (keyPropsFile.exists()) { - println("Loading keystore properties from ${keyPropsFile.absolutePath}") - keyProps.load(new FileInputStream(keyPropsFile)) -} - -android { - compileSdk 34 - - defaultConfig { - applicationId "me.ash.reader" - minSdk 26 - targetSdk 33 - versionCode 25 - versionName "0.10.1" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary true - } - - javaCompileOptions { - annotationProcessorOptions { - arguments += [ - "room.schemaLocation": "$projectDir/schemas".toString(), - "room.incremental" : "true" - ] - } - } - } - - flavorDimensions "channel" - productFlavors { - github { - dimension "channel" - } - fdroid { - dimension "channel" - } - googlePlay { - dimension "channel" - applicationIdSuffix ".google.play" - } - } - signingConfigs { - release { - keyAlias keyProps["keyAlias"] - keyPassword keyProps["keyPassword"] - storeFile keyProps["storeFile"] ? file(keyProps["storeFile"]) : null - storePassword keyProps["storePassword"] - } - } - lint { - disable.addAll("MissingTranslation", "ExtraTranslation") - } - buildTypes { - release { - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" - signingConfig signingConfigs.release - } - } - applicationVariants.all { variant -> - variant.outputs.each { output -> - output.outputFileName = "ReadYou-${defaultConfig.versionName}-${gitCommitHash}.apk" - } - } - kotlinOptions { - freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.RequiresOptIn" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11 - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.5.8' - } - packagingOptions { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } - -// https://developer.android.com/guide/topics/resources/app-languages#auto-localeconfig - androidResources { - generateLocaleConfig true - } - - namespace 'me.ash.reader' -} - -dependencies { - // https://github.com/mikepenz/AboutLibraries/releases - implementation "com.mikepenz:aboutlibraries-core:${aboutLibsRelease}" - implementation "com.mikepenz:aboutlibraries-compose-m3:${aboutLibsRelease}" - - // https://github.com/ireward/compose-html/tags - implementation "com.github.ireward:compose-html:1.0.2" - - // http://bigbadaboom.github.io/androidsvg/release_notes.html - implementation "com.caverock:androidsvg-aar:$androidSVG" - - // https://github.com/mdewilde/opml-parser - implementation "be.ceau:opml-parser:$opmlParser" - - // https://github.com/dankito/Readability4J - implementation "net.dankito.readability4j:readability4j:$readability4j" - - // https://mvnrepository.com/artifact/com.rometools/rome - implementation "com.rometools:rome:$rome" - - // https://coil-kt.github.io/coil/changelog/ - implementation("io.coil-kt:coil-base:$coil") - implementation("io.coil-kt:coil-compose:$coil") - implementation("io.coil-kt:coil-svg:$coil") - implementation("io.coil-kt:coil-gif:$coil") - - // https://saket.github.io/telephoto/zoomableimage/ - implementation("me.saket.telephoto:zoomable:0.7.1") - - // Cancel TLSv1.3 support pre Android10 - // implementation 'org.conscrypt:conscrypt-android:2.5.2' - - // https://square.github.io/okhttp/changelogs/changelog/ - implementation "com.squareup.okhttp3:okhttp:$okhttp" - implementation "com.squareup.okhttp3:okhttp-coroutines-jvm:$okhttp" - implementation "com.squareup.retrofit2:retrofit:$retrofit2" - implementation "com.squareup.retrofit2:converter-gson:$retrofit2" - - // https://developer.android.com/jetpack/androidx/releases/profileinstaller - implementation "androidx.profileinstaller:profileinstaller:$profileinstaller" - - // https://developer.android.com/jetpack/androidx/releases/work - implementation "androidx.work:work-runtime-ktx:$work" - - // https://developer.android.com/jetpack/androidx/releases/datastore - implementation "androidx.datastore:datastore-preferences:$datastore" - - // https://developer.android.com/jetpack/androidx/releases/room - implementation "androidx.room:room-paging:$room" - implementation "androidx.room:room-common:$room" - implementation "androidx.room:room-ktx:$room" - kapt "androidx.room:room-compiler:$room" - - // https://developer.android.com/jetpack/androidx/releases/paging - implementation "androidx.paging:paging-common-ktx:$paging" - implementation "androidx.paging:paging-runtime-ktx:$paging" - implementation "androidx.paging:paging-compose:$paging" - - // https://developer.android.com/jetpack/androidx/releases/paging - implementation "androidx.browser:browser:1.8.0" - - // https://developer.android.com/jetpack/androidx/releases/navigation - implementation "androidx.navigation:navigation-compose:$navigation" - - // https://developer.android.com/jetpack/androidx/releases/lifecycle - implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle" - implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle" - - // https://developer.android.com/jetpack/androidx/releases/compose-material3 - implementation "androidx.compose.material3:material3" - - // https://github.com/google/accompanist/releases - implementation "com.google.accompanist:accompanist-pager:$accompanist" - implementation "com.google.accompanist:accompanist-flowlayout:$accompanist" - implementation "com.google.accompanist:accompanist-swiperefresh:$accompanist" - - implementation platform("androidx.compose:compose-bom:$composeBom") - androidTestImplementation(platform("androidx.compose:compose-bom:$composeBom")) - - // https://developer.android.com/jetpack/androidx/releases/compose-animation - implementation "androidx.compose.animation:animation-graphics" - // https://developer.android.com/jetpack/androidx/releases/compose-ui - implementation "androidx.compose.ui:ui" - implementation "androidx.compose.ui:ui-util" - // https://developer.android.com/jetpack/androidx/releases/compose-material - implementation "androidx.compose.material:material" - implementation "androidx.compose.material:material-icons-extended" - implementation "androidx.compose.ui:ui-tooling" - implementation "androidx.compose.ui:ui-tooling-preview" - - androidTestImplementation "androidx.compose.ui:ui-test-junit4" - - // hilt - implementation "androidx.hilt:hilt-work:1.1.0" - implementation "com.google.dagger:hilt-android:2.50" - kapt "com.google.dagger:hilt-android-compiler:2.50" -// implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03" - kapt "androidx.hilt:hilt-compiler:1.1.0" - implementation "androidx.hilt:hilt-navigation-compose:1.1.0" - - // android - implementation "androidx.core:core-ktx:1.13.1" - implementation "androidx.activity:activity-compose:1.9.0" - implementation 'androidx.appcompat:appcompat:1.7.0' - testImplementation "junit:junit:4.13.2" - androidTestImplementation "androidx.test.ext:junit:1.1.5" - androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1" - - // mockito - testImplementation "org.mockito:mockito-core:5.11.0" - testImplementation 'org.mockito:mockito-junit-jupiter:5.11.0' - testImplementation "org.mockito.kotlin:mockito-kotlin:5.2.1" -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..e7f6e6f18 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,173 @@ +import java.util.Properties +import java.io.FileInputStream + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("dagger.hilt.android.plugin") + id("com.google.dagger.hilt.android") + id("com.mikepenz.aboutlibraries.plugin") + id("com.google.devtools.ksp") +} + +fun fetchGitCommitHash(): String { + val process = ProcessBuilder("git", "rev-parse", "--verify", "--short", "HEAD") + .redirectErrorStream(true) + .start() + return process.inputStream.bufferedReader().use { it.readText().trim() } +} + +val gitCommitHash = fetchGitCommitHash() +val keyProps = Properties() +val keyPropsFile = rootProject.file("signature/keystore.properties") +if (keyPropsFile.exists()) { + println("Loading keystore properties from ${keyPropsFile.absolutePath}") + keyProps.load(FileInputStream(keyPropsFile)) +} + +android { + compileSdk = 34 + + defaultConfig { + applicationId = "me.ash.reader" + minSdk = 26 + targetSdk = 33 + versionCode = 25 + versionName = "0.10.1" + + buildConfigField("String", "USER_AGENT_STRING", "\"ReadYou/${'$'}{versionName}(${versionCode})\"") + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables.useSupportLibrary = true + + javaCompileOptions { + annotationProcessorOptions { + arguments.putAll(mapOf( + "room.schemaLocation" to "$projectDir/schemas", + "room.incremental" to "true" + )) + } + } + } + + flavorDimensions.add("channel") + productFlavors { + create("github") { + dimension = "channel" + } + create("fdroid") { + dimension = "channel" + } + create("googlePlay") { + dimension = "channel" + applicationIdSuffix = ".google.play" + } + } + signingConfigs { + create("release") { + keyAlias = keyProps["keyAlias"] as String? + keyPassword = keyProps["keyPassword"] as String? + storeFile = keyProps["storeFile"]?.let { file(it as String) } + storePassword = keyProps["storePassword"] as String? + } + } + lint { + disable.addAll(listOf("MissingTranslation", "ExtraTranslation")) + } + buildTypes { + getByName("release") { + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + signingConfig = signingConfigs.getByName("release") + } + } + applicationVariants.all { + outputs.all { + (this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName = "ReadYou-${defaultConfig.versionName}-${gitCommitHash}.apk" + } + } + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.RequiresOptIn" + jvmTarget = JavaVersion.VERSION_11.toString() + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + buildFeatures { + compose = true + buildConfig = true + } + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() + } + packaging { + resources.excludes.add("/META-INF/{AL2.0,LGPL2.1}") + } + androidResources { + generateLocaleConfig = true + } + namespace = "me.ash.reader" +} + +dependencies { + implementation(libs.aboutLibrariesCore) + implementation(libs.aboutLibrariesComposeM3) + implementation(libs.composeHtml) + implementation(libs.androidSVG) + implementation(libs.opmlParser) + implementation(libs.readability4j) + implementation(libs.rome) + implementation(libs.coilBase) + implementation(libs.coilCompose) + implementation(libs.coilSvg) + implementation(libs.coilGif) + implementation(libs.telephoto) + implementation(libs.okhttp) + implementation(libs.okhttpCoroutines) + implementation(libs.retrofit) + implementation(libs.retrofitGson) + implementation(libs.profileinstaller) + implementation(libs.workRuntimeKtx) + implementation(libs.datastorePreferences) + implementation(libs.roomPaging) + implementation(libs.roomCommon) + implementation(libs.roomKtx) + ksp(libs.roomCompiler) + implementation(libs.pagingCommonKtx) + implementation(libs.pagingRuntimeKtx) + implementation(libs.pagingCompose) + implementation(libs.browser) + implementation(libs.navigationCompose) + implementation(libs.lifecycleViewModelCompose) + implementation(libs.lifecycleRuntimeKtx) + implementation(libs.composeMaterial3) + implementation(libs.accompanistPager) + implementation(libs.accompanistFlowlayout) + implementation(libs.accompanistSwiperefresh) + implementation(platform(libs.composeBom)) + androidTestImplementation(platform(libs.composeBom)) + implementation(libs.composeAnimationGraphics) + implementation(libs.composeUi) + implementation(libs.composeUiUtil) + implementation(libs.composeMaterial) + implementation(libs.composeMaterialIconsExtended) + implementation(libs.composeUiTooling) + implementation(libs.composeUiToolingPreview) + androidTestImplementation(libs.composeUiTestJunit4) + implementation(libs.hiltWork) + implementation(libs.hiltAndroid) + ksp(libs.hiltAndroidCompiler) + ksp(libs.hiltCompiler) + implementation(libs.hiltNavigationCompose) + implementation(libs.coreKtx) + implementation(libs.activityCompose) + implementation(libs.appcompat) + testImplementation(libs.junit) + androidTestImplementation(libs.junitExt) + androidTestImplementation(libs.espressoCore) + testImplementation(libs.mockitoCore) + testImplementation(libs.mockitoJUnitJupiter) + testImplementation(libs.mockitoKotlin) +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/infrastructure/di/OkHttpClientModule.kt b/app/src/main/java/me/ash/reader/infrastructure/di/OkHttpClientModule.kt index 2d45df76f..2973f4ff9 100644 --- a/app/src/main/java/me/ash/reader/infrastructure/di/OkHttpClientModule.kt +++ b/app/src/main/java/me/ash/reader/infrastructure/di/OkHttpClientModule.kt @@ -122,4 +122,4 @@ object UserAgentInterceptor : Interceptor { } } -const val USER_AGENT_STRING = "ReadYou/${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})" +const val USER_AGENT_STRING = BuildConfig.USER_AGENT_STRING \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 0b29d6ca7..000000000 --- a/build.gradle +++ /dev/null @@ -1,56 +0,0 @@ -buildscript { - ext { -// https://developer.android.com/jetpack/androidx/releases/compose-ui -// compose = '1.2.0-beta02' - // https://developer.android.com/jetpack/compose/bom - composeBom = '2024.05.00' - // https://github.com/google/accompanist/releases - accompanist = '0.34.0' - // https://developer.android.com/jetpack/androidx/releases/compose-material3 -// material3 = '1.2.0-rc01' - // https://developer.android.com/jetpack/androidx/releases/lifecycle - lifecycle = '2.8.1' - // https://developer.android.com/jetpack/androidx/releases/navigation - navigation = '2.7.7' - // https://developer.android.com/jetpack/androidx/releases/paging - paging = '3.3.0' - // https://developer.android.com/jetpack/androidx/releases/room - room = '2.6.1' - // https://developer.android.com/jetpack/androidx/releases/datastore - datastore = '1.1.1' - // https://developer.android.com/jetpack/androidx/releases/work - work = '2.9.0' - // https://developer.android.com/jetpack/androidx/releases/profileinstaller - profileinstaller = '1.3.1' - // https://square.github.io/okhttp/changelogs/changelog/ - okhttp = '5.0.0-alpha.12' - retrofit2 = '2.9.0' - // https://coil-kt.github.io/coil/changelog/ - coil = '2.5.0' - // https://mvnrepository.com/artifact/com.rometools/rome - rome = '1.18.0' - // https://github.com/dankito/Readability4J - readability4j = '1.0.8' - // https://github.com/mdewilde/opml-parser - opmlParser = '3.1.0' - // http://bigbadaboom.github.io/androidsvg/release_notes.html - androidSVG = '1.4' - // https://github.com/mikepenz/AboutLibraries/releases - aboutLibsRelease = '11.1.1' - } - - dependencies { - classpath 'com.google.dagger:hilt-android-gradle-plugin:2.50' - } -} - -plugins { - id 'com.android.application' version '8.2.1' apply false - id 'com.android.library' version '8.2.1' apply false - id 'org.jetbrains.kotlin.android' version '1.9.22' apply false - id 'com.mikepenz.aboutlibraries.plugin' version "${aboutLibsRelease}" apply false -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..2ead1b740 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,17 @@ +buildscript { + dependencies { + classpath(libs.daggerHiltPlugin) + } +} + +plugins { + id("com.android.application") version libs.versions.androidGradlePlugin.get() apply false + id("com.android.library") version libs.versions.androidGradlePlugin.get() apply false + id("org.jetbrains.kotlin.android") version libs.versions.kotlin.get() apply false + id("com.mikepenz.aboutlibraries.plugin") version libs.versions.aboutLibsRelease.get() apply false + id("com.google.devtools.ksp") version libs.versions.ksp.get() apply false +} + +tasks.register("clean") { + delete(rootProject.buildDir) +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index a77285de8..58126b292 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -XX:+UseParallelGC org.gradle.parallel=true +android.buildConfig = true android.useAndroidX=true -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false android.enableR8.fullMode=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..60d0b810f --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,98 @@ +[versions] +composeBom = "2024.05.00" +accompanist = "0.34.0" +lifecycle = "2.8.1" +navigation = "2.7.7" +paging = "3.3.0" +room = "2.6.1" +datastore = "1.1.1" +work = "2.9.0" +profileinstaller = "1.3.1" +okhttp = "5.0.0-alpha.12" +retrofit2 = "2.9.0" +coil = "2.5.0" +rome = "1.18.0" +readability4j = "1.0.8" +opmlParser = "3.1.0" +androidSVG = "1.4" +aboutLibsRelease = "11.1.1" +daggerHilt = "2.50" +androidGradlePlugin = "8.2.1" +kotlin = "1.9.22" +ksp = "1.9.22-1.0.17" +composeCompiler = "1.5.8" +telephoto = "0.7.1" +browser = "1.8.0" +coreKtx = "1.13.1" +activityCompose = "1.9.0" +appcompat = "1.7.0" +junit = "4.13.2" +junitExt = "1.1.5" +espresso = "3.5.1" +mockitoCore = "5.11.0" +mockitoJUnitJupiter = "5.11.0" +mockitoKotlin = "5.2.1" +hiltWork = "1.1.0" +hiltAndroid = "2.50" +hiltCompiler = "1.1.0" +hiltNavigationCompose = "1.1.0" + +[libraries] +daggerHiltPlugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "daggerHilt" } +aboutLibrariesCore = { group = "com.mikepenz", name = "aboutlibraries-core", version.ref = "aboutLibsRelease" } +aboutLibrariesComposeM3 = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "aboutLibsRelease" } +composeHtml = { group = "com.github.ireward", name = "compose-html", version = "1.0.2" } +androidSVG = { group = "com.caverock", name = "androidsvg-aar", version.ref = "androidSVG" } +opmlParser = { group = "be.ceau", name = "opml-parser", version.ref = "opmlParser" } +readability4j = { group = "net.dankito.readability4j", name = "readability4j", version.ref = "readability4j" } +rome = { group = "com.rometools", name = "rome", version.ref = "rome" } +coilBase = { group = "io.coil-kt", name = "coil-base", version.ref = "coil" } +coilCompose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } +coilSvg = { group = "io.coil-kt", name = "coil-svg", version.ref = "coil" } +coilGif = { group = "io.coil-kt", name = "coil-gif", version.ref = "coil" } +telephoto = { group = "me.saket.telephoto", name = "zoomable", version.ref = "telephoto" } +okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } +okhttpCoroutines = { group = "com.squareup.okhttp3", name = "okhttp-coroutines-jvm", version.ref = "okhttp" } +retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit2" } +retrofitGson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit2" } +profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "profileinstaller" } +workRuntimeKtx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" } +datastorePreferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" } +roomPaging = { group = "androidx.room", name = "room-paging", version.ref = "room" } +roomCommon = { group = "androidx.room", name = "room-common", version.ref = "room" } +roomKtx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } +roomCompiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } +pagingCommonKtx = { group = "androidx.paging", name = "paging-common-ktx", version.ref = "paging" } +pagingRuntimeKtx = { group = "androidx.paging", name = "paging-runtime-ktx", version.ref = "paging" } +pagingCompose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging" } +browser = { group = "androidx.browser", name = "browser", version.ref = "browser" } +navigationCompose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } +lifecycleViewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" } +lifecycleRuntimeKtx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } +composeMaterial3 = { group = "androidx.compose.material3", name = "material3" } +accompanistPager = { group = "com.google.accompanist", name = "accompanist-pager", version.ref = "accompanist" } +accompanistFlowlayout = { group = "com.google.accompanist", name = "accompanist-flowlayout", version.ref = "accompanist" } +accompanistSwiperefresh = { group = "com.google.accompanist", name = "accompanist-swiperefresh", version.ref = "accompanist" } +composeBom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +composeAnimationGraphics = { group = "androidx.compose.animation", name = "animation-graphics" } +composeUi = { group = "androidx.compose.ui", name = "ui" } +composeUiUtil = { group = "androidx.compose.ui", name = "ui-util" } +composeMaterial = { group = "androidx.compose.material", name = "material" } +composeMaterialIconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" } +composeUiTooling = { group = "androidx.compose.ui", name = "ui-tooling" } +composeUiToolingPreview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +composeUiTestJunit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +hiltWork = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltWork" } +hiltAndroid = { group = "com.google.dagger", name = "hilt-android", version.ref = "hiltAndroid" } +hiltAndroidCompiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hiltAndroid" } +hiltCompiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltCompiler" } +hiltNavigationCompose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } +coreKtx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +activityCompose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +junitExt = { group = "androidx.test.ext", name = "junit", version.ref = "junitExt" } +espressoCore = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" } +mockitoCore = { group = "org.mockito", name = "mockito-core", version.ref = "mockitoCore" } +mockitoJUnitJupiter = { group = "org.mockito", name = "mockito-junit-jupiter", version.ref = "mockitoJUnitJupiter" } +mockitoKotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version.ref = "mockitoKotlin" } diff --git a/settings.gradle b/settings.gradle.kts similarity index 81% rename from settings.gradle rename to settings.gradle.kts index efa8c3962..421184d26 100644 --- a/settings.gradle +++ b/settings.gradle.kts @@ -5,13 +5,15 @@ pluginManagement { mavenCentral() } } + dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() - maven { url 'https://jitpack.io' } + maven { url = uri("https://jitpack.io") } } } + rootProject.name = "Reader" -include ':app' +include(":app") From 8d1676aa8c7f496892dc07f62b48857747e03084 Mon Sep 17 00:00:00 2001 From: aalbert Date: Thu, 6 Jun 2024 17:28:28 +0200 Subject: [PATCH 2/9] replace buildDir with layout.buildDirectory --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2ead1b740..e4b8169a3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,5 +13,5 @@ plugins { } tasks.register("clean") { - delete(rootProject.buildDir) + delete(rootProject.layout.buildDirectory) } \ No newline at end of file From fe8cd063c2be6a081b5c65ec473e9c6102bdc123 Mon Sep 17 00:00:00 2001 From: aalbert Date: Fri, 7 Jun 2024 12:33:33 +0200 Subject: [PATCH 3/9] declare plugins in version catalogs --- build.gradle.kts | 10 +++---- gradle/libs.versions.toml | 63 ++++++++++++++++++++++----------------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e4b8169a3..aabee4120 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,11 +5,11 @@ buildscript { } plugins { - id("com.android.application") version libs.versions.androidGradlePlugin.get() apply false - id("com.android.library") version libs.versions.androidGradlePlugin.get() apply false - id("org.jetbrains.kotlin.android") version libs.versions.kotlin.get() apply false - id("com.mikepenz.aboutlibraries.plugin") version libs.versions.aboutLibsRelease.get() apply false - id("com.google.devtools.ksp") version libs.versions.ksp.get() apply false + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.aboutlibraries.plugin) apply false } tasks.register("clean") { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 60d0b810f..70ff51c5d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,41 +1,41 @@ [versions] -composeBom = "2024.05.00" -accompanist = "0.34.0" -lifecycle = "2.8.1" -navigation = "2.7.7" -paging = "3.3.0" -room = "2.6.1" -datastore = "1.1.1" -work = "2.9.0" -profileinstaller = "1.3.1" -okhttp = "5.0.0-alpha.12" -retrofit2 = "2.9.0" -coil = "2.5.0" -rome = "1.18.0" -readability4j = "1.0.8" -opmlParser = "3.1.0" -androidSVG = "1.4" aboutLibsRelease = "11.1.1" -daggerHilt = "2.50" +accompanist = "0.34.0" +activityCompose = "1.9.0" androidGradlePlugin = "8.2.1" -kotlin = "1.9.22" -ksp = "1.9.22-1.0.17" -composeCompiler = "1.5.8" -telephoto = "0.7.1" +androidSVG = "1.4" +appcompat = "1.7.0" browser = "1.8.0" +coil = "2.5.0" +composeBom = "2024.05.00" +composeCompiler = "1.5.8" coreKtx = "1.13.1" -activityCompose = "1.9.0" -appcompat = "1.7.0" +daggerHilt = "2.50" +datastore = "1.1.1" +espresso = "3.5.1" +hiltAndroid = "2.50" +hiltCompiler = "1.1.0" +hiltNavigationCompose = "1.1.0" +hiltWork = "1.1.0" junit = "4.13.2" junitExt = "1.1.5" -espresso = "3.5.1" +kotlin = "1.9.22" +ksp = "1.9.22-1.0.17" +lifecycle = "2.8.1" mockitoCore = "5.11.0" mockitoJUnitJupiter = "5.11.0" mockitoKotlin = "5.2.1" -hiltWork = "1.1.0" -hiltAndroid = "2.50" -hiltCompiler = "1.1.0" -hiltNavigationCompose = "1.1.0" +navigation = "2.7.7" +okhttp = "5.0.0-alpha.12" +opmlParser = "3.1.0" +paging = "3.3.0" +profileinstaller = "1.3.1" +readability4j = "1.0.8" +retrofit2 = "2.9.0" +rome = "1.18.0" +room = "2.6.1" +telephoto = "0.7.1" +work = "2.9.0" [libraries] daggerHiltPlugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "daggerHilt" } @@ -96,3 +96,10 @@ espressoCore = { group = "androidx.test.espresso", name = "espresso-core", versi mockitoCore = { group = "org.mockito", name = "mockito-core", version.ref = "mockitoCore" } mockitoJUnitJupiter = { group = "org.mockito", name = "mockito-junit-jupiter", version.ref = "mockitoJUnitJupiter" } mockitoKotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version.ref = "mockitoKotlin" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin"} +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +aboutlibraries-plugin = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibsRelease" } \ No newline at end of file From bda15a01f78edfcf736ccb58f728fff11cab870f Mon Sep 17 00:00:00 2001 From: aalbert Date: Fri, 7 Jun 2024 12:54:23 +0200 Subject: [PATCH 4/9] add room plugin --- app/build.gradle.kts | 14 +++++++------- build.gradle.kts | 1 + gradle/libs.versions.toml | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e7f6e6f18..ba20bcd7b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -8,6 +8,7 @@ plugins { id("com.google.dagger.hilt.android") id("com.mikepenz.aboutlibraries.plugin") id("com.google.devtools.ksp") + id("androidx.room") } fun fetchGitCommitHash(): String { @@ -40,13 +41,12 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true - javaCompileOptions { - annotationProcessorOptions { - arguments.putAll(mapOf( - "room.schemaLocation" to "$projectDir/schemas", - "room.incremental" to "true" - )) - } + room { + schemaDirectory("$projectDir/schemas") + } + + ksp { + arg("room.incremental","true") } } diff --git a/build.gradle.kts b/build.gradle.kts index aabee4120..6a85c9062 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,7 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.aboutlibraries.plugin) apply false + alias(libs.plugins.room) apply false } tasks.register("clean") { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 70ff51c5d..411a55753 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -102,4 +102,5 @@ android-application = { id = "com.android.application", version.ref = "androidGr android-library = { id = "com.android.library", version.ref = "androidGradlePlugin"} kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -aboutlibraries-plugin = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibsRelease" } \ No newline at end of file +aboutlibraries-plugin = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibsRelease" } +room = { id = "androidx.room", version.ref = "room" } \ No newline at end of file From 4cb9ad777b2ff3699ab60e81571cbfda25800628 Mon Sep 17 00:00:00 2001 From: aalbert Date: Fri, 7 Jun 2024 12:55:23 +0200 Subject: [PATCH 5/9] specify type of keyPropsFile --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ba20bcd7b..66328ca39 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -20,7 +20,7 @@ fun fetchGitCommitHash(): String { val gitCommitHash = fetchGitCommitHash() val keyProps = Properties() -val keyPropsFile = rootProject.file("signature/keystore.properties") +val keyPropsFile: File = rootProject.file("signature/keystore.properties") if (keyPropsFile.exists()) { println("Loading keystore properties from ${keyPropsFile.absolutePath}") keyProps.load(FileInputStream(keyPropsFile)) From 32587b605faccf58fa8a688c9d2799d6c35d4e57 Mon Sep 17 00:00:00 2001 From: aalbert Date: Fri, 7 Jun 2024 13:44:15 +0200 Subject: [PATCH 6/9] added missing version number in [versions] --- gradle/libs.versions.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 411a55753..98dbb8064 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,7 @@ browser = "1.8.0" coil = "2.5.0" composeBom = "2024.05.00" composeCompiler = "1.5.8" +composeHtml = "1.0.2" coreKtx = "1.13.1" daggerHilt = "2.50" datastore = "1.1.1" @@ -41,7 +42,7 @@ work = "2.9.0" daggerHiltPlugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "daggerHilt" } aboutLibrariesCore = { group = "com.mikepenz", name = "aboutlibraries-core", version.ref = "aboutLibsRelease" } aboutLibrariesComposeM3 = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "aboutLibsRelease" } -composeHtml = { group = "com.github.ireward", name = "compose-html", version = "1.0.2" } +composeHtml = { group = "com.github.ireward", name = "compose-html", version.ref = "composeHtml" } androidSVG = { group = "com.caverock", name = "androidsvg-aar", version.ref = "androidSVG" } opmlParser = { group = "be.ceau", name = "opml-parser", version.ref = "opmlParser" } readability4j = { group = "net.dankito.readability4j", name = "readability4j", version.ref = "readability4j" } From 2a772c1eb156e2a1093e26c5755c94b6fef4860f Mon Sep 17 00:00:00 2001 From: aalbert Date: Fri, 7 Jun 2024 15:00:59 +0200 Subject: [PATCH 7/9] use alias instead of id whenever possible --- app/build.gradle.kts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 66328ca39..b612a8c61 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,13 +2,13 @@ import java.util.Properties import java.io.FileInputStream plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") + kotlin("android") + alias(libs.plugins.android.application) + alias(libs.plugins.ksp) + alias(libs.plugins.aboutlibraries.plugin) + alias(libs.plugins.room) id("dagger.hilt.android.plugin") id("com.google.dagger.hilt.android") - id("com.mikepenz.aboutlibraries.plugin") - id("com.google.devtools.ksp") - id("androidx.room") } fun fetchGitCommitHash(): String { From 285770cffdf3480f6b6f435cb2d3bb535bb24338 Mon Sep 17 00:00:00 2001 From: aalbert Date: Fri, 7 Jun 2024 15:18:24 +0200 Subject: [PATCH 8/9] finishes replacing id with alias --- app/build.gradle.kts | 3 +-- build.gradle.kts | 7 +------ gradle/libs.versions.toml | 5 ++--- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b612a8c61..ff2d5f842 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,8 +7,7 @@ plugins { alias(libs.plugins.ksp) alias(libs.plugins.aboutlibraries.plugin) alias(libs.plugins.room) - id("dagger.hilt.android.plugin") - id("com.google.dagger.hilt.android") + alias(libs.plugins.hilt) } fun fetchGitCommitHash(): String { diff --git a/build.gradle.kts b/build.gradle.kts index 6a85c9062..fd07e5011 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,3 @@ -buildscript { - dependencies { - classpath(libs.daggerHiltPlugin) - } -} - plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false @@ -11,6 +5,7 @@ plugins { alias(libs.plugins.ksp) apply false alias(libs.plugins.aboutlibraries.plugin) apply false alias(libs.plugins.room) apply false + alias(libs.plugins.hilt) apply false } tasks.register("clean") { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 98dbb8064..322e89c82 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,6 @@ composeBom = "2024.05.00" composeCompiler = "1.5.8" composeHtml = "1.0.2" coreKtx = "1.13.1" -daggerHilt = "2.50" datastore = "1.1.1" espresso = "3.5.1" hiltAndroid = "2.50" @@ -39,7 +38,6 @@ telephoto = "0.7.1" work = "2.9.0" [libraries] -daggerHiltPlugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "daggerHilt" } aboutLibrariesCore = { group = "com.mikepenz", name = "aboutlibraries-core", version.ref = "aboutLibsRelease" } aboutLibrariesComposeM3 = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "aboutLibsRelease" } composeHtml = { group = "com.github.ireward", name = "compose-html", version.ref = "composeHtml" } @@ -104,4 +102,5 @@ android-library = { id = "com.android.library", version.ref = "androidGradlePlug kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } aboutlibraries-plugin = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibsRelease" } -room = { id = "androidx.room", version.ref = "room" } \ No newline at end of file +room = { id = "androidx.room", version.ref = "room" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" } \ No newline at end of file From a71e3867964de3dd6e4efd5581c05c85152c3f62 Mon Sep 17 00:00:00 2001 From: aalbert Date: Thu, 13 Jun 2024 09:12:50 +0200 Subject: [PATCH 9/9] applies commits from pull request 568 on top of main --- .../infrastructure/preference/Preference.kt | 1 + .../preference/ReadingRendererPreference.kt | 46 +++ .../ReadingSubheadAlignPreference.kt | 8 + .../preference/ReadingTextAlignPreference.kt | 8 + .../infrastructure/preference/Settings.kt | 2 + .../ash/reader/ui/component/base/RYWebView.kt | 377 ++++++++++++++++++ .../ash/reader/ui/component/base/WebView.kt | 215 ---------- .../java/me/ash/reader/ui/ext/DataStoreExt.kt | 2 + .../reader/ui/page/home/reading/Content.kt | 57 ++- .../color/reading/ReadingStylePage.kt | 26 +- app/src/main/res/values-zh-rCN/strings.xml | 2 + app/src/main/res/values/strings.xml | 3 + 12 files changed, 498 insertions(+), 249 deletions(-) create mode 100644 app/src/main/java/me/ash/reader/infrastructure/preference/ReadingRendererPreference.kt create mode 100644 app/src/main/java/me/ash/reader/ui/component/base/RYWebView.kt delete mode 100644 app/src/main/java/me/ash/reader/ui/component/base/WebView.kt diff --git a/app/src/main/java/me/ash/reader/infrastructure/preference/Preference.kt b/app/src/main/java/me/ash/reader/infrastructure/preference/Preference.kt index b001b01a0..801c7a09e 100644 --- a/app/src/main/java/me/ash/reader/infrastructure/preference/Preference.kt +++ b/app/src/main/java/me/ash/reader/infrastructure/preference/Preference.kt @@ -53,6 +53,7 @@ fun Preferences.toSettings(): Settings { flowArticleListTonalElevation = FlowArticleListTonalElevationPreference.fromPreferences(this), // Reading page + readingRenderer = ReadingRendererPreference.fromPreferences(this), readingTheme = ReadingThemePreference.fromPreferences(this), readingDarkTheme = ReadingDarkThemePreference.fromPreferences(this), readingPageTonalElevation = ReadingPageTonalElevationPreference.fromPreferences(this), diff --git a/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingRendererPreference.kt b/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingRendererPreference.kt new file mode 100644 index 000000000..2c0ac6a71 --- /dev/null +++ b/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingRendererPreference.kt @@ -0,0 +1,46 @@ +package me.ash.reader.infrastructure.preference + +import android.content.Context +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.compositionLocalOf +import androidx.datastore.preferences.core.Preferences +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import me.ash.reader.R +import me.ash.reader.ui.ext.DataStoreKey +import me.ash.reader.ui.ext.DataStoreKey.Companion.readingRenderer +import me.ash.reader.ui.ext.dataStore +import me.ash.reader.ui.ext.put + +val LocalReadingRenderer = + compositionLocalOf { ReadingRendererPreference.default } +@Immutable +sealed class ReadingRendererPreference(val value: Int) : Preference() { + object WebView : ReadingRendererPreference(0) + object NativeComponent : ReadingRendererPreference(1) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch { + context.dataStore.put(DataStoreKey.readingRenderer, value) + } + } + + fun toDesc(context: Context): String = + when (this) { + WebView -> context.getString(R.string.web_view) + NativeComponent -> context.getString(R.string.native_component) + } + + companion object { + + val default = WebView + val values = listOf(WebView, NativeComponent) + + fun fromPreferences(preferences: Preferences): ReadingRendererPreference = + when (preferences[DataStoreKey.keys[readingRenderer]?.key as Preferences.Key]) { + 0 -> WebView + 1 -> NativeComponent + else -> default + } + } +} diff --git a/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingSubheadAlignPreference.kt b/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingSubheadAlignPreference.kt index 80de07d22..32eafd084 100644 --- a/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingSubheadAlignPreference.kt +++ b/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingSubheadAlignPreference.kt @@ -46,6 +46,14 @@ sealed class ReadingSubheadAlignPreference(val value: Int) : Preference() { Justify -> TextAlign.Justify } + fun toTextAlignCSS(): String = + when (this) { + Start -> "left" + End -> "right" + Center -> "center" + Justify -> "justify" + } + companion object { val default = Start diff --git a/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingTextAlignPreference.kt b/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingTextAlignPreference.kt index 467146312..25631fe82 100644 --- a/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingTextAlignPreference.kt +++ b/app/src/main/java/me/ash/reader/infrastructure/preference/ReadingTextAlignPreference.kt @@ -55,6 +55,14 @@ sealed class ReadingTextAlignPreference(val value: Int) : Preference() { Justify -> Alignment.Start } + fun toTextAlignCSS(): String = + when (this) { + Start -> "left" + End -> "right" + Center -> "center" + Justify -> "justify" + } + companion object { val default = Start diff --git a/app/src/main/java/me/ash/reader/infrastructure/preference/Settings.kt b/app/src/main/java/me/ash/reader/infrastructure/preference/Settings.kt index c7d8b8459..56de1ac3e 100644 --- a/app/src/main/java/me/ash/reader/infrastructure/preference/Settings.kt +++ b/app/src/main/java/me/ash/reader/infrastructure/preference/Settings.kt @@ -51,6 +51,7 @@ data class Settings( val flowArticleListReadIndicator: FlowArticleReadIndicatorPreference = FlowArticleReadIndicatorPreference.default, // Reading page + val readingRenderer: ReadingRendererPreference = ReadingRendererPreference.default, val readingTheme: ReadingThemePreference = ReadingThemePreference.default, val readingDarkTheme: ReadingDarkThemePreference = ReadingDarkThemePreference.default, val readingPageTonalElevation: ReadingPageTonalElevationPreference = ReadingPageTonalElevationPreference.default, @@ -140,6 +141,7 @@ fun SettingsProvider( LocalFlowArticleListReadIndicator provides settings.flowArticleListReadIndicator, // Reading page + LocalReadingRenderer provides settings.readingRenderer, LocalReadingTheme provides settings.readingTheme, LocalReadingDarkTheme provides settings.readingDarkTheme, LocalReadingPageTonalElevation provides settings.readingPageTonalElevation, diff --git a/app/src/main/java/me/ash/reader/ui/component/base/RYWebView.kt b/app/src/main/java/me/ash/reader/ui/component/base/RYWebView.kt new file mode 100644 index 000000000..c5b7de485 --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/component/base/RYWebView.kt @@ -0,0 +1,377 @@ +package me.ash.reader.ui.component.base + +import android.content.Context +import android.net.http.SslError +import android.util.Log +import android.webkit.SslErrorHandler +import android.webkit.WebResourceError +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import me.ash.reader.infrastructure.preference.LocalOpenLink +import me.ash.reader.infrastructure.preference.LocalOpenLinkSpecificBrowser +import me.ash.reader.infrastructure.preference.LocalReadingImageHorizontalPadding +import me.ash.reader.infrastructure.preference.LocalReadingImageRoundedCorners +import me.ash.reader.infrastructure.preference.LocalReadingTextLetterSpacing +import me.ash.reader.infrastructure.preference.LocalReadingPageTonalElevation +import me.ash.reader.infrastructure.preference.LocalReadingSubheadAlign +import me.ash.reader.infrastructure.preference.LocalReadingSubheadBold +import me.ash.reader.infrastructure.preference.LocalReadingTextAlign +import me.ash.reader.infrastructure.preference.LocalReadingTextBold +import me.ash.reader.infrastructure.preference.LocalReadingTextFontSize +import me.ash.reader.infrastructure.preference.LocalReadingTextHorizontalPadding +import me.ash.reader.ui.ext.openURL +import me.ash.reader.ui.ext.surfaceColorAtElevation +import kotlin.math.absoluteValue + +const val INJECTION_TOKEN = "/android_asset_font/" + +@Composable +fun RYWebView( + modifier: Modifier = Modifier, + content: String, + onReceivedError: (error: WebResourceError?) -> Unit = {}, +) { + val context = LocalContext.current + val maxWidth = LocalConfiguration.current.screenWidthDp.dp.value + val openLink = LocalOpenLink.current + val openLinkSpecificBrowser = LocalOpenLinkSpecificBrowser.current + val tonalElevation = LocalReadingPageTonalElevation.current + val backgroundColor = MaterialTheme.colorScheme + .surfaceColorAtElevation(tonalElevation.value.dp).toArgb() + val bodyColor: Int = MaterialTheme.colorScheme.onSurfaceVariant.toArgb() + val linkColor: Int = MaterialTheme.colorScheme.primary.toArgb() + val subheadColor: Int = MaterialTheme.colorScheme.onSurface.toArgb() + val subheadBold: Boolean = LocalReadingSubheadBold.current.value + val subheadAlign: String = LocalReadingSubheadAlign.current.toTextAlignCSS() + val textBold: Boolean = LocalReadingTextBold.current.value + val textAlign: String = LocalReadingTextAlign.current.toTextAlignCSS() + val textFontSize: Int = LocalReadingTextFontSize.current + val textLetterSpacing: Float = LocalReadingTextLetterSpacing.current + val imageHorizontalPadding: Int = LocalReadingImageHorizontalPadding.current + val textHorizontalPadding: Int = LocalReadingTextHorizontalPadding.current + val imageShape: Int = LocalReadingImageRoundedCorners.current + val codeColor: Int = MaterialTheme.colorScheme.primary.toArgb() + val codeBackgroundColor: Int = MaterialTheme.colorScheme + .surfaceColorAtElevation((tonalElevation.value + 6).dp).toArgb() + val webViewClient by remember { + mutableStateOf(object : WebViewClient() { + + override fun shouldInterceptRequest( + view: WebView?, + url: String?, + ): WebResourceResponse? { + if (url != null && url.contains(INJECTION_TOKEN)) { + try { + val assetPath = url.substring( + url.indexOf(INJECTION_TOKEN) + INJECTION_TOKEN.length, + url.length + ) + return WebResourceResponse( + "text/HTML", + "UTF-8", + context.assets.open(assetPath) + ) + } catch (e: Exception) { + Log.e("RLog", "WebView shouldInterceptRequest: $e") + } + } + return super.shouldInterceptRequest(view, url); + } + + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) + val jsCode = "javascript:(function(){" + + "var imgs=document.getElementsByTagName(\"img\");" + + "for(var i=0;i +""" \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/component/base/WebView.kt b/app/src/main/java/me/ash/reader/ui/component/base/WebView.kt deleted file mode 100644 index d5da58dbf..000000000 --- a/app/src/main/java/me/ash/reader/ui/component/base/WebView.kt +++ /dev/null @@ -1,215 +0,0 @@ -package me.ash.reader.ui.component.base - -import android.net.http.SslError -import android.util.Log -import android.webkit.* -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.viewinterop.AndroidView -import me.ash.reader.infrastructure.preference.LocalOpenLink -import me.ash.reader.infrastructure.preference.LocalOpenLinkSpecificBrowser -import me.ash.reader.ui.ext.openURL - -const val INJECTION_TOKEN = "/android_asset_font/" - -@Composable -fun WebView( - modifier: Modifier = Modifier, - content: String, - onReceivedError: (error: WebResourceError?) -> Unit = {}, -) { - val context = LocalContext.current - val openLink = LocalOpenLink.current - val openLinkSpecificBrowser = LocalOpenLinkSpecificBrowser.current - val color = MaterialTheme.colorScheme.onSurfaceVariant.toArgb() - val backgroundColor = MaterialTheme.colorScheme.surface.toArgb() - val webViewClient by remember { - mutableStateOf(object : WebViewClient() { - - override fun shouldInterceptRequest( - view: WebView?, - url: String?, - ): WebResourceResponse? { - if (url != null && url.contains(INJECTION_TOKEN)) { - try { - val assetPath = url.substring( - url.indexOf(INJECTION_TOKEN) + INJECTION_TOKEN.length, - url.length - ) - return WebResourceResponse( - "text/HTML", - "UTF-8", - context.assets.open(assetPath) - ) - } catch (e: Exception) { - Log.e("RLog", "WebView shouldInterceptRequest: $e") - } - } - return super.shouldInterceptRequest(view, url); - } - - override fun onPageFinished(view: WebView?, url: String?) { - super.onPageFinished(view, url) - val jsCode = "javascript:(function(){" + - "var imgs=document.getElementsByTagName(\"img\");" + - "for(var i=0;i -""" diff --git a/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt b/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt index 4205d288a..e3eb9e194 100644 --- a/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt +++ b/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt @@ -134,6 +134,7 @@ data class DataStoreKey( const val flowArticleListReadIndicator = "flowArticleListReadIndicator" // Reading page + const val readingRenderer = "readingRenderer" const val readingDarkTheme = "readingDarkTheme" const val readingPageTonalElevation = "readingPageTonalElevation" const val readingTextFontSize = "readingTextFontSize" @@ -207,6 +208,7 @@ data class DataStoreKey( flowArticleListTonalElevation to DataStoreKey(intPreferencesKey(flowArticleListTonalElevation), Int::class.java), flowArticleListReadIndicator to DataStoreKey(booleanPreferencesKey(flowArticleListReadIndicator), Boolean::class.java), // Reading page + readingRenderer to DataStoreKey(intPreferencesKey(readingRenderer), Int::class.java), readingDarkTheme to DataStoreKey(intPreferencesKey(readingDarkTheme), Int::class.java), readingPageTonalElevation to DataStoreKey(intPreferencesKey(readingPageTonalElevation), Int::class.java), readingTextFontSize to DataStoreKey(intPreferencesKey(readingTextFontSize), Int::class.java), diff --git a/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt b/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt index ee10dd0e5..6e27ee18b 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt @@ -1,44 +1,26 @@ package me.ash.reader.ui.page.home.reading -import android.util.Log -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.tween -import androidx.compose.animation.expandVertically -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.shrinkVertically -import androidx.compose.animation.togetherWith -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.text.selection.DisableSelection import androidx.compose.foundation.text.selection.SelectionContainer -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.KeyboardArrowDown -import androidx.compose.material.icons.outlined.KeyboardArrowUp import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp -import androidx.compose.ui.zIndex +import java.util.Date import me.ash.reader.infrastructure.preference.LocalOpenLink import me.ash.reader.infrastructure.preference.LocalOpenLinkSpecificBrowser +import me.ash.reader.infrastructure.preference.LocalReadingRenderer import me.ash.reader.infrastructure.preference.LocalReadingSubheadUpperCase +import me.ash.reader.infrastructure.preference.ReadingRendererPreference +import me.ash.reader.ui.component.base.RYWebView import me.ash.reader.ui.component.reader.Reader import me.ash.reader.ui.ext.drawVerticalScrollbar import me.ash.reader.ui.ext.openURL -import me.ash.reader.ui.ext.pagerAnimate -import java.util.* -import kotlin.math.abs @Composable fun Content( @@ -54,6 +36,7 @@ fun Content( onImageClick: ((imgUrl: String, altText: String) -> Unit)? = null, ) { val context = LocalContext.current + val renderer = LocalReadingRenderer.current val subheadUpperCase = LocalReadingSubheadUpperCase.current val openLink = LocalOpenLink.current val openLinkSpecificBrowser = LocalOpenLinkSpecificBrowser.current @@ -95,16 +78,26 @@ fun Content( } } } - Reader( - context = context, - subheadUpperCase = subheadUpperCase.value, - link = link ?: "", - content = content, - onImageClick = onImageClick, - onLinkClick = { - context.openURL(it, openLink, openLinkSpecificBrowser) - } - ) + when (renderer) { + ReadingRendererPreference.WebView -> + item { + DisableSelection { + RYWebView(content = content) + } + } + + ReadingRendererPreference.NativeComponent -> + Reader( + context = context, + subheadUpperCase = subheadUpperCase.value, + link = link ?: "", + content = content, + onImageClick = onImageClick, + onLinkClick = { + context.openURL(it, openLink, openLinkSpecificBrowser) + } + ) + } item { Spacer(modifier = Modifier.height(128.dp)) diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt index cf687784b..3126d959c 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt @@ -23,7 +23,6 @@ import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.automirrored.rounded.Segment import androidx.compose.material.icons.outlined.Image import androidx.compose.material.icons.outlined.Movie -import androidx.compose.material.icons.rounded.Segment import androidx.compose.material.icons.rounded.Title import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -46,9 +45,11 @@ import me.ash.reader.infrastructure.preference.LocalReadingAutoHideToolbar import me.ash.reader.infrastructure.preference.LocalReadingDarkTheme import me.ash.reader.infrastructure.preference.LocalReadingFonts import me.ash.reader.infrastructure.preference.LocalReadingPageTonalElevation +import me.ash.reader.infrastructure.preference.LocalReadingRenderer import me.ash.reader.infrastructure.preference.LocalReadingTheme import me.ash.reader.infrastructure.preference.ReadingFontsPreference import me.ash.reader.infrastructure.preference.ReadingPageTonalElevationPreference +import me.ash.reader.infrastructure.preference.ReadingRendererPreference import me.ash.reader.infrastructure.preference.ReadingThemePreference import me.ash.reader.infrastructure.preference.not import me.ash.reader.ui.component.ReadingThemePrev @@ -73,6 +74,7 @@ fun ReadingStylePage( val context = LocalContext.current val scope = rememberCoroutineScope() + val renderer = LocalReadingRenderer.current val readingTheme = LocalReadingTheme.current val darkTheme = LocalReadingDarkTheme.current val darkThemeNot = !darkTheme @@ -81,7 +83,7 @@ fun ReadingStylePage( val autoHideToolbar = LocalReadingAutoHideToolbar.current val pullToSwitchArticle = LocalPullToSwitchArticle.current - + var rendererDialogVisible by remember { mutableStateOf(false) } var tonalElevationDialogVisible by remember { mutableStateOf(false) } var fontsDialogVisible by remember { mutableStateOf(false) } @@ -152,6 +154,11 @@ fun ReadingStylePage( modifier = Modifier.padding(horizontal = 24.dp), text = stringResource(R.string.general) ) + SettingItem( + title = stringResource(R.string.content_renderer), + desc = renderer.toDesc(context), + onClick = { rendererDialogVisible = true }, + ) {} SettingItem( title = stringResource(R.string.reading_fonts), desc = fonts.toDesc(context), @@ -310,4 +317,19 @@ fun ReadingStylePage( ) { fontsDialogVisible = false } + + RadioDialog( + visible = rendererDialogVisible, + title = stringResource(R.string.content_renderer), + options = ReadingRendererPreference.values.map { + RadioDialogOption( + text = it.toDesc(context), + selected = it == renderer, + ) { + it.put(context, scope) + } + } + ) { + rendererDialogVisible = false + } } diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index dfaea2d55..8723f0a96 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -302,4 +302,6 @@ 从 JSON 文件导入 导出为 JSON 文件 该文件可能不是有效的 JSON 文件!导入该文件可能会损坏应用程序并导致当前偏好设置丢失,您确定要继续吗? + 内容渲染器 + 原生组件(实验性) \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5288ec6ce..f6a8fe5a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -443,4 +443,7 @@ Import from JSON Export as JSON This file may not be a valid JSON file. Importing it could potentially corrupt the app and result in the loss of current preferences. Are you sure you want to proceed? + Content renderer + WebView + Native Component (experimental)