From 80820fd3166051ce99039e2de54f1f32df3f168a Mon Sep 17 00:00:00 2001 From: Simon Schubert Date: Mon, 11 Sep 2023 00:59:28 +0200 Subject: [PATCH] Upgrade sdks --- .github/FUNDING.yml | 2 +- .github/workflows/android.yml | 2 +- README.md | 26 ++- android/build.gradle.kts | 37 ++-- .../ComposeScreenshots.kt | 3 +- .../linuxcommandbibliotheca/ComposeTests.kt | 2 - .../linuxcommandbibliotheca/MainActivity.kt | 197 +++++++++--------- .../ui/composables/TopBar.kt | 6 +- art/assetlinks.json | 9 +- build.gradle.kts | 10 +- .../jvmMain/resources/application.properties | 2 +- common/build.gradle.kts | 8 +- common/src/androidMain/AndroidManifest.xml | 2 +- .../com/linuxcommandlibrary/shared/App.kt | 29 ++- .../linuxcommandlibrary/shared/platform.kt | 9 +- .../linuxcommandlibrary/shared/platform.kt | 3 +- desktop/build.gradle.kts | 2 +- .../desktop/MarkdownBuilder.kt | 3 +- .../desktop/WebsiteBuilder.kt | 166 ++++++++++++--- .../metadata/android/en-US/changelogs/83.txt | 1 + gradle/wrapper/gradle-wrapper.properties | 2 +- 21 files changed, 330 insertions(+), 191 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/83.txt diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index f93e2c7..023c2cf 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: [SimonSchubert] +github: [ SimonSchubert ] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 877e1c3..7cd56ab 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -64,7 +64,7 @@ jobs: with: name: jar path: cli/out/linuxcommandlibrary.jar - + release: name: Release APK and JAR needs: apk diff --git a/README.md b/README.md index 92b3210..401b1d8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ ![Icon](https://raw.githubusercontent.com/SimonSchubert/LinuxCommandLibrary/master/art/web_hi_res_144.png) -The app currently has **5055** manual pages, **22+** basic categories and a bunch of general terminal tips. It works 100% offline, doesn't need an internet connection and has no tracking software. +The app currently has **5055** manual pages, **22+** basic categories and a bunch of general +terminal tips. It works 100% offline, doesn't need an internet connection and has no tracking +software. [![Play Store](https://raw.githubusercontent.com/SimonSchubert/LinuxCommandBibliotheca/master/art/play_store_badge.png)](https://play.google.com/store/apps/details?id=com.inspiredandroid.linuxcommandbibliotheca) [![F-Droid](https://raw.githubusercontent.com/SimonSchubert/LinuxCommandBibliotheca/master/art/fdroid_badge.png)](https://f-droid.org/en/packages/com.inspiredandroid.linuxcommandbibliotheca/) @@ -30,27 +32,37 @@ Execute `gradle :cli:buildJar` to create jar file for Linux, Windows and Mac. #### Categories -One-liners, System information, System control, Users & Groups, Files & Folders, Input, Printing, JSON, Network, Search & Find, GIT, SSH, Video & Audio, Package manager, Hacking tools, Terminal games, Crypto currencies, VIM Texteditor, Emacs Texteditor, Nano Texteditor, Pico Texteditor, Micro Texteditor +One-liners, System information, System control, Users & Groups, Files & Folders, Input, Printing, +JSON, Network, Search & Find, GIT, SSH, Video & Audio, Package manager, Hacking tools, Terminal +games, Crypto currencies, VIM Texteditor, Emacs Texteditor, Nano Texteditor, Pico Texteditor, Micro +Texteditor #### Tips -Clear and reset the terminal, List of recent commands, Close a frozen window/application, Tab Completion, Temporary aliases, Permanent aliases, Chain commands, Command syntax, Cursor navigation, Redirection, Special characters in commands, View file permissions, Modify file permissions, Set file permissions via binary references +Clear and reset the terminal, List of recent commands, Close a frozen window/application, Tab +Completion, Temporary aliases, Permanent aliases, Chain commands, Command syntax, Cursor navigation, +Redirection, Special characters in commands, View file permissions, Modify file permissions, Set +file permissions via binary references ### CI/CD -[Github Action](.github/workflows/android.yml) to automatically create a new Github release with APK and JAR and upload an AAB to the Play Store. +[Github Action](.github/workflows/android.yml) to automatically create a new Github release with APK +and JAR and upload an AAB to the Play Store. ### Tests -Android Jetpack Compose screen tests: [ComposeTests.kt](android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeTests.kt) +Android Jetpack Compose screen +tests: [ComposeTests.kt](android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeTests.kt) -Android Jetpack Compose deeplinking tests: [ComposeDeeplinkTests.kt](android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeDeeplinkTests.kt) +Android Jetpack Compose deeplinking +tests: [ComposeDeeplinkTests.kt](android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeDeeplinkTests.kt) Common code unit tests: [CommonTests.kt](common/src/commonTest/kotlin/CommonTests.kt) ### Licensing -The source code is licensed under the Apache 2.0 license and the copyright of the man pages in the `database.db` file are copyrighted by their respective authors. +The source code is licensed under the Apache 2.0 license and the copyright of the man pages in +the `database.db` file are copyrighted by their respective authors. ### Thanks to diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 564b838..837f9d0 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -13,22 +13,22 @@ repositories { dependencies { implementation(project(":common")) implementation("androidx.activity:activity-compose:1.7.2") - implementation("androidx.compose.material:material:1.4.3") - implementation("androidx.navigation:navigation-compose:2.6.0") - implementation("com.google.accompanist:accompanist-appcompat-theme:0.30.1") - implementation("com.google.accompanist:accompanist-systemuicontroller:0.30.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1") - implementation("androidx.preference:preference:1.2.0") - implementation("androidx.compose.ui:ui-tooling-preview:1.4.3") + implementation("androidx.compose.material:material:1.5.1") + implementation("androidx.navigation:navigation-compose:2.7.2") + implementation("com.google.accompanist:accompanist-appcompat-theme:0.32.0") + implementation("com.google.accompanist:accompanist-systemuicontroller:0.32.0") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") + implementation("androidx.preference:preference:1.2.1") + implementation("androidx.compose.ui:ui-tooling-preview:1.5.1") - implementation("io.insert-koin:koin-core:3.4.2") - implementation("io.insert-koin:koin-android:3.4.2") - implementation("io.insert-koin:koin-androidx-compose:3.4.5") - implementation("androidx.compose.foundation:foundation:1.4.3") + implementation("io.insert-koin:koin-core:3.4.3") + implementation("io.insert-koin:koin-android:3.4.3") + implementation("io.insert-koin:koin-androidx-compose:3.4.6") + implementation("androidx.compose.foundation:foundation:1.5.1") - androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.4.3") - debugImplementation("androidx.compose.ui:ui-test-manifest:1.4.3") - debugImplementation("androidx.compose.ui:ui-tooling:1.4.3") + androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.1") + debugImplementation("androidx.compose.ui:ui-test-manifest:1.5.1") + debugImplementation("androidx.compose.ui:ui-tooling:1.5.1") } android { @@ -37,7 +37,7 @@ android { applicationId = "com.inspiredandroid.linuxcommandbibliotheca" minSdk = 24 targetSdk = 34 - versionCode = 82 + versionCode = 83 versionName = project.version.toString() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -45,7 +45,10 @@ android { buildTypes { getByName("release") { isMinifyEnabled = true - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) } getByName("debug") { isMinifyEnabled = false @@ -59,7 +62,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = "1.4.8" + kotlinCompilerExtensionVersion = "1.5.3" } compileOptions { diff --git a/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeScreenshots.kt b/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeScreenshots.kt index a23b865..a70a2e3 100644 --- a/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeScreenshots.kt +++ b/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeScreenshots.kt @@ -105,7 +105,8 @@ class ComposeScreenshots { // Tips composeTestRule.onNodeWithText("Tips").performClick() - composeTestRule.onNodeWithContentDescription("Scroll").performScrollToNode(hasText("$ [command] --help")) + composeTestRule.onNodeWithContentDescription("Scroll") + .performScrollToNode(hasText("$ [command] --help")) composeTestRule.takeScreenshot("screen-2$prefix.png") } diff --git a/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeTests.kt b/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeTests.kt index 284d63d..6ec0160 100644 --- a/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeTests.kt +++ b/android/src/androidTest/java/com/inspiredandroid/linuxcommandbibliotheca/ComposeTests.kt @@ -8,8 +8,6 @@ import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.linuxcommandlibrary.shared.databaseHelper import com.linuxcommandlibrary.shared.initDatabase -import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Rule import org.junit.Test diff --git a/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/MainActivity.kt b/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/MainActivity.kt index d844458..65fa22d 100644 --- a/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/MainActivity.kt +++ b/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/MainActivity.kt @@ -74,118 +74,115 @@ class MainActivity : AppCompatActivity() { LinuxApp() } } +} - @Composable - fun LinuxApp() { - val navController = rememberNavController() - val navBackStackEntry = navController.currentBackStackEntryAsState() - val searchTextValue = remember { - mutableStateOf( - TextFieldValue(text = "", selection = TextRange(0)) - ) - } - val onNavigate: (String) -> Unit = { - navController.navigate(it) - } - - LinuxTheme { - Scaffold( - topBar = { - TopBar(navBackStackEntry, - searchTextValue, - preferenceManager, - onNavigateBack = { - navController.popBackStack() - }) - }, - bottomBar = { - BottomBar(navController) - }) { innerPadding -> +@Composable +fun LinuxApp() { + val navController = rememberNavController() + val navBackStackEntry = navController.currentBackStackEntryAsState() + val searchTextValue = remember { + mutableStateOf( + TextFieldValue(text = "", selection = TextRange(0)) + ) + } + val onNavigate: (String) -> Unit = { + navController.navigate(it) + } - NavHost( - navController, - startDestination = Screen.Basics.route, - Modifier.padding(innerPadding) + LinuxTheme { + Scaffold( + topBar = { + TopBar(navBackStackEntry, + searchTextValue, + onNavigateBack = { + navController.popBackStack() + }) + }, + bottomBar = { + BottomBar(navController) + }) { innerPadding -> + + NavHost( + navController, + startDestination = Screen.Basics.route, + Modifier.padding(innerPadding) + ) { + + composable( + Screen.Basics.route, + deepLinks = listOf( + navDeepLink { uriPattern = "$deepLinkUri/basics" }, + navDeepLink { uriPattern = "$deepLinkUri/basics.html" }) ) { + BasicCategoriesScreen(onNavigate) + } + composable( + Screen.Commands.route, + deepLinks = listOf( + navDeepLink { uriPattern = "$deepLinkUri/" }, + navDeepLink { uriPattern = "$deepLinkUri/index.html" }) + ) { + val viewModel = getViewModel() - composable( - Screen.Basics.route, - deepLinks = listOf( - navDeepLink { uriPattern = "$deepLinkUri/basics" }, - navDeepLink { uriPattern = "$deepLinkUri/basics.html" }) - ) { - BasicCategoriesScreen(onNavigate) - } - composable( - Screen.Commands.route, - deepLinks = listOf( - navDeepLink { uriPattern = "$deepLinkUri/" }, - navDeepLink { uriPattern = "$deepLinkUri/index.html" }) - ) { - val viewModel = getViewModel() - - CommandListScreen( - searchTextValue.value.text, - viewModel, - onNavigate + CommandListScreen( + searchTextValue.value.text, + viewModel, + onNavigate + ) + } + composable( + Screen.Tips.route, + deepLinks = listOf( + navDeepLink { uriPattern = "$deepLinkUri/tips" }, + navDeepLink { uriPattern = "$deepLinkUri/tips.html" }) + ) { + TipsScreen(onNavigate) + } + composable( + "basicgroups?categoryId={categoryId}&categoryName={categoryName}", + arguments = listOf( + navArgument("categoryId") { defaultValue = "" }, + navArgument("categoryName") {}), + deepLinks = listOf( + navDeepLink { + uriPattern = "$deepLinkUri/basic/{categoryName}.html" + }, + navDeepLink { uriPattern = "$deepLinkUri/basic/{categoryName}" }) + ) { backStackEntry -> + val categoryId = backStackEntry.getCategoryId() + if (categoryId != null) { + val viewModel = getViewModel( + parameters = { parametersOf(categoryId) } ) - } - composable( - Screen.Tips.route, - deepLinks = listOf( - navDeepLink { uriPattern = "$deepLinkUri/tips" }, - navDeepLink { uriPattern = "$deepLinkUri/tips.html" }) - ) { + BasicGroupsScreen(onNavigate, viewModel) + } else { + // open tips screen on invalid deeplink parameters TipsScreen(onNavigate) } - composable( - "basicgroups?categoryId={categoryId}&categoryName={categoryName}", - arguments = listOf( - navArgument("categoryId") { defaultValue = "" }, - navArgument("categoryName") {}), - deepLinks = listOf( - navDeepLink { - uriPattern = "$deepLinkUri/basic/{categoryName}.html" - }, - navDeepLink { uriPattern = "$deepLinkUri/basic/{categoryName}" }) - ) { backStackEntry -> - val categoryId = backStackEntry.getCategoryId() - if (categoryId != null) { - val viewModel = getViewModel( - parameters = { parametersOf(categoryId) } - ) - BasicGroupsScreen(onNavigate, viewModel) - } else { - // open tips screen on invalid deeplink parameters - TipsScreen(onNavigate) - } - } - composable( - "command?commandId={commandId}&commandName={commandName}", - arguments = listOf( - navArgument("commandId") { defaultValue = "" }, - navArgument("commandName") {}), - deepLinks = listOf( - navDeepLink { uriPattern = "$deepLinkUri/man/{commandName}.html" }, - navDeepLink { uriPattern = "$deepLinkUri/man/{commandName}" }) - ) { backStackEntry -> - val commandId = backStackEntry.getCommandId() - if (commandId != null) { - val viewModel = getViewModel( - parameters = { parametersOf(commandId) } - ) - CommandDetailScreen(onNavigate, viewModel) - } else { - // open tips screen on invalid deeplink parameters - TipsScreen(onNavigate) - } + } + composable( + "command?commandId={commandId}&commandName={commandName}", + arguments = listOf( + navArgument("commandId") { defaultValue = "" }, + navArgument("commandName") {}), + deepLinks = listOf( + navDeepLink { uriPattern = "$deepLinkUri/man/{commandName}.html" }, + navDeepLink { uriPattern = "$deepLinkUri/man/{commandName}" }) + ) { backStackEntry -> + val commandId = backStackEntry.getCommandId() + if (commandId != null) { + val viewModel = getViewModel( + parameters = { parametersOf(commandId) } + ) + CommandDetailScreen(onNavigate, viewModel) + } else { + // open tips screen on invalid deeplink parameters + TipsScreen(onNavigate) } } } } } - - } sealed class Screen( diff --git a/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/ui/composables/TopBar.kt b/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/ui/composables/TopBar.kt index 75d4d25..bb376a2 100644 --- a/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/ui/composables/TopBar.kt +++ b/android/src/main/java/com/inspiredandroid/linuxcommandbibliotheca/ui/composables/TopBar.kt @@ -40,6 +40,7 @@ import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.AppInfoDialog import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.BookmarkFeedbackDialog import com.linuxcommandlibrary.shared.databaseHelper import com.linuxcommandlibrary.shared.getHtmlFileName +import org.koin.java.KoinJavaComponent.inject /* Copyright 2022 Simon Schubert * @@ -60,10 +61,13 @@ import com.linuxcommandlibrary.shared.getHtmlFileName fun TopBar( navBackStackEntry: State, textFieldValue: MutableState, - bookmarkManager: PreferenceUtil, onNavigateBack: () -> Unit = {} ) { val focusRequester = remember { FocusRequester() } + val bookmarkManager = remember { + val preferenceManager by inject(PreferenceUtil::class.java) + preferenceManager + } val route = navBackStackEntry.value?.destination?.route if (route == "commands") { diff --git a/art/assetlinks.json b/art/assetlinks.json index a07dce7..1e5b4f7 100644 --- a/art/assetlinks.json +++ b/art/assetlinks.json @@ -1,11 +1,14 @@ [ { - "relation": ["delegate_permission/common.handle_all_urls"], + "relation": [ + "delegate_permission/common.handle_all_urls" + ], "target": { "namespace": "android_app", "package_name": "com.inspiredandroid.linuxcommandbibliotheca", - "sha256_cert_fingerprints": - ["01:76:7F:F9:25:17:A7:25:AF:AE:87:3F:40:E3:67:BD:A4:2F:0E:DB:A5:65:3A:D1:5C:AF:04:93:C6:43:5E:60"] + "sha256_cert_fingerprints": [ + "01:76:7F:F9:25:17:A7:25:AF:AE:87:3F:40:E3:67:BD:A4:2F:0E:DB:A5:65:3A:D1:5C:AF:04:93:C6:43:5E:60" + ] } } ] \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 8dab676..34e3757 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask plugins { - id("com.github.ben-manes.versions") version "0.47.0" + id("com.github.ben-manes.versions") version "0.48.0" } buildscript { @@ -11,14 +11,14 @@ buildscript { mavenCentral() } dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22") - classpath("com.android.tools.build:gradle:8.0.2") - classpath( "com.squareup.sqldelight:gradle-plugin:1.5.5") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10") + classpath("com.android.tools.build:gradle:8.1.1") + classpath("com.squareup.sqldelight:gradle-plugin:1.5.5") } } group = "org.example" -version = "3.2.0" +version = "3.2.1" allprojects { repositories { diff --git a/cli/src/jvmMain/resources/application.properties b/cli/src/jvmMain/resources/application.properties index ebdb097..ba31d71 100644 --- a/cli/src/jvmMain/resources/application.properties +++ b/cli/src/jvmMain/resources/application.properties @@ -1 +1 @@ -version=3.2.0 \ No newline at end of file +version=3.2.1 \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 46fb98d..1e16bef 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -14,7 +14,7 @@ group = "com.linuxcommandlibrary" version = "1.0" kotlin { - android() + androidTarget() jvm("desktop") { compilations.all { kotlinOptions.jvmTarget = "17" @@ -35,7 +35,7 @@ kotlin { val androidMain by getting { dependencies { api("androidx.appcompat:appcompat:1.6.1") - api("androidx.core:core-ktx:1.10.1") + api("androidx.core:core-ktx:1.12.0") implementation("com.squareup.sqldelight:android-driver:1.5.5") } } @@ -50,11 +50,11 @@ kotlin { } android { - compileSdk = 33 + compileSdk = 34 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { minSdk = 24 - targetSdk = 33 + targetSdk = 34 } compileOptions { diff --git a/common/src/androidMain/AndroidManifest.xml b/common/src/androidMain/AndroidManifest.xml index de749ac..568741e 100644 --- a/common/src/androidMain/AndroidManifest.xml +++ b/common/src/androidMain/AndroidManifest.xml @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/App.kt b/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/App.kt index deb491d..0149f71 100644 --- a/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/App.kt +++ b/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/App.kt @@ -3,7 +3,7 @@ package com.linuxcommandlibrary.shared import databases.BasicCategory import databases.Command import databases.CommandSection -import java.util.* +import java.util.Locale /* Copyright 2022 Simon Schubert * @@ -30,22 +30,27 @@ sealed class CommandElement { * Search in name and description and return sorted by priority */ fun List.search(phrase: String): List { - return this.filter { it.name.contains(phrase, true) || it.description.contains(phrase, true) }.sortedBy { - val name = it.name.lowercase() - val lowercasePhrase = phrase.lowercase() - when { - !name.contains(lowercasePhrase) -> 30 - name == lowercasePhrase -> 0 - name.startsWith(lowercasePhrase) -> 10 - else -> 20 + return this.filter { it.name.contains(phrase, true) || it.description.contains(phrase, true) } + .sortedBy { + val name = it.name.lowercase() + val lowercasePhrase = phrase.lowercase() + when { + !name.contains(lowercasePhrase) -> 30 + name == lowercasePhrase -> 0 + name.startsWith(lowercasePhrase) -> 10 + else -> 20 + } } - } } /** * Return a list of sealed Elements for visual representation */ -fun String.getCommandList(mans: String, hasBrackets: Boolean = false, checkExisting: Boolean = false): List { +fun String.getCommandList( + mans: String, + hasBrackets: Boolean = false, + checkExisting: Boolean = false +): List { var command = " $this" val list = mutableListOf() mans.split(",").filterNot { it.isEmpty() }.map { it.replace("(", "").replace(")", "") } @@ -78,9 +83,11 @@ fun String.getCommandList(mans: String, hasBrackets: Boolean = false, checkExist val cmd = currentCommand.substring(4).split("|").first() list.add(CommandElement.Url(cmd, url)) } + checkExisting && databaseHelper.getCommand(currentCommand) == null -> { list.add(CommandElement.Text(currentCommand)) } + else -> { list.add(CommandElement.Man(currentCommand)) } diff --git a/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/platform.kt b/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/platform.kt index d638380..c847db5 100644 --- a/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/platform.kt +++ b/common/src/commonMain/kotlin/com/linuxcommandlibrary/shared/platform.kt @@ -2,7 +2,14 @@ package com.linuxcommandlibrary.shared import com.linuxcommandlibrary.CommandDatabase import com.squareup.sqldelight.db.SqlDriver -import databases.* +import databases.BasicCategory +import databases.BasicCommand +import databases.BasicGroup +import databases.Command +import databases.CommandQueries +import databases.CommandSection +import databases.Tip +import databases.TipSection /* Copyright 2022 Simon Schubert * diff --git a/common/src/desktopMain/kotlin/com/linuxcommandlibrary/shared/platform.kt b/common/src/desktopMain/kotlin/com/linuxcommandlibrary/shared/platform.kt index 7ae217a..8c7b460 100644 --- a/common/src/desktopMain/kotlin/com/linuxcommandlibrary/shared/platform.kt +++ b/common/src/desktopMain/kotlin/com/linuxcommandlibrary/shared/platform.kt @@ -5,8 +5,7 @@ import com.squareup.sqldelight.db.SqlDriver import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver import java.io.File import java.io.IOException -import java.io.InputStream -import java.util.* +import java.util.Properties /* Copyright 2022 Simon Schubert * diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index b02f6f5..2096e1e 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -16,7 +16,7 @@ kotlin { val jvmMain by getting { dependencies { implementation(project(":common")) - implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.9.0") + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.9.1") implementation("org.json:json:20230618") } } diff --git a/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/MarkdownBuilder.kt b/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/MarkdownBuilder.kt index 32f17a3..138a68a 100644 --- a/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/MarkdownBuilder.kt +++ b/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/MarkdownBuilder.kt @@ -45,7 +45,8 @@ class MarkdownBuilder { stream.appendLine("### Mobile screenshots") stream.appendLine() stream.appendLine("

") - val mobileScreenshotFiles = listOf("screen-1.png", "screen-2-dark.png", "screen-3.png", "screen-4-dark.png") + val mobileScreenshotFiles = + listOf("screen-1.png", "screen-2-dark.png", "screen-3.png", "screen-4-dark.png") mobileScreenshotFiles.forEach { fileName -> stream.appendLine("") } diff --git a/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/WebsiteBuilder.kt b/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/WebsiteBuilder.kt index f9dbe73..000f4bd 100644 --- a/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/WebsiteBuilder.kt +++ b/desktop/src/jvmMain/kotlin/com/linuxcommandlibrary/desktop/WebsiteBuilder.kt @@ -1,14 +1,63 @@ package com.linuxcommandlibrary.desktop -import com.linuxcommandlibrary.shared.* +import com.linuxcommandlibrary.shared.CommandElement +import com.linuxcommandlibrary.shared.databaseHelper +import com.linuxcommandlibrary.shared.getCommandList +import com.linuxcommandlibrary.shared.getHtmlFileName +import com.linuxcommandlibrary.shared.getSortPriority +import com.linuxcommandlibrary.shared.initDatabase import databases.BasicCategory -import kotlinx.html.* +import kotlinx.html.ATarget +import kotlinx.html.FlowContent +import kotlinx.html.HEAD +import kotlinx.html.HTMLTag +import kotlinx.html.HtmlTagMarker +import kotlinx.html.InputType +import kotlinx.html.LINK +import kotlinx.html.META +import kotlinx.html.UL +import kotlinx.html.a +import kotlinx.html.attributesMapOf +import kotlinx.html.b +import kotlinx.html.body +import kotlinx.html.br +import kotlinx.html.button +import kotlinx.html.classes +import kotlinx.html.div +import kotlinx.html.footer +import kotlinx.html.h1 +import kotlinx.html.h2 +import kotlinx.html.head +import kotlinx.html.html +import kotlinx.html.i +import kotlinx.html.id +import kotlinx.html.img +import kotlinx.html.input +import kotlinx.html.lang +import kotlinx.html.li +import kotlinx.html.link +import kotlinx.html.nav +import kotlinx.html.noScript +import kotlinx.html.onClick +import kotlinx.html.onKeyUp +import kotlinx.html.p +import kotlinx.html.script +import kotlinx.html.span import kotlinx.html.stream.appendHTML +import kotlinx.html.style +import kotlinx.html.styleLink +import kotlinx.html.table +import kotlinx.html.td +import kotlinx.html.title +import kotlinx.html.tr +import kotlinx.html.ul +import kotlinx.html.unsafe +import kotlinx.html.visit import org.json.JSONArray import org.json.JSONObject import java.io.File import java.io.PrintStream -import java.util.* +import java.util.Locale /* Copyright 2022 Simon Schubert * @@ -156,7 +205,11 @@ class WebsiteBuilder { title = title, description = "Handy cheat sheets with linux tips and terminal basics about System control, Users, Files, Package managers, Video and Audio, Hacking tools, Terminal games and many more categories.", url = "https://linuxcommandlibrary.com/${folder.name}/${file.nameWithoutExtension}", - keywords = "linux,cmd,basics,terminal,console,cheat sheets,tips,${basicCategories.joinToString(",") { it.title }}" + keywords = "linux,cmd,basics,terminal,console,cheat sheets,tips,${ + basicCategories.joinToString( + "," + ) { it.title } + }" ) styleLink("/stylesheets/main.css?v=$cacheVersion") @@ -175,7 +228,8 @@ class WebsiteBuilder { if (!listOf(253, 254, 255).contains(it.id.toInt())) { classes = setOf("invert-color") } - style = "background-image: url(\"images/${it.getIconResource()}\");" + style = + "background-image: url(\"images/${it.getIconResource()}\");" } h2 { text(it.title) @@ -277,7 +331,13 @@ class WebsiteBuilder { } } databaseHelper.getBasicCommands(group.id).forEach { command -> - if (listOf("VIM", "Emacs", "Nano", "Pico").contains(category.title)) { + if (listOf( + "VIM", + "Emacs", + "Nano", + "Pico" + ).contains(category.title) + ) { table { command.command.split("\n").forEach { tr { @@ -289,10 +349,21 @@ class WebsiteBuilder { } } } - } else if (listOf("Terminal games", "Fun").contains(category.title)) { - code("$ ${command.command.replace("\\n", "
")}", command.mans, true) + } else if (listOf( + "Terminal games", + "Fun" + ).contains(category.title) + ) { + code( + "$ ${command.command.replace("\\n", "
")}", + command.mans, + true + ) } else { - code("$ ${command.command.replace("\\n", "
")}", command.mans) + code( + "$ ${command.command.replace("\\n", "
")}", + command.mans + ) } } } @@ -390,9 +461,11 @@ class WebsiteBuilder { } br } + 1L -> { code(it.data1.replace("\\n", "
"), it.extra) } + 3L -> { unsafe { +"" @@ -502,7 +575,8 @@ class WebsiteBuilder { h2 { onClick = "togglePanel(this)" classes = setOf("accordion-button", "active") - val sectionId = section.title.lowercase(Locale.US).replace(" ", "-") + val sectionId = + section.title.lowercase(Locale.US).replace(" ", "-") a("/man/${command.name.lowercase(Locale.US)}#$sectionId") { id = sectionId text(section.title) @@ -513,7 +587,8 @@ class WebsiteBuilder { when (section.title) { "SEE ALSO" -> { p { - val elements = getSeeAlsoSectionElements(section.content) + val elements = + getSeeAlsoSectionElements(section.content) elements.forEach { element -> when (element) { is CommandElement.Man -> { @@ -522,16 +597,19 @@ class WebsiteBuilder { text(element.man) } } + is CommandElement.Text -> { unsafe { +element.text } } + else -> {} } } } } + "TLDR" -> { p { unsafe { @@ -539,6 +617,7 @@ class WebsiteBuilder { } } } + else -> { p { unsafe { @@ -580,7 +659,8 @@ class WebsiteBuilder { } val mans = text.getCommaSeparatedMans() - return text.getCommandList(mans, + return text.getCommandList( + mans, hasBrackets = true, checkExisting = true ) @@ -643,7 +723,12 @@ class WebsiteBuilder { } } - private fun UL.headerNav(title: String, href: String, index: Int, selectedIndex: Int): FlowContent { + private fun UL.headerNav( + title: String, + href: String, + index: Int, + selectedIndex: Int + ): FlowContent { li { a(href) { if (selectedIndex == index) { @@ -757,7 +842,12 @@ class WebsiteBuilder { meta(name = "theme-color", content = "#ffffff") } - private fun HEAD.uncommonMeta(title: String, description: String, url: String, keywords: String) { + private fun HEAD.uncommonMeta( + title: String, + description: String, + url: String, + keywords: String + ) { title(title) meta(name = "description", content = description) @@ -775,7 +865,10 @@ class WebsiteBuilder { meta(property = "twitter:card", content = "summary") meta(property = "twitter:title", content = title) meta(property = "twitter:description", content = description) - meta(property = "twitter:image", content = "https://linuxcommandlibrary.com/images/preview.jpg") + meta( + property = "twitter:image", + content = "https://linuxcommandlibrary.com/images/preview.jpg" + ) } private inline fun HTMLTag.link( @@ -784,7 +877,10 @@ class WebsiteBuilder { type: String? = null, sizes: String?, crossinline block: LINK.() -> Unit = {} - ): Unit = LINK(attributesMapOf("href", href, "rel", rel, "type", type, "sizes", sizes), consumer).visit(block) + ): Unit = LINK( + attributesMapOf("href", href, "rel", rel, "type", type, "sizes", sizes), + consumer + ).visit(block) private fun FlowContent.footer(showAd: Boolean = true): FlowContent { if (showAd) { @@ -893,7 +989,11 @@ class WebsiteBuilder { return this } - private fun FlowContent.code(command: String, mans: String, isMonospace: Boolean = false): FlowContent { + private fun FlowContent.code( + command: String, + mans: String, + isMonospace: Boolean = false + ): FlowContent { div { classes = setOf("code-wrapper") span { @@ -909,21 +1009,24 @@ class WebsiteBuilder { text(element.man) } } + is CommandElement.Text -> { - element.text.split("
").map { it.replace("$ ", "$ ") }.forEachIndexed { index, s -> - if (index != 0) { - br - } - s.split(" ").forEachIndexed { index2, s2 -> - if (index2 != 0) { - unsafe { - +" " + element.text.split("
").map { it.replace("$ ", "$ ") } + .forEachIndexed { index, s -> + if (index != 0) { + br + } + s.split(" ").forEachIndexed { index2, s2 -> + if (index2 != 0) { + unsafe { + +" " + } } + text(s2) } - text(s2) } - } } + is CommandElement.Url -> { a(element.url) { target = ATarget.blank @@ -941,7 +1044,8 @@ class WebsiteBuilder { } else { onClick = "javascript:copy('${ - command.split("
").first().drop(2).replace("'", "'").replace("\n", "").trim() + command.split("
").first().drop(2).replace("'", "'") + .replace("\n", "").trim() }')" } @@ -1069,7 +1173,8 @@ class WebsiteBuilder { var content = this var matches = quoteRegex.findAll(content) matches.forEach { - val command = it.value.replace("`", "").replace("'", "'").replace(">", ">").replace("<", "<") + val command = it.value.replace("`", "").replace("'", "'").replace(">", ">") + .replace("<", "<") .replace("\"", """) content = content.replace( it.value, @@ -1080,7 +1185,8 @@ class WebsiteBuilder { matches = h2Regex.findAll(content) matches.forEachIndexed { index, matchResult -> val text = - matchResult.value.replace("

", "").replace("

", "").replace(">", ">").replace("<", "<") + matchResult.value.replace("

", "").replace("

", "").replace(">", ">") + .replace("<", "<") content = content.replace( matchResult.value, diff --git a/fastlane/metadata/android/en-US/changelogs/83.txt b/fastlane/metadata/android/en-US/changelogs/83.txt new file mode 100644 index 0000000..5a3206c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/83.txt @@ -0,0 +1 @@ +Upgrade sdks \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 15de902..db9a6b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists