diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7101007 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# noinspection EditorConfigKeyCorrectness +[{*.kt,*.kts}] +ktlint_standard_annotation = disabled +ktlint_standard_filename = disabled +ktlint_standard_wrapping = disabled +ktlint_standard_import-ordering = enabled +ktlint_standard_max-line-length = disabled +ktlint_standard_multiline-if-else = disabled +ktlint_standard_argument-list-wrapping = disabled +ktlint_standard_parameter-list-wrapping = disabled +ktlint_standard_trailing-comma-on-declaration-site = disabled +ktlint_function_signature_body_expression_wrapping = multiline +ij_continuation_indent_size = 2 +indent_size = 4 +indent_style = space +insert_final_newline = false +max_line_length = 150 \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 386c86b..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,40 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: Publish To Maven Central - -# Controls when the workflow will run -on: - # Triggers the workflow when tag is pushed - push: - tags: - - 'v*' - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "publish" - publish: - # The type of runner that the job will run on - runs-on: macos-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - - # Runs a single command using the runners shell - - name: publish - run: ./gradlew publish --no-daemon --no-parallel - env: - ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }} - ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} - ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }} - ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }} - ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }} diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml deleted file mode 100644 index 370c0c3..0000000 --- a/.github/workflows/static-analysis.yml +++ /dev/null @@ -1,47 +0,0 @@ -# This is a workflow to verify PRs with static code analysis tools -name: Static Analysis - -# Controls when the workflow will run -on: - pull_request: - branches: [main] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -jobs: - detekt: - name: Detekt - runs-on: macos-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - - # Runs a single command using the runners shell - - name: detekt - run: ./gradlew detekt - - spotless: - name: Spotless - runs-on: macos-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - - # Runs a single command using the runners shell - - name: spotless - run: ./gradlew spotlessCheck diff --git a/.gitignore b/.gitignore index e44d96a..aa724b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,15 @@ *.iml .gradle /local.properties -/.idea +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml .DS_Store -build/ +/build /captures .externalNativeBuild .cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore index 26d3352..3ad4a12 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -1,3 +1,5 @@ # Default ignored files /shelf/ -/workspace.xml +/gradle.xml +/misc.xml +/workspace.xml \ No newline at end of file diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml new file mode 100644 index 0000000..371f2e2 --- /dev/null +++ b/.idea/appInsightsSettings.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 1b4dd5a..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,205 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..b1d56a7 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 10965d5..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png b/.idea/icon.png similarity index 100% rename from demo/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to .idea/icon.png diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..146ab09 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..f8467b4 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/ktlint.xml b/.idea/ktlint.xml new file mode 100644 index 0000000..92c4441 --- /dev/null +++ b/.idea/ktlint.xml @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index c9a2cd7..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index 2e90b9c..da2d3fa 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,18 @@ [![Maven Central](https://img.shields.io/maven-central/v/io.github.oleksandrbalan/pagecurl.svg?label=Maven%20Central)](https://mvnrepository.com/artifact/io.github.oleksandrbalan/pagecurl) - +LOGO -# Page Curl +# Page Curl (Multiplatform) -Page Curl library for Jetpack Compose. +Page Curl library for Jetpack Compose Multiplatform. + +Support for Android, iOS, Desktop (JVM): + +SHOT + +> Note + +This is just an attempt at multiplatform porting, and there may still be some problems. ## Motivation @@ -12,122 +20,19 @@ This library allows to create an effect of turning pages, which can be used in b ## Usage -### Get a dependency +> Note -**Step 1.** Add the MavenCentral repository to your build file. -Add it in your root `build.gradle.kts` at the end of repositories: -```kotlin -allprojects { - repositories { - ... - mavenCentral() - } -} -``` +This multiplatform library's artifact is not upload to any repositories, +you can clone this repository or use git submodule to use it. -Or in `settings.gradle.kts`: -```kotlin -pluginManagement { - repositories { - ... - mavenCentral() - } -} -``` +For an Android version and a sample usage, please visit: https://github.com/oleksandrbalan/pagecurl. -**Step 2.** Add the dependency. -Check latest version on the [releases page](https://github.com/oleksandrbalan/pagecurl/releases). -```kotlin -dependencies { - implementation("io.github.oleksandrbalan:pagecurl:$version") -} -``` +See Demo application +and [examples](https://github.com/fankes/pagecurl/blob/multiplatform/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens) for more usage +examples. -### Use in Composable +## Thanks -The `PageCurl` has 2 mandatory arguments: -* **count** - The count of pages. -* **content** - The content lambda to provide the page composable. Receives the page number. +[The compose multiplatform shadows way](https://github.com/oleksandrbalan/pagecurl/issues/23#issuecomment-1767145310) -``` -val pages = listOf("One", "Two", "Three") -PageCurl(count = pages.size) { index -> - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .background(MaterialTheme.colors.background) - .fillMaxSize() - ) { - Text( - text = pages[index], - style = MaterialTheme.typography.h1, - ) - } -} -``` - -Optionally `state` could be provided to observe and manage PageCurl state. -* **state** - The state of the PageCurl. Use it to programmatically change the current page or observe changes, and to configure shadow, back-page and interactions. -``` -Column { - val scope = rememberCoroutineScope() - val state = rememberPageCurlState() - Button(onClick = { scope.launch { state.next() } }) { - Text(text = "Next") - } - - val pages = listOf("One", "Two", "Three") - PageCurl( - count = pages.size, - state = state, - ) { index -> - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .background(MaterialTheme.colors.background) - .fillMaxSize() - ) { - Text( - text = pages[index], - style = MaterialTheme.typography.h1, - ) - } - } -} -``` - -Optionally `key` lambda could be provided with stable key for each item. PageCurl with keys for each page will correctly preserve a current position when items are added or removed. -* **key** - The lambda to provide stable key for each item. Useful when adding and removing items before current page. -``` -Column { - var pages by remember { mutableStateOf(listOf("Four", "Five", "Six")) } - Button(onClick = { pages = listOf("One", "Two", "Three") + pages }) { - Text(text = "Prepend new pages") - } - - PageCurl( - count = pages.size, - key = { pages[it].hashCode() }, - ) { index -> - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .background(MaterialTheme.colors.background) - .fillMaxSize() - ) { - Text( - text = pages[index], - style = MaterialTheme.typography.h1, - ) - } - } -} -``` - -See Demo application and [examples](demo/src/main/kotlin/eu/wewox/pagecurl/screens) for more usage examples. - -https://user-images.githubusercontent.com/20944869/185782671-2861c2ed-c033-4318-bf12-1d8db74fc8b5.mp4 - -https://user-images.githubusercontent.com/20944869/185782668-b52da2b9-be8d-49db-8729-88b6f9a8ee48.mp4 - -https://user-images.githubusercontent.com/20944869/185782663-4bd97a57-1a46-408d-a07b-34c193f01aba.mp4 +[Multiplatform Paging](https://github.com/cashapp/multiplatform-paging) \ No newline at end of file diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts deleted file mode 100644 index a21a774..0000000 --- a/build-logic/convention/build.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -plugins { - `kotlin-dsl` -} - -java { - toolchain { - val version = libs.versions.java.toolchain.get() - languageVersion.set(JavaLanguageVersion.of(version)) - } -} - -gradlePlugin { - plugins { - register("conventionJvmToolchain") { - id = "convention.jvm.toolchain" - implementationClass = "JvmToolchainConventionPlugin" - } - } -} diff --git a/build-logic/convention/src/main/kotlin/JvmToolchainConventionPlugin.kt b/build-logic/convention/src/main/kotlin/JvmToolchainConventionPlugin.kt deleted file mode 100644 index 8ee9599..0000000 --- a/build-logic/convention/src/main/kotlin/JvmToolchainConventionPlugin.kt +++ /dev/null @@ -1,18 +0,0 @@ -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.jvm.toolchain.JavaLanguageVersion -import org.gradle.kotlin.dsl.configure -import utils.libs - -class JvmToolchainConventionPlugin : Plugin { - override fun apply(target: Project) = - with(target) { - extensions.configure { - toolchain { - val version = libs.findVersion("java-toolchain").get().displayName - languageVersion.set(JavaLanguageVersion.of(version)) - } - } - } -} diff --git a/build-logic/convention/src/main/kotlin/utils/ProjectExtensions.kt b/build-logic/convention/src/main/kotlin/utils/ProjectExtensions.kt deleted file mode 100644 index 3b0a623..0000000 --- a/build-logic/convention/src/main/kotlin/utils/ProjectExtensions.kt +++ /dev/null @@ -1,9 +0,0 @@ -package utils - -import org.gradle.api.Project -import org.gradle.api.artifacts.VersionCatalog -import org.gradle.api.artifacts.VersionCatalogsExtension -import org.gradle.kotlin.dsl.getByType - -val Project.libs: VersionCatalog - get() = extensions.getByType().named("libs") diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts deleted file mode 100644 index c97f8ca..0000000 --- a/build-logic/settings.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -dependencyResolutionManagement { - repositories { - google() - mavenCentral() - } - versionCatalogs { - create("libs") { - from(files("../gradle/libs.versions.toml")) - } - } -} - -plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version ("0.7.0") -} - -rootProject.name = "build-logic" -include(":convention") diff --git a/build.gradle.kts b/build.gradle.kts index 78f7c3a..19264c6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,23 +1,6 @@ -import com.diffplug.gradle.spotless.SpotlessPlugin -import io.gitlab.arturbosch.detekt.DetektPlugin - plugins { - alias(libs.plugins.android.application) apply false - alias(libs.plugins.android.library) apply false - alias(libs.plugins.kotlin) apply false - alias(libs.plugins.detekt) - alias(libs.plugins.spotless) - alias(libs.plugins.mavenpublish) -} - -configure(subprojects) { - apply() - apply() - - spotless { - kotlin { - target("**/*.kt") - ktlint("0.43.2") - } - } -} + autowire(libs.plugins.kotlin.multiplatform) apply false + autowire(libs.plugins.android.application) apply false + autowire(libs.plugins.android.library) apply false + autowire(libs.plugins.jetbrains.compose) apply false +} \ No newline at end of file diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml deleted file mode 100644 index 4dbb501..0000000 --- a/config/detekt/detekt.yml +++ /dev/null @@ -1,684 +0,0 @@ -build: - maxIssues: 0 - excludeCorrectable: false - weights: - # complexity: 2 - # LongParameterList: 1 - # style: 1 - # comments: 1 - -config: - validation: true - warningsAsErrors: false - # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]' - excludes: '' - -processors: - active: true - exclude: - - 'DetektProgressListener' - # - 'KtFileCountProcessor' - # - 'PackageCountProcessor' - # - 'ClassCountProcessor' - # - 'FunctionCountProcessor' - # - 'PropertyCountProcessor' - # - 'ProjectComplexityProcessor' - # - 'ProjectCognitiveComplexityProcessor' - # - 'ProjectLLOCProcessor' - # - 'ProjectCLOCProcessor' - # - 'ProjectLOCProcessor' - # - 'ProjectSLOCProcessor' - # - 'LicenseHeaderLoaderExtension' - -console-reports: - active: true - exclude: - - 'ProjectStatisticsReport' - - 'ComplexityReport' - - 'NotificationReport' - - 'FindingsReport' - - 'FileBasedFindingsReport' - # - 'LiteFindingsReport' - -output-reports: - active: true - exclude: - # - 'TxtOutputReport' - # - 'XmlOutputReport' - # - 'HtmlOutputReport' - -comments: - active: true - AbsentOrWrongFileLicense: - active: false - licenseTemplateFile: 'license.template' - licenseTemplateIsRegex: false - CommentOverPrivateFunction: - active: false - CommentOverPrivateProperty: - active: false - DeprecatedBlockTag: - active: false - EndOfSentenceFormat: - active: false - endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' - OutdatedDocumentation: - active: false - matchTypeParameters: true - matchDeclarationsOrder: true - allowParamOnConstructorProperties: false - UndocumentedPublicClass: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - searchInNestedClass: true - searchInInnerClass: true - searchInInnerObject: true - searchInInnerInterface: true - UndocumentedPublicFunction: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - UndocumentedPublicProperty: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - -complexity: - active: true - ComplexCondition: - active: true - threshold: 4 - ComplexInterface: - active: false - threshold: 10 - includeStaticDeclarations: false - includePrivateDeclarations: false - ComplexMethod: - active: true - threshold: 15 - ignoreSingleWhenExpression: false - ignoreSimpleWhenEntries: false - ignoreNestingFunctions: false - nestingFunctions: - - 'also' - - 'apply' - - 'forEach' - - 'isNotNull' - - 'ifNull' - - 'let' - - 'run' - - 'use' - - 'with' - LabeledExpression: - active: false - ignoredLabels: [] - LargeClass: - active: true - threshold: 600 - LongMethod: - active: true - threshold: 60 - LongParameterList: - active: true - functionThreshold: 10 - constructorThreshold: 7 - ignoreDefaultParameters: false - ignoreDataClasses: true - ignoreAnnotated: [ 'Composable' ] - ignoreAnnotatedParameter: [] - MethodOverloading: - active: false - threshold: 6 - NamedArguments: - active: false - threshold: 3 - ignoreArgumentsMatchingNames: false - NestedBlockDepth: - active: true - threshold: 4 - ReplaceSafeCallChainWithRun: - active: false - StringLiteralDuplication: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - threshold: 3 - ignoreAnnotation: true - excludeStringsWithLessThan5Characters: true - ignoreStringsRegex: '$^' - TooManyFunctions: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - thresholdInFiles: 11 - thresholdInClasses: 11 - thresholdInInterfaces: 11 - thresholdInObjects: 11 - thresholdInEnums: 11 - ignoreDeprecated: false - ignorePrivate: false - ignoreOverridden: false - -coroutines: - active: true - GlobalCoroutineUsage: - active: false - InjectDispatcher: - active: false - dispatcherNames: - - 'IO' - - 'Default' - - 'Unconfined' - RedundantSuspendModifier: - active: false - SleepInsteadOfDelay: - active: false - SuspendFunWithCoroutineScopeReceiver: - active: false - SuspendFunWithFlowReturnType: - active: false - -empty-blocks: - active: true - EmptyCatchBlock: - active: true - allowedExceptionNameRegex: '_|(ignore|expected).*' - EmptyClassBlock: - active: true - EmptyDefaultConstructor: - active: true - EmptyDoWhileBlock: - active: true - EmptyElseBlock: - active: true - EmptyFinallyBlock: - active: true - EmptyForBlock: - active: true - EmptyFunctionBlock: - active: true - ignoreOverridden: false - EmptyIfBlock: - active: true - EmptyInitBlock: - active: true - EmptyKtFile: - active: true - EmptySecondaryConstructor: - active: true - EmptyTryBlock: - active: true - EmptyWhenBlock: - active: true - EmptyWhileBlock: - active: true - -exceptions: - active: true - ExceptionRaisedInUnexpectedLocation: - active: true - methodNames: - - 'equals' - - 'finalize' - - 'hashCode' - - 'toString' - InstanceOfCheckForException: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - NotImplementedDeclaration: - active: false - ObjectExtendsThrowable: - active: false - PrintStackTrace: - active: true - RethrowCaughtException: - active: true - ReturnFromFinally: - active: true - ignoreLabeled: false - SwallowedException: - active: true - ignoredExceptionTypes: - - 'InterruptedException' - - 'MalformedURLException' - - 'NumberFormatException' - - 'ParseException' - allowedExceptionNameRegex: '_|(ignore|expected).*' - ThrowingExceptionFromFinally: - active: true - ThrowingExceptionInMain: - active: false - ThrowingExceptionsWithoutMessageOrCause: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - exceptions: - - 'ArrayIndexOutOfBoundsException' - - 'Exception' - - 'IllegalArgumentException' - - 'IllegalMonitorStateException' - - 'IllegalStateException' - - 'IndexOutOfBoundsException' - - 'NullPointerException' - - 'RuntimeException' - - 'Throwable' - ThrowingNewInstanceOfSameException: - active: true - TooGenericExceptionCaught: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - exceptionNames: - - 'ArrayIndexOutOfBoundsException' - - 'Error' - - 'Exception' - - 'IllegalMonitorStateException' - - 'IndexOutOfBoundsException' - - 'NullPointerException' - - 'RuntimeException' - - 'Throwable' - allowedExceptionNameRegex: '_|(ignore|expected).*' - TooGenericExceptionThrown: - active: true - exceptionNames: - - 'Error' - - 'Exception' - - 'RuntimeException' - - 'Throwable' - -naming: - active: true - BooleanPropertyNaming: - active: false - allowedPattern: '^(is|has|are)' - ignoreOverridden: true - ClassNaming: - active: true - classPattern: '[A-Z][a-zA-Z0-9]*' - ConstructorParameterNaming: - active: true - parameterPattern: '[a-z][A-Za-z0-9]*' - privateParameterPattern: '[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - EnumNaming: - active: true - enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' - ForbiddenClassName: - active: false - forbiddenName: [] - FunctionMaxLength: - active: false - maximumFunctionNameLength: 30 - FunctionMinLength: - active: false - minimumFunctionNameLength: 3 - FunctionNaming: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - functionPattern: '[a-z][a-zA-Z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - ignoreAnnotated: [ 'Composable' ] - FunctionParameterNaming: - active: true - parameterPattern: '[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - InvalidPackageDeclaration: - active: false - rootPackage: '' - requireRootInDeclaration: false - LambdaParameterNaming: - active: false - parameterPattern: '[a-z][A-Za-z0-9]*|_' - MatchingDeclarationName: - active: true - mustBeFirst: true - MemberNameEqualsClassName: - active: true - ignoreOverridden: true - NoNameShadowing: - active: false - NonBooleanPropertyPrefixedWithIs: - active: false - ObjectPropertyNaming: - active: true - constantPattern: '[A-Za-z][_A-Za-z0-9]*' - propertyPattern: '[A-Za-z][_A-Za-z0-9]*' - privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' - PackageNaming: - active: true - packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' - TopLevelPropertyNaming: - active: true - constantPattern: '[A-Z][A-Za-z0-9]*' - propertyPattern: '[A-Za-z][_A-Za-z0-9]*' - privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*' - VariableMaxLength: - active: false - maximumVariableNameLength: 64 - VariableMinLength: - active: false - minimumVariableNameLength: 1 - VariableNaming: - active: true - variablePattern: '[a-z][A-Za-z0-9]*' - privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - -performance: - active: true - ArrayPrimitive: - active: true - ForEachOnRange: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - SpreadOperator: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - UnnecessaryTemporaryInstantiation: - active: true - -potential-bugs: - active: true - AvoidReferentialEquality: - active: false - forbiddenTypePatterns: - - 'kotlin.String' - CastToNullableType: - active: false - Deprecation: - active: false - DontDowncastCollectionTypes: - active: false - DoubleMutabilityForCollection: - active: false - mutableTypes: - - 'kotlin.collections.MutableList' - - 'kotlin.collections.MutableMap' - - 'kotlin.collections.MutableSet' - - 'java.util.ArrayList' - - 'java.util.LinkedHashSet' - - 'java.util.HashSet' - - 'java.util.LinkedHashMap' - - 'java.util.HashMap' - DuplicateCaseInWhenExpression: - active: true - ElseCaseInsteadOfExhaustiveWhen: - active: false - EqualsAlwaysReturnsTrueOrFalse: - active: true - EqualsWithHashCodeExist: - active: true - ExitOutsideMain: - active: false - ExplicitGarbageCollectionCall: - active: true - HasPlatformType: - active: false - IgnoredReturnValue: - active: false - restrictToAnnotatedMethods: true - returnValueAnnotations: - - '*.CheckResult' - - '*.CheckReturnValue' - ignoreReturnValueAnnotations: - - '*.CanIgnoreReturnValue' - ignoreFunctionCall: [] - ImplicitDefaultLocale: - active: true - ImplicitUnitReturnType: - active: false - allowExplicitReturnType: true - InvalidRange: - active: true - IteratorHasNextCallsNextMethod: - active: true - IteratorNotThrowingNoSuchElementException: - active: true - LateinitUsage: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - ignoreOnClassesPattern: '' - MapGetWithNotNullAssertionOperator: - active: false - MissingPackageDeclaration: - active: false - excludes: ['**/*.kts'] - MissingWhenCase: - active: true - allowElseExpression: true - NullCheckOnMutableProperty: - active: false - NullableToStringCall: - active: false - RedundantElseInWhen: - active: true - UnconditionalJumpStatementInLoop: - active: false - UnnecessaryNotNullOperator: - active: true - UnnecessarySafeCall: - active: true - UnreachableCatchBlock: - active: false - UnreachableCode: - active: true - UnsafeCallOnNullableType: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - UnsafeCast: - active: true - UnusedUnaryOperator: - active: false - UselessPostfixExpression: - active: false - WrongEqualsTypeParameter: - active: true - -style: - active: true - CanBeNonNullable: - active: false - ClassOrdering: - active: false - CollapsibleIfStatements: - active: false - DataClassContainsFunctions: - active: false - conversionFunctionPrefix: 'to' - DataClassShouldBeImmutable: - active: false - DestructuringDeclarationWithTooManyEntries: - active: false - maxDestructuringEntries: 3 - EqualsNullCall: - active: true - EqualsOnSignatureLine: - active: false - ExplicitCollectionElementAccessMethod: - active: false - ExplicitItLambdaParameter: - active: false - ExpressionBodySyntax: - active: false - includeLineWrapping: false - ForbiddenComment: - active: true - values: - - 'FIXME:' - - 'STOPSHIP:' - - 'TODO:' - allowedPatterns: '' - customMessage: '' - ForbiddenImport: - active: false - imports: [] - forbiddenPatterns: '' - ForbiddenMethodCall: - active: false - methods: - - 'kotlin.io.print' - - 'kotlin.io.println' - ForbiddenPublicDataClass: - active: true - excludes: ['**'] - ignorePackages: - - '*.internal' - - '*.internal.*' - ForbiddenVoid: - active: false - ignoreOverridden: false - ignoreUsageInGenerics: false - FunctionOnlyReturningConstant: - active: true - ignoreOverridableFunction: true - ignoreActualFunction: true - excludedFunctions: '' - LibraryCodeMustSpecifyReturnType: - active: true - excludes: ['**'] - LibraryEntitiesShouldNotBePublic: - active: true - excludes: ['**'] - LoopWithTooManyJumpStatements: - active: true - maxJumpCount: 1 - MagicNumber: - active: false - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - ignoreNumbers: - - '-1' - - '0' - - '1' - - '2' - ignoreHashCodeFunction: true - ignorePropertyDeclaration: false - ignoreLocalVariableDeclaration: false - ignoreConstantDeclaration: true - ignoreCompanionObjectPropertyDeclaration: true - ignoreAnnotation: false - ignoreNamedArgument: true - ignoreEnums: false - ignoreRanges: false - ignoreExtensionFunctions: true - MandatoryBracesIfStatements: - active: false - MandatoryBracesLoops: - active: false - MaxLineLength: - active: true - maxLineLength: 120 - excludePackageStatements: true - excludeImportStatements: true - excludeCommentStatements: false - MayBeConst: - active: true - ModifierOrder: - active: true - MultilineLambdaItParameter: - active: false - NestedClassesVisibility: - active: true - NewLineAtEndOfFile: - active: true - NoTabs: - active: false - ObjectLiteralToLambda: - active: false - OptionalAbstractKeyword: - active: true - OptionalUnit: - active: false - OptionalWhenBraces: - active: false - PreferToOverPairSyntax: - active: false - ProtectedMemberInFinalClass: - active: true - RedundantExplicitType: - active: false - RedundantHigherOrderMapUsage: - active: false - RedundantVisibilityModifierRule: - active: false - ReturnCount: - active: true - max: 2 - excludedFunctions: 'equals' - excludeLabeled: false - excludeReturnFromLambda: true - excludeGuardClauses: false - SafeCast: - active: true - SerialVersionUIDInSerializableClass: - active: true - SpacingBetweenPackageAndImports: - active: false - ThrowsCount: - active: true - max: 2 - excludeGuardClauses: false - TrailingWhitespace: - active: false - UnderscoresInNumericLiterals: - active: false - acceptableLength: 4 - allowNonStandardGrouping: false - UnnecessaryAbstractClass: - active: true - UnnecessaryAnnotationUseSiteTarget: - active: false - UnnecessaryApply: - active: true - UnnecessaryFilter: - active: false - UnnecessaryInheritance: - active: true - UnnecessaryInnerClass: - active: false - UnnecessaryLet: - active: false - UnnecessaryParentheses: - active: false - UntilInsteadOfRangeTo: - active: false - UnusedImports: - active: false - UnusedPrivateClass: - active: true - UnusedPrivateMember: - active: true - allowedNames: '(_|ignored|expected|serialVersionUID)' - UseAnyOrNoneInsteadOfFind: - active: false - UseArrayLiteralsInAnnotations: - active: false - UseCheckNotNull: - active: false - UseCheckOrError: - active: false - UseDataClass: - active: false - allowVars: false - UseEmptyCounterpart: - active: false - UseIfEmptyOrIfBlank: - active: false - UseIfInsteadOfWhen: - active: false - UseIsNullOrEmpty: - active: false - UseOrEmpty: - active: false - UseRequire: - active: false - UseRequireNotNull: - active: false - UselessCallOnNotNull: - active: true - UtilityClassWithPublicConstructor: - active: true - VarCouldBeVal: - active: true - WildcardImport: - active: true - excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - excludeImports: - - 'java.util.*' diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts deleted file mode 100644 index 0fee587..0000000 --- a/demo/build.gradle.kts +++ /dev/null @@ -1,61 +0,0 @@ -plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.kotlin) - id("convention.jvm.toolchain") -} - -android { - namespace = "eu.wewox.pagecurl" - - compileSdk = libs.versions.sdk.compile.get().toInt() - - defaultConfig { - applicationId = "eu.wewox.pagecurl" - - minSdk = libs.versions.sdk.min.get().toInt() - targetSdk = libs.versions.sdk.target.get().toInt() - - versionCode = 1 - versionName = "1.0" - - vectorDrawables { - useSupportLibrary = true - } - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() - } - kotlinOptions { - freeCompilerArgs = freeCompilerArgs + - "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api" - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } -} - -dependencies { - implementation(project(":pagecurl")) - - implementation(platform(libs.compose.bom)) - implementation(libs.compose.material3) - implementation(libs.compose.ui) - implementation(libs.androidx.activitycompose) - implementation(libs.androidx.pagingruntime) - implementation(libs.androidx.pagingcompose) -} diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/MainActivity.kt b/demo/src/main/kotlin/eu/wewox/pagecurl/MainActivity.kt deleted file mode 100644 index db56fb0..0000000 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/MainActivity.kt +++ /dev/null @@ -1,63 +0,0 @@ -package eu.wewox.pagecurl - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.BackHandler -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.animation.Crossfade -import androidx.compose.foundation.layout.safeDrawingPadding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.core.view.WindowCompat -import eu.wewox.pagecurl.screens.BackPagePageCurlScreen -import eu.wewox.pagecurl.screens.InteractionConfigInPageCurlScreen -import eu.wewox.pagecurl.screens.PagingPageCurlScreen -import eu.wewox.pagecurl.screens.SettingsPageCurlScreen -import eu.wewox.pagecurl.screens.ShadowInPageCurlScreen -import eu.wewox.pagecurl.screens.SimplePageCurlScreen -import eu.wewox.pagecurl.screens.StateInPageCurlScreen -import eu.wewox.pagecurl.ui.theme.PageCurlTheme - -/** - * Main activity for demo application. - * Contains simple "Crossfade" based navigation to various examples. - */ -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - - WindowCompat.setDecorFitsSystemWindows(window, false) - - setContent { - PageCurlTheme { - var example by rememberSaveable { mutableStateOf(null) } - - BackHandler(enabled = example != null) { - example = null - } - - Surface(color = MaterialTheme.colorScheme.background) { - Crossfade(targetState = example, Modifier.safeDrawingPadding(), label = "Crossfade") { selected -> - when (selected) { - null -> RootScreen(onExampleClick = { example = it }) - Example.SimplePageCurl -> SimplePageCurlScreen() - Example.PagingPageCurl -> PagingPageCurlScreen() - Example.SettingsPageCurl -> SettingsPageCurlScreen() - Example.StateInPageCurl -> StateInPageCurlScreen() - Example.InteractionConfigInPageCurl -> InteractionConfigInPageCurlScreen() - Example.ShadowPageCurl -> ShadowInPageCurlScreen() - Example.BackPagePageCurl -> BackPagePageCurlScreen() - } - } - } - } - } - } -} diff --git a/gradle.properties b/gradle.properties index 754d361..7b94f5d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,48 +1,21 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. +# Compiler Configuration org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app"s APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -# Kotlin code style for this project: "official" or "obsolete": -kotlin.code.style=official -# Enables namespacing of each library's R class so that its R class includes only the -# resources declared in the library itself and none from the library's dependencies, -# thereby reducing the size of the R class for that library android.nonTransitiveRClass=true - -# Maven setup with https://github.com/vanniktech/gradle-maven-publish-plugin -SONATYPE_HOST=S01 -RELEASE_SIGNING_ENABLED=true - -GROUP=io.github.oleksandrbalan -POM_ARTIFACT_ID=pagecurl -VERSION_NAME=1.4.1 - -POM_NAME=Page Curl -POM_DESCRIPTION=This library allows to create an effect of turning pages, which can be used in book reader applications, custom on-boarding screens or elsewhere. -POM_INCEPTION_YEAR=2022 -POM_URL=https://github.com/oleksandrbalan/pagecurl - -POM_LICENSE_NAME=The Apache Software License, Version 2.0 -POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENSE_DIST=repo - -POM_SCM_URL=https://github.com/oleksandrbalan/pagecurl -POM_SCM_CONNECTION=scm:git:git://github.com/oleksandrbalan/pagecurl.git -POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/oleksandrbalan/pagecurl.git - -POM_DEVELOPER_ID=oleksandrbalan -POM_DEVELOPER_NAME=Oleksandr Balan -POM_DEVELOPER_URL=https://github.com/oleksandrbalan +kotlin.code.style=official +kotlin.incremental.useClasspathSnapshot=true +org.jetbrains.compose.experimental.uikit.enabled=true +# Project Configuration +project.name=pagecurl-multiplatform +project.description=Page Curl library for Jetpack Compose Multiplatform. +project.url=https://github.com/fankes/pagecurl-multiplatform +project.groupName=eu.wewox.pagecurl +project.moduleName=pagecurl-multiplatform +project.version="1.4.1" +project.licence.name=Apache License 2.0 +project.licence.url=https://github.com/fankes/pagecurl-multiplatform/blob/master/LICENSE +project.android.compileSdk=34 +project.android.minSdk=21 +project.android.targetSdk=34 +project.samples.androidApp.versionName=universal +project.samples.androidApp.versionCode=1 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml deleted file mode 100644 index 579ffb2..0000000 --- a/gradle/libs.versions.toml +++ /dev/null @@ -1,34 +0,0 @@ -[versions] -sdk-compile = "34" -sdk-min = "21" -sdk-target = "33" - -compose-bom = "2023.09.00" -compose-compiler = "1.5.3" -activity-compose = "1.8.0-beta01" -paging = "3.2.1" - -plugin-android-gradle = "8.1.1" -plugin-kotlin = "1.9.10" -plugin-detekt = "1.21.0" -plugin-spotless = "6.5.1" -plugin-mavenpublish = "0.25.3" - -java-toolchain = "17" - -[libraries] -compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" } -compose-foundation = { module = "androidx.compose.foundation:foundation" } -compose-material3 = { module = "androidx.compose.material3:material3" } -compose-ui = { module = "androidx.compose.ui:ui" } -androidx-activitycompose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" } -androidx-pagingruntime = { module = "androidx.paging:paging-runtime", version.ref = "paging" } -androidx-pagingcompose = { module = "androidx.paging:paging-compose", version.ref = "paging" } - -[plugins] -android-application = { id = "com.android.application", version.ref = "plugin-android-gradle" } -android-library = { id = "com.android.library", version.ref = "plugin-android-gradle" } -kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "plugin-kotlin" } -detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "plugin-detekt" } -spotless = { id = "com.diffplug.spotless", version.ref = "plugin-spotless" } -mavenpublish = { id = "com.vanniktech.maven.publish", version.ref = "plugin-mavenpublish" } diff --git a/gradle/sweet-dependency/sweet-dependency-config.yaml b/gradle/sweet-dependency/sweet-dependency-config.yaml new file mode 100644 index 0000000..b020053 --- /dev/null +++ b/gradle/sweet-dependency/sweet-dependency-config.yaml @@ -0,0 +1,65 @@ +preferences: + autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES + repositories-mode: FAIL_ON_PROJECT_REPOS + +repositories: + gradle-plugin-portal: + scope: PLUGINS + google: + maven-central: + +plugins: + org.jetbrains.kotlin.multiplatform: + alias: kotlin-multiplatform + version: 1.9.10 + org.jetbrains.compose: + alias: jetbrains-compose + version: 1.5.1 + com.android.application: + alias: android-application + version: 8.1.2 + com.android.library: + alias: android-library + version-ref: android-application + +libraries: + app.cash.paging: + paging-common: + version: 3.3.0-alpha02-0.4.0 + paging-compose-common: + version-ref: ::paging-common + androidx.compose: + compose-bom: + version: 2023.09.02 + androidx.compose.foundation: + foundation: + version: + androidx.compose.ui: + ui: + version: + androidx.compose.material3: + material3: + version: + androidx.activity: + activity: + version: 1.8.0 + activity-compose: + version: 1.7.2 + androidx.core: + core-ktx: + version: 1.10.0 + androidx.appcompat: + appcompat: + version: 1.6.1 + com.google.android.material: + material: + version: 1.8.0 + androidx.test.ext: + junit: + version: 1.1.5 + androidx.test.espresso: + espresso-core: + version: 3.5.1 + junit: + junit: + version: 4.13.2 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3e49027..692fc5c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Sep 06 22:11:14 CEST 2023 distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip -zipStoreBase=GRADLE_USER_HOME +distributionPath=wrapper/dists zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME \ No newline at end of file diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..107acd3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pagecurl/build.gradle.kts b/pagecurl/build.gradle.kts index 1a22fd1..d842e04 100644 --- a/pagecurl/build.gradle.kts +++ b/pagecurl/build.gradle.kts @@ -1,32 +1,65 @@ plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin) - alias(libs.plugins.mavenpublish) - id("convention.jvm.toolchain") + autowire(libs.plugins.kotlin.multiplatform) + autowire(libs.plugins.android.library) + autowire(libs.plugins.jetbrains.compose) +} + +group = property.project.groupName + +kotlin { + androidTarget() + jvm("desktop") + iosX64() + iosArm64() + iosSimulatorArm64() + jvmToolchain(17) + sourceSets { + all { + languageSettings { + optIn("kotlinx.cinterop.ExperimentalForeignApi") + } + } + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + } + } + val androidMain by getting + val desktopMain by getting { + dependencies { + implementation(compose.desktop.currentOs) + } + } + val iosX64Main by getting + val iosArm64Main by getting + val iosSimulatorArm64Main by getting + val iosMain by creating { + dependsOn(commonMain) + iosX64Main.dependsOn(this) + iosArm64Main.dependsOn(this) + iosSimulatorArm64Main.dependsOn(this) + } + } } android { - namespace = "eu.wewox.pagecurl" + namespace = property.project.groupName + compileSdk = property.project.android.compileSdk - compileSdk = libs.versions.sdk.compile.get().toInt() + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { - minSdk = libs.versions.sdk.min.get().toInt() + minSdk = property.project.android.minSdk } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() - } - kotlinOptions { - freeCompilerArgs = freeCompilerArgs + - "-Xexplicit-api=strict" + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } } -dependencies { - implementation(platform(libs.compose.bom)) - implementation(libs.compose.foundation) - implementation(libs.compose.ui) -} +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file diff --git a/pagecurl/src/androidMain/AndroidManifest.xml b/pagecurl/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..568741e --- /dev/null +++ b/pagecurl/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/pagecurl/src/androidMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.android.kt b/pagecurl/src/androidMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.android.kt new file mode 100644 index 0000000..9ccc680 --- /dev/null +++ b/pagecurl/src/androidMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.android.kt @@ -0,0 +1,9 @@ +package eu.wewox.pagecurl.page + +import android.graphics.BlurMaskFilter +import androidx.compose.ui.graphics.Paint + +actual fun Paint.setBlurred(value: Float) { + if (value == 0f) return + asFrameworkPaint().maskFilter = BlurMaskFilter(value, BlurMaskFilter.Blur.NORMAL) +} \ No newline at end of file diff --git a/pagecurl/src/androidMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.android.kt b/pagecurl/src/androidMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.android.kt new file mode 100644 index 0000000..332cc68 --- /dev/null +++ b/pagecurl/src/androidMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.android.kt @@ -0,0 +1,3 @@ +package eu.wewox.pagecurl.page + +internal actual fun systemCurrentTimeMillis() = System.currentTimeMillis() \ No newline at end of file diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/ExperimentalPageCurlApi.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/ExperimentalPageCurlApi.kt similarity index 100% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/ExperimentalPageCurlApi.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/ExperimentalPageCurlApi.kt diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/config/PageCurlConfig.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/config/PageCurlConfig.kt similarity index 99% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/config/PageCurlConfig.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/config/PageCurlConfig.kt index b4c0d69..875c72d 100644 --- a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/config/PageCurlConfig.kt +++ b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/config/PageCurlConfig.kt @@ -48,7 +48,7 @@ public fun rememberPageCurlConfig( backPageColor: Color = Color.White, backPageContentAlpha: Float = 0.1f, shadowColor: Color = Color.Black, - shadowAlpha: Float = 0.2f, + shadowAlpha: Float = 0.5f, shadowRadius: Dp = 15.dp, shadowOffset: DpOffset = DpOffset((-5).dp, 0.dp), dragForwardEnabled: Boolean = true, diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/CurlDraw.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.kt similarity index 85% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/CurlDraw.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.kt index 1d8d040..574ec16 100644 --- a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/CurlDraw.kt +++ b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.kt @@ -1,23 +1,22 @@ package eu.wewox.pagecurl.page -import android.graphics.Bitmap -import android.graphics.Canvas -import android.os.Build import androidx.compose.ui.Modifier import androidx.compose.ui.draw.CacheDrawScope import androidx.compose.ui.draw.DrawResult import androidx.compose.ui.draw.drawWithCache import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.toRect +import androidx.compose.ui.graphics.Canvas +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.ImageBitmapConfig import androidx.compose.ui.graphics.Paint import androidx.compose.ui.graphics.Path -import androidx.compose.ui.graphics.asAndroidPath import androidx.compose.ui.graphics.drawscope.ContentDrawScope import androidx.compose.ui.graphics.drawscope.clipPath import androidx.compose.ui.graphics.drawscope.drawIntoCanvas import androidx.compose.ui.graphics.drawscope.rotateRad import androidx.compose.ui.graphics.drawscope.withTransform -import androidx.compose.ui.graphics.nativeCanvas import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.unit.dp import eu.wewox.pagecurl.ExperimentalPageCurlApi @@ -25,8 +24,9 @@ import eu.wewox.pagecurl.config.PageCurlConfig import eu.wewox.pagecurl.utils.Polygon import eu.wewox.pagecurl.utils.lineLineIntersection import eu.wewox.pagecurl.utils.rotate -import java.lang.Float.max +import kotlin.math.PI import kotlin.math.atan2 +import kotlin.math.max @ExperimentalPageCurlApi internal fun Modifier.drawCurl( @@ -157,7 +157,7 @@ private fun CacheDrawScope.prepareCurl( // Calculate the angle in radians between X axis and the curl line, this is used to rotate mirrored content to the // right position of the curled back-page val lineVector = topCurlOffset - bottomCurlOffset - val angle = Math.PI.toFloat() - atan2(lineVector.y, lineVector.x) * 2 + val angle = PI.toFloat() - atan2(lineVector.y, lineVector.x) * 2 // Prepare a lambda to draw the shadow of the back-page val drawShadow = prepareShadow(config, polygon, angle) @@ -197,29 +197,27 @@ private fun CacheDrawScope.prepareShadow( // Prepare shadow parameters val radius = config.shadowRadius.toPx() val shadowColor = config.shadowColor.copy(alpha = config.shadowAlpha).toArgb() - val transparent = config.shadowColor.copy(alpha = 0f).toArgb() + // TODO shadowOffset to be set here val shadowOffset = Offset(-config.shadowOffset.x.toPx(), config.shadowOffset.y.toPx()) - .rotate(2 * Math.PI.toFloat() - angle) + .rotate(2 * PI.toFloat() - angle) // Prepare shadow paint with a shadow layer val paint = Paint().apply { - val frameworkPaint = asFrameworkPaint() - frameworkPaint.color = transparent - frameworkPaint.setShadowLayer( - config.shadowRadius.toPx(), - shadowOffset.x, - shadowOffset.y, - shadowColor - ) + color = Color(shadowColor) + setBlurred(radius) + +// val frameworkPaint = asFrameworkPaint() +// frameworkPaint.color = transparent +// frameworkPaint.setShadowLayer( +// config.shadowRadius.toPx(), +// shadowOffset.x, +// shadowOffset.y, +// shadowColor +// ) } - // Hardware acceleration supports setShadowLayer() only on API 28 and above, thus to support previous API versions // draw a shadow to the bitmap instead - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - prepareShadowApi28(radius, paint, polygon) - } else { - prepareShadowImage(radius, paint, polygon) - } + return prepareShadowImage(radius, paint, polygon) } private fun prepareShadowApi28( @@ -228,12 +226,7 @@ private fun prepareShadowApi28( polygon: Polygon, ): ContentDrawScope.() -> Unit = { drawIntoCanvas { - it.nativeCanvas.drawPath( - polygon - .offset(radius).toPath() - .asAndroidPath(), - paint.asFrameworkPaint() - ) + it.drawPath(polygon.offset(radius).toPath(), paint) } } @@ -243,26 +236,26 @@ private fun CacheDrawScope.prepareShadowImage( polygon: Polygon, ): ContentDrawScope.() -> Unit { // Increase the size a little bit so that shadow is not clipped - val bitmap = Bitmap.createBitmap( + val bitmap = ImageBitmap( (size.width + radius * 4).toInt(), (size.height + radius * 4).toInt(), - Bitmap.Config.ARGB_8888 + ImageBitmapConfig.Argb8888 ) Canvas(bitmap).apply { drawPath( polygon // As bitmap size is increased we should translate the polygon so that shadow remains in center .translate(Offset(2 * radius, 2 * radius)) - .offset(radius).toPath() - .asAndroidPath(), - paint.asFrameworkPaint() + .offset(radius).toPath(), paint ) } return { drawIntoCanvas { // As bitmap size is increased we should shift the drawing so that shadow remains in center - it.nativeCanvas.drawBitmap(bitmap, -2 * radius, -2 * radius, null) + it.drawImage(bitmap, Offset(-2 * radius, -2 * radius), paint) } } } + +internal expect fun Paint.setBlurred(value: Float) \ No newline at end of file diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/CurlGesture.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.kt similarity index 60% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/CurlGesture.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.kt index 3fbdeda..fbafa4f 100644 --- a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/CurlGesture.kt +++ b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.kt @@ -5,9 +5,9 @@ import androidx.compose.animation.core.AnimationVector4D import androidx.compose.animation.core.VectorConverter import androidx.compose.animation.core.calculateTargetValue import androidx.compose.animation.splineBasedDecay +import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.gestures.drag -import androidx.compose.foundation.gestures.forEachGesture import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Rect @@ -84,50 +84,50 @@ internal fun Modifier.curlGesture( val velocityTracker = VelocityTracker() val startRect by lazy { targetStart.multiply(size) } val endRect by lazy { targetEnd.multiply(size) } - forEachGesture { - awaitPointerEventScope { - val down = awaitFirstDown(requireUnconsumed = false) - if (!startRect.contains(down.position)) { - return@awaitPointerEventScope - } + awaitEachGesture { + val down = awaitFirstDown(requireUnconsumed = false) + if (!startRect.contains(down.position)) { + return@awaitEachGesture + } - // Change X position to be always on the right side for more convenient gesture tracking - val dragStart = down.position.copy(x = size.width.toFloat()) + // Change X position to be always on the right side for more convenient gesture tracking + val dragStart = down.position.copy(x = size.width.toFloat()) - onStart() + onStart() - var dragCurrent = dragStart - drag(down.id) { change -> - dragCurrent = change.position - velocityTracker.addPosition(System.currentTimeMillis(), dragCurrent) - change.consume() - val vector = (dragStart - dragCurrent).rotate(PI.toFloat() / 2) - onCurl(dragCurrent - vector, dragCurrent + vector) - } + var dragCurrent = dragStart + drag(down.id) { change -> + dragCurrent = change.position + velocityTracker.addPosition(systemCurrentTimeMillis(), dragCurrent) + change.consume() + val vector = (dragStart - dragCurrent).rotate(PI.toFloat() / 2) + onCurl(dragCurrent - vector, dragCurrent + vector) + } - if (dragCurrent == dragStart) { - onCancel() - return@awaitPointerEventScope - } + if (dragCurrent == dragStart) { + onCancel() + return@awaitEachGesture + } - val velocity = velocityTracker.calculateVelocity() - val decay = splineBasedDecay(this) - val target = decay.calculateTargetValue( - Offset.VectorConverter, - dragCurrent, - Offset(velocity.x, velocity.y) - ).let { - Offset( - it.x.coerceIn(0f, size.width.toFloat() - 1), - it.y.coerceIn(0f, size.height.toFloat() - 1) - ) - } + val velocity = velocityTracker.calculateVelocity() + val decay = splineBasedDecay(this) + val target = decay.calculateTargetValue( + Offset.VectorConverter, + dragCurrent, + Offset(velocity.x, velocity.y) + ).let { + Offset( + it.x.coerceIn(0f, size.width.toFloat() - 1), + it.y.coerceIn(0f, size.height.toFloat() - 1) + ) + } - if (endRect.contains(target)) { - onEnd() - } else { - onCancel() - } + if (endRect.contains(target)) { + onEnd() + } else { + onCancel() } } } + +internal expect fun systemCurrentTimeMillis(): Long \ No newline at end of file diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/PageCurl.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/PageCurl.kt similarity index 100% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/PageCurl.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/PageCurl.kt diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/PageCurlState.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/PageCurlState.kt similarity index 100% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/PageCurlState.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/PageCurlState.kt diff --git a/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/TapGesture.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/TapGesture.kt new file mode 100644 index 0000000..4ac537d --- /dev/null +++ b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/page/TapGesture.kt @@ -0,0 +1,51 @@ +package eu.wewox.pagecurl.page + +import androidx.compose.foundation.gestures.awaitEachGesture +import androidx.compose.foundation.gestures.awaitFirstDown +import androidx.compose.foundation.gestures.waitForUpOrCancellation +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.pointer.pointerInput +import eu.wewox.pagecurl.ExperimentalPageCurlApi +import eu.wewox.pagecurl.config.PageCurlConfig +import eu.wewox.pagecurl.utils.multiply +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +@ExperimentalPageCurlApi +internal fun Modifier.tapGesture( + config: PageCurlConfig, + scope: CoroutineScope, + onTapForward: suspend () -> Unit, + onTapBackward: suspend () -> Unit, +): Modifier = pointerInput(config) { + awaitEachGesture { + val down = awaitFirstDown().also { it.consume() } + val up = waitForUpOrCancellation() ?: return@awaitEachGesture + + if ((down.position - up.position).getDistance() > viewConfiguration.touchSlop) { + return@awaitEachGesture + } + + if (config.tapCustomEnabled && config.onCustomTap(this, size, up.position)) { + return@awaitEachGesture + } + + if (config.tapForwardEnabled && config.tapForwardInteraction.target.multiply(size).contains(up.position)) { + scope.launch { + onTapForward() + } + return@awaitEachGesture + } + + if (config.tapBackwardEnabled && + config.tapBackwardInteraction.target + .multiply(size) + .contains(up.position) + ) { + scope.launch { + onTapBackward() + } + return@awaitEachGesture + } + } +} \ No newline at end of file diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/utils/MathUtils.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/utils/MathUtils.kt similarity index 100% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/utils/MathUtils.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/utils/MathUtils.kt diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/utils/Polygon.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/utils/Polygon.kt similarity index 100% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/utils/Polygon.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/utils/Polygon.kt diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/utils/RectUtils.kt b/pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/utils/RectUtils.kt similarity index 100% rename from pagecurl/src/main/kotlin/eu/wewox/pagecurl/utils/RectUtils.kt rename to pagecurl/src/commonMain/kotlin/eu/wewox/pagecurl/utils/RectUtils.kt diff --git a/pagecurl/src/desktopMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.desktop.kt b/pagecurl/src/desktopMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.desktop.kt new file mode 100644 index 0000000..0f6604a --- /dev/null +++ b/pagecurl/src/desktopMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.desktop.kt @@ -0,0 +1,10 @@ +package eu.wewox.pagecurl.page + +import androidx.compose.ui.graphics.Paint +import org.jetbrains.skia.FilterBlurMode +import org.jetbrains.skia.MaskFilter + +actual fun Paint.setBlurred(value: Float) { + if (value == 0f) return + asFrameworkPaint().maskFilter = MaskFilter.makeBlur(FilterBlurMode.NORMAL, value / 2f) +} \ No newline at end of file diff --git a/pagecurl/src/desktopMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.desktop.kt b/pagecurl/src/desktopMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.desktop.kt new file mode 100644 index 0000000..332cc68 --- /dev/null +++ b/pagecurl/src/desktopMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.desktop.kt @@ -0,0 +1,3 @@ +package eu.wewox.pagecurl.page + +internal actual fun systemCurrentTimeMillis() = System.currentTimeMillis() \ No newline at end of file diff --git a/pagecurl/src/iosMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.ios.kt b/pagecurl/src/iosMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.ios.kt new file mode 100644 index 0000000..0f6604a --- /dev/null +++ b/pagecurl/src/iosMain/kotlin/eu/wewox/pagecurl/page/CurlDraw.ios.kt @@ -0,0 +1,10 @@ +package eu.wewox.pagecurl.page + +import androidx.compose.ui.graphics.Paint +import org.jetbrains.skia.FilterBlurMode +import org.jetbrains.skia.MaskFilter + +actual fun Paint.setBlurred(value: Float) { + if (value == 0f) return + asFrameworkPaint().maskFilter = MaskFilter.makeBlur(FilterBlurMode.NORMAL, value / 2f) +} \ No newline at end of file diff --git a/pagecurl/src/iosMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.ios.kt b/pagecurl/src/iosMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.ios.kt new file mode 100644 index 0000000..ae1c9a6 --- /dev/null +++ b/pagecurl/src/iosMain/kotlin/eu/wewox/pagecurl/page/CurlGesture.ios.kt @@ -0,0 +1,13 @@ +package eu.wewox.pagecurl.page + +import kotlinx.cinterop.alloc +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.ptr +import platform.posix.gettimeofday +import platform.posix.timeval + +internal actual fun systemCurrentTimeMillis() = memScoped { + val timeVal = alloc() + gettimeofday(timeVal.ptr, null) + (timeVal.tv_sec * 1000) + (timeVal.tv_usec / 1000) +} \ No newline at end of file diff --git a/pagecurl/src/main/AndroidManifest.xml b/pagecurl/src/main/AndroidManifest.xml deleted file mode 100644 index c191e0f..0000000 --- a/pagecurl/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/TapGesture.kt b/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/TapGesture.kt deleted file mode 100644 index 20dd2ef..0000000 --- a/pagecurl/src/main/kotlin/eu/wewox/pagecurl/page/TapGesture.kt +++ /dev/null @@ -1,53 +0,0 @@ -package eu.wewox.pagecurl.page - -import androidx.compose.foundation.gestures.awaitFirstDown -import androidx.compose.foundation.gestures.forEachGesture -import androidx.compose.foundation.gestures.waitForUpOrCancellation -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.pointer.pointerInput -import eu.wewox.pagecurl.ExperimentalPageCurlApi -import eu.wewox.pagecurl.config.PageCurlConfig -import eu.wewox.pagecurl.utils.multiply -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch - -@ExperimentalPageCurlApi -internal fun Modifier.tapGesture( - config: PageCurlConfig, - scope: CoroutineScope, - onTapForward: suspend () -> Unit, - onTapBackward: suspend () -> Unit, -): Modifier = pointerInput(config) { - forEachGesture { - awaitPointerEventScope { - val down = awaitFirstDown().also { it.consume() } - val up = waitForUpOrCancellation() ?: return@awaitPointerEventScope - - if ((down.position - up.position).getDistance() > viewConfiguration.touchSlop) { - return@awaitPointerEventScope - } - - if (config.tapCustomEnabled && config.onCustomTap(this, size, up.position)) { - return@awaitPointerEventScope - } - - if (config.tapForwardEnabled && config.tapForwardInteraction.target.multiply(size).contains(up.position)) { - scope.launch { - onTapForward() - } - return@awaitPointerEventScope - } - - if (config.tapBackwardEnabled && - config.tapBackwardInteraction.target - .multiply(size) - .contains(up.position) - ) { - scope.launch { - onTapBackward() - } - return@awaitPointerEventScope - } - } - } -} diff --git a/build-logic/.gitignore b/samples/.gitignore similarity index 100% rename from build-logic/.gitignore rename to samples/.gitignore diff --git a/build-logic/convention/.gitignore b/samples/androidApp/.gitignore similarity index 100% rename from build-logic/convention/.gitignore rename to samples/androidApp/.gitignore diff --git a/samples/androidApp/build.gradle.kts b/samples/androidApp/build.gradle.kts new file mode 100644 index 0000000..a04d949 --- /dev/null +++ b/samples/androidApp/build.gradle.kts @@ -0,0 +1,45 @@ +plugins { + autowire(libs.plugins.kotlin.multiplatform) + autowire(libs.plugins.android.application) + autowire(libs.plugins.jetbrains.compose) +} + +group = property.project.groupName + +kotlin { + androidTarget() + jvmToolchain(17) + sourceSets { + val androidMain by getting { + dependencies { + implementation(projects.samples.shared) + } + } + } +} + +android { + namespace = property.project.groupName + compileSdk = property.project.android.compileSdk + + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + + defaultConfig { + applicationId = property.project.groupName + minSdk = property.project.android.minSdk + targetSdk = property.project.android.targetSdk + versionName = property.project.samples.androidApp.versionName + versionCode = property.project.samples.androidApp.versionCode + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } +} \ No newline at end of file diff --git a/demo/proguard-rules.pro b/samples/androidApp/proguard-rules.pro similarity index 88% rename from demo/proguard-rules.pro rename to samples/androidApp/proguard-rules.pro index 481bb43..ff59496 100644 --- a/demo/proguard-rules.pro +++ b/samples/androidApp/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/demo/src/main/AndroidManifest.xml b/samples/androidApp/src/androidMain/AndroidManifest.xml similarity index 95% rename from demo/src/main/AndroidManifest.xml rename to samples/androidApp/src/androidMain/AndroidManifest.xml index b32aa5c..ddd8703 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/samples/androidApp/src/androidMain/AndroidManifest.xml @@ -1,6 +1,5 @@ - + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/samples/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/samples/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..ee7e3ca --- /dev/null +++ b/samples/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} \ No newline at end of file diff --git a/samples/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/samples/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..083f644 --- /dev/null +++ b/samples/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "app-icon-512.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/samples/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-512.png b/samples/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-512.png new file mode 100644 index 0000000..5365c18 Binary files /dev/null and b/samples/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-512.png differ diff --git a/samples/iosApp/iosApp/Assets.xcassets/Contents.json b/samples/iosApp/iosApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/samples/iosApp/iosApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/samples/iosApp/iosApp/ContentView.swift b/samples/iosApp/iosApp/ContentView.swift new file mode 100644 index 0000000..473b05a --- /dev/null +++ b/samples/iosApp/iosApp/ContentView.swift @@ -0,0 +1,19 @@ +import UIKit +import SwiftUI +import shared + +struct ComposeView: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + let viewController = Main_iosKt.createUIViewController() + return viewController + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} +} + +struct ContentView: View { + var body: some View { + ComposeView() + .ignoresSafeArea(.all, edges: .bottom) // Compose has own keyboard handler + } +} diff --git a/samples/iosApp/iosApp/Info.plist b/samples/iosApp/iosApp/Info.plist new file mode 100644 index 0000000..412e378 --- /dev/null +++ b/samples/iosApp/iosApp/Info.plist @@ -0,0 +1,50 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + + UILaunchScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/samples/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/samples/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..4aa7c53 --- /dev/null +++ b/samples/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} \ No newline at end of file diff --git a/samples/iosApp/iosApp/iOSApp.swift b/samples/iosApp/iosApp/iOSApp.swift new file mode 100644 index 0000000..b7bf2f4 --- /dev/null +++ b/samples/iosApp/iosApp/iOSApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct iOSApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/samples/shared/.gitignore b/samples/shared/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/samples/shared/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/samples/shared/build.gradle.kts b/samples/shared/build.gradle.kts new file mode 100644 index 0000000..f1ff602 --- /dev/null +++ b/samples/shared/build.gradle.kts @@ -0,0 +1,87 @@ +plugins { + autowire(libs.plugins.kotlin.multiplatform) + autowire(libs.plugins.android.library) + autowire(libs.plugins.jetbrains.compose) +} + +group = property.project.groupName + +kotlin { + androidTarget() + jvm("desktop") + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "shared" + isStatic = true + } + } + jvmToolchain(17) + sourceSets { + all { + languageSettings { + optIn("androidx.compose.material3.ExperimentalMaterial3Api") + optIn("eu.wewox.pagecurl.ExperimentalPageCurlApi") + } + } + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(app.cash.paging.paging.common) + implementation(app.cash.paging.paging.compose.common) + implementation(projects.pagecurl) + } + } + val androidMain by getting { + dependencies { + api(compose.foundation) + api(androidx.core.core.ktx) + api(androidx.appcompat.appcompat) + api(androidx.activity.activity) + api(androidx.activity.activity.compose) + } + } + val desktopMain by getting { + dependencies { + api(compose.desktop.currentOs) + api(compose.runtime) + api(compose.foundation) + api(compose.material3) + } + } + val iosX64Main by getting + val iosArm64Main by getting + val iosSimulatorArm64Main by getting + val iosMain by creating { + dependsOn(commonMain) + iosX64Main.dependsOn(this) + iosArm64Main.dependsOn(this) + iosSimulatorArm64Main.dependsOn(this) + } + } +} + +android { + namespace = property.project.groupName + compileSdk = property.project.android.compileSdk + + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + + defaultConfig { + minSdk = property.project.android.minSdk + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file diff --git a/samples/shared/src/androidMain/kotlin/eu/wewox/pagecurl/App.android.kt b/samples/shared/src/androidMain/kotlin/eu/wewox/pagecurl/App.android.kt new file mode 100644 index 0000000..1145196 --- /dev/null +++ b/samples/shared/src/androidMain/kotlin/eu/wewox/pagecurl/App.android.kt @@ -0,0 +1,8 @@ +package eu.wewox.pagecurl + +import androidx.compose.runtime.Composable + +@Composable +internal actual fun BackablePageScreen(content: @Composable () -> Unit) { + content() +} \ No newline at end of file diff --git a/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/App.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/App.kt new file mode 100644 index 0000000..ff9f88e --- /dev/null +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/App.kt @@ -0,0 +1,62 @@ +package eu.wewox.pagecurl + +import androidx.compose.animation.Crossfade +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import eu.wewox.pagecurl.screens.BackPagePageCurlScreen +import eu.wewox.pagecurl.screens.InteractionConfigInPageCurlScreen +import eu.wewox.pagecurl.screens.PagingPageCurlScreen +import eu.wewox.pagecurl.screens.SettingsPageCurlScreen +import eu.wewox.pagecurl.screens.ShadowInPageCurlScreen +import eu.wewox.pagecurl.screens.SimplePageCurlScreen +import eu.wewox.pagecurl.screens.StateInPageCurlScreen +import eu.wewox.pagecurl.ui.theme.PageCurlTheme + +/** + * Main view for demo application. + * Contains simple "Crossfade" based navigation to various examples. + */ +@Composable +fun App(modifier: Modifier = Modifier) { + PageCurlTheme { + var example by rememberSaveable { mutableStateOf(null) } + PageStateHandler.callNavToMain = { example = null } + Surface(color = MaterialTheme.colorScheme.background) { + Crossfade(targetState = example, modifier, label = "Crossfade") { selected -> + when (selected) { + null -> RootScreen(onExampleClick = { PageStateHandler.onLeftMain?.invoke(); example = it }) + Example.SimplePageCurl -> BackablePageScreen { SimplePageCurlScreen() } + Example.PagingPageCurl -> BackablePageScreen { PagingPageCurlScreen() } + Example.SettingsPageCurl -> BackablePageScreen { SettingsPageCurlScreen() } + Example.StateInPageCurl -> BackablePageScreen { StateInPageCurlScreen() } + Example.InteractionConfigInPageCurl -> BackablePageScreen { InteractionConfigInPageCurlScreen() } + Example.ShadowPageCurl -> BackablePageScreen { ShadowInPageCurlScreen() } + Example.BackPagePageCurl -> BackablePageScreen { BackPagePageCurlScreen() } + } + } + } + } +} + +object PageStateHandler { + + internal var onLeftMain: (() -> Unit)? = null + internal var callNavToMain: (() -> Unit)? = null + + fun onLeftMain(onLeftMain: () -> Unit) { + this.onLeftMain = onLeftMain + } + + fun navToMain() { + callNavToMain?.invoke() + } +} + +@Composable +internal expect fun BackablePageScreen(content: @Composable () -> Unit) \ No newline at end of file diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/Example.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/Example.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/Example.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/Example.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/HowToPageData.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/HowToPageData.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/HowToPageData.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/HowToPageData.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/RootScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/RootScreen.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/RootScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/RootScreen.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/components/HowToPage.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/HowToPage.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/components/HowToPage.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/HowToPage.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/components/SettingsPopup.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/SettingsPopup.kt similarity index 97% rename from demo/src/main/kotlin/eu/wewox/pagecurl/components/SettingsPopup.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/SettingsPopup.kt index ccba5fe..94fcefb 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/components/SettingsPopup.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/SettingsPopup.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.components import androidx.compose.foundation.layout.Arrangement @@ -20,7 +18,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.config.PageCurlConfig @Composable diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/components/TopBar.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/TopBar.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/components/TopBar.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/TopBar.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/components/ZoomOutLayout.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/ZoomOutLayout.kt similarity index 97% rename from demo/src/main/kotlin/eu/wewox/pagecurl/components/ZoomOutLayout.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/ZoomOutLayout.kt index 58f40a0..2d3b404 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/components/ZoomOutLayout.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/components/ZoomOutLayout.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.components import androidx.compose.animation.AnimatedVisibility @@ -18,7 +16,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Layout import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.config.PageCurlConfig /** diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/BackPagePageCurlScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/BackPagePageCurlScreen.kt similarity index 98% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/BackPagePageCurlScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/BackPagePageCurlScreen.kt index d951277..0b7cb84 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/BackPagePageCurlScreen.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/BackPagePageCurlScreen.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) @file:Suppress("MagicNumber") package eu.wewox.pagecurl.screens @@ -31,7 +30,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.center import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toOffset -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.HowToPageData import eu.wewox.pagecurl.components.HowToPage import eu.wewox.pagecurl.components.ZoomOutLayout diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/InteractionConfigInPageCurl.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/InteractionConfigInPageCurl.kt similarity index 98% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/InteractionConfigInPageCurl.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/InteractionConfigInPageCurl.kt index 791250b..c2b2186 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/InteractionConfigInPageCurl.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/InteractionConfigInPageCurl.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.screens import androidx.compose.foundation.layout.Arrangement @@ -26,7 +24,6 @@ import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.center import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toOffset -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.HowToPageData import eu.wewox.pagecurl.components.HowToPage import eu.wewox.pagecurl.components.ZoomOutLayout diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/PagingPageCurlScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/PagingPageCurlScreen.kt similarity index 96% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/PagingPageCurlScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/PagingPageCurlScreen.kt index 0c44745..10b6815 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/PagingPageCurlScreen.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/PagingPageCurlScreen.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.screens import androidx.compose.foundation.background @@ -20,8 +18,7 @@ import androidx.paging.PagingConfig import androidx.paging.PagingData import androidx.paging.PagingSource import androidx.paging.PagingState -import androidx.paging.compose.collectAsLazyPagingItems -import eu.wewox.pagecurl.ExperimentalPageCurlApi +import app.cash.paging.compose.collectAsLazyPagingItems import eu.wewox.pagecurl.page.PageCurl import eu.wewox.pagecurl.page.rememberPageCurlState import kotlinx.coroutines.delay diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/SettingsPageCurlScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/SettingsPageCurlScreen.kt similarity index 95% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/SettingsPageCurlScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/SettingsPageCurlScreen.kt index fa1d6a3..c402f82 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/SettingsPageCurlScreen.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/SettingsPageCurlScreen.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.screens import androidx.compose.foundation.layout.Box @@ -14,7 +12,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.center import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toOffset -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.HowToPageData import eu.wewox.pagecurl.components.HowToPage import eu.wewox.pagecurl.components.SettingsPopup diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/ShadowInPageCurlScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/ShadowInPageCurlScreen.kt similarity index 97% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/ShadowInPageCurlScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/ShadowInPageCurlScreen.kt index cfe7736..e17e8ed 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/ShadowInPageCurlScreen.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/ShadowInPageCurlScreen.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) @file:Suppress("MagicNumber") package eu.wewox.pagecurl.screens @@ -20,7 +19,6 @@ import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.center import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toOffset -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.HowToPageData import eu.wewox.pagecurl.components.HowToPage import eu.wewox.pagecurl.components.ZoomOutLayout diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/SimplePageCurlScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/SimplePageCurlScreen.kt similarity index 87% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/SimplePageCurlScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/SimplePageCurlScreen.kt index 824fc5b..0932db0 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/SimplePageCurlScreen.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/SimplePageCurlScreen.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.screens import androidx.compose.foundation.layout.Box @@ -7,7 +5,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.HowToPageData import eu.wewox.pagecurl.components.HowToPage import eu.wewox.pagecurl.page.PageCurl diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/StateInPageCurlScreen.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/StateInPageCurlScreen.kt similarity index 97% rename from demo/src/main/kotlin/eu/wewox/pagecurl/screens/StateInPageCurlScreen.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/StateInPageCurlScreen.kt index 375827b..143d575 100644 --- a/demo/src/main/kotlin/eu/wewox/pagecurl/screens/StateInPageCurlScreen.kt +++ b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens/StateInPageCurlScreen.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalPageCurlApi::class) - package eu.wewox.pagecurl.screens import androidx.compose.foundation.horizontalScroll @@ -23,7 +21,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.center import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toOffset -import eu.wewox.pagecurl.ExperimentalPageCurlApi import eu.wewox.pagecurl.HowToPageData import eu.wewox.pagecurl.components.HowToPage import eu.wewox.pagecurl.components.ZoomOutLayout diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/ui/Spacing.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/ui/Spacing.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/ui/Spacing.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/ui/Spacing.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/ui/theme/Color.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/ui/theme/Color.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/ui/theme/Color.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/ui/theme/Color.kt diff --git a/demo/src/main/kotlin/eu/wewox/pagecurl/ui/theme/Theme.kt b/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/ui/theme/Theme.kt similarity index 100% rename from demo/src/main/kotlin/eu/wewox/pagecurl/ui/theme/Theme.kt rename to samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/ui/theme/Theme.kt diff --git a/samples/shared/src/desktopMain/kotlin/eu/wewox/pagecurl/App.desktop.kt b/samples/shared/src/desktopMain/kotlin/eu/wewox/pagecurl/App.desktop.kt new file mode 100644 index 0000000..d0231aa --- /dev/null +++ b/samples/shared/src/desktopMain/kotlin/eu/wewox/pagecurl/App.desktop.kt @@ -0,0 +1,13 @@ +package eu.wewox.pagecurl + +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import eu.wewox.pagecurl.components.TopBar + +@Composable +internal actual fun BackablePageScreen(content: @Composable () -> Unit) { + Box { + content() + TopBar(title = "", onBackClick = { PageStateHandler.navToMain() }) + } +} \ No newline at end of file diff --git a/samples/shared/src/iosMain/kotlin/Main.ios.kt b/samples/shared/src/iosMain/kotlin/Main.ios.kt new file mode 100644 index 0000000..9aaf6a8 --- /dev/null +++ b/samples/shared/src/iosMain/kotlin/Main.ios.kt @@ -0,0 +1,6 @@ +@file:Suppress("unused") + +import androidx.compose.ui.window.ComposeUIViewController +import eu.wewox.pagecurl.App + +fun createUIViewController() = ComposeUIViewController { App() } \ No newline at end of file diff --git a/samples/shared/src/iosMain/kotlin/eu/wewox/pagecurl/App.ios.kt b/samples/shared/src/iosMain/kotlin/eu/wewox/pagecurl/App.ios.kt new file mode 100644 index 0000000..d0231aa --- /dev/null +++ b/samples/shared/src/iosMain/kotlin/eu/wewox/pagecurl/App.ios.kt @@ -0,0 +1,13 @@ +package eu.wewox.pagecurl + +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import eu.wewox.pagecurl.components.TopBar + +@Composable +internal actual fun BackablePageScreen(content: @Composable () -> Unit) { + Box { + content() + TopBar(title = "", onBackClick = { PageStateHandler.navToMain() }) + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index dc66895..753a76c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,23 +1,19 @@ +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") pluginManagement { - includeBuild("build-logic") repositories { - google() - mavenCentral() gradlePluginPortal() - } -} - -plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version ("0.7.0") -} - -dependencyResolutionManagement { - repositories { google() mavenCentral() } } - -rootProject.name = "PageCurl" -include(":demo") -include(":pagecurl") +plugins { + id("com.highcapable.sweetdependency") version "1.0.2" + id("com.highcapable.sweetproperty") version "1.0.3" +} +sweetProperty { + global { sourcesCode { isEnable = false } } + rootProject { all { isEnable = false } } +} +rootProject.name = "pagecurl-multiplatform" +include(":samples:androidApp", ":samples:desktopApp", ":samples:shared") +include(":pagecurl") \ No newline at end of file