feat: support compose multiplatform
17
.editorconfig
Normal file
@@ -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
|
40
.github/workflows/publish.yml
vendored
@@ -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 }}
|
|
47
.github/workflows/static-analysis.yml
vendored
@@ -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
|
|
10
.gitignore
vendored
@@ -1,9 +1,15 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
/local.properties
|
/local.properties
|
||||||
/.idea
|
/.idea/caches
|
||||||
|
/.idea/libraries
|
||||||
|
/.idea/modules.xml
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/navEditor.xml
|
||||||
|
/.idea/assetWizardSettings.xml
|
||||||
.DS_Store
|
.DS_Store
|
||||||
build/
|
/build
|
||||||
/captures
|
/captures
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
.cxx
|
.cxx
|
||||||
|
local.properties
|
||||||
|
4
.idea/.gitignore
generated
vendored
@@ -1,3 +1,5 @@
|
|||||||
# Default ignored files
|
# Default ignored files
|
||||||
/shelf/
|
/shelf/
|
||||||
/workspace.xml
|
/gradle.xml
|
||||||
|
/misc.xml
|
||||||
|
/workspace.xml
|
26
.idea/appInsightsSettings.xml
generated
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AppInsightsSettings">
|
||||||
|
<option name="tabSettings">
|
||||||
|
<map>
|
||||||
|
<entry key="Firebase Crashlytics">
|
||||||
|
<value>
|
||||||
|
<InsightsFilterSettings>
|
||||||
|
<option name="connection">
|
||||||
|
<ConnectionSetting>
|
||||||
|
<option name="appId" value="PLACEHOLDER" />
|
||||||
|
<option name="mobileSdkAppId" value="" />
|
||||||
|
<option name="projectId" value="" />
|
||||||
|
<option name="projectNumber" value="" />
|
||||||
|
</ConnectionSetting>
|
||||||
|
</option>
|
||||||
|
<option name="signal" value="SIGNAL_UNSPECIFIED" />
|
||||||
|
<option name="timeIntervalDays" value="THIRTY_DAYS" />
|
||||||
|
<option name="visibilityType" value="ALL" />
|
||||||
|
</InsightsFilterSettings>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
205
.idea/codeStyles/Project.xml
generated
@@ -1,205 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<option name="AUTODETECT_INDENTS" value="false" />
|
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
|
||||||
<option name="RIGHT_MARGIN" value="120" />
|
|
||||||
<HTMLCodeStyleSettings>
|
|
||||||
<option name="HTML_TEXT_WRAP" value="0" />
|
|
||||||
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
|
||||||
<option name="HTML_ENFORCE_QUOTES" value="true" />
|
|
||||||
</HTMLCodeStyleSettings>
|
|
||||||
<JSON>
|
|
||||||
<option name="ARRAY_WRAPPING" value="5" />
|
|
||||||
</JSON>
|
|
||||||
<JavaCodeStyleSettings>
|
|
||||||
<option name="FIELD_NAME_PREFIX" value="m" />
|
|
||||||
<option name="STATIC_FIELD_NAME_PREFIX" value="s" />
|
|
||||||
<option name="IMPORT_LAYOUT_TABLE">
|
|
||||||
<value>
|
|
||||||
<package name="android" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="com" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="junit" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="net" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="org" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="java" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="javax" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="" withSubpackages="true" static="true" />
|
|
||||||
<emptyLine />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
|
|
||||||
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
|
|
||||||
</JavaCodeStyleSettings>
|
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
|
||||||
<value>
|
|
||||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" />
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<XML>
|
|
||||||
<option name="XML_ATTRIBUTE_WRAP" value="4" />
|
|
||||||
</XML>
|
|
||||||
<editorconfig>
|
|
||||||
<option name="ENABLED" value="false" />
|
|
||||||
</editorconfig>
|
|
||||||
<codeStyleSettings language="Groovy">
|
|
||||||
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="JAVA">
|
|
||||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
|
|
||||||
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
|
|
||||||
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
|
|
||||||
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
|
|
||||||
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="JSON">
|
|
||||||
<option name="KEEP_LINE_BREAKS" value="false" />
|
|
||||||
<indentOptions>
|
|
||||||
<option name="INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="ObjectiveC">
|
|
||||||
<indentOptions>
|
|
||||||
<option name="USE_TAB_CHARACTER" value="true" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="XML">
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
<arrangement>
|
|
||||||
<rules>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:android</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:id</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>style</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
</rules>
|
|
||||||
</arrangement>
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
|
||||||
<option name="CALL_PARAMETERS_WRAP" value="0" />
|
|
||||||
<option name="METHOD_PARAMETERS_WRAP" value="0" />
|
|
||||||
<option name="EXTENDS_LIST_WRAP" value="0" />
|
|
||||||
<option name="METHOD_CALL_CHAIN_WRAP" value="0" />
|
|
||||||
<option name="ASSIGNMENT_WRAP" value="0" />
|
|
||||||
<option name="VARIABLE_ANNOTATION_WRAP" value="2" />
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
10
.idea/deploymentTargetDropDown.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetDropDown">
|
||||||
|
<value>
|
||||||
|
<entry key="androidApp">
|
||||||
|
<State />
|
||||||
|
</entry>
|
||||||
|
</value>
|
||||||
|
</component>
|
||||||
|
</project>
|
35
.idea/gradle.xml
generated
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<compositeConfiguration>
|
|
||||||
<compositeBuild compositeDefinitionSource="SCRIPT">
|
|
||||||
<builds>
|
|
||||||
<build path="$PROJECT_DIR$/build-logic" name="build-logic">
|
|
||||||
<projects>
|
|
||||||
<project path="$PROJECT_DIR$/build-logic" />
|
|
||||||
<project path="$PROJECT_DIR$/build-logic/convention" />
|
|
||||||
</projects>
|
|
||||||
</build>
|
|
||||||
</builds>
|
|
||||||
</compositeBuild>
|
|
||||||
</compositeConfiguration>
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="gradleHome" value="/usr/local/Cellar/gradle/6.0.1/libexec" />
|
|
||||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
<option value="$PROJECT_DIR$/build-logic" />
|
|
||||||
<option value="$PROJECT_DIR$/build-logic/convention" />
|
|
||||||
<option value="$PROJECT_DIR$/demo" />
|
|
||||||
<option value="$PROJECT_DIR$/pagecurl" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
<option name="resolveExternalAnnotations" value="false" />
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
.idea/kotlinc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="KotlinJpsPluginSettings">
|
||||||
|
<option name="version" value="1.9.10" />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/ktlint.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="KtlintProjectConfiguration">
|
||||||
|
<treatAsErrors>false</treatAsErrors>
|
||||||
|
</component>
|
||||||
|
</project>
|
16
.idea/misc.xml
generated
@@ -1,16 +0,0 @@
|
|||||||
<project version="4">
|
|
||||||
<component name="DesignSurface">
|
|
||||||
<option name="filePathToZoomLevelMap">
|
|
||||||
<map>
|
|
||||||
<entry key="../../../../../layout/compose-model-1647938366739.xml" value="0.34881756756756754" />
|
|
||||||
<entry key="app/src/main/res/drawable/ic_launcher_foreground.xml" value="0.247" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectType">
|
|
||||||
<option name="id" value="Android" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
2
.idea/vcs.xml
generated
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
137
README.md
@@ -1,10 +1,18 @@
|
|||||||
[](https://mvnrepository.com/artifact/io.github.oleksandrbalan/pagecurl)
|
[](https://mvnrepository.com/artifact/io.github.oleksandrbalan/pagecurl)
|
||||||
|
|
||||||
<img align="right" src="https://user-images.githubusercontent.com/20944869/200791917-a2436c9a-d062-4c14-9c71-c94fe8703061.png">
|
<img alt="LOGO" align="right" src="https://user-images.githubusercontent.com/20944869/200791917-a2436c9a-d062-4c14-9c71-c94fe8703061.png">
|
||||||
|
|
||||||
# Page Curl
|
# Page Curl (Multiplatform)
|
||||||
|
|
||||||
Page Curl library for Jetpack Compose.
|
Page Curl library for Jetpack Compose Multiplatform.
|
||||||
|
|
||||||
|
Support for Android, iOS, Desktop (JVM):
|
||||||
|
|
||||||
|
<img width="1614" alt="SHOT" src="https://github.com/fankes/pagecurl-multiplatform/assets/37344460/48bb2aa7-12a5-43c5-aa9f-028e83a06746">
|
||||||
|
|
||||||
|
> Note
|
||||||
|
|
||||||
|
This is just an attempt at multiplatform porting, and there may still be some problems.
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
|
|
||||||
@@ -12,122 +20,19 @@ This library allows to create an effect of turning pages, which can be used in b
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Get a dependency
|
> Note
|
||||||
|
|
||||||
**Step 1.** Add the MavenCentral repository to your build file.
|
This multiplatform library's artifact is not upload to any repositories,
|
||||||
Add it in your root `build.gradle.kts` at the end of repositories:
|
you can clone this repository or use git submodule to use it.
|
||||||
```kotlin
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
...
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Or in `settings.gradle.kts`:
|
For an Android version and a sample usage, please visit: https://github.com/oleksandrbalan/pagecurl.
|
||||||
```kotlin
|
|
||||||
pluginManagement {
|
|
||||||
repositories {
|
|
||||||
...
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2.** Add the dependency.
|
See Demo application
|
||||||
Check latest version on the [releases page](https://github.com/oleksandrbalan/pagecurl/releases).
|
and [examples](https://github.com/fankes/pagecurl/blob/multiplatform/samples/shared/src/commonMain/kotlin/eu/wewox/pagecurl/screens) for more usage
|
||||||
```kotlin
|
examples.
|
||||||
dependencies {
|
|
||||||
implementation("io.github.oleksandrbalan:pagecurl:$version")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use in Composable
|
## Thanks
|
||||||
|
|
||||||
The `PageCurl` has 2 mandatory arguments:
|
[The compose multiplatform shadows way](https://github.com/oleksandrbalan/pagecurl/issues/23#issuecomment-1767145310)
|
||||||
* **count** - The count of pages.
|
|
||||||
* **content** - The content lambda to provide the page composable. Receives the page number.
|
|
||||||
|
|
||||||
```
|
[Multiplatform Paging](https://github.com/cashapp/multiplatform-paging)
|
||||||
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
|
|
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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<Project> {
|
|
||||||
override fun apply(target: Project) =
|
|
||||||
with(target) {
|
|
||||||
extensions.configure<JavaPluginExtension> {
|
|
||||||
toolchain {
|
|
||||||
val version = libs.findVersion("java-toolchain").get().displayName
|
|
||||||
languageVersion.set(JavaLanguageVersion.of(version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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<VersionCatalogsExtension>().named("libs")
|
|
@@ -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")
|
|
@@ -1,23 +1,6 @@
|
|||||||
import com.diffplug.gradle.spotless.SpotlessPlugin
|
|
||||||
import io.gitlab.arturbosch.detekt.DetektPlugin
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
autowire(libs.plugins.kotlin.multiplatform) apply false
|
||||||
alias(libs.plugins.android.library) apply false
|
autowire(libs.plugins.android.application) apply false
|
||||||
alias(libs.plugins.kotlin) apply false
|
autowire(libs.plugins.android.library) apply false
|
||||||
alias(libs.plugins.detekt)
|
autowire(libs.plugins.jetbrains.compose) apply false
|
||||||
alias(libs.plugins.spotless)
|
}
|
||||||
alias(libs.plugins.mavenpublish)
|
|
||||||
}
|
|
||||||
|
|
||||||
configure(subprojects) {
|
|
||||||
apply<DetektPlugin>()
|
|
||||||
apply<SpotlessPlugin>()
|
|
||||||
|
|
||||||
spotless {
|
|
||||||
kotlin {
|
|
||||||
target("**/*.kt")
|
|
||||||
ktlint("0.43.2")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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.*'
|
|
@@ -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)
|
|
||||||
}
|
|
@@ -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<Example?>(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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +1,21 @@
|
|||||||
# Project-wide Gradle settings.
|
# Compiler Configuration
|
||||||
# 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.
|
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
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
|
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
|
android.nonTransitiveRClass=true
|
||||||
|
kotlin.code.style=official
|
||||||
# Maven setup with https://github.com/vanniktech/gradle-maven-publish-plugin
|
kotlin.incremental.useClasspathSnapshot=true
|
||||||
SONATYPE_HOST=S01
|
org.jetbrains.compose.experimental.uikit.enabled=true
|
||||||
RELEASE_SIGNING_ENABLED=true
|
# Project Configuration
|
||||||
|
project.name=pagecurl-multiplatform
|
||||||
GROUP=io.github.oleksandrbalan
|
project.description=Page Curl library for Jetpack Compose Multiplatform.
|
||||||
POM_ARTIFACT_ID=pagecurl
|
project.url=https://github.com/fankes/pagecurl-multiplatform
|
||||||
VERSION_NAME=1.4.1
|
project.groupName=eu.wewox.pagecurl
|
||||||
|
project.moduleName=pagecurl-multiplatform
|
||||||
POM_NAME=Page Curl
|
project.version="1.4.1"
|
||||||
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.
|
project.licence.name=Apache License 2.0
|
||||||
POM_INCEPTION_YEAR=2022
|
project.licence.url=https://github.com/fankes/pagecurl-multiplatform/blob/master/LICENSE
|
||||||
POM_URL=https://github.com/oleksandrbalan/pagecurl
|
project.android.compileSdk=34
|
||||||
|
project.android.minSdk=21
|
||||||
POM_LICENSE_NAME=The Apache Software License, Version 2.0
|
project.android.targetSdk=34
|
||||||
POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
|
project.samples.androidApp.versionName=universal
|
||||||
POM_LICENSE_DIST=repo
|
project.samples.androidApp.versionCode=1
|
||||||
|
|
||||||
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
|
|
@@ -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" }
|
|
65
gradle/sweet-dependency/sweet-dependency-config.yaml
Normal file
@@ -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: <this>::paging-common
|
||||||
|
androidx.compose:
|
||||||
|
compose-bom:
|
||||||
|
version: 2023.09.02
|
||||||
|
androidx.compose.foundation:
|
||||||
|
foundation:
|
||||||
|
version: <no-spec>
|
||||||
|
androidx.compose.ui:
|
||||||
|
ui:
|
||||||
|
version: <no-spec>
|
||||||
|
androidx.compose.material3:
|
||||||
|
material3:
|
||||||
|
version: <no-spec>
|
||||||
|
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
|
5
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
|||||||
#Wed Sep 06 22:11:14 CEST 2023
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
178
gradlew.bat
vendored
@@ -1,89 +1,89 @@
|
|||||||
@rem
|
@rem
|
||||||
@rem Copyright 2015 the original author or authors.
|
@rem Copyright 2015 the original author or authors.
|
||||||
@rem
|
@rem
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
@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 not use this file except in compliance with the License.
|
||||||
@rem You may obtain a copy of the License at
|
@rem You may obtain a copy of the License at
|
||||||
@rem
|
@rem
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@rem
|
@rem
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
@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 distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
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.
|
@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"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
@@ -1,32 +1,65 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.library)
|
autowire(libs.plugins.kotlin.multiplatform)
|
||||||
alias(libs.plugins.kotlin)
|
autowire(libs.plugins.android.library)
|
||||||
alias(libs.plugins.mavenpublish)
|
autowire(libs.plugins.jetbrains.compose)
|
||||||
id("convention.jvm.toolchain")
|
}
|
||||||
|
|
||||||
|
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 {
|
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 {
|
defaultConfig {
|
||||||
minSdk = libs.versions.sdk.min.get().toInt()
|
minSdk = property.project.android.minSdk
|
||||||
}
|
}
|
||||||
buildFeatures {
|
compileOptions {
|
||||||
compose = true
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
composeOptions {
|
|
||||||
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
|
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
freeCompilerArgs = freeCompilerArgs +
|
|
||||||
"-Xexplicit-api=strict"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
java {
|
||||||
implementation(platform(libs.compose.bom))
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
implementation(libs.compose.foundation)
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
implementation(libs.compose.ui)
|
}
|
||||||
}
|
|
2
pagecurl/src/androidMain/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest />
|
@@ -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)
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
package eu.wewox.pagecurl.page
|
||||||
|
|
||||||
|
internal actual fun systemCurrentTimeMillis() = System.currentTimeMillis()
|
@@ -48,7 +48,7 @@ public fun rememberPageCurlConfig(
|
|||||||
backPageColor: Color = Color.White,
|
backPageColor: Color = Color.White,
|
||||||
backPageContentAlpha: Float = 0.1f,
|
backPageContentAlpha: Float = 0.1f,
|
||||||
shadowColor: Color = Color.Black,
|
shadowColor: Color = Color.Black,
|
||||||
shadowAlpha: Float = 0.2f,
|
shadowAlpha: Float = 0.5f,
|
||||||
shadowRadius: Dp = 15.dp,
|
shadowRadius: Dp = 15.dp,
|
||||||
shadowOffset: DpOffset = DpOffset((-5).dp, 0.dp),
|
shadowOffset: DpOffset = DpOffset((-5).dp, 0.dp),
|
||||||
dragForwardEnabled: Boolean = true,
|
dragForwardEnabled: Boolean = true,
|
@@ -1,23 +1,22 @@
|
|||||||
package eu.wewox.pagecurl.page
|
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.Modifier
|
||||||
import androidx.compose.ui.draw.CacheDrawScope
|
import androidx.compose.ui.draw.CacheDrawScope
|
||||||
import androidx.compose.ui.draw.DrawResult
|
import androidx.compose.ui.draw.DrawResult
|
||||||
import androidx.compose.ui.draw.drawWithCache
|
import androidx.compose.ui.draw.drawWithCache
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.toRect
|
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.Paint
|
||||||
import androidx.compose.ui.graphics.Path
|
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.ContentDrawScope
|
||||||
import androidx.compose.ui.graphics.drawscope.clipPath
|
import androidx.compose.ui.graphics.drawscope.clipPath
|
||||||
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
|
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
|
||||||
import androidx.compose.ui.graphics.drawscope.rotateRad
|
import androidx.compose.ui.graphics.drawscope.rotateRad
|
||||||
import androidx.compose.ui.graphics.drawscope.withTransform
|
import androidx.compose.ui.graphics.drawscope.withTransform
|
||||||
import androidx.compose.ui.graphics.nativeCanvas
|
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.wewox.pagecurl.ExperimentalPageCurlApi
|
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.Polygon
|
||||||
import eu.wewox.pagecurl.utils.lineLineIntersection
|
import eu.wewox.pagecurl.utils.lineLineIntersection
|
||||||
import eu.wewox.pagecurl.utils.rotate
|
import eu.wewox.pagecurl.utils.rotate
|
||||||
import java.lang.Float.max
|
import kotlin.math.PI
|
||||||
import kotlin.math.atan2
|
import kotlin.math.atan2
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
@ExperimentalPageCurlApi
|
@ExperimentalPageCurlApi
|
||||||
internal fun Modifier.drawCurl(
|
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
|
// 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
|
// right position of the curled back-page
|
||||||
val lineVector = topCurlOffset - bottomCurlOffset
|
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
|
// Prepare a lambda to draw the shadow of the back-page
|
||||||
val drawShadow = prepareShadow(config, polygon, angle)
|
val drawShadow = prepareShadow(config, polygon, angle)
|
||||||
@@ -197,29 +197,27 @@ private fun CacheDrawScope.prepareShadow(
|
|||||||
// Prepare shadow parameters
|
// Prepare shadow parameters
|
||||||
val radius = config.shadowRadius.toPx()
|
val radius = config.shadowRadius.toPx()
|
||||||
val shadowColor = config.shadowColor.copy(alpha = config.shadowAlpha).toArgb()
|
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())
|
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
|
// Prepare shadow paint with a shadow layer
|
||||||
val paint = Paint().apply {
|
val paint = Paint().apply {
|
||||||
val frameworkPaint = asFrameworkPaint()
|
color = Color(shadowColor)
|
||||||
frameworkPaint.color = transparent
|
setBlurred(radius)
|
||||||
frameworkPaint.setShadowLayer(
|
|
||||||
config.shadowRadius.toPx(),
|
// val frameworkPaint = asFrameworkPaint()
|
||||||
shadowOffset.x,
|
// frameworkPaint.color = transparent
|
||||||
shadowOffset.y,
|
// frameworkPaint.setShadowLayer(
|
||||||
shadowColor
|
// 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
|
// draw a shadow to the bitmap instead
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
return prepareShadowImage(radius, paint, polygon)
|
||||||
prepareShadowApi28(radius, paint, polygon)
|
|
||||||
} else {
|
|
||||||
prepareShadowImage(radius, paint, polygon)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareShadowApi28(
|
private fun prepareShadowApi28(
|
||||||
@@ -228,12 +226,7 @@ private fun prepareShadowApi28(
|
|||||||
polygon: Polygon,
|
polygon: Polygon,
|
||||||
): ContentDrawScope.() -> Unit = {
|
): ContentDrawScope.() -> Unit = {
|
||||||
drawIntoCanvas {
|
drawIntoCanvas {
|
||||||
it.nativeCanvas.drawPath(
|
it.drawPath(polygon.offset(radius).toPath(), paint)
|
||||||
polygon
|
|
||||||
.offset(radius).toPath()
|
|
||||||
.asAndroidPath(),
|
|
||||||
paint.asFrameworkPaint()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,26 +236,26 @@ private fun CacheDrawScope.prepareShadowImage(
|
|||||||
polygon: Polygon,
|
polygon: Polygon,
|
||||||
): ContentDrawScope.() -> Unit {
|
): ContentDrawScope.() -> Unit {
|
||||||
// Increase the size a little bit so that shadow is not clipped
|
// 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.width + radius * 4).toInt(),
|
||||||
(size.height + radius * 4).toInt(),
|
(size.height + radius * 4).toInt(),
|
||||||
Bitmap.Config.ARGB_8888
|
ImageBitmapConfig.Argb8888
|
||||||
)
|
)
|
||||||
Canvas(bitmap).apply {
|
Canvas(bitmap).apply {
|
||||||
drawPath(
|
drawPath(
|
||||||
polygon
|
polygon
|
||||||
// As bitmap size is increased we should translate the polygon so that shadow remains in center
|
// As bitmap size is increased we should translate the polygon so that shadow remains in center
|
||||||
.translate(Offset(2 * radius, 2 * radius))
|
.translate(Offset(2 * radius, 2 * radius))
|
||||||
.offset(radius).toPath()
|
.offset(radius).toPath(), paint
|
||||||
.asAndroidPath(),
|
|
||||||
paint.asFrameworkPaint()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
drawIntoCanvas {
|
drawIntoCanvas {
|
||||||
// As bitmap size is increased we should shift the drawing so that shadow remains in center
|
// 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)
|
@@ -5,9 +5,9 @@ import androidx.compose.animation.core.AnimationVector4D
|
|||||||
import androidx.compose.animation.core.VectorConverter
|
import androidx.compose.animation.core.VectorConverter
|
||||||
import androidx.compose.animation.core.calculateTargetValue
|
import androidx.compose.animation.core.calculateTargetValue
|
||||||
import androidx.compose.animation.splineBasedDecay
|
import androidx.compose.animation.splineBasedDecay
|
||||||
|
import androidx.compose.foundation.gestures.awaitEachGesture
|
||||||
import androidx.compose.foundation.gestures.awaitFirstDown
|
import androidx.compose.foundation.gestures.awaitFirstDown
|
||||||
import androidx.compose.foundation.gestures.drag
|
import androidx.compose.foundation.gestures.drag
|
||||||
import androidx.compose.foundation.gestures.forEachGesture
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Rect
|
import androidx.compose.ui.geometry.Rect
|
||||||
@@ -84,50 +84,50 @@ internal fun Modifier.curlGesture(
|
|||||||
val velocityTracker = VelocityTracker()
|
val velocityTracker = VelocityTracker()
|
||||||
val startRect by lazy { targetStart.multiply(size) }
|
val startRect by lazy { targetStart.multiply(size) }
|
||||||
val endRect by lazy { targetEnd.multiply(size) }
|
val endRect by lazy { targetEnd.multiply(size) }
|
||||||
forEachGesture {
|
awaitEachGesture {
|
||||||
awaitPointerEventScope {
|
val down = awaitFirstDown(requireUnconsumed = false)
|
||||||
val down = awaitFirstDown(requireUnconsumed = false)
|
if (!startRect.contains(down.position)) {
|
||||||
if (!startRect.contains(down.position)) {
|
return@awaitEachGesture
|
||||||
return@awaitPointerEventScope
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Change X position to be always on the right side for more convenient gesture tracking
|
// Change X position to be always on the right side for more convenient gesture tracking
|
||||||
val dragStart = down.position.copy(x = size.width.toFloat())
|
val dragStart = down.position.copy(x = size.width.toFloat())
|
||||||
|
|
||||||
onStart()
|
onStart()
|
||||||
|
|
||||||
var dragCurrent = dragStart
|
var dragCurrent = dragStart
|
||||||
drag(down.id) { change ->
|
drag(down.id) { change ->
|
||||||
dragCurrent = change.position
|
dragCurrent = change.position
|
||||||
velocityTracker.addPosition(System.currentTimeMillis(), dragCurrent)
|
velocityTracker.addPosition(systemCurrentTimeMillis(), dragCurrent)
|
||||||
change.consume()
|
change.consume()
|
||||||
val vector = (dragStart - dragCurrent).rotate(PI.toFloat() / 2)
|
val vector = (dragStart - dragCurrent).rotate(PI.toFloat() / 2)
|
||||||
onCurl(dragCurrent - vector, dragCurrent + vector)
|
onCurl(dragCurrent - vector, dragCurrent + vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragCurrent == dragStart) {
|
if (dragCurrent == dragStart) {
|
||||||
onCancel()
|
onCancel()
|
||||||
return@awaitPointerEventScope
|
return@awaitEachGesture
|
||||||
}
|
}
|
||||||
|
|
||||||
val velocity = velocityTracker.calculateVelocity()
|
val velocity = velocityTracker.calculateVelocity()
|
||||||
val decay = splineBasedDecay<Offset>(this)
|
val decay = splineBasedDecay<Offset>(this)
|
||||||
val target = decay.calculateTargetValue(
|
val target = decay.calculateTargetValue(
|
||||||
Offset.VectorConverter,
|
Offset.VectorConverter,
|
||||||
dragCurrent,
|
dragCurrent,
|
||||||
Offset(velocity.x, velocity.y)
|
Offset(velocity.x, velocity.y)
|
||||||
).let {
|
).let {
|
||||||
Offset(
|
Offset(
|
||||||
it.x.coerceIn(0f, size.width.toFloat() - 1),
|
it.x.coerceIn(0f, size.width.toFloat() - 1),
|
||||||
it.y.coerceIn(0f, size.height.toFloat() - 1)
|
it.y.coerceIn(0f, size.height.toFloat() - 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endRect.contains(target)) {
|
if (endRect.contains(target)) {
|
||||||
onEnd()
|
onEnd()
|
||||||
} else {
|
} else {
|
||||||
onCancel()
|
onCancel()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal expect fun systemCurrentTimeMillis(): Long
|
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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)
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
package eu.wewox.pagecurl.page
|
||||||
|
|
||||||
|
internal actual fun systemCurrentTimeMillis() = System.currentTimeMillis()
|
@@ -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)
|
||||||
|
}
|
@@ -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<timeval>()
|
||||||
|
gettimeofday(timeVal.ptr, null)
|
||||||
|
(timeVal.tv_sec * 1000) + (timeVal.tv_usec / 1000)
|
||||||
|
}
|
@@ -1,2 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="eu.wewox.pagecurl" />
|
|
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
45
samples/androidApp/build.gradle.kts
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
# Add project specific ProGuard rules here.
|
# Add project specific ProGuard rules here.
|
||||||
# You can control the set of applied configuration files using the
|
# 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
|
# For more details, see
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="eu.wewox.pagecurl">
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,26 @@
|
|||||||
|
package eu.wewox.pagecurl
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.addCallback
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
|
||||||
|
class MainActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
enableEdgeToEdge()
|
||||||
|
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
|
setContent { App(Modifier.safeDrawingPadding()) }
|
||||||
|
val callback = onBackPressedDispatcher.addCallback(enabled = false) {
|
||||||
|
isEnabled = false
|
||||||
|
PageStateHandler.navToMain()
|
||||||
|
}
|
||||||
|
PageStateHandler.onLeftMain { callback.isEnabled = true }
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 286 KiB After Width: | Height: | Size: 286 KiB |
Before Width: | Height: | Size: 607 KiB After Width: | Height: | Size: 607 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
29
samples/desktopApp/build.gradle.kts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
plugins {
|
||||||
|
autowire(libs.plugins.kotlin.multiplatform)
|
||||||
|
autowire(libs.plugins.jetbrains.compose)
|
||||||
|
}
|
||||||
|
|
||||||
|
group = property.project.groupName
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm("desktop")
|
||||||
|
jvmToolchain(17)
|
||||||
|
sourceSets {
|
||||||
|
val desktopMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.samples.shared)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
compose.desktop {
|
||||||
|
application {
|
||||||
|
mainClass = "${property.project.groupName}.MainKt"
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
package eu.wewox.pagecurl
|
||||||
|
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Window
|
||||||
|
import androidx.compose.ui.window.application
|
||||||
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
Window(
|
||||||
|
onCloseRequest = ::exitApplication,
|
||||||
|
title = "PageCurl Demo",
|
||||||
|
state = rememberWindowState(width = 450.dp, height = 750.dp)
|
||||||
|
) { App() }
|
||||||
|
}
|
6
samples/iosApp/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
## User settings
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Xcode 8 and earlier
|
||||||
|
*.xcscmblueprint
|
||||||
|
*.xccheckout
|
3
samples/iosApp/Configuration/Config.xcconfig
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
TEAM_ID=
|
||||||
|
BUNDLE_ID=com.myapplication.MyApplication
|
||||||
|
APP_NAME=PageCurl
|
400
samples/iosApp/iosApp.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 50;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; };
|
||||||
|
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; };
|
||||||
|
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; };
|
||||||
|
7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||||
|
2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
|
||||||
|
7555FF7B242A565900829871 /* PageCurl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PageCurl.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
|
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
F85CB1118929364A9C6EFABC /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
058557D7273AAEEB004C7B11 /* Preview Content */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */,
|
||||||
|
);
|
||||||
|
path = "Preview Content";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
42799AB246E5F90AF97AA0EF /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7555FF72242A565900829871 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AB1DB47929225F7C00F7AF9C /* Configuration */,
|
||||||
|
7555FF7D242A565900829871 /* iosApp */,
|
||||||
|
7555FF7C242A565900829871 /* Products */,
|
||||||
|
42799AB246E5F90AF97AA0EF /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7555FF7C242A565900829871 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7555FF7B242A565900829871 /* PageCurl.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7555FF7D242A565900829871 /* iosApp */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
058557BA273AAA24004C7B11 /* Assets.xcassets */,
|
||||||
|
7555FF82242A565900829871 /* ContentView.swift */,
|
||||||
|
7555FF8C242A565B00829871 /* Info.plist */,
|
||||||
|
2152FB032600AC8F00CF470E /* iOSApp.swift */,
|
||||||
|
058557D7273AAEEB004C7B11 /* Preview Content */,
|
||||||
|
);
|
||||||
|
path = iosApp;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
AB1DB47929225F7C00F7AF9C /* Configuration */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AB3632DC29227652001CCB65 /* Config.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Configuration;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
7555FF7A242A565900829871 /* iosApp */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */;
|
||||||
|
buildPhases = (
|
||||||
|
05D91A912A5EF49C00F138EB /* Compile Kotlin */,
|
||||||
|
7555FF77242A565900829871 /* Sources */,
|
||||||
|
7555FF79242A565900829871 /* Resources */,
|
||||||
|
F85CB1118929364A9C6EFABC /* Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = iosApp;
|
||||||
|
productName = iosApp;
|
||||||
|
productReference = 7555FF7B242A565900829871 /* PageCurl.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
7555FF73242A565900829871 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastSwiftUpdateCheck = 1130;
|
||||||
|
LastUpgradeCheck = 1130;
|
||||||
|
ORGANIZATIONNAME = orgName;
|
||||||
|
TargetAttributes = {
|
||||||
|
7555FF7A242A565900829871 = {
|
||||||
|
CreatedOnToolsVersion = 11.3.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 7555FF72242A565900829871;
|
||||||
|
productRefGroup = 7555FF7C242A565900829871 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
7555FF7A242A565900829871 /* iosApp */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
7555FF79242A565900829871 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */,
|
||||||
|
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
05D91A912A5EF49C00F138EB /* Compile Kotlin */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Compile Kotlin";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "cd \"$(dirname \"$(dirname \"$SRCROOT\")\")\"\n./gradlew :samples:shared:embedAndSignAppleFrameworkForXcode\n";
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
7555FF77242A565900829871 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */,
|
||||||
|
7555FF83242A565900829871 /* ContentView.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
7555FFA3242A565B00829871 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = AB3632DC29227652001CCB65 /* Config.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
7555FFA4242A565B00829871 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = AB3632DC29227652001CCB65 /* Config.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
7555FFA6242A565B00829871 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
|
DEVELOPMENT_TEAM = "${TEAM_ID}";
|
||||||
|
ENABLE_PREVIEWS = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
"$(inherited)\n",
|
||||||
|
"$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n",
|
||||||
|
);
|
||||||
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-framework",
|
||||||
|
"shared\n$(inherited)",
|
||||||
|
"-framework",
|
||||||
|
"shared\n",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_ID}${TEAM_ID}";
|
||||||
|
PRODUCT_NAME = "${APP_NAME}";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
7555FFA7242A565B00829871 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
|
DEVELOPMENT_TEAM = "${TEAM_ID}";
|
||||||
|
ENABLE_PREVIEWS = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
"$(inherited)\n",
|
||||||
|
"$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n",
|
||||||
|
);
|
||||||
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-framework",
|
||||||
|
"shared\n$(inherited)",
|
||||||
|
"-framework",
|
||||||
|
"shared\n",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_ID}${TEAM_ID}";
|
||||||
|
PRODUCT_NAME = "${APP_NAME}";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
7555FFA3242A565B00829871 /* Debug */,
|
||||||
|
7555FFA4242A565B00829871 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
7555FFA6242A565B00829871 /* Debug */,
|
||||||
|
7555FFA7242A565B00829871 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 7555FF73242A565900829871 /* Project object */;
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "app-icon-512.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 17 KiB |
6
samples/iosApp/iosApp/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
19
samples/iosApp/iosApp/ContentView.swift
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
}
|
50
samples/iosApp/iosApp/Info.plist
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIApplicationSceneManifest</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>UILaunchScreen</key>
|
||||||
|
<dict/>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>armv7</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
10
samples/iosApp/iosApp/iOSApp.swift
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct iOSApp: App {
|
||||||
|
var body: some Scene {
|
||||||
|
WindowGroup {
|
||||||
|
ContentView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
samples/shared/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build
|
87
samples/shared/build.gradle.kts
Normal file
@@ -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
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
package eu.wewox.pagecurl
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal actual fun BackablePageScreen(content: @Composable () -> Unit) {
|
||||||
|
content()
|
||||||
|
}
|
@@ -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<Example?>(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)
|
@@ -1,5 +1,3 @@
|
|||||||
@file:OptIn(ExperimentalPageCurlApi::class)
|
|
||||||
|
|
||||||
package eu.wewox.pagecurl.components
|
package eu.wewox.pagecurl.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
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.unit.dp
|
||||||
import androidx.compose.ui.window.Popup
|
import androidx.compose.ui.window.Popup
|
||||||
import androidx.compose.ui.window.PopupProperties
|
import androidx.compose.ui.window.PopupProperties
|
||||||
import eu.wewox.pagecurl.ExperimentalPageCurlApi
|
|
||||||
import eu.wewox.pagecurl.config.PageCurlConfig
|
import eu.wewox.pagecurl.config.PageCurlConfig
|
||||||
|
|
||||||
@Composable
|
@Composable
|