13 |
14 |
54 |
--------------------------------------------------------------------------------
/android-sample/README.md:
--------------------------------------------------------------------------------
1 | ## Rust Cross Platform Development: Android Sample
2 |
3 | In order to **get started,** please refer to the the following **article/post** I have written:
4 |
5 | - [Rust cross-platform... The Android part...](https://fernandocejas.com/blog/engineering/2023-07-27-rust-cross-platform-android/).
6 |
7 | ## The Idea
8 |
9 | **A picture worth a thousand words!** Here is a summary of what this repo tries to accomplish:
10 |
11 |
12 |
13 |
18 |
19 |
52 |
--------------------------------------------------------------------------------
/ios-sample/.gitignore:
--------------------------------------------------------------------------------
1 | ### Swift ###
2 | # Xcode
3 | #
4 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
5 |
6 | ## User settings
7 | xcuserdata/
8 |
9 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
10 | *.xcscmblueprint
11 | *.xccheckout
12 |
13 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
14 | build/
15 | DerivedData/
16 | *.moved-aside
17 | *.pbxuser
18 | !default.pbxuser
19 | *.mode1v3
20 | !default.mode1v3
21 | *.mode2v3
22 | !default.mode2v3
23 | *.perspectivev3
24 | !default.perspectivev3
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 |
29 | ## App packaging
30 | *.ipa
31 | *.dSYM.zip
32 | *.dSYM
33 |
34 | ## Playgrounds
35 | timeline.xctimeline
36 | playground.xcworkspace
37 |
38 | # Swift Package Manager
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
45 | # hence it is not needed unless you have added a package configuration file to your project
46 | # .swiftpm
47 |
48 | .build/
49 |
50 | # CocoaPods
51 | # We recommend against adding the Pods directory to your .gitignore. However
52 | # you should judge for yourself, the pros and cons are mentioned at:
53 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
54 | # Pods/
55 | # Add this line if you want to avoid checking in source code from the Xcode workspace
56 | # *.xcworkspace
57 |
58 | # Carthage
59 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
60 | # Carthage/Checkouts
61 |
62 | Carthage/Build/
63 |
64 | # Accio dependency management
65 | Dependencies/
66 | .accio/
67 |
68 | # fastlane
69 | # It is recommended to not store the screenshots in the git repo.
70 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
71 | # For more information about the recommended setup visit:
72 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
73 |
74 | fastlane/report.xml
75 | fastlane/Preview.html
76 | fastlane/screenshots/**/*.png
77 | fastlane/test_output
78 |
79 | # Code Injection
80 | # After new code Injection tools there's a generated folder /iOSInjectionProject
81 | # https://github.com/johnno1962/injectionforxcode
82 |
83 | iOSInjectionProject/
84 |
--------------------------------------------------------------------------------
/android-sample/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/rust-library/cryptor_jni/src/bin/release.rs:
--------------------------------------------------------------------------------
1 | ///
2 | /// This is a binary targets, which is an executable program
3 | /// that can be run after crate compilation.
4 | ///
5 | /// It will basically build release versions of
6 | /// each android target.
7 | ///
8 | /// ## Examples
9 | /// ```
10 | /// $ cd cryptor_jni/
11 | /// $ cargo run --bin release
12 | /// ```
13 | ///
14 | /// For more information, refer to the official doc:
15 | /// - https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries
16 | ///
17 |
18 |
19 | // https://doc.rust-lang.org/reference/items/modules.html
20 | #[path="../../build.rs"]
21 | mod build;
22 |
23 | use cryptor_global::console;
24 |
25 | ///
26 | /// Release android targets from Configuration.
27 | /// Check ['build.rs'] File.
28 | ///
29 | /// ## Example
30 | ///
31 | /// ```
32 | /// cargo build --target armv7-linux-androideabi --release
33 | /// cargo build --target aarch64-linux-android --release
34 | /// cargo build --target i686-linux-android --release
35 | /// cargo build --target x86_64-linux-android --release
36 | /// ```
37 | fn release_android_targets() {
38 | for target in build::ANDROID_TARGET_ABI_CONFIG.keys() {
39 | console::print(format!("Building Android Target --> {}", &target));
40 |
41 | let command_args = build_command_args_for_target(&target);
42 | console::run_command("cargo", &command_args);
43 | }
44 | }
45 |
46 | ///
47 | /// Build `cargo` arguments for building android targets.
48 | ///
49 | /// ## Example
50 | ///
51 | /// ```
52 | /// cargo build --target armv7-linux-androideabi --release
53 | /// ```
54 | fn build_command_args_for_target(target: &str) -> Vec<&str> {
55 | let mut command_args = Vec::new();
56 |
57 | command_args.push("build");
58 | command_args.push("--target");
59 | command_args.push(target);
60 | command_args.push("--release");
61 |
62 | command_args
63 | }
64 |
65 | fn main() {
66 | console::out("Releasing Android Targets...Be patient... :)");
67 |
68 | release_android_targets();
69 | }
70 |
71 | //
72 | // T E S T S
73 | //
74 | #[cfg(test)]
75 | mod tests {
76 | use super::*;
77 |
78 | #[test]
79 | fn test_build_android_release_argument() {
80 | let command_args = build_command_args_for_target("armv7-linux-androideabi");
81 | let expected_result = "build --target armv7-linux-androideabi --release";
82 |
83 | assert_eq!(command_args.join(" "), expected_result.trim());
84 | }
85 |
86 | #[test]
87 | fn test_build_android_release_arguments_for_all_targets() {
88 | for target in build::ANDROID_TARGET_ABI_CONFIG.keys() {
89 | let command_args = build_command_args_for_target(&target);
90 | let expected_result = format!("build --target {target} --release", target = &target);
91 |
92 | assert_eq!(command_args.join(" "), expected_result.trim());
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/android-sample/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 | class AppConfig {
4 | val id = "com.fernandocejas.sample"
5 | val javaVersion = JavaVersion.VERSION_17
6 |
7 | val compileSdk = libs.versions.compileSdk.get().toInt()
8 | val minSdk = libs.versions.minSdk.get().toInt()
9 | val targetSdk = libs.versions.targetSdk.get().toInt()
10 | }
11 |
12 |
13 | plugins {
14 | alias(libs.plugins.android.application)
15 | alias(libs.plugins.kotlin.android)
16 | }
17 |
18 | android {
19 | val appConfig = AppConfig()
20 |
21 | namespace = appConfig.id
22 | compileSdk = appConfig.compileSdk
23 |
24 | defaultConfig {
25 | applicationId = appConfig.id
26 |
27 | minSdk = appConfig.minSdk
28 | targetSdk = appConfig.targetSdk
29 | versionCode = 1
30 | versionName = "1.0"
31 |
32 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
33 |
34 | ndk {
35 | // Specifies the ABI configurations of your native
36 | // libraries Gradle should build and package with your APK.
37 | // Here is a list of supported ABIs:
38 | // https://developer.android.com/ndk/guides/abis
39 | abiFilters.addAll(
40 | setOf(
41 | "armeabi-v7a",
42 | "arm64-v8a",
43 | "x86",
44 | "x86_64"
45 | )
46 | )
47 | }
48 | }
49 |
50 | compileOptions {
51 | sourceCompatibility = appConfig.javaVersion
52 | targetCompatibility = appConfig.javaVersion
53 | }
54 |
55 | kotlinOptions {
56 | jvmTarget = appConfig.javaVersion.toString()
57 | }
58 |
59 | buildFeatures {
60 | // https://developer.android.com/jetpack/compose/setup
61 | compose = true
62 | }
63 |
64 | composeOptions {
65 | // https://developer.android.com/jetpack/androidx/releases/compose-kotlin
66 | kotlinCompilerExtensionVersion = "1.4.8"
67 | }
68 |
69 | buildTypes {
70 | getByName("debug") {
71 | isMinifyEnabled = false
72 | }
73 | getByName("release") {
74 | isMinifyEnabled = true
75 | }
76 | }
77 | }
78 |
79 | dependencies {
80 | implementation(libs.kotlin.stdlib.jdk8)
81 | implementation(libs.kotlinx.coroutines.core)
82 | implementation(libs.kotlinx.coroutines.android)
83 | implementation(libs.android.core.ktx)
84 | implementation(libs.android.appcompat)
85 |
86 | // Jetpack Compose
87 | // https://developer.android.com/jetpack/compose/setup#kotlin_1
88 | val composeBom = platform(libs.androidx.compose.bom)
89 | implementation(composeBom)
90 | androidTestImplementation(composeBom)
91 |
92 | // Livedata
93 | implementation(libs.androidx.compose.runtime.livedata)
94 |
95 | // Material Design 3
96 | implementation(libs.androidx.compose.material3)
97 | implementation(libs.androidx.compose.material3.window.size)
98 |
99 | // Compose Activity Integration
100 | implementation(libs.androidx.activty.compose)
101 |
102 | // Android Studio Preview support
103 | implementation(libs.androidx.compose.ui.tooling.preview)
104 | implementation(libs.androidx.compose.ui.tooling)
105 | }
106 |
--------------------------------------------------------------------------------
/rust-library/README.md:
--------------------------------------------------------------------------------
1 | ## Rust Crypto Library (Encryption/Decryption)
2 |
3 | **Crypto** is a SAMPLE **Rust Crate** that showcases **cross-platform compilation for different projects and environments**. In terms of functinality and for **LEARNING PURPOSE**, it simulates **'encryption/decryption'** by using `base64 encoding/decoding`.
4 |
5 | In order to **fully understand the purpose of this repo**, please refer to the follwing blog posts:
6 |
7 | - [Rust cross-platform... The Android part...](https://fernandocejas.com/blog/engineering/2023-07-27-rust-cross-platform-android/).
8 | - **TODO:** Blog Post two
9 | - **TODO:** Blog Post three
10 |
11 | ## Local Development
12 |
13 | - `cargo build` -> builds the entire project.
14 | - `cargo test` -> run all the tests.
15 |
16 | ## Sub-projects
17 |
18 | The Crypto Library is composed by a [Rust Workspace](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html) containing a [set of crates](Cargo.toml).
19 |
20 |
21 |
22 |
70 |
--------------------------------------------------------------------------------
/rust-library/cryptor_jni/src/lib.rs:
--------------------------------------------------------------------------------
1 | ///
2 | /// [cfg(target_os = "android")]: Compiler flag ("cfg") which exposes
3 | /// the JNI interface for targeting Android in this case
4 | ///
5 | /// [allow(non_snake_case)]: Tells the compiler not to warn if
6 | /// we are not using snake_case for a variable or function names.
7 | /// For Android Development we want to be consistent with code style.
8 | ///
9 | /// Some useful links:
10 | /// - https://doc.rust-lang.org/reference/items/external-blocks.html
11 | /// - https://doc.rust-lang.org/reference/abi.html
12 | /// - https://doc.rust-lang.org/reference/items/functions.html#extern-function-qualifier
13 | /// - https://doc.rust-lang.org/reference/items/external-blocks.html
14 | ///
15 | #[cfg(target_os = "android")]
16 | #[allow(non_snake_case)]
17 | pub mod android {
18 |
19 | extern crate jni;
20 |
21 | // This is the interface to the JVM
22 | // that we'll call the majority of our
23 | // methods on.
24 | // @See https://docs.rs/jni/latest/jni/
25 | use self::jni::JNIEnv;
26 |
27 | // These objects are what you should use as arguments to your
28 | // native function. They carry extra lifetime information to
29 | // prevent them escaping this context and getting used after
30 | // being GC'd.
31 | use self::jni::objects::{JClass, JString};
32 |
33 | // This is just a pointer. We'll be returning it from our function.
34 | // We can't return one of the objects with lifetime information
35 | // because the lifetime checker won't let us.
36 | use self::jni::sys::jstring;
37 |
38 | use cryptor::encrypt;
39 | use cryptor::decrypt;
40 |
41 | ///
42 | /// Encrypts a String.
43 | ///
44 | #[no_mangle] // This keeps Rust from "mangling" the name so it is unique (crate).
45 | pub extern "system" fn Java_com_fernandocejas_rust_Cryptor_encrypt<'local>(
46 | mut env: JNIEnv<'local>,
47 | // This is the class that owns our static method. It's not going to be used,
48 | // but still must be present to match the expected signature of a static
49 | // native method.
50 | _class: JClass<'local>,
51 | input: JString<'local>,
52 | ) -> jstring {
53 |
54 | // First, we have to get the string out of Java. Check out the `strings`
55 | // module for more info on how this works.
56 | let to_encrypt: String = env.get_string(&input).expect("Couldn't get java string!").into();
57 |
58 | // We encrypt our str calling the cryptor library
59 | let encrypted_str = encrypt(&to_encrypt);
60 |
61 | // Here we have to create a new Java string to return. Again, more info
62 | // in the `strings` module.
63 | let output = env.new_string(&encrypted_str).expect("Couldn't create Java String!");
64 |
65 | // Finally, extract the raw pointer to return.
66 | output.into_raw()
67 | }
68 |
69 | ///
70 | /// Decrypts a String.
71 | ///
72 | #[no_mangle] // This keeps Rust from "mangling" the name so it is unique (crate).
73 | pub extern "system" fn Java_com_fernandocejas_rust_Cryptor_decrypt<'local>(
74 | mut env: JNIEnv<'local>,
75 | // This is the class that owns our static method. It's not going to be used,
76 | // but still must be present to match the expected signature of a static
77 | // native method.
78 | _class: JClass<'local>,
79 | input: JString<'local>,
80 | ) -> jstring {
81 |
82 | // First, we have to get the string out of Java. Check out the `strings`
83 | // module for more info on how this works.
84 | let to_decrypt: String = env.get_string(&input).expect("Couldn't get java string!").into();
85 |
86 | // We decrypt our str calling the cryptor library
87 | let decrypted_str = decrypt(&to_decrypt.to_owned());
88 |
89 | // Here we have to create a new Java string to return. Again, more info
90 | // in the `strings` module.
91 | let output = env.new_string(&decrypted_str).expect("Couldn't create Java String!");
92 |
93 | // Finally, extract the raw pointer to return.
94 | output.into_raw()
95 | }
96 | }
--------------------------------------------------------------------------------
/web-sample/README.md:
--------------------------------------------------------------------------------
1 | ## Rust Cross Platform Development: Wev Sample with Vue.js
2 |
3 | In order to **get started,** please refer to the the following **article/post** I have written:
4 |
5 | - [Rust cross-platform... The Web (Vue.js) part...](https://fernandocejas.com/blog/engineering/2023-10-31-rust-cross-platform-web/).
6 |
7 | ## The Idea
8 |
9 | **A picture worth a thousand words!** Here is a summary of what this project tries to accomplished:
10 |
11 |
14 |
15 | TODO
16 |
17 | And here the **implemantion details:**
18 |
19 |
22 |
23 | TODO
24 |
25 | ## Recommended `nodejs` version
26 |
27 | - If you use [asdf-vm](https://asdf-vm.com/) as **Version Manager**, please check the [.tool-versions](.tool-versions) file.
28 |
29 | ## Recommended IDE Setup
30 |
31 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
32 |
33 | ## Type Support for `.vue` Imports in TS
34 |
35 | TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
36 |
37 | If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
38 |
39 | 1. Disable the built-in TypeScript Extension
40 | 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
41 | 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
42 | 2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
43 |
44 | ## Customize configuration
45 |
46 | See [Vite Configuration Reference](https://vitejs.dev/config/).
47 |
48 | ## Local Development
49 |
50 | ```bash
51 | pnpm install # Install project dependencies
52 | pnpm dev # Compile and Hot-Reload for Development
53 | pnpm build # Type-Check, Compile and Minify for Production
54 | ```
55 |
56 | ## Testing and Code quality
57 |
58 | It includes, Static Analisys, Lint and Unit, Integration and Functions tests.
59 |
60 | ### Run Tests with [Vitest](https://vitest.dev/)
61 |
62 | ```sh
63 | pnpm test
64 | ```
65 |
66 | ### Lint with [ESLint](https://eslint.org/)
67 |
68 | ```sh
69 | pnpm lint
70 | ```
71 |
72 | ## References
73 |
74 | - https://vitejs.dev/guide/
75 | - https://vitest.dev/guide/
76 | - https://vuejs.org/guide/
77 | - https://github.com/vuejs/language-tools
78 | - https://pinia.vuejs.org/
79 | - https://github.com/vuejs/awesome-vue
80 |
81 | ## License
82 |
83 | Copyright 2023 Fernando Cejas
84 |
85 | Licensed under the Apache License, Version 2.0 (the "License");
86 | you may not use this file except in compliance with the License.
87 | You may obtain a copy of the License at
88 |
89 | http://www.apache.org/licenses/LICENSE-2.0
90 |
91 | Unless required by applicable law or agreed to in writing, software
92 | distributed under the License is distributed on an "AS IS" BASIS,
93 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
94 | See the License for the specific language governing permissions and
95 | limitations under the License.
96 |
97 |
98 | 
99 |
100 |
101 |
--------------------------------------------------------------------------------
/android-sample/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/android-sample/app/src/main/kotlin/com/fernandocejas/sample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2020 Fernando Cejas Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.fernandocejas.sample
17 |
18 | import android.os.Bundle
19 | import androidx.activity.compose.setContent
20 | import androidx.activity.viewModels
21 | import androidx.appcompat.app.AppCompatActivity
22 | import androidx.compose.foundation.layout.Arrangement
23 | import androidx.compose.foundation.layout.Column
24 | import androidx.compose.foundation.layout.Row
25 | import androidx.compose.foundation.layout.Spacer
26 | import androidx.compose.foundation.layout.fillMaxSize
27 | import androidx.compose.foundation.layout.height
28 | import androidx.compose.foundation.layout.padding
29 | import androidx.compose.material3.Button
30 | import androidx.compose.material3.CenterAlignedTopAppBar
31 | import androidx.compose.material3.ExperimentalMaterial3Api
32 | import androidx.compose.material3.MaterialTheme
33 | import androidx.compose.material3.Surface
34 | import androidx.compose.material3.Text
35 | import androidx.compose.material3.TextField
36 | import androidx.compose.material3.TopAppBarDefaults
37 | import androidx.compose.runtime.Composable
38 | import androidx.compose.runtime.State
39 | import androidx.compose.runtime.getValue
40 | import androidx.compose.runtime.livedata.observeAsState
41 | import androidx.compose.runtime.mutableStateOf
42 | import androidx.compose.runtime.remember
43 | import androidx.compose.runtime.setValue
44 | import androidx.compose.ui.Alignment
45 | import androidx.compose.ui.Modifier
46 | import androidx.compose.ui.graphics.Color
47 | import androidx.compose.ui.res.stringResource
48 | import androidx.compose.ui.unit.dp
49 | import androidx.core.view.WindowCompat
50 |
51 | @OptIn(ExperimentalMaterial3Api::class)
52 | class MainActivity : AppCompatActivity() {
53 |
54 | private val viewModel: MainViewModel by viewModels()
55 |
56 | override fun onCreate(savedInstanceState: Bundle?) {
57 | super.onCreate(savedInstanceState)
58 |
59 | // Turn off the decor fitting system windows, which allows
60 | // us to handle insets, including IME animations.
61 | WindowCompat.setDecorFitsSystemWindows(window, false)
62 |
63 | setContent {
64 | MaterialTheme {
65 | Surface(
66 | modifier = Modifier.fillMaxSize(),
67 | color = MaterialTheme.colorScheme.background
68 | ) {
69 | Column(modifier = Modifier.fillMaxSize()) {
70 | MainScreenComponent()
71 | }
72 | }
73 | }
74 | }
75 | }
76 |
77 | @Composable
78 | fun MainScreenComponent() {
79 | TopBarComponent()
80 | Column(
81 | modifier = Modifier
82 | .fillMaxSize()
83 | .padding(top = 50.dp),
84 | horizontalAlignment = Alignment.CenterHorizontally,
85 | verticalArrangement = Arrangement.Top,
86 | ) {
87 | EncryptDecryptComponent(
88 | observableState = viewModel.encryptedStringResult.observeAsState(initial = ""),
89 | textFieldLabel = stringResource(id = R.string.txt_encrypt_label_hint),
90 | buttonText = stringResource(id = R.string.txt_encrypt),
91 | buttonClickFn = viewModel.encryptString,
92 | )
93 | Spacer(modifier = Modifier.height(height = 50.dp))
94 | EncryptDecryptComponent(
95 | observableState = viewModel.decryptedStringResult.observeAsState(initial = ""),
96 | textFieldLabel = stringResource(id = R.string.txt_decrypt_label_hint),
97 | buttonText = stringResource(id = R.string.txt_decrypt),
98 | buttonClickFn = viewModel.decryptString,
99 | )
100 | }
101 | }
102 |
103 | @Composable
104 | fun TopBarComponent(title: String = stringResource(id = R.string.app_name)) {
105 | CenterAlignedTopAppBar(
106 | title = {
107 | Text(
108 | text = title,
109 | color = MaterialTheme.colorScheme.background,
110 | )
111 | },
112 | colors = TopAppBarDefaults.topAppBarColors(
113 | containerColor = MaterialTheme.colorScheme.primary
114 | )
115 | )
116 | }
117 |
118 | @Composable
119 | fun EncryptDecryptComponent(
120 | observableState: State