diff --git a/apps/android/.gitignore b/apps/android/.gitignore
deleted file mode 100644
index 9ddf412fc2..0000000000
--- a/apps/android/.gitignore
+++ /dev/null
@@ -1,20 +0,0 @@
-*.iml
-.gradle
-/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
-/.idea/deploymentTargetDropDown.xml
-/.idea/misc.xml
-/.idea/uiDesigner.xml
-/.idea/kotlinc.xml
-.DS_Store
-/build
-/captures
-.externalNativeBuild
-.cxx
-local.properties
-app/src/main/cpp/libs/
diff --git a/apps/android/.idea/.name b/apps/android/.idea/.name
deleted file mode 100644
index ccb58e52e1..0000000000
--- a/apps/android/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-SimpleX
\ No newline at end of file
diff --git a/apps/android/.idea/compiler.xml b/apps/android/.idea/compiler.xml
deleted file mode 100644
index fb7f4a8a46..0000000000
--- a/apps/android/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/android/.idea/gradle.xml b/apps/android/.idea/gradle.xml
deleted file mode 100644
index a2d7c21338..0000000000
--- a/apps/android/.idea/gradle.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/android/.idea/inspectionProfiles/Project_Default.xml b/apps/android/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 28422375b6..0000000000
--- a/apps/android/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/android/.idea/vcs.xml b/apps/android/.idea/vcs.xml
deleted file mode 100644
index b2bdec2d71..0000000000
--- a/apps/android/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle
deleted file mode 100644
index 4f8b6cbe30..0000000000
--- a/apps/android/app/build.gradle
+++ /dev/null
@@ -1,243 +0,0 @@
-plugins {
- id 'com.android.application'
- id 'org.jetbrains.kotlin.android'
- id 'org.jetbrains.kotlin.plugin.serialization'
-}
-
-android {
- compileSdk 32
-
- defaultConfig {
- applicationId "chat.simplex.app"
- minSdk 26
- targetSdk 32
- // !!!
- // skip version code after release to F-Droid, as it uses two version codes
- versionCode 127
- versionName "5.1.3"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- vectorDrawables {
- useSupportLibrary true
- }
- externalNativeBuild {
- cmake {
- cppFlags ''
- }
- }
- manifestPlaceholders.app_name = "@string/app_name"
- manifestPlaceholders.provider_authorities = "chat.simplex.app.provider"
- manifestPlaceholders.extract_native_libs = compression_level != "0"
- }
-
- buildTypes {
- debug {
- applicationIdSuffix "$application_id_suffix"
- debuggable new Boolean("$enable_debuggable")
- manifestPlaceholders.app_name = "$app_name"
- // Provider can't be the same for different apps on the same device
- manifestPlaceholders.provider_authorities = "chat.simplex.app${application_id_suffix}.provider"
- }
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = '1.8'
- freeCompilerArgs += "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"
- freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi"
- freeCompilerArgs += "-opt-in=androidx.compose.ui.text.ExperimentalTextApi"
- freeCompilerArgs += "-opt-in=androidx.compose.material.ExperimentalMaterialApi"
- freeCompilerArgs += "-opt-in=com.google.accompanist.insets.ExperimentalAnimatedInsets"
- freeCompilerArgs += "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi"
- freeCompilerArgs += "-opt-in=kotlinx.serialization.InternalSerializationApi"
- freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
- }
- externalNativeBuild {
- cmake {
- path file('src/main/cpp/CMakeLists.txt')
- }
- }
- buildFeatures {
- compose true
- }
- composeOptions {
- kotlinCompilerExtensionVersion compose_version
- }
- packagingOptions {
- resources {
- excludes += '/META-INF/{AL2.0,LGPL2.1}'
- }
- jniLibs.useLegacyPackaging = compression_level != "0"
- }
- def isRelease = gradle.getStartParameter().taskNames.find({ it.toLowerCase().contains("release") }) != null
- def isBundle = gradle.getStartParameter().taskNames.find({ it.toLowerCase().contains("bundle") }) != null
-// if (isRelease) {
- // Comma separated list of languages that will be included in the apk
- android.defaultConfig.resConfigs(
- "en",
- "cs",
- "de",
- "es",
- "fr",
- "it",
- "ja",
- "nl",
- "pl",
- "pt-rBR",
- "ru",
- "zh-rCN"
- )
-// }
- if (isBundle) {
- defaultConfig.ndk.abiFilters 'arm64-v8a', 'armeabi-v7a'
- } else {
- splits {
- abi {
- enable true
- reset()
- if (isRelease) {
- include 'arm64-v8a', 'armeabi-v7a'
- } else {
- include 'arm64-v8a', 'armeabi-v7a'
- universalApk false
- }
- }
- }
- }
-}
-
-dependencies {
- implementation 'androidx.core:core-ktx:1.7.0'
- implementation "androidx.compose.ui:ui:$compose_version"
- implementation "androidx.compose.material:material:$compose_version"
- implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
- implementation 'androidx.lifecycle:lifecycle-process:2.4.1'
- implementation 'androidx.activity:activity-compose:1.4.0'
- implementation 'androidx.fragment:fragment:1.4.1'
- implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.3.2'
- implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2'
- implementation 'com.charleskorn.kaml:kaml:0.43.0'
- //implementation "androidx.compose.material:material-icons-extended:$compose_version"
- implementation "androidx.compose.ui:ui-util:$compose_version"
- implementation "androidx.navigation:navigation-compose:2.4.1"
- implementation "com.google.accompanist:accompanist-insets:0.23.0"
- implementation 'androidx.webkit:webkit:1.4.0'
- implementation "com.godaddy.android.colorpicker:compose-color-picker:0.4.2"
-
- def work_version = "2.7.1"
- implementation "androidx.work:work-runtime-ktx:$work_version"
- implementation "androidx.work:work-multiprocess:$work_version"
-
- def camerax_version = "1.1.0-beta01"
- implementation "androidx.camera:camera-core:${camerax_version}"
- implementation "androidx.camera:camera-camera2:${camerax_version}"
- implementation "androidx.camera:camera-lifecycle:${camerax_version}"
- implementation "androidx.camera:camera-view:${camerax_version}"
-
- //Barcode
- implementation 'org.boofcv:boofcv-android:0.40.1'
- implementation 'org.boofcv:boofcv-core:0.40.1'
-
- //Camera Permission
- implementation "com.google.accompanist:accompanist-permissions:0.23.0"
- implementation "com.google.accompanist:accompanist-pager:0.25.1"
-
- // Link Previews
- implementation 'org.jsoup:jsoup:1.13.1'
-
- // Biometric authentication
- implementation 'androidx.biometric:biometric:1.2.0-alpha04'
-
- // GIFs support
- implementation "io.coil-kt:coil-compose:2.1.0"
- implementation "io.coil-kt:coil-gif:2.1.0"
-
- // Video support
- implementation "com.google.android.exoplayer:exoplayer:2.17.1"
-
- // Wheel picker
- implementation 'com.github.zj565061763:compose-wheel-picker:1.0.0-alpha10'
-
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
- debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
- implementation "com.jakewharton:process-phoenix:2.1.2"
-}
-
-// Don't do anything if no compression is needed
-if (compression_level != "0") {
- tasks.whenTaskAdded { task ->
- if (task.name == 'packageDebug') {
- task.finalizedBy compressApk
- } else if (task.name == 'packageRelease') {
- task.finalizedBy compressApk
- }
- }
-}
-
-tasks.register("compressApk") {
- doLast {
- def isRelease = gradle.getStartParameter().taskNames.find({ it.toLowerCase().contains("release") }) != null
- def buildType
- if (isRelease) {
- buildType = "release"
- } else {
- buildType = "debug"
- }
- def javaHome = System.properties['java.home'] ?: org.gradle.internal.jvm.Jvm.current().getJavaHome()
- def sdkDir = android.getSdkDirectory().getAbsolutePath()
- def keyAlias = ""
- def keyPassword = ""
- def storeFile = ""
- def storePassword = ""
- if (project.properties['android.injected.signing.key.alias'] != null) {
- keyAlias = project.properties['android.injected.signing.key.alias']
- keyPassword = project.properties['android.injected.signing.key.password']
- storeFile = project.properties['android.injected.signing.store.file']
- storePassword = project.properties['android.injected.signing.store.password']
- } else if (android.signingConfigs.hasProperty(buildType)) {
- def gradleConfig = android.signingConfigs[buildType]
- keyAlias = gradleConfig.keyAlias
- keyPassword = gradleConfig.keyPassword
- storeFile = gradleConfig.storeFile
- storePassword = gradleConfig.storePassword
- } else {
- // There is no signing config for current build type, can't sign the apk
- println("No signing configs for this build type: $buildType")
- return
- }
-
- def outputDir = tasks["package${buildType.capitalize()}"].outputs.files.last()
-
- exec {
- workingDir '../../../scripts/android'
- setEnvironment(['JAVA_HOME': "$javaHome"])
- commandLine './compress-and-sign-apk.sh', \
- "$compression_level", \
- "$outputDir", \
- "$sdkDir", \
- "$storeFile", \
- "$storePassword", \
- "$keyAlias", \
- "$keyPassword"
- }
-
- if (project.properties['android.injected.signing.key.alias'] != null && buildType == 'release') {
- new File(outputDir, "app-release.apk").renameTo(new File(outputDir, "simplex.apk"))
- new File(outputDir, "app-armeabi-v7a-release.apk").renameTo(new File(outputDir, "simplex-armv7a.apk"))
- new File(outputDir, "app-arm64-v8a-release.apk").renameTo(new File(outputDir, "simplex.apk"))
- }
-
- // View all gradle properties set
- // project.properties.each { k, v -> println "$k -> $v" }
- }
-}
diff --git a/apps/android/build.gradle b/apps/android/build.gradle
deleted file mode 100644
index 08dbb3f98d..0000000000
--- a/apps/android/build.gradle
+++ /dev/null
@@ -1,50 +0,0 @@
-buildscript {
- Properties localProperties = new Properties()
- if (rootProject.file('local.properties').canRead()) {
- localProperties.load(rootProject.file("local.properties").newDataInputStream())
- }
-
- ext {
- compose_version = localProperties['compose_version'] ?: '1.2.0-beta02'
- kotlin_version = localProperties['kotlin_version'] ?: '1.6.21'
- gradle_plugin_version = localProperties['gradle_plugin_version'] ?: '7.2.0'
- abi_filter = localProperties['abi_filter'] ?: 'arm64-v8a'
-
- // Name that will be shown for debug build. By default it is from strings
- app_name = localProperties['app_name'] ?: "@string/app_name"
- // Whether the app is debuggable or not. Specify `false` if you want good performance in debug builds
- enable_debuggable = localProperties['debuggable'] ?: true
- // Ending part of package name.
- // Provide, for example, `application_id_suffix=.debug` in local.properties
- // to allow debug & release versions to coexist
- application_id_suffix = localProperties['application_id_suffix'] ?: ''
-
- // Compression level for debug AND release apk. 0 = disable compression. Max is 9
- compression_level = localProperties['compression_level'] ?: '0'
-
- // NOTE: If you need a different version of something, provide it in `local.properties`
- // like so: compose_version=123, or gradle_plugin_version=1.2.3, etc
- }
- repositories {
- google()
- mavenCentral()
- }
- dependencies {
- classpath "com.android.tools.build:gradle:$gradle_plugin_version"
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "org.jetbrains.kotlin:kotlin-serialization:1.3.2"
-
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
- }
-}// Top-level build file where you can add configuration options common to all sub-projects/modules.
-plugins {
- id 'com.android.application' version "$gradle_plugin_version" apply false
- id 'com.android.library' version "$gradle_plugin_version" apply false
- id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false
- id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
\ No newline at end of file
diff --git a/apps/android/settings.gradle b/apps/android/settings.gradle
deleted file mode 100644
index 3621283ff6..0000000000
--- a/apps/android/settings.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-pluginManagement {
- repositories {
- gradlePluginPortal()
- google()
- mavenCentral()
- }
-}
-dependencyResolutionManagement {
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
- repositories {
- google()
- mavenCentral()
- maven { url 'https://jitpack.io' }
- }
-}
-rootProject.name = "SimpleX"
-include ':app'
diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj
index 4e6f128f9f..fdb2d5412b 100644
--- a/apps/ios/SimpleX.xcodeproj/project.pbxproj
+++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj
@@ -115,11 +115,6 @@
5CC2C0FC2809BF11000C35E3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FA2809BF11000C35E3 /* Localizable.strings */; };
5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; };
5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; };
- 5CCAA6D52A4B38F700BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCAA6D02A4B38F600BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ.a */; };
- 5CCAA6D62A4B38F700BAF93B /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCAA6D12A4B38F600BAF93B /* libgmp.a */; };
- 5CCAA6D72A4B38F700BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCAA6D22A4B38F600BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ-ghc8.10.7.a */; };
- 5CCAA6D82A4B38F700BAF93B /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCAA6D32A4B38F600BAF93B /* libgmpxx.a */; };
- 5CCAA6D92A4B38F700BAF93B /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCAA6D42A4B38F600BAF93B /* libffi.a */; };
5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; };
5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; };
5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; };
@@ -170,6 +165,11 @@
648010AB281ADD15009009B9 /* CIFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648010AA281ADD15009009B9 /* CIFileView.swift */; };
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; };
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; };
+ 64A353102A4C84CE007CD71D /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64A3530B2A4C84CE007CD71D /* libgmp.a */; };
+ 64A353112A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64A3530C2A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm.a */; };
+ 64A353122A4C84CE007CD71D /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64A3530D2A4C84CE007CD71D /* libffi.a */; };
+ 64A353132A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64A3530E2A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm-ghc8.10.7.a */; };
+ 64A353142A4C84CE007CD71D /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64A3530F2A4C84CE007CD71D /* libgmpxx.a */; };
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; };
64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; };
64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */; };
@@ -253,7 +253,7 @@
18415B08031E8FB0F7FC27F9 /* CallViewRenderers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewRenderers.swift; sourceTree = ""; };
18415DAAAD1ADBEDB0EDA852 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = ""; };
18415FD2E36F13F596A45BB4 /* CIVideoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIVideoView.swift; sourceTree = ""; };
- 3C714779281C0F6800CB4D4B /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../android/app/src/main/assets/www; sourceTree = ""; };
+ 3C714779281C0F6800CB4D4B /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../multiplatform/android/src/main/assets/www; sourceTree = ""; };
3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteToConnectView.swift; sourceTree = ""; };
3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeLinkView.swift; sourceTree = ""; };
3CDBCF4727FF621E00354CDD /* CILinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CILinkView.swift; sourceTree = ""; };
@@ -392,11 +392,6 @@
5CC2C0FB2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; };
5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; };
5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIRcvDecryptionError.swift; sourceTree = ""; };
- 5CCAA6D02A4B38F600BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ.a"; sourceTree = ""; };
- 5CCAA6D12A4B38F600BAF93B /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; };
- 5CCAA6D22A4B38F600BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ-ghc8.10.7.a"; sourceTree = ""; };
- 5CCAA6D32A4B38F600BAF93B /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; };
- 5CCAA6D42A4B38F600BAF93B /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; };
5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = ""; };
5CCD403327A5F6DF00368C90 /* AddContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactView.swift; sourceTree = ""; };
5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = ""; };
@@ -446,6 +441,11 @@
6493D667280ED77F007A76FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; };
649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = ""; };
649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = ""; };
+ 64A3530B2A4C84CE007CD71D /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; };
+ 64A3530C2A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm.a"; sourceTree = ""; };
+ 64A3530D2A4C84CE007CD71D /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; };
+ 64A3530E2A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm-ghc8.10.7.a"; sourceTree = ""; };
+ 64A3530F2A4C84CE007CD71D /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; };
64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = ""; };
64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = ""; };
64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemInfoView.swift; sourceTree = ""; };
@@ -497,13 +497,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 5CCAA6D82A4B38F700BAF93B /* libgmpxx.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
- 5CCAA6D72A4B38F700BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ-ghc8.10.7.a in Frameworks */,
- 5CCAA6D52A4B38F700BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ.a in Frameworks */,
- 5CCAA6D92A4B38F700BAF93B /* libffi.a in Frameworks */,
- 5CCAA6D62A4B38F700BAF93B /* libgmp.a in Frameworks */,
+ 64A353132A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm-ghc8.10.7.a in Frameworks */,
+ 64A353102A4C84CE007CD71D /* libgmp.a in Frameworks */,
+ 64A353112A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm.a in Frameworks */,
+ 64A353122A4C84CE007CD71D /* libffi.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
+ 64A353142A4C84CE007CD71D /* libgmpxx.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -564,11 +564,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
- 5CCAA6D42A4B38F600BAF93B /* libffi.a */,
- 5CCAA6D12A4B38F600BAF93B /* libgmp.a */,
- 5CCAA6D32A4B38F600BAF93B /* libgmpxx.a */,
- 5CCAA6D22A4B38F600BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ-ghc8.10.7.a */,
- 5CCAA6D02A4B38F600BAF93B /* libHSsimplex-chat-5.1.3.0-5OWMsZbPutPDzQF8wFktLQ.a */,
+ 64A3530D2A4C84CE007CD71D /* libffi.a */,
+ 64A3530B2A4C84CE007CD71D /* libgmp.a */,
+ 64A3530F2A4C84CE007CD71D /* libgmpxx.a */,
+ 64A3530E2A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm-ghc8.10.7.a */,
+ 64A3530C2A4C84CE007CD71D /* libHSsimplex-chat-5.2.0.0-ESKsZ4YorLH7yFQuFvHeIm.a */,
);
path = Libraries;
sourceTree = "";
@@ -1470,7 +1470,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 150;
+ CURRENT_PROJECT_VERSION = 151;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1491,7 +1491,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 5.1.3;
+ MARKETING_VERSION = 5.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1512,7 +1512,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 150;
+ CURRENT_PROJECT_VERSION = 151;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1533,7 +1533,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 5.1.3;
+ MARKETING_VERSION = 5.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1592,7 +1592,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 150;
+ CURRENT_PROJECT_VERSION = 151;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1605,7 +1605,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 5.1.3;
+ MARKETING_VERSION = 5.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1624,7 +1624,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 150;
+ CURRENT_PROJECT_VERSION = 151;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1637,7 +1637,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 5.1.3;
+ MARKETING_VERSION = 5.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
diff --git a/apps/multiplatform/.gitignore b/apps/multiplatform/.gitignore
new file mode 100644
index 0000000000..d8419431db
--- /dev/null
+++ b/apps/multiplatform/.gitignore
@@ -0,0 +1,19 @@
+*.iml
+.gradle
+/local.properties
+/.idea
+!/.idea/codeStyles/*
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
+common/src/commonMain/cpp/android/libs/
+common/src/commonMain/cpp/desktop/libs/
+common/src/commonMain/resources/libs/
+android/build
+android/release
+common/build
+desktop/build
+release
\ No newline at end of file
diff --git a/apps/android/.idea/codeStyles/Project.xml b/apps/multiplatform/.idea/codeStyles/Project.xml
similarity index 100%
rename from apps/android/.idea/codeStyles/Project.xml
rename to apps/multiplatform/.idea/codeStyles/Project.xml
diff --git a/apps/android/.idea/codeStyles/codeStyleConfig.xml b/apps/multiplatform/.idea/codeStyles/codeStyleConfig.xml
similarity index 100%
rename from apps/android/.idea/codeStyles/codeStyleConfig.xml
rename to apps/multiplatform/.idea/codeStyles/codeStyleConfig.xml
diff --git a/apps/android/README.md b/apps/multiplatform/README.md
similarity index 100%
rename from apps/android/README.md
rename to apps/multiplatform/README.md
diff --git a/apps/android/app/.gitignore b/apps/multiplatform/android/.gitignore
similarity index 100%
rename from apps/android/app/.gitignore
rename to apps/multiplatform/android/.gitignore
diff --git a/apps/multiplatform/android/build.gradle.kts b/apps/multiplatform/android/build.gradle.kts
new file mode 100644
index 0000000000..5d54c5f7b6
--- /dev/null
+++ b/apps/multiplatform/android/build.gradle.kts
@@ -0,0 +1,210 @@
+@file:Suppress("UnstableApiUsage")
+
+plugins {
+ id("com.android.application")
+ id("org.jetbrains.compose")
+ kotlin("android")
+ id("org.jetbrains.kotlin.plugin.serialization")
+}
+
+repositories {
+ maven("https://jitpack.io")
+}
+
+android {
+ compileSdkVersion(33)
+
+ defaultConfig {
+ applicationId = "chat.simplex.app"
+ minSdkVersion(26)
+ targetSdkVersion(33)
+ // !!!
+ // skip version code after release to F-Droid, as it uses two version codes
+ versionCode = (extra["android.version_code"] as String).toInt()
+ versionName = extra["android.version_name"] as String
+
+ testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
+ vectorDrawables {
+ useSupportLibrary = true
+ }
+ externalNativeBuild {
+ cmake {
+ cppFlags("")
+ }
+ }
+ manifestPlaceholders["app_name"] = "@string/app_name"
+ manifestPlaceholders["provider_authorities"] = "chat.simplex.app.provider"
+ manifestPlaceholders["extract_native_libs"] = rootProject.extra["compression.level"] as Int != 0
+ }
+
+ buildTypes {
+ debug {
+ applicationIdSuffix = rootProject.extra["application_id.suffix"] as String
+ isDebuggable = rootProject.extra["enable_debuggable"] as Boolean
+ manifestPlaceholders["app_name"] = rootProject.extra["app.name"] as String
+ // Provider can"t be the same for different apps on the same device
+ manifestPlaceholders["provider_authorities"] = "chat.simplex.app${rootProject.extra["application_id.suffix"]}.provider"
+ }
+ release {
+ isMinifyEnabled = false
+ proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ freeCompilerArgs += "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"
+ freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi"
+ freeCompilerArgs += "-opt-in=androidx.compose.ui.text.ExperimentalTextApi"
+ freeCompilerArgs += "-opt-in=androidx.compose.material.ExperimentalMaterialApi"
+ freeCompilerArgs += "-opt-in=com.google.accompanist.insets.ExperimentalAnimatedInsets"
+ freeCompilerArgs += "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi"
+ freeCompilerArgs += "-opt-in=kotlinx.serialization.InternalSerializationApi"
+ freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
+ }
+ externalNativeBuild {
+ cmake {
+ path(File("../common/src/commonMain/cpp/android/CMakeLists.txt"))
+ }
+ }
+ buildTypes {
+ getByName("release") {
+ isMinifyEnabled = false
+ }
+ }
+ packagingOptions {
+ resources {
+ excludes += "/META-INF/{AL2.0,LGPL2.1}"
+ }
+ jniLibs.useLegacyPackaging = rootProject.extra["compression.level"] as Int != 0
+ }
+ val isRelease = gradle.startParameter.taskNames.find { it.toLowerCase().contains("release") } != null
+ val isBundle = gradle.startParameter.taskNames.find { it.toLowerCase().contains("bundle") } != null
+ // if (isRelease) {
+ // Comma separated list of languages that will be included in the apk
+ android.defaultConfig.resConfigs(
+ "en",
+ "cs",
+ "de",
+ "es",
+ "fr",
+ "it",
+ "ja",
+ "nl",
+ "pl",
+ "pt-rBR",
+ "ru",
+ "zh-rCN"
+ )
+ // }
+ if (isBundle) {
+ defaultConfig.ndk.abiFilters("arm64-v8a", "armeabi-v7a")
+ } else {
+ splits {
+ abi {
+ isEnable = true
+ reset()
+ if (isRelease) {
+ include("arm64-v8a", "armeabi-v7a")
+ } else {
+ include("arm64-v8a", "armeabi-v7a")
+ isUniversalApk = false
+ }
+ }
+ }
+ }
+}
+
+dependencies {
+ implementation(project(":common"))
+ implementation("androidx.core:core-ktx:1.7.0")
+ //implementation("androidx.compose.ui:ui:${rootProject.extra["compose.version"] as String}")
+ //implementation("androidx.compose.material:material:$compose_version")
+ //implementation("androidx.compose.ui:ui-tooling-preview:$compose_version")
+ implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.1")
+ implementation("androidx.lifecycle:lifecycle-process:2.4.1")
+ implementation("androidx.activity:activity-compose:1.5.0")
+ //implementation("androidx.compose.material:material-icons-extended:$compose_version")
+ //implementation("androidx.compose.ui:ui-util:$compose_version")
+
+ implementation("com.google.accompanist:accompanist-pager:0.25.1")
+
+ testImplementation("junit:junit:4.13.2")
+ androidTestImplementation("androidx.test.ext:junit:1.1.3")
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
+ //androidTestImplementation("androidx.compose.ui:ui-test-junit4:$compose_version")
+ debugImplementation("androidx.compose.ui:ui-tooling:${rootProject.extra["compose.version"] as String}")
+}
+
+tasks {
+ val compressApk by creating {
+ doLast {
+ val isRelease = gradle.startParameter.taskNames.find { it.toLowerCase().contains("release") } != null
+ val buildType: String = if (isRelease) "release" else "debug"
+ val javaHome = System.getProperties()["java.home"] ?: org.gradle.internal.jvm.Jvm.current().javaHome
+ val sdkDir = android.sdkDirectory.absolutePath
+ var keyAlias = ""
+ var keyPassword = ""
+ var storeFile = ""
+ var storePassword = ""
+ if (project.properties["android.injected.signing.key.alias"] != null) {
+ keyAlias = project.properties["android.injected.signing.key.alias"] as String
+ keyPassword = project.properties["android.injected.signing.key.password"] as String
+ storeFile = project.properties["android.injected.signing.store.file"] as String
+ storePassword = project.properties["android.injected.signing.store.password"] as String
+ } else {
+ try {
+ val gradleConfig = android.signingConfigs.getByName(buildType)
+ keyAlias = gradleConfig.keyAlias!!
+ keyPassword = gradleConfig.keyPassword!!
+ storeFile = gradleConfig.storeFile!!.absolutePath
+ storePassword = gradleConfig.storePassword!!
+ } catch (e: UnknownDomainObjectException) {
+ // There is no signing config for current build type, can"t sign the apk
+ println("No signing configs for this build type: $buildType")
+ return@doLast
+ }
+ }
+ lateinit var outputDir: File
+ named(if (isRelease) "packageRelease" else "packageDebug") {
+ outputDir = outputs.files.files.last()
+ }
+ exec {
+ workingDir("../../../scripts/android")
+ setEnvironment(mapOf("JAVA_HOME" to "$javaHome"))
+ commandLine = listOf(
+ "./compress-and-sign-apk.sh",
+ "${rootProject.extra["compression.level"]}",
+ "$outputDir",
+ "$sdkDir",
+ "$storeFile",
+ "$storePassword",
+ "$keyAlias",
+ "$keyPassword"
+ )
+ }
+
+ if (project.properties["android.injected.signing.key.alias"] != null && buildType == "release") {
+ File(outputDir, "android-release.apk").renameTo(File(outputDir, "simplex.apk"))
+ File(outputDir, "android-armeabi-v7a-release.apk").renameTo(File(outputDir, "simplex-armv7a.apk"))
+ File(outputDir, "android-arm64-v8a-release.apk").renameTo(File(outputDir, "simplex.apk"))
+ }
+ // View all gradle properties set
+ // project.properties.each { k, v -> println "$k -> $v" }
+ }
+ }
+
+ // Don"t do anything if no compression is needed
+ if (rootProject.extra["compression.level"] as Int != 0) {
+ whenTaskAdded {
+ if (name == "packageDebug") {
+ finalizedBy(compressApk)
+ } else if (name == "packageRelease") {
+ finalizedBy(compressApk)
+ }
+ }
+ }
+}
diff --git a/apps/android/app/proguard-rules.pro b/apps/multiplatform/android/proguard-rules.pro
similarity index 100%
rename from apps/android/app/proguard-rules.pro
rename to apps/multiplatform/android/proguard-rules.pro
diff --git a/apps/android/app/src/androidTest/java/chat/simplex/app/ExampleInstrumentedTest.kt b/apps/multiplatform/android/src/androidTest/java/chat/simplex/app/ExampleInstrumentedTest.kt
similarity index 100%
rename from apps/android/app/src/androidTest/java/chat/simplex/app/ExampleInstrumentedTest.kt
rename to apps/multiplatform/android/src/androidTest/java/chat/simplex/app/ExampleInstrumentedTest.kt
diff --git a/apps/android/app/src/main/AndroidManifest.xml b/apps/multiplatform/android/src/main/AndroidManifest.xml
similarity index 98%
rename from apps/android/app/src/main/AndroidManifest.xml
rename to apps/multiplatform/android/src/main/AndroidManifest.xml
index 6d090e381e..f3d48fe88f 100644
--- a/apps/android/app/src/main/AndroidManifest.xml
+++ b/apps/multiplatform/android/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
diff --git a/apps/android/app/src/main/assets/www/README.md b/apps/multiplatform/android/src/main/assets/www/README.md
similarity index 100%
rename from apps/android/app/src/main/assets/www/README.md
rename to apps/multiplatform/android/src/main/assets/www/README.md
diff --git a/apps/android/app/src/main/assets/www/call.html b/apps/multiplatform/android/src/main/assets/www/call.html
similarity index 100%
rename from apps/android/app/src/main/assets/www/call.html
rename to apps/multiplatform/android/src/main/assets/www/call.html
diff --git a/apps/android/app/src/main/assets/www/call.js b/apps/multiplatform/android/src/main/assets/www/call.js
similarity index 100%
rename from apps/android/app/src/main/assets/www/call.js
rename to apps/multiplatform/android/src/main/assets/www/call.js
diff --git a/apps/android/app/src/main/assets/www/lz-string.min.js b/apps/multiplatform/android/src/main/assets/www/lz-string.min.js
similarity index 100%
rename from apps/android/app/src/main/assets/www/lz-string.min.js
rename to apps/multiplatform/android/src/main/assets/www/lz-string.min.js
diff --git a/apps/android/app/src/main/assets/www/style.css b/apps/multiplatform/android/src/main/assets/www/style.css
similarity index 100%
rename from apps/android/app/src/main/assets/www/style.css
rename to apps/multiplatform/android/src/main/assets/www/style.css
diff --git a/apps/android/app/src/main/icon-playstore.png b/apps/multiplatform/android/src/main/icon-playstore.png
similarity index 100%
rename from apps/android/app/src/main/icon-playstore.png
rename to apps/multiplatform/android/src/main/icon-playstore.png
diff --git a/apps/android/app/src/main/icon_dark_blue-playstore.png b/apps/multiplatform/android/src/main/icon_dark_blue-playstore.png
similarity index 100%
rename from apps/android/app/src/main/icon_dark_blue-playstore.png
rename to apps/multiplatform/android/src/main/icon_dark_blue-playstore.png
diff --git a/apps/android/app/src/main/java/chat/simplex/app/BackupAgent.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/BackupAgent.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/BackupAgent.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/BackupAgent.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt
index 3d6b891af2..946973d973 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt
@@ -24,7 +24,7 @@ import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.*
import chat.simplex.app.MainActivity.Companion.enteredBackground
import chat.simplex.app.model.*
-import chat.simplex.app.model.NtfManager.Companion.getUserIdFromIntent
+import chat.simplex.app.model.NtfManager.getUserIdFromIntent
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.SplashView
import chat.simplex.app.views.call.ActiveCallView
@@ -42,6 +42,7 @@ import chat.simplex.app.views.onboarding.*
import chat.simplex.app.views.usersettings.LAMode
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.distinctUntilChanged
+import java.lang.ref.WeakReference
class MainActivity: FragmentActivity() {
companion object {
@@ -65,6 +66,7 @@ class MainActivity: FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ SimplexApp.context.mainActivity = WeakReference(this)
// testJson()
val m = vm.chatModel
applyAppLocale(m.controller.appPrefs.appLanguage)
@@ -181,7 +183,6 @@ class MainActivity: FragmentActivity() {
else
generalGetString(R.string.auth_unlock),
selfDestruct = true,
- this@MainActivity,
completed = { laResult ->
when (laResult) {
LAResult.Success ->
@@ -250,7 +251,6 @@ class MainActivity: FragmentActivity() {
authenticate(
generalGetString(R.string.auth_enable_simplex_lock),
generalGetString(R.string.auth_confirm_credential),
- activity = activity,
completed = { laResult ->
when (laResult) {
LAResult.Success -> {
@@ -317,7 +317,6 @@ class MainActivity: FragmentActivity() {
generalGetString(R.string.auth_confirm_credential)
else
"",
- activity = activity,
completed = { laResult ->
val prefPerformLA = m.controller.appPrefs.performLA
when (laResult) {
@@ -353,7 +352,6 @@ class MainActivity: FragmentActivity() {
generalGetString(R.string.auth_confirm_credential)
else
generalGetString(R.string.auth_disable_simplex_lock),
- activity = activity,
completed = { laResult ->
val prefPerformLA = m.controller.appPrefs.performLA
val selfDestructPref = m.controller.appPrefs.selfDestruct
diff --git a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt
similarity index 95%
rename from apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt
index 7a2aecaae6..29a20ff768 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt
@@ -14,6 +14,7 @@ import com.jakewharton.processphoenix.ProcessPhoenix
import kotlinx.coroutines.*
import kotlinx.serialization.decodeFromString
import java.io.*
+import java.lang.ref.WeakReference
import java.util.*
import java.util.concurrent.Semaphore
import java.util.concurrent.TimeUnit
@@ -37,13 +38,20 @@ external fun chatParseServer(str: String): String
external fun chatPasswordHash(pwd: String, salt: String): String
class SimplexApp: Application(), LifecycleEventObserver {
+ var mainActivity: WeakReference = WeakReference(null)
+ val chatModel: ChatModel
+ get() = chatController.chatModel
+ val appPreferences: AppPreferences
+ get() = chatController.appPrefs
+
+ val chatController: ChatController = ChatController
var isAppOnForeground: Boolean = false
val defaultLocale: Locale = Locale.getDefault()
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: Boolean = true) {
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
- val dbAbsolutePathPrefix = getFilesDirectory(SimplexApp.context)
+ val dbAbsolutePathPrefix = getFilesDirectory()
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
val migrated: Array = chatMigrateInit(dbAbsolutePathPrefix, dbKey, confirm.value)
val res: DBMigrationResult = kotlin.runCatching {
@@ -84,21 +92,6 @@ class SimplexApp: Application(), LifecycleEventObserver {
}
}
- val chatModel: ChatModel
- get() = chatController.chatModel
-
- private val ntfManager: NtfManager by lazy {
- NtfManager(applicationContext, appPreferences)
- }
-
- private val appPreferences: AppPreferences by lazy {
- AppPreferences(applicationContext)
- }
-
- val chatController: ChatController by lazy {
- ChatController(0L, ntfManager, applicationContext, appPreferences)
- }
-
override fun onCreate() {
super.onCreate()
@@ -162,12 +155,12 @@ class SimplexApp: Application(), LifecycleEventObserver {
fun allowToStartServiceAfterAppExit() = with(chatModel.controller) {
appPrefs.notificationsMode.get() == NotificationsMode.SERVICE.name &&
- (!NotificationsMode.SERVICE.requiresIgnoringBattery || isIgnoringBatteryOptimizations(chatModel.controller.appContext))
+ (!NotificationsMode.SERVICE.requiresIgnoringBattery || isIgnoringBatteryOptimizations())
}
private fun allowToStartPeriodically() = with(chatModel.controller) {
appPrefs.notificationsMode.get() == NotificationsMode.PERIODIC.name &&
- (!NotificationsMode.PERIODIC.requiresIgnoringBattery || isIgnoringBatteryOptimizations(chatModel.controller.appContext))
+ (!NotificationsMode.PERIODIC.requiresIgnoringBattery || isIgnoringBatteryOptimizations())
}
/*
diff --git a/apps/android/app/src/main/java/chat/simplex/app/SimplexService.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/SimplexService.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt
index 3d9de2d35f..b480814144 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt
@@ -34,7 +34,8 @@ import kotlin.time.*
* Without this annotation an animation from ChatList to ChatView has 1 frame per the whole animation. Don't delete it
* */
@Stable
-class ChatModel(val controller: ChatController) {
+object ChatModel {
+ val controller: ChatController = ChatController
val onboardingStage = mutableStateOf(null)
val currentUser = mutableStateOf(null)
val users = mutableStateListOf()
@@ -65,11 +66,11 @@ class ChatModel(val controller: ChatController) {
val appOpenUrl = mutableStateOf(null)
// preferences
- val notificationsMode = mutableStateOf(NotificationsMode.default)
- var notificationPreviewMode = mutableStateOf(NotificationPreviewMode.default)
- val performLA = mutableStateOf(false)
+ val notificationsMode by lazy { mutableStateOf(NotificationsMode.values().firstOrNull { it.name == controller.appPrefs.notificationsMode.get() } ?: NotificationsMode.default) }
+ val notificationPreviewMode by lazy { mutableStateOf(NotificationPreviewMode.values().firstOrNull { it.name == controller.appPrefs.notificationPreviewMode.get() } ?: NotificationPreviewMode.default) }
+ val performLA by lazy { mutableStateOf(controller.appPrefs.performLA.get()) }
val showAdvertiseLAUnavailableAlert = mutableStateOf(false)
- var incognito = mutableStateOf(false)
+ val incognito by lazy { mutableStateOf(controller.appPrefs.incognito.get()) }
// current WebRTC call
val callManager = CallManager(this)
@@ -91,7 +92,7 @@ class ChatModel(val controller: ChatController) {
val sharedContent = mutableStateOf(null as SharedContent?)
val filesToDelete = mutableSetOf()
- val simplexLinkMode = mutableStateOf(controller.appPrefs.simplexLinkMode.get())
+ val simplexLinkMode by lazy { mutableStateOf(controller.appPrefs.simplexLinkMode.get()) }
fun getUser(userId: Long): User? = if (currentUser.value?.userId == userId) {
currentUser.value
diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.kt
similarity index 86%
rename from apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.kt
index bc5985c5e5..1a52030c84 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.kt
@@ -1,15 +1,17 @@
package chat.simplex.app.model
+import android.Manifest
import android.app.*
+import android.app.TaskStackBuilder
import android.content.*
+import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.hardware.display.DisplayManager
import android.media.AudioAttributes
import android.net.Uri
import android.util.Log
import android.view.Display
-import androidx.core.app.NotificationCompat
-import androidx.core.app.NotificationManagerCompat
+import androidx.core.app.*
import chat.simplex.app.*
import chat.simplex.app.views.call.*
import chat.simplex.app.views.chatlist.acceptContactRequest
@@ -17,29 +19,29 @@ import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.NotificationPreviewMode
import kotlinx.datetime.Clock
-class NtfManager(val context: Context, private val appPreferences: AppPreferences) {
- companion object {
- const val MessageChannel: String = "chat.simplex.app.MESSAGE_NOTIFICATION"
- const val MessageGroup: String = "chat.simplex.app.MESSAGE_NOTIFICATION"
- const val OpenChatAction: String = "chat.simplex.app.OPEN_CHAT"
- const val ShowChatsAction: String = "chat.simplex.app.SHOW_CHATS"
+object NtfManager {
+ const val MessageChannel: String = "chat.simplex.app.MESSAGE_NOTIFICATION"
+ const val MessageGroup: String = "chat.simplex.app.MESSAGE_NOTIFICATION"
+ const val OpenChatAction: String = "chat.simplex.app.OPEN_CHAT"
+ const val ShowChatsAction: String = "chat.simplex.app.SHOW_CHATS"
- // DO NOT change notification channel settings / names
- const val CallChannel: String = "chat.simplex.app.CALL_NOTIFICATION_1"
- const val AcceptCallAction: String = "chat.simplex.app.ACCEPT_CALL"
- const val RejectCallAction: String = "chat.simplex.app.REJECT_CALL"
- const val CallNotificationId: Int = -1
+ // DO NOT change notification channel settings / names
+ const val CallChannel: String = "chat.simplex.app.CALL_NOTIFICATION_1"
+ const val AcceptCallAction: String = "chat.simplex.app.ACCEPT_CALL"
+ const val RejectCallAction: String = "chat.simplex.app.REJECT_CALL"
+ const val CallNotificationId: Int = -1
+ private const val UserIdKey: String = "userId"
+ private const val ChatIdKey: String = "chatId"
+ private val appPreferences: AppPreferences by lazy { ChatController.appPrefs }
+ private val context: Context
+ get() = SimplexApp.context
- private const val UserIdKey: String = "userId"
- private const val ChatIdKey: String = "chatId"
-
- fun getUserIdFromIntent(intent: Intent?): Long? {
- val userId = intent?.getLongExtra(UserIdKey, -1L)
- return if (userId == -1L || userId == null) null else userId
- }
+ fun getUserIdFromIntent(intent: Intent?): Long? {
+ val userId = intent?.getLongExtra(UserIdKey, -1L)
+ return if (userId == -1L || userId == null) null else userId
}
- private val manager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ private val manager: NotificationManager = SimplexApp.context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private var prevNtfTime = mutableMapOf()
private val msgNtfTimeoutMs = 30000L
@@ -58,7 +60,7 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.build()
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.packageName + "/" + R.raw.ring_once)
- Log.d(TAG,"callNotificationChannel sound: $soundUri")
+ Log.d(TAG, "callNotificationChannel sound: $soundUri")
callChannel.setSound(soundUri, attrs)
callChannel.enableVibration(true)
// the numbers below are explained here: https://developer.android.com/reference/android/os/Vibrator
@@ -70,8 +72,8 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
fun cancelNotificationsForChat(chatId: String) {
prevNtfTime.remove(chatId)
manager.cancel(chatId.hashCode())
- val msgNtfs = manager.activeNotifications.filter {
- ntf -> ntf.notification.channelId == MessageChannel
+ val msgNtfs = manager.activeNotifications.filter { ntf ->
+ ntf.notification.channelId == MessageChannel
}
if (msgNtfs.count() == 1) {
// Have a group notification with no children so cancel it
@@ -110,7 +112,6 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
val now = Clock.System.now().toEpochMilliseconds()
val recentNotification = (now - prevNtfTime.getOrDefault(chatId, 0) < msgNtfTimeoutMs)
prevNtfTime[chatId] = now
-
val previewMode = appPreferences.notificationPreviewMode.get()
val title = if (previewMode == NotificationPreviewMode.HIDDEN.name) generalGetString(R.string.notification_preview_somebody) else displayName
val content = if (previewMode != NotificationPreviewMode.MESSAGE.name) generalGetString(R.string.notification_preview_new_message) else msgText
@@ -145,7 +146,6 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
}
builder.addAction(0, actionButton, actionPendingIntent)
}
-
val summary = NotificationCompat.Builder(context, MessageChannel)
.setSmallIcon(R.drawable.ntf_icon)
.setColor(0x88FFFF)
@@ -157,14 +157,17 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
with(NotificationManagerCompat.from(context)) {
// using cInfo.id only shows one notification per chat and updates it when the message arrives
- notify(chatId.hashCode(), builder.build())
- notify(0, summary)
+ if (ActivityCompat.checkSelfPermission(SimplexApp.context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
+ notify(chatId.hashCode(), builder.build())
+ notify(0, summary)
+ }
}
}
fun notifyCallInvitation(invitation: RcvCallInvitation) {
val keyguardManager = getKeyguardManager(context)
- Log.d(TAG,
+ Log.d(
+ TAG,
"notifyCallInvitation pre-requests: " +
"keyguard locked ${keyguardManager.isKeyguardLocked}, " +
"callOnLockScreen ${appPreferences.callOnLockScreen.get()}, " +
@@ -223,7 +226,9 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
// This makes notification sound and vibration repeat endlessly
notification.flags = notification.flags or NotificationCompat.FLAG_INSISTENT
with(NotificationManagerCompat.from(context)) {
- notify(CallNotificationId, notification)
+ if (ActivityCompat.checkSelfPermission(SimplexApp.context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
+ notify(CallNotificationId, notification)
+ }
}
}
@@ -237,7 +242,7 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
fun hasNotificationsForChat(chatId: String): Boolean = manager.activeNotifications.any { it.id == chatId.hashCode() }
- private fun hideSecrets(cItem: ChatItem) : String {
+ private fun hideSecrets(cItem: ChatItem): String {
val md = cItem.formattedText
return if (md != null) {
var res = ""
@@ -302,14 +307,16 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
}
val apiId = chatId.replace("<@", "").toLongOrNull() ?: return
acceptContactRequest(apiId, cInfo, isCurrentUser, m)
- m.controller.ntfManager.cancelNotificationsForChat(chatId)
+ cancelNotificationsForChat(chatId)
}
+
RejectCallAction -> {
val invitation = m.callInvitations[chatId]
if (invitation != null) {
m.callManager.endCall(invitation = invitation)
}
}
+
else -> {
Log.e(TAG, "Unknown action. Make sure you provide action from NotificationAction enum")
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
index e1fbbaa0ce..c55f697048 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
@@ -58,9 +58,9 @@ enum class SimplexLinkMode {
}
}
-class AppPreferences(val context: Context) {
- private val sharedPreferences: SharedPreferences = context.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE)
- private val sharedPreferencesThemes: SharedPreferences = context.getSharedPreferences(SHARED_PREFS_THEMES_ID, Context.MODE_PRIVATE)
+class AppPreferences {
+ private val sharedPreferences: SharedPreferences = SimplexApp.context.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE)
+ private val sharedPreferencesThemes: SharedPreferences = SimplexApp.context.getSharedPreferences(SHARED_PREFS_THEMES_ID, Context.MODE_PRIVATE)
// deprecated, remove in 2024
private val runServiceInBackground = mkBoolPreference(SHARED_PREFS_RUN_SERVICE_IN_BACKGROUND, true)
@@ -298,21 +298,16 @@ class AppPreferences(val context: Context) {
private const val MESSAGE_TIMEOUT: Int = 15_000_000
-open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val appContext: Context, val appPrefs: AppPreferences) {
- val chatModel = ChatModel(this)
+object ChatController {
+ var ctrl: ChatCtrl? = -1
+ val appPrefs: AppPreferences by lazy { AppPreferences() }
+ val ntfManager by lazy { NtfManager }
+
+ val chatModel = ChatModel
private var receiverStarted = false
var lastMsgReceivedTimestamp: Long = System.currentTimeMillis()
private set
- init {
- chatModel.notificationsMode.value =
- kotlin.runCatching { NotificationsMode.valueOf(appPrefs.notificationsMode.get()!!) }.getOrDefault(NotificationsMode.default)
- chatModel.notificationPreviewMode.value =
- kotlin.runCatching { NotificationPreviewMode.valueOf(appPrefs.notificationPreviewMode.get()!!) }.getOrDefault(NotificationPreviewMode.default)
- chatModel.performLA.value = appPrefs.performLA.get()
- chatModel.incognito.value = appPrefs.incognito.get()
- }
-
private fun currentUserId(funcName: String): Long {
val userId = chatModel.currentUser.value?.userId
if (userId == null) {
@@ -328,8 +323,8 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
try {
if (chatModel.chatRunning.value == true) return
apiSetNetworkConfig(getNetCfg())
- apiSetTempFolder(getTempFilesDirectory(appContext))
- apiSetFilesFolder(getAppFilesDirectory(appContext))
+ apiSetTempFolder(getTempFilesDirectory())
+ apiSetFilesFolder(getAppFilesDirectory())
apiSetXFTPConfig(getXFTPCfg())
val justStarted = apiStartChat()
val users = listUsers()
@@ -1602,7 +1597,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
mc is MsgContent.MCFile
&& fileName != null
) {
- removeFile(appContext, fileName)
+ removeFile(fileName)
}
}
@@ -1671,7 +1666,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
if (!appPrefs.backgroundServiceNoticeShown.get()) {
// the branch for the new users who have never seen service notice
- if (!mode.requiresIgnoringBattery || isIgnoringBatteryOptimizations(appContext)) {
+ if (!mode.requiresIgnoringBattery || isIgnoringBatteryOptimizations()) {
showBGServiceNotice(mode)
} else {
showBGServiceNoticeIgnoreOptimization(mode)
@@ -1679,7 +1674,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
// set both flags, so that if the user doesn't allow ignoring optimizations, the service will be disabled without additional notice
appPrefs.backgroundServiceNoticeShown.set(true)
appPrefs.backgroundServiceBatteryNoticeShown.set(true)
- } else if (mode.requiresIgnoringBattery && !isIgnoringBatteryOptimizations(appContext)) {
+ } else if (mode.requiresIgnoringBattery && !isIgnoringBatteryOptimizations()) {
// the branch for users who have app installed, and have seen the service notice,
// but the battery optimization for the app is on (Android 12) AND the service is running
if (appPrefs.backgroundServiceBatteryNoticeShown.get()) {
@@ -1738,7 +1733,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
private fun showBGServiceNoticeIgnoreOptimization(mode: NotificationsMode) = AlertManager.shared.showAlert {
val ignoreOptimization = {
AlertManager.shared.hideAlert()
- askAboutIgnoringBatteryOptimization(appContext)
+ askAboutIgnoringBatteryOptimization()
}
AlertDialog(
onDismissRequest = ignoreOptimization,
@@ -1800,19 +1795,19 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
)
}
- fun isIgnoringBatteryOptimizations(context: Context): Boolean {
- val powerManager = context.getSystemService(Application.POWER_SERVICE) as PowerManager
- return powerManager.isIgnoringBatteryOptimizations(context.packageName)
+ fun isIgnoringBatteryOptimizations(): Boolean {
+ val powerManager = SimplexApp.context.getSystemService(Application.POWER_SERVICE) as PowerManager
+ return powerManager.isIgnoringBatteryOptimizations(SimplexApp.context.packageName)
}
- private fun askAboutIgnoringBatteryOptimization(context: Context) {
+ private fun askAboutIgnoringBatteryOptimization() {
Intent().apply {
@SuppressLint("BatteryLife")
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
- data = Uri.parse("package:${context.packageName}")
+ data = Uri.parse("package:${SimplexApp.context.packageName}")
// This flag is needed when you start a new activity from non-Activity context
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- context.startActivity(this)
+ SimplexApp.context.startActivity(this)
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Color.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Color.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Shape.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Shape.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/ui/theme/Shape.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Shape.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt
index 24652c76ff..8f1ec7eab3 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt
@@ -16,7 +16,6 @@ import chat.simplex.app.views.helpers.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
-import okhttp3.internal.toHexString
enum class DefaultTheme {
SYSTEM, LIGHT, DARK, SIMPLEX;
@@ -150,7 +149,7 @@ data class ThemeColors(
private fun String.colorFromReadableHex(): Color =
Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong())
-private fun Color.toReadableHex(): String = "#" + toArgb().toHexString()
+private fun Color.toReadableHex(): String = "#" + Integer.toHexString(toArgb())
@Serializable
data class ThemeOverrides (
diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt
index 3453dad7e9..b7df77b0ae 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt
@@ -7,7 +7,6 @@ import chat.simplex.app.R
import chat.simplex.app.SimplexApp
import chat.simplex.app.model.AppPreferences
import chat.simplex.app.views.helpers.generalGetString
-import okhttp3.internal.toHexString
object ThemeManager {
private val appPrefs: AppPreferences by lazy {
@@ -149,4 +148,4 @@ object ThemeManager {
}
}
-private fun Color.toReadableHex(): String = "#" + toArgb().toHexString()
+private fun Color.toReadableHex(): String = "#" + Integer.toHexString(toArgb())
diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Type.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Type.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/ui/theme/Type.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Type.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/SplashView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/SplashView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/SplashView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/SplashView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/TerminalView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/TerminalView.kt
index cb00859314..264c243ebd 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/TerminalView.kt
@@ -128,7 +128,7 @@ fun TerminalLog(terminalItems: List) {
modifier = Modifier
.fillMaxWidth()
.clickable {
- ModalManager.shared.showModal(endButtons = { ShareButton { shareText(context, item.details) } }) {
+ ModalManager.shared.showModal(endButtons = { ShareButton { shareText(item.details) } }) {
SelectionContainer(modifier = Modifier.verticalScroll(rememberScrollState())) {
Text(item.details, modifier = Modifier.padding(horizontal = DEFAULT_PADDING).padding(bottom = DEFAULT_PADDING))
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/WelcomeView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/WelcomeView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallManager.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/CallManager.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/call/CallManager.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/CallManager.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/CallView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/CallView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt
index d5282f3c37..5708759ca9 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt
@@ -33,7 +33,7 @@ import androidx.compose.ui.unit.sp
import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.model.*
-import chat.simplex.app.model.NtfManager.Companion.OpenChatAction
+import chat.simplex.app.model.NtfManager.OpenChatAction
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.ProfileImage
import kotlinx.datetime.Clock
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt
index 6afe1b3492..a8548fadac 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt
@@ -28,7 +28,7 @@ fun IncomingCallAlertView(invitation: RcvCallInvitation, chatModel: ChatModel) {
val cm = chatModel.callManager
val cxt = LocalContext.current
val scope = rememberCoroutineScope()
- LaunchedEffect(true) { SoundPlayer.shared.start(cxt, scope, sound = !chatModel.showCallView.value) }
+ LaunchedEffect(true) { SoundPlayer.shared.start(scope, sound = !chatModel.showCallView.value) }
DisposableEffect(true) { onDispose { SoundPlayer.shared.stop() } }
IncomingCallAlertLayout(
invitation,
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/SoundPlayer.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/SoundPlayer.kt
similarity index 89%
rename from apps/android/app/src/main/java/chat/simplex/app/views/call/SoundPlayer.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/SoundPlayer.kt
index 456f50d0bd..314032984a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/call/SoundPlayer.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/SoundPlayer.kt
@@ -16,7 +16,7 @@ class SoundPlayer {
private var player: MediaPlayer? = null
var playing = false
- fun start(cxt: Context, scope: CoroutineScope, sound: Boolean) {
+ fun start(scope: CoroutineScope, sound: Boolean) {
player?.reset()
player = MediaPlayer().apply {
setAudioAttributes(
@@ -28,7 +28,7 @@ class SoundPlayer {
setDataSource(SimplexApp.context, Uri.parse("android.resource://" + SimplexApp.context.packageName + "/" + R.raw.ring_once))
prepare()
}
- val vibrator = ContextCompat.getSystemService(cxt, Vibrator::class.java)
+ val vibrator = ContextCompat.getSystemService(SimplexApp.context, Vibrator::class.java)
val effect = VibrationEffect.createOneShot(250, VibrationEffect.DEFAULT_AMPLITUDE)
playing = true
withScope(scope) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/WebRTC.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/WebRTC.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/call/WebRTC.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/WebRTC.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
index 75edc77c05..2c105155a9 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
@@ -211,10 +211,9 @@ fun ChatInfoLayout(
SectionDividerSpaced()
if (contact.contactLink != null) {
- val context = LocalContext.current
SectionView(stringResource(R.string.address_section_title).uppercase()) {
QRCode(contact.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
- ShareAddressButton { shareText(context, contact.contactLink) }
+ ShareAddressButton { shareText(contact.contactLink) }
SectionTextFooter(stringResource(R.string.you_can_share_this_address_with_your_contacts).format(contact.displayName))
}
SectionDividerSpaced()
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatItemInfoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatItemInfoView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatItemInfoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatItemInfoView.kt
index 8ef98933da..a6dcaa97be 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatItemInfoView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatItemInfoView.kt
@@ -12,7 +12,6 @@ import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -32,7 +31,6 @@ fun ChatItemInfoView(ci: ChatItem, ciInfo: ChatItemInfo, devTools: Boolean) {
val sent = ci.chatDir.sent
val appColors = CurrentColors.collectAsState().value.appColors
val itemColor = if (sent) appColors.sentMessage else appColors.receivedMessage
- val context = LocalContext.current
val uriHandler = LocalUriHandler.current
@Composable
@@ -83,11 +81,11 @@ fun ChatItemInfoView(ci: ChatItem, ciInfo: ChatItemInfo, devTools: Boolean) {
if (text != "") {
DefaultDropdownMenu(showMenu) {
ItemAction(stringResource(R.string.share_verb), painterResource(R.drawable.ic_share), onClick = {
- shareText(context, text)
+ shareText(text)
showMenu.value = false
})
ItemAction(stringResource(R.string.copy_verb), painterResource(R.drawable.ic_content_copy), onClick = {
- copyText(context, text)
+ copyText(text)
showMenu.value = false
})
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatView.kt
index 7681b79b73..809f529844 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ChatView.kt
@@ -278,7 +278,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: () -> Unit) {
val ciInfo = chatModel.controller.apiGetChatItemInfo(cInfo.chatType, cInfo.apiId, cItem.id)
if (ciInfo != null) {
ModalManager.shared.showModal(endButtons = { ShareButton {
- shareText(context, itemInfoShareText(cItem, ciInfo, chatModel.controller.appPrefs.developerTools.get()))
+ shareText(itemInfoShareText(cItem, ciInfo, chatModel.controller.appPrefs.developerTools.get()))
} }) {
ChatItemInfoView(cItem, ciInfo, devTools = chatModel.controller.appPrefs.developerTools.get())
}
@@ -976,7 +976,7 @@ private fun providerForGallery(
scrollTo: (Int) -> Unit
): ImageGalleryProvider {
fun canShowMedia(item: ChatItem): Boolean =
- (item.content.msgContent is MsgContent.MCImage || item.content.msgContent is MsgContent.MCVideo) && (item.file?.loaded == true && getLoadedFilePath(SimplexApp.context, item.file) != null)
+ (item.content.msgContent is MsgContent.MCImage || item.content.msgContent is MsgContent.MCVideo) && (item.file?.loaded == true && getLoadedFilePath(item.file) != null)
fun item(skipInternalIndex: Int, initialChatId: Long): Pair? {
var processedInternalIndex = -skipInternalIndex.sign
@@ -1003,15 +1003,15 @@ private fun providerForGallery(
val item = item(internalIndex, initialChatId)?.second ?: return null
return when (item.content.msgContent) {
is MsgContent.MCImage -> {
- val imageBitmap: Bitmap? = getLoadedImage(SimplexApp.context, item.file)
- val filePath = getLoadedFilePath(SimplexApp.context, item.file)
+ val imageBitmap: Bitmap? = getLoadedImage(item.file)
+ val filePath = getLoadedFilePath(item.file)
if (imageBitmap != null && filePath != null) {
val uri = FileProvider.getUriForFile(SimplexApp.context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
ProviderMedia.Image(uri, imageBitmap)
} else null
}
is MsgContent.MCVideo -> {
- val filePath = getLoadedFilePath(SimplexApp.context, item.file)
+ val filePath = getLoadedFilePath(item.file)
if (filePath != null) {
val uri = FileProvider.getUriForFile(SimplexApp.context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
ProviderMedia.Video(uri, (item.content.msgContent as MsgContent.MCVideo).image)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
index 189a8e4ad9..8b43cb39ad 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
@@ -201,7 +201,7 @@ fun ComposeView(
val imagesPreview = ArrayList()
uris.forEach { uri ->
var bitmap: Bitmap? = null
- val isImage = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileName(SimplexApp.context, uri)?.split(".")?.last())?.contains("image/") == true
+ val isImage = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileName(uri)?.split(".")?.last())?.contains("image/") == true
when {
isImage -> {
// Image
@@ -209,10 +209,10 @@ fun ComposeView(
bitmap = if (drawable != null) getBitmapFromUri(uri) else null
val isAnimNewApi = Build.VERSION.SDK_INT >= 28 && drawable is AnimatedImageDrawable
val isAnimOldApi = Build.VERSION.SDK_INT < 28 &&
- (getFileName(SimplexApp.context, uri)?.endsWith(".gif") == true || getFileName(SimplexApp.context, uri)?.endsWith(".webp") == true)
+ (getFileName(uri)?.endsWith(".gif") == true || getFileName(uri)?.endsWith(".webp") == true)
if (isAnimNewApi || isAnimOldApi) {
// It's a gif or webp
- val fileSize = getFileSize(context, uri)
+ val fileSize = getFileSize(uri)
if (fileSize != null && fileSize <= maxFileSize) {
content.add(UploadContent.AnimatedImage(uri))
} else {
@@ -244,9 +244,9 @@ fun ComposeView(
}
val processPickedFile = { uri: Uri?, text: String? ->
if (uri != null) {
- val fileSize = getFileSize(context, uri)
+ val fileSize = getFileSize(uri)
if (fileSize != null && fileSize <= maxFileSize) {
- val fileName = getFileName(SimplexApp.context, uri)
+ val fileName = getFileName(uri)
if (fileName != null) {
composeState.value = composeState.value.copy(message = text ?: composeState.value.message, preview = ComposePreview.FilePreview(fileName, uri))
}
@@ -381,7 +381,7 @@ fun ComposeView(
chatModel.addChatItem(cInfo, aChatItem.chatItem)
return aChatItem.chatItem
}
- if (file != null) removeFile(context, file)
+ if (file != null) removeFile(file)
return null
}
@@ -460,9 +460,9 @@ fun ComposeView(
is ComposePreview.MediaPreview -> {
preview.content.forEachIndexed { index, it ->
val file = when (it) {
- is UploadContent.SimpleImage -> saveImage(context, it.uri)
- is UploadContent.AnimatedImage -> saveAnimImage(context, it.uri)
- is UploadContent.Video -> saveFileFromUri(context, it.uri)
+ is UploadContent.SimpleImage -> saveImage(it.uri)
+ is UploadContent.AnimatedImage -> saveAnimImage(it.uri)
+ is UploadContent.Video -> saveFileFromUri(it.uri)
}
if (file != null) {
files.add(file)
@@ -477,7 +477,7 @@ fun ComposeView(
is ComposePreview.VoicePreview -> {
val tmpFile = File(preview.voice)
AudioPlayer.stop(tmpFile.absolutePath)
- val actualFile = File(getAppFilePath(SimplexApp.context, tmpFile.name.replaceAfter(RecorderNative.extension, "")))
+ val actualFile = File(getAppFilePath(tmpFile.name.replaceAfter(RecorderNative.extension, "")))
withContext(Dispatchers.IO) {
Files.move(tmpFile.toPath(), actualFile.toPath())
}
@@ -486,7 +486,7 @@ fun ComposeView(
msgs.add(MsgContent.MCVoice(if (msgs.isEmpty()) msgText else "", preview.durationMs / 1000))
}
is ComposePreview.FilePreview -> {
- val file = saveFileFromUri(context, preview.uri)
+ val file = saveFileFromUri(preview.uri)
if (file != null) {
files.add((file))
msgs.add(MsgContent.MCFile(if (msgs.isEmpty()) msgText else ""))
@@ -594,7 +594,7 @@ fun ComposeView(
suspend fun sendLiveMessage() {
val cs = composeState.value
val typedMsg = cs.message
- if ((cs.sendEnabled() || cs.contextItem is ComposeContextItem.QuotedItem) && (cs.liveMessage == null || !cs.liveMessage?.sent)) {
+ if ((cs.sendEnabled() || cs.contextItem is ComposeContextItem.QuotedItem) && (cs.liveMessage == null || !cs.liveMessage.sent)) {
val ci = sendMessageAsync(typedMsg, live = true, ttl = null)
if (ci != null) {
composeState.value = composeState.value.copy(liveMessage = LiveMessage(ci, typedMsg = typedMsg, sentMsg = typedMsg, sent = true))
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ScanCodeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ScanCodeView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/ScanCodeView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ScanCodeView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
similarity index 95%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
index 12e8ab1aa9..472883d556 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
@@ -10,7 +10,6 @@ import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
@@ -86,9 +85,8 @@ private fun VerifyCodeLayout(
maxLines = 20
)
}
- val context = LocalContext.current
Box(Modifier.weight(1f)) {
- IconButton({ shareText(context, connectionCode) }, Modifier.size(20.dp).align(Alignment.CenterStart)) {
+ IconButton({ shareText(connectionCode) }, Modifier.size(20.dp).align(Alignment.CenterStart)) {
Icon(painterResource(R.drawable.ic_share_filled), null, tint = MaterialTheme.colors.primary)
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt
index 42a893ce99..45ccb4ca56 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt
@@ -10,7 +10,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@@ -26,7 +25,6 @@ fun GroupLinkView(chatModel: ChatModel, groupInfo: GroupInfo, connReqContact: St
var groupLink by rememberSaveable { mutableStateOf(connReqContact) }
val groupLinkMemberRole = rememberSaveable { mutableStateOf(memberRole) }
var creatingLink by rememberSaveable { mutableStateOf(false) }
- val cxt = LocalContext.current
fun createLink() {
creatingLink = true
withApi {
@@ -50,7 +48,7 @@ fun GroupLinkView(chatModel: ChatModel, groupInfo: GroupInfo, connReqContact: St
groupLinkMemberRole,
creatingLink,
createLink = ::createLink,
- share = { shareText(cxt, groupLink ?: return@GroupLinkLayout) },
+ share = { shareText(groupLink ?: return@GroupLinkLayout) },
updateLink = {
val role = groupLinkMemberRole.value
if (role != null) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt
index 1ed56a8874..79a8162892 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt
@@ -220,7 +220,7 @@ fun GroupMemberInfoLayout(
val context = LocalContext.current
SectionView(stringResource(R.string.address_section_title).uppercase()) {
QRCode(member.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
- ShareAddressButton { shareText(context, member.contactLink) }
+ ShareAddressButton { shareText(member.contactLink) }
if (contactId != null) {
if (knownDirectChat(contactId) == null && !groupInfo.fullGroupPreferences.directMessages.on) {
ConnectViaAddressButton(onClick = { connectViaAddress(member.contactLink) })
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt
index db3fd4daa1..91a999c6f7 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt
@@ -98,7 +98,7 @@ private fun GroupWelcomeLayout(
},
wt.value.isEmpty()
)
- CopyTextButton { copyText(SimplexApp.context, wt.value) }
+ CopyTextButton { copyText(wt.value) }
SectionDividerSpaced(maxBottomPadding = false)
SaveButton(
save = save,
@@ -106,7 +106,7 @@ private fun GroupWelcomeLayout(
)
} else {
TextPreview(wt.value, linkMode)
- CopyTextButton { copyText(SimplexApp.context, wt.value) }
+ CopyTextButton { copyText(wt.value) }
}
SectionBottomSpacer()
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
index 52a4a417f9..98aedc361e 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
@@ -32,7 +32,7 @@ fun CIFileView(
receiveFile: (Long) -> Unit
) {
val context = LocalContext.current
- val saveFileLauncher = rememberSaveFileLauncher(cxt = context, ciFile = file)
+ val saveFileLauncher = rememberSaveFileLauncher(ciFile = file)
@Composable
fun fileIcon(
@@ -95,7 +95,7 @@ fun CIFileView(
)
}
is CIFileStatus.RcvComplete -> {
- val filePath = getLoadedFilePath(context, file)
+ val filePath = getLoadedFilePath(file)
if (filePath != null) {
saveFileLauncher.launch(file.fileName)
} else {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
index c4368e1b7a..4c94bed48d 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
@@ -139,8 +139,8 @@ fun CIImageView(
}
fun imageAndFilePath(file: CIFile?): Pair {
- val imageBitmap: Bitmap? = getLoadedImage(SimplexApp.context, file)
- val filePath = getLoadedFilePath(SimplexApp.context, file)
+ val imageBitmap: Bitmap? = getLoadedImage(file)
+ val filePath = getLoadedFilePath(file)
return imageBitmap to filePath
}
@@ -160,7 +160,7 @@ fun CIImageView(
val view = LocalView.current
imageView(imagePainter, onClick = {
hideKeyboard(view)
- if (getLoadedFilePath(context, file) != null) {
+ if (getLoadedFilePath(file) != null) {
ModalManager.shared.showCustomModal(animated = false) { close ->
ImageFullScreenView(imageProvider, close)
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
similarity index 90%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
index f22fcf46a2..34ea631c72 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
@@ -1,6 +1,5 @@
package chat.simplex.app.views.chat.item
-import SectionSpacer
import SectionView
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
@@ -8,7 +7,6 @@ import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
@@ -33,9 +31,8 @@ fun InvalidJSONView(json: String) {
Column {
Spacer(Modifier.height(DEFAULT_PADDING))
SectionView {
- val context = LocalContext.current
SettingsActionItem(painterResource(R.drawable.ic_share), generalGetString(R.string.share_verb), click = {
- shareText(context, json)
+ shareText(json)
})
}
Column(Modifier.padding(DEFAULT_PADDING).fillMaxWidth().verticalScroll(rememberScrollState())) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIRcvDecryptionError.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIRcvDecryptionError.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIRcvDecryptionError.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIRcvDecryptionError.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
index 63d554b9bb..cfbfb714b0 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
@@ -46,7 +46,7 @@ fun CIVideoView(
contentAlignment = Alignment.TopEnd
) {
val context = LocalContext.current
- val filePath = remember(file) { getLoadedFilePath(SimplexApp.context, file) }
+ val filePath = remember(file) { getLoadedFilePath(file) }
val preview = remember(image) { base64ToBitmap(image) }
if (file != null && filePath != null) {
val uri = remember(filePath) { FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath)) }
@@ -100,7 +100,7 @@ fun CIVideoView(
@Composable
private fun VideoView(uri: Uri, file: CIFile, defaultPreview: Bitmap, defaultDuration: Long, showMenu: MutableState, onClick: () -> Unit) {
val context = LocalContext.current
- val player = remember(uri) { VideoPlayer.getOrCreate(uri, false, defaultPreview, defaultDuration, true, context) }
+ val player = remember(uri) { VideoPlayer.getOrCreate(uri, false, defaultPreview, defaultDuration, true) }
val videoPlaying = remember(uri.path) { player.videoPlaying }
val progress = remember(uri.path) { player.progress }
val duration = remember(uri.path) { player.duration }
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
index 00f96c60f7..840ba7b03f 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
@@ -44,7 +44,7 @@ fun CIVoiceView(
) {
if (file != null) {
val context = LocalContext.current
- val filePath = remember(file.filePath, file.fileStatus) { getLoadedFilePath(context, file) }
+ val filePath = remember(file.filePath, file.fileStatus) { getLoadedFilePath(file) }
var brokenAudio by rememberSaveable(file.filePath) { mutableStateOf(false) }
val audioPlaying = rememberSaveable(file.filePath) { mutableStateOf(false) }
val progress = rememberSaveable(file.filePath) { mutableStateOf(0) }
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
index cd9dad7086..582d50b489 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
@@ -3,7 +3,6 @@ package chat.simplex.app.views.chat.item
import android.Manifest
import android.os.Build
import androidx.compose.foundation.*
-import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
@@ -21,13 +20,11 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.chat.*
import chat.simplex.app.views.helpers.*
-import chat.simplex.app.views.usersettings.IncognitoView
import com.google.accompanist.permissions.rememberPermissionState
import kotlinx.datetime.Clock
@@ -59,7 +56,7 @@ fun ChatItemView(
val showMenu = remember { mutableStateOf(false) }
val revealed = remember { mutableStateOf(false) }
val fullDeleteAllowed = remember(cInfo) { cInfo.featureEnabled(ChatFeature.FullDelete) }
- val saveFileLauncher = rememberSaveFileLauncher(cxt = context, ciFile = cItem.file)
+ val saveFileLauncher = rememberSaveFileLauncher(ciFile = cItem.file)
val onLinkLongClick = { _: String -> showMenu.value = true }
val live = composeState.value.liveMessage != null
@@ -176,26 +173,26 @@ fun ChatItemView(
})
}
ItemAction(stringResource(R.string.share_verb), painterResource(R.drawable.ic_share), onClick = {
- val filePath = getLoadedFilePath(SimplexApp.context, cItem.file)
+ val filePath = getLoadedFilePath(cItem.file)
when {
- filePath != null -> shareFile(context, cItem.text, filePath)
- else -> shareText(context, cItem.content.text)
+ filePath != null -> shareFile(cItem.text, filePath)
+ else -> shareText(cItem.content.text)
}
showMenu.value = false
})
ItemAction(stringResource(R.string.copy_verb), painterResource(R.drawable.ic_content_copy), onClick = {
- copyText(context, cItem.content.text)
+ copyText(cItem.content.text)
showMenu.value = false
})
if (cItem.content.msgContent is MsgContent.MCImage || cItem.content.msgContent is MsgContent.MCVideo || cItem.content.msgContent is MsgContent.MCFile || cItem.content.msgContent is MsgContent.MCVoice) {
- val filePath = getLoadedFilePath(context, cItem.file)
+ val filePath = getLoadedFilePath(cItem.file)
if (filePath != null) {
val writePermissionState = rememberPermissionState(permission = Manifest.permission.WRITE_EXTERNAL_STORAGE)
ItemAction(stringResource(R.string.save_verb), painterResource(R.drawable.ic_download), onClick = {
when (cItem.content.msgContent) {
is MsgContent.MCImage -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || writePermissionState.hasPermission) {
- saveImage(context, cItem.file)
+ saveImage(cItem.file)
} else {
writePermissionState.launchPermissionRequest()
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/EmojiItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/EmojiItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/EmojiItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/EmojiItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
index 61d8080e06..d81b7943bc 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
@@ -21,7 +21,6 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.*
import androidx.compose.ui.unit.*
-import androidx.compose.ui.util.fastMap
import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
@@ -300,7 +299,7 @@ fun PriorityLayout(
// Find important element which should tell what max width other elements can use
// Expecting only one such element. Can be less than one but not more
val imagePlaceable = measureable.firstOrNull { it.layoutId == priorityLayoutId }?.measure(constraints)
- val placeables: List = measureable.fastMap {
+ val placeables: List = measureable.map {
if (it.layoutId == priorityLayoutId)
imagePlaceable!!
else
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt
index d916e4cb94..a0279d0220 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt
@@ -178,7 +178,7 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () ->
@Composable
private fun VideoView(modifier: Modifier, uri: Uri, defaultPreview: Bitmap, currentPage: Boolean) {
val context = LocalContext.current
- val player = remember(uri) { VideoPlayer.getOrCreate(uri, true, defaultPreview, 0L, true, context) }
+ val player = remember(uri) { VideoPlayer.getOrCreate(uri, true, defaultPreview, 0L, true) }
val isCurrentPage = rememberUpdatedState(currentPage)
val play = {
player.play(true)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListNavLinkView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ShareListNavLinkView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListNavLinkView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ShareListNavLinkView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt
similarity index 92%
rename from apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt
index 6df30f9170..6bafc207c1 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt
@@ -14,15 +14,14 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
+import chat.simplex.app.*
import chat.simplex.app.R
-import chat.simplex.app.TAG
import chat.simplex.app.model.ChatModel
import chat.simplex.app.ui.theme.SimpleXTheme
import chat.simplex.app.views.helpers.*
@@ -36,8 +35,8 @@ import java.util.*
@Composable
fun ChatArchiveView(m: ChatModel, title: String, archiveName: String, archiveTime: Instant) {
val context = LocalContext.current
- val archivePath = "${getFilesDirectory(context)}/$archiveName"
- val saveArchiveLauncher = rememberSaveArchiveLauncher(cxt = context, archivePath)
+ val archivePath = "${getFilesDirectory()}/$archiveName"
+ val saveArchiveLauncher = rememberSaveArchiveLauncher(archivePath)
ChatArchiveLayout(
title,
archiveTime,
@@ -82,10 +81,11 @@ fun ChatArchiveLayout(
}
@Composable
-private fun rememberSaveArchiveLauncher(cxt: Context, chatArchivePath: String): ManagedActivityResultLauncher =
+private fun rememberSaveArchiveLauncher(chatArchivePath: String): ManagedActivityResultLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.CreateDocument(),
onResult = { destination ->
+ val cxt = SimplexApp.context
try {
destination?.let {
val contentResolver = cxt.contentResolver
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt
index 8923962bcd..642d855ac1 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt
@@ -497,7 +497,7 @@ fun PreviewDatabaseEncryptionLayout() {
SimpleXTheme {
DatabaseEncryptionLayout(
useKeychain = remember { mutableStateOf(true) },
- prefs = AppPreferences(SimplexApp.context),
+ prefs = AppPreferences(),
chatDbEncrypted = true,
currentKey = remember { mutableStateOf("") },
newKey = remember { mutableStateOf("") },
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt
index c1aa1fe5a6..a8192e3d89 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt
@@ -42,7 +42,7 @@ fun DatabaseErrorView(
var storedDBKey by remember { mutableStateOf(DatabaseUtils.ksDatabasePassword.get()) }
var useKeychain by remember { mutableStateOf(appPreferences.storeDBPassphrase.get()) }
val context = LocalContext.current
- val restoreDbFromBackup = remember { mutableStateOf(shouldShowRestoreDbButton(appPreferences, context)) }
+ val restoreDbFromBackup = remember { mutableStateOf(shouldShowRestoreDbButton(appPreferences)) }
fun callRunChat(confirmMigrations: MigrationConfirmation? = null) {
val useKey = if (useKeychain) null else dbKey.value
@@ -164,7 +164,7 @@ fun DatabaseErrorView(
title = generalGetString(R.string.restore_database_alert_title),
text = generalGetString(R.string.restore_database_alert_desc),
confirmText = generalGetString(R.string.restore_database_alert_confirm),
- onConfirm = { restoreDb(restoreDbFromBackup, appPreferences, context) },
+ onConfirm = { restoreDb(restoreDbFromBackup, appPreferences) },
destructive = true,
)
}
@@ -226,7 +226,8 @@ private fun runChat(
}
}
-private fun shouldShowRestoreDbButton(prefs: AppPreferences, context: Context): Boolean {
+private fun shouldShowRestoreDbButton(prefs: AppPreferences): Boolean {
+ val context = SimplexApp.context
val startedAt = prefs.encryptionStartedAt.get() ?: return false
/** Just in case there is any small difference between reported Java's [Clock.System.now] and Linux's time on a file */
val safeDiffInTime = 10_000L
@@ -238,7 +239,8 @@ private fun shouldShowRestoreDbButton(prefs: AppPreferences, context: Context):
startedAt.toEpochMilliseconds() - safeDiffInTime <= filesAgent.lastModified()
}
-private fun restoreDb(restoreDbFromBackup: MutableState, prefs: AppPreferences, context: Context) {
+private fun restoreDb(restoreDbFromBackup: MutableState, prefs: AppPreferences) {
+ val context = SimplexApp.context
val filesChatBase = context.dataDir.absolutePath + File.separator + "files_chat.db"
val filesAgentBase = context.dataDir.absolutePath + File.separator + "files_agent.db"
try {
@@ -299,7 +301,7 @@ fun PreviewChatInfoLayout() {
SimpleXTheme {
DatabaseErrorView(
remember { mutableStateOf(DBMigrationResult.ErrorNotADatabase("simplex_v1_chat.db")) },
- AppPreferences(SimplexApp.context)
+ AppPreferences()
)
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseView.kt
similarity index 90%
rename from apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseView.kt
index 99293f76ef..41b19cb60c 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/database/DatabaseView.kt
@@ -57,11 +57,11 @@ fun DatabaseView(
val chatArchiveTime = remember { mutableStateOf(prefs.chatArchiveTime.get()) }
val chatLastStart = remember { mutableStateOf(prefs.chatLastStart.get()) }
val chatArchiveFile = remember { mutableStateOf(null) }
- val saveArchiveLauncher = rememberSaveArchiveLauncher(cxt = context, chatArchiveFile)
- val appFilesCountAndSize = remember { mutableStateOf(directoryFileCountAndSize(getAppFilesDirectory(context))) }
+ val saveArchiveLauncher = rememberSaveArchiveLauncher(chatArchiveFile)
+ val appFilesCountAndSize = remember { mutableStateOf(directoryFileCountAndSize(getAppFilesDirectory())) }
val importArchiveLauncher = rememberGetContentLauncher { uri: Uri? ->
if (uri != null) {
- importArchiveAlert(m, context, uri, appFilesCountAndSize, progressIndicator)
+ importArchiveAlert(m, uri, appFilesCountAndSize, progressIndicator)
}
}
LaunchedEffect(m.chatRunning) {
@@ -88,17 +88,17 @@ fun DatabaseView(
m.currentUser.value,
m.users,
startChat = { startChat(m, runChat, chatLastStart, m.chatDbChanged) },
- stopChatAlert = { stopChatAlert(m, runChat, context) },
- exportArchive = { exportArchive(context, m, progressIndicator, chatArchiveName, chatArchiveTime, chatArchiveFile, saveArchiveLauncher) },
+ stopChatAlert = { stopChatAlert(m, runChat) },
+ exportArchive = { exportArchive(m, progressIndicator, chatArchiveName, chatArchiveTime, chatArchiveFile, saveArchiveLauncher) },
deleteChatAlert = { deleteChatAlert(m, progressIndicator) },
- deleteAppFilesAndMedia = { deleteFilesAndMediaAlert(context, appFilesCountAndSize) },
+ deleteAppFilesAndMedia = { deleteFilesAndMediaAlert(appFilesCountAndSize) },
onChatItemTTLSelected = {
val oldValue = chatItemTTL.value
chatItemTTL.value = it
if (it < oldValue) {
- setChatItemTTLAlert(m, chatItemTTL, progressIndicator, appFilesCountAndSize, context)
+ setChatItemTTLAlert(m, chatItemTTL, progressIndicator, appFilesCountAndSize)
} else if (it != oldValue) {
- setCiTTL(m, chatItemTTL, progressIndicator, appFilesCountAndSize, context)
+ setCiTTL(m, chatItemTTL, progressIndicator, appFilesCountAndSize)
}
},
showSettingsModal
@@ -283,13 +283,12 @@ private fun setChatItemTTLAlert(
m: ChatModel, selectedChatItemTTL: MutableState,
progressIndicator: MutableState,
appFilesCountAndSize: MutableState>,
- context: Context
) {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.enable_automatic_deletion_question),
text = generalGetString(R.string.enable_automatic_deletion_message),
confirmText = generalGetString(R.string.delete_messages),
- onConfirm = { setCiTTL(m, selectedChatItemTTL, progressIndicator, appFilesCountAndSize, context) },
+ onConfirm = { setCiTTL(m, selectedChatItemTTL, progressIndicator, appFilesCountAndSize) },
onDismiss = { selectedChatItemTTL.value = m.chatItemTTL.value },
destructive = true,
)
@@ -387,12 +386,12 @@ private fun startChat(m: ChatModel, runChat: MutableState, chatLastSta
}
}
-private fun stopChatAlert(m: ChatModel, runChat: MutableState, context: Context) {
+private fun stopChatAlert(m: ChatModel, runChat: MutableState) {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.stop_chat_question),
text = generalGetString(R.string.stop_chat_to_export_import_or_delete_chat_database),
confirmText = generalGetString(R.string.stop_chat_confirmation),
- onConfirm = { authStopChat(m, runChat, context) },
+ onConfirm = { authStopChat(m, runChat) },
onDismiss = { runChat.value = true }
)
}
@@ -404,16 +403,15 @@ private fun exportProhibitedAlert() {
)
}
-private fun authStopChat(m: ChatModel, runChat: MutableState, context: Context) {
+private fun authStopChat(m: ChatModel, runChat: MutableState) {
if (m.controller.appPrefs.performLA.get()) {
authenticate(
generalGetString(R.string.auth_stop_chat),
generalGetString(R.string.auth_log_in_using_credential),
- activity = context as FragmentActivity,
completed = { laResult ->
when (laResult) {
LAResult.Success, is LAResult.Unavailable -> {
- stopChat(m, runChat, context)
+ stopChat(m, runChat)
}
is LAResult.Error -> {
runChat.value = true
@@ -425,11 +423,11 @@ private fun authStopChat(m: ChatModel, runChat: MutableState, context:
}
)
} else {
- stopChat(m, runChat, context)
+ stopChat(m, runChat)
}
}
-private fun stopChat(m: ChatModel, runChat: MutableState, context: Context) {
+private fun stopChat(m: ChatModel, runChat: MutableState) {
withApi {
try {
runChat.value = false
@@ -455,7 +453,6 @@ suspend fun deleteChatAsync(m: ChatModel) {
}
private fun exportArchive(
- context: Context,
m: ChatModel,
progressIndicator: MutableState,
chatArchiveName: MutableState,
@@ -466,7 +463,7 @@ private fun exportArchive(
progressIndicator.value = true
withApi {
try {
- val archiveFile = exportChatArchive(m, context, chatArchiveName, chatArchiveTime, chatArchiveFile)
+ val archiveFile = exportChatArchive(m, chatArchiveName, chatArchiveTime, chatArchiveFile)
chatArchiveFile.value = archiveFile
saveArchiveLauncher.launch(archiveFile.substringAfterLast("/"))
progressIndicator.value = false
@@ -479,7 +476,6 @@ private fun exportArchive(
private suspend fun exportChatArchive(
m: ChatModel,
- context: Context,
chatArchiveName: MutableState,
chatArchiveTime: MutableState,
chatArchiveFile: MutableState
@@ -487,10 +483,10 @@ private suspend fun exportChatArchive(
val archiveTime = Clock.System.now()
val ts = SimpleDateFormat("yyyy-MM-dd'T'HHmmss", Locale.US).format(Date.from(archiveTime.toJavaInstant()))
val archiveName = "simplex-chat.$ts.zip"
- val archivePath = "${getFilesDirectory(context)}/$archiveName"
- val config = ArchiveConfig(archivePath, parentTempDirectory = context.cacheDir.toString())
+ val archivePath = "${getFilesDirectory()}/$archiveName"
+ val config = ArchiveConfig(archivePath, parentTempDirectory = SimplexApp.context.cacheDir.toString())
m.controller.apiExportArchive(config)
- deleteOldArchive(m, context)
+ deleteOldArchive(m)
m.controller.appPrefs.chatArchiveName.set(archiveName)
chatArchiveName.value = archiveName
m.controller.appPrefs.chatArchiveTime.set(archiveTime)
@@ -499,10 +495,10 @@ private suspend fun exportChatArchive(
return archivePath
}
-private fun deleteOldArchive(m: ChatModel, context: Context) {
+private fun deleteOldArchive(m: ChatModel) {
val chatArchiveName = m.controller.appPrefs.chatArchiveName.get()
if (chatArchiveName != null) {
- val file = File("${getFilesDirectory(context)}/$chatArchiveName")
+ val file = File("${getFilesDirectory()}/$chatArchiveName")
val fileDeleted = file.delete()
if (fileDeleted) {
m.controller.appPrefs.chatArchiveName.set(null)
@@ -514,15 +510,16 @@ private fun deleteOldArchive(m: ChatModel, context: Context) {
}
@Composable
-private fun rememberSaveArchiveLauncher(cxt: Context, chatArchiveFile: MutableState): ManagedActivityResultLauncher =
+private fun rememberSaveArchiveLauncher(chatArchiveFile: MutableState): ManagedActivityResultLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.CreateDocument(),
onResult = { destination ->
+ val cxt = SimplexApp.context
try {
destination?.let {
val filePath = chatArchiveFile.value
if (filePath != null) {
- val contentResolver = cxt.contentResolver
+ val contentResolver = SimplexApp.context.contentResolver
contentResolver.openOutputStream(destination)?.let { stream ->
val outputStream = BufferedOutputStream(stream)
File(filePath).inputStream().use { it.copyTo(outputStream) }
@@ -544,7 +541,6 @@ private fun rememberSaveArchiveLauncher(cxt: Context, chatArchiveFile: MutableSt
private fun importArchiveAlert(
m: ChatModel,
- context: Context,
importedArchiveUri: Uri,
appFilesCountAndSize: MutableState>,
progressIndicator: MutableState
@@ -553,29 +549,28 @@ private fun importArchiveAlert(
title = generalGetString(R.string.import_database_question),
text = generalGetString(R.string.your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one),
confirmText = generalGetString(R.string.import_database_confirmation),
- onConfirm = { importArchive(m, context, importedArchiveUri, appFilesCountAndSize, progressIndicator) },
+ onConfirm = { importArchive(m, importedArchiveUri, appFilesCountAndSize, progressIndicator) },
destructive = true,
)
}
private fun importArchive(
m: ChatModel,
- context: Context,
importedArchiveUri: Uri,
appFilesCountAndSize: MutableState>,
progressIndicator: MutableState
) {
progressIndicator.value = true
- val archivePath = saveArchiveFromUri(context, importedArchiveUri)
+ val archivePath = saveArchiveFromUri(importedArchiveUri)
if (archivePath != null) {
withApi {
try {
m.controller.apiDeleteStorage()
try {
- val config = ArchiveConfig(archivePath, parentTempDirectory = context.cacheDir.toString())
+ val config = ArchiveConfig(archivePath, parentTempDirectory = SimplexApp.context.cacheDir.toString())
val archiveErrors = m.controller.apiImportArchive(config)
DatabaseUtils.ksDatabasePassword.remove()
- appFilesCountAndSize.value = directoryFileCountAndSize(getAppFilesDirectory(context))
+ appFilesCountAndSize.value = directoryFileCountAndSize(getAppFilesDirectory())
if (archiveErrors.isEmpty()) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(R.string.chat_database_imported), text = generalGetString(R.string.restart_the_app_to_use_imported_chat_database))
@@ -601,12 +596,12 @@ private fun importArchive(
}
}
-private fun saveArchiveFromUri(context: Context, importedArchiveUri: Uri): String? {
+private fun saveArchiveFromUri(importedArchiveUri: Uri): String? {
return try {
- val inputStream = context.contentResolver.openInputStream(importedArchiveUri)
- val archiveName = getFileName(context, importedArchiveUri)
+ val inputStream = SimplexApp.context.contentResolver.openInputStream(importedArchiveUri)
+ val archiveName = getFileName(importedArchiveUri)
if (inputStream != null && archiveName != null) {
- val archivePath = "${context.cacheDir}/$archiveName"
+ val archivePath = "${SimplexApp.context.cacheDir}/$archiveName"
val destFile = File(archivePath)
IOUtils.copy(inputStream, FileOutputStream(destFile))
archivePath
@@ -651,7 +646,6 @@ private fun setCiTTL(
chatItemTTL: MutableState,
progressIndicator: MutableState,
appFilesCountAndSize: MutableState>,
- context: Context
) {
Log.d(TAG, "DatabaseView setChatItemTTL ${chatItemTTL.value.seconds ?: -1}")
progressIndicator.value = true
@@ -660,11 +654,11 @@ private fun setCiTTL(
m.controller.setChatItemTTL(chatItemTTL.value)
// Update model on success
m.chatItemTTL.value = chatItemTTL.value
- afterSetCiTTL(m, progressIndicator, appFilesCountAndSize, context)
+ afterSetCiTTL(m, progressIndicator, appFilesCountAndSize)
} catch (e: Exception) {
// Rollback to model's value
chatItemTTL.value = m.chatItemTTL.value
- afterSetCiTTL(m, progressIndicator, appFilesCountAndSize, context)
+ afterSetCiTTL(m, progressIndicator, appFilesCountAndSize)
AlertManager.shared.showAlertMsg(generalGetString(R.string.error_changing_message_deletion), e.stackTraceToString())
}
}
@@ -673,11 +667,10 @@ private fun setCiTTL(
private fun afterSetCiTTL(
m: ChatModel,
progressIndicator: MutableState,
- appFilesCountAndSize: MutableState>,
- context: Context
+ appFilesCountAndSize: MutableState>
) {
progressIndicator.value = false
- appFilesCountAndSize.value = directoryFileCountAndSize(getAppFilesDirectory(context))
+ appFilesCountAndSize.value = directoryFileCountAndSize(getAppFilesDirectory())
withApi {
try {
val chats = m.controller.apiGetChats()
@@ -688,19 +681,19 @@ private fun afterSetCiTTL(
}
}
-private fun deleteFilesAndMediaAlert(context: Context, appFilesCountAndSize: MutableState>) {
+private fun deleteFilesAndMediaAlert(appFilesCountAndSize: MutableState>) {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.delete_files_and_media_question),
text = generalGetString(R.string.delete_files_and_media_desc),
confirmText = generalGetString(R.string.delete_verb),
- onConfirm = { deleteFiles(appFilesCountAndSize, context) },
+ onConfirm = { deleteFiles(appFilesCountAndSize) },
destructive = true
)
}
-private fun deleteFiles(appFilesCountAndSize: MutableState>, context: Context) {
- deleteAppFiles(context)
- appFilesCountAndSize.value = directoryFileCountAndSize(getAppFilesDirectory(context))
+private fun deleteFiles(appFilesCountAndSize: MutableState>) {
+ deleteAppFiles()
+ appFilesCountAndSize.value = directoryFileCountAndSize(getAppFilesDirectory())
}
private fun operationEnded(m: ChatModel, progressIndicator: MutableState, alert: () -> Unit) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CustomIcons.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/CustomIcons.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/CustomIcons.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/CustomIcons.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CustomTimePicker.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/CustomTimePicker.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/CustomTimePicker.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/CustomTimePicker.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DataClasses.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DataClasses.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/DataClasses.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DataClasses.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DatabaseUtils.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DatabaseUtils.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/DatabaseUtils.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DatabaseUtils.kt
index 68829da559..f200d4ab69 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DatabaseUtils.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DatabaseUtils.kt
@@ -2,8 +2,7 @@ package chat.simplex.app.views.helpers
import android.util.Log
import chat.simplex.app.*
-import chat.simplex.app.model.AppPreferences
-import chat.simplex.app.model.SharedPreference
+import chat.simplex.app.model.*
import chat.simplex.app.views.usersettings.Cryptor
import kotlinx.serialization.*
import java.io.File
@@ -13,7 +12,7 @@ object DatabaseUtils {
private val cryptor = Cryptor()
private val appPreferences: AppPreferences by lazy {
- AppPreferences(SimplexApp.context)
+ ChatController.appPrefs
}
private const val DATABASE_PASSWORD_ALIAS: String = "databasePassword"
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Enums.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Enums.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/Enums.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Enums.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt
similarity index 94%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt
index 463d0eacbd..daf323dc0d 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt
@@ -28,9 +28,6 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.unit.Density
-import androidx.compose.ui.util.fastAll
-import androidx.compose.ui.util.fastAny
-import androidx.compose.ui.util.fastForEach
import chat.simplex.app.TAG
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
@@ -98,8 +95,8 @@ suspend fun PointerInputScope.detectGesture(
private suspend fun AwaitPointerEventScope.consumeUntilUp() {
do {
val event = awaitPointerEvent()
- event.changes.fastForEach { it.consumeAllChanges() }
- } while (event.changes.fastAny { it.pressed })
+ event.changes.forEach { it.consumeAllChanges() }
+ } while (event.changes.any { it.pressed })
}
suspend fun AwaitPointerEventScope.awaitFirstDown(
@@ -115,7 +112,7 @@ internal suspend fun AwaitPointerEventScope.awaitFirstDownOnPass(
do {
event = awaitPointerEvent(pass)
} while (
- !event.changes.fastAll {
+ !event.changes.all {
if (requireUnconsumed) it.changedToDown() else it.changedToDownIgnoreConsumed()
}
)
@@ -125,18 +122,18 @@ internal suspend fun AwaitPointerEventScope.awaitFirstDownOnPass(
suspend fun AwaitPointerEventScope.waitForUpOrCancellation(): PointerInputChange? {
while (true) {
val event = awaitPointerEvent(PointerEventPass.Main)
- if (event.changes.fastAll { it.changedToUp() }) {
+ if (event.changes.all { it.changedToUp() }) {
return event.changes[0]
}
- if (event.changes.fastAny {
+ if (event.changes.any {
it.consumed.downChange || it.isOutOfBounds(size, extendedTouchPadding)
}
) {
return null
}
val consumeCheck = awaitPointerEvent(PointerEventPass.Final)
- if (consumeCheck.changes.fastAny { it.positionChangeConsumed() }) {
+ if (consumeCheck.changes.any { it.positionChangeConsumed() }) {
return null
}
}
@@ -254,7 +251,7 @@ suspend fun PointerInputScope.detectTransformGestures(
awaitFirstDown(requireUnconsumed = false)
do {
val event = awaitPointerEvent()
- val canceled = event.changes.fastAny { it.isConsumed }
+ val canceled = event.changes.any { it.isConsumed }
if (!canceled) {
val zoomChange = event.calculateZoom()
val rotationChange = event.calculateRotation()
@@ -288,14 +285,14 @@ suspend fun PointerInputScope.detectTransformGestures(
) {
onGesture(centroid, panChange, zoomChange, effectiveRotation)
}
- event.changes.fastForEach {
+ event.changes.forEach {
if (it.positionChanged() && zoom != 1f && allowIntercept()) {
it.consume()
}
}
}
}
- } while (!canceled && event.changes.fastAny { it.pressed })
+ } while (!canceled && event.changes.any { it.pressed })
}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
index 9ad3180ae5..0ea74b4b5f 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
@@ -111,7 +111,7 @@ fun base64ToBitmap(base64ImageString: String): Bitmap {
class CustomTakePicturePreview(var uri: Uri?, var tmpFile: File?): ActivityResultContract() {
@CallSuper
override fun createIntent(context: Context, input: Void?): Intent {
- tmpFile = File.createTempFile("image", ".bmp", File(getAppFilesDirectory(SimplexApp.context)))
+ tmpFile = File.createTempFile("image", ".bmp", File(getAppFilesDirectory()))
// Since the class should return Uri, the file should be deleted somewhere else. And in order to be sure, delegate this to system
tmpFile?.deleteOnExit()
uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", tmpFile!!)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
index 74c8cdedd0..ed406c32fd 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
@@ -40,10 +40,10 @@ fun authenticate(
promptTitle: String,
promptSubtitle: String,
selfDestruct: Boolean = false,
- activity: FragmentActivity,
usingLAMode: LAMode = SimplexApp.context.chatModel.controller.appPrefs.laMode.get(),
completed: (LAResult) -> Unit
) {
+ val activity = SimplexApp.context.mainActivity.get() ?: return completed(LAResult.Error(""))
when (usingLAMode) {
LAMode.SYSTEM -> when {
SDK_INT in 28..29 ->
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/MessagesFetcherWorker.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/MessagesFetcherWorker.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/MessagesFetcherWorker.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/MessagesFetcherWorker.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ModalView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/ModalView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Modifiers.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Modifiers.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/Modifiers.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Modifiers.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/RecAndPlay.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/RecAndPlay.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/RecAndPlay.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/RecAndPlay.kt
index 63da5f5c24..e902f3dc37 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/RecAndPlay.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/RecAndPlay.kt
@@ -51,7 +51,7 @@ class RecorderNative(): Recorder {
rec.setAudioEncodingBitRate(32000)
rec.setMaxDuration(MAX_VOICE_MILLIS_FOR_SENDING)
val tmpDir = SimplexApp.context.getDir("temp", Application.MODE_PRIVATE)
- val fileToSave = File.createTempFile(generateNewFileName(SimplexApp.context, "voice", "${extension}_"), ".tmp", tmpDir)
+ val fileToSave = File.createTempFile(generateNewFileName("voice", "${extension}_"), ".tmp", tmpDir)
fileToSave.deleteOnExit()
val path = fileToSave.absolutePath
filePath = path
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Section.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Section.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Share.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Share.kt
similarity index 78%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/Share.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Share.kt
index 015f05f0e6..0affca2e34 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Share.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Share.kt
@@ -18,17 +18,19 @@ import chat.simplex.app.model.CIFile
import java.io.BufferedOutputStream
import java.io.File
-fun shareText(cxt: Context, text: String) {
+fun shareText(text: String) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
- cxt.startActivity(shareIntent)
+ // This flag is needed when you start a new activity from non-Activity context
+ shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ SimplexApp.context.startActivity(shareIntent)
}
-fun shareFile(cxt: Context, text: String, filePath: String) {
+fun shareFile(text: String, filePath: String) {
val uri = FileProvider.getUriForFile(SimplexApp.context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
val ext = filePath.substringAfterLast(".")
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext) ?: return
@@ -41,32 +43,37 @@ fun shareFile(cxt: Context, text: String, filePath: String) {
type = mimeType
}
val shareIntent = Intent.createChooser(sendIntent, null)
- cxt.startActivity(shareIntent)
+ // This flag is needed when you start a new activity from non-Activity context
+ shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ SimplexApp.context.startActivity(shareIntent)
}
-fun copyText(cxt: Context, text: String) {
- val clipboard = ContextCompat.getSystemService(cxt, ClipboardManager::class.java)
+fun copyText(text: String) {
+ val clipboard = ContextCompat.getSystemService(SimplexApp.context, ClipboardManager::class.java)
clipboard?.setPrimaryClip(ClipData.newPlainText("text", text))
}
-fun sendEmail(context: Context, subject: String, body: CharSequence) {
+fun sendEmail(subject: String, body: CharSequence) {
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
+ // This flag is needed when you start a new activity from non-Activity context
+ emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
- context.startActivity(emailIntent)
+ SimplexApp.context.startActivity(emailIntent)
} catch (e: ActivityNotFoundException) {
Log.e(TAG, "No activity was found for handling email intent")
}
}
@Composable
-fun rememberSaveFileLauncher(cxt: Context, ciFile: CIFile?): ManagedActivityResultLauncher =
+fun rememberSaveFileLauncher(ciFile: CIFile?): ManagedActivityResultLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.CreateDocument(),
onResult = { destination ->
destination?.let {
- val filePath = getLoadedFilePath(cxt, ciFile)
+ val cxt = SimplexApp.context
+ val filePath = getLoadedFilePath(ciFile)
if (filePath != null) {
val contentResolver = cxt.contentResolver
contentResolver.openOutputStream(destination)?.let { stream ->
@@ -95,8 +102,9 @@ fun imageMimeType(fileName: String): String {
}
/** Before calling, make sure the user allows to write to external storage [Manifest.permission.WRITE_EXTERNAL_STORAGE] */
-fun saveImage(cxt: Context, ciFile: CIFile?) {
- val filePath = getLoadedFilePath(cxt, ciFile)
+fun saveImage(ciFile: CIFile?) {
+ val cxt = SimplexApp.context
+ val filePath = getLoadedFilePath(ciFile)
val fileName = ciFile?.fileName
if (filePath != null && fileName != null) {
val values = ContentValues()
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Util.kt
similarity index 87%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Util.kt
index 1f6d3e7f0b..dea06315a7 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/Util.kt
@@ -247,30 +247,30 @@ const val MAX_FILE_SIZE_SMP: Long = 8000000
const val MAX_FILE_SIZE_XFTP: Long = 1_073_741_824 // 1GB
-fun getFilesDirectory(context: Context): String {
- return context.filesDir.toString()
+fun getFilesDirectory(): String {
+ return SimplexApp.context.filesDir.toString()
}
-fun getTempFilesDirectory(context: Context): String {
- return "${getFilesDirectory(context)}/temp_files"
+fun getTempFilesDirectory(): String {
+ return "${getFilesDirectory()}/temp_files"
}
-fun getAppFilesDirectory(context: Context): String {
- return "${getFilesDirectory(context)}/app_files"
+fun getAppFilesDirectory(): String {
+ return "${getFilesDirectory()}/app_files"
}
-fun getAppFilePath(context: Context, fileName: String): String {
- return "${getAppFilesDirectory(context)}/$fileName"
+fun getAppFilePath(fileName: String): String {
+ return "${getAppFilesDirectory()}/$fileName"
}
fun getAppFileUri(fileName: String): Uri {
- return Uri.parse("${getAppFilesDirectory(SimplexApp.context)}/$fileName")
+ return Uri.parse("${getAppFilesDirectory()}/$fileName")
}
-fun getLoadedFilePath(context: Context, file: CIFile?): String? {
+fun getLoadedFilePath(file: CIFile?): String? {
return if (file?.filePath != null && file.loaded) {
- val filePath = getAppFilePath(context, file.filePath)
+ val filePath = getAppFilePath(file.filePath)
if (File(filePath).exists()) filePath else null
} else {
null
@@ -278,12 +278,12 @@ fun getLoadedFilePath(context: Context, file: CIFile?): String? {
}
// https://developer.android.com/training/data-storage/shared/documents-files#bitmap
-fun getLoadedImage(context: Context, file: CIFile?): Bitmap? {
- val filePath = getLoadedFilePath(context, file)
+fun getLoadedImage(file: CIFile?): Bitmap? {
+ val filePath = getLoadedFilePath(file)
return if (filePath != null) {
try {
- val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
- val parcelFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r")
+ val uri = FileProvider.getUriForFile(SimplexApp.context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
+ val parcelFileDescriptor = SimplexApp.context.contentResolver.openFileDescriptor(uri, "r")
val fileDescriptor = parcelFileDescriptor?.fileDescriptor
val image = decodeSampledBitmapFromFileDescriptor(fileDescriptor, 1000, 1000)
parcelFileDescriptor?.close()
@@ -329,24 +329,24 @@ private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int,
return inSampleSize
}
-fun getFileName(context: Context, uri: Uri): String? {
- return context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
+fun getFileName(uri: Uri): String? {
+ return SimplexApp.context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
cursor.getString(nameIndex)
}
}
-fun getAppFilePath(context: Context, uri: Uri): String? {
- return context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
+fun getAppFilePath(uri: Uri): String? {
+ return SimplexApp.context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
- getAppFilePath(context, cursor.getString(nameIndex))
+ getAppFilePath(cursor.getString(nameIndex))
}
}
-fun getFileSize(context: Context, uri: Uri): Long? {
- return context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
+fun getFileSize(uri: Uri): Long? {
+ return SimplexApp.context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
cursor.getLong(sizeIndex)
@@ -369,7 +369,7 @@ fun getBitmapFromUri(uri: Uri, withAlertOnException: Boolean = true): Bitmap? {
null
}
} else {
- BitmapFactory.decodeFile(getAppFilePath(SimplexApp.context, uri))
+ BitmapFactory.decodeFile(getAppFilePath(uri))
}
}
@@ -389,7 +389,7 @@ fun getDrawableFromUri(uri: Uri, withAlertOnException: Boolean = true): Drawable
null
}
} else {
- Drawable.createFromPath(getAppFilePath(SimplexApp.context, uri))
+ Drawable.createFromPath(getAppFilePath(uri))
}
}
@@ -409,17 +409,17 @@ fun getThemeFromUri(uri: Uri, withAlertOnException: Boolean = true): ThemeOverri
return null
}
-fun saveImage(context: Context, uri: Uri): String? {
+fun saveImage(uri: Uri): String? {
val bitmap = getBitmapFromUri(uri) ?: return null
- return saveImage(context, bitmap)
+ return saveImage(bitmap)
}
-fun saveImage(context: Context, image: Bitmap): String? {
+fun saveImage(image: Bitmap): String? {
return try {
val ext = if (image.hasAlpha()) "png" else "jpg"
val dataResized = resizeImageToDataSize(image, ext == "png", maxDataSize = MAX_IMAGE_SIZE)
- val fileToSave = generateNewFileName(context, "IMG", ext)
- val file = File(getAppFilePath(context, fileToSave))
+ val fileToSave = generateNewFileName("IMG", ext)
+ val file = File(getAppFilePath(fileToSave))
val output = FileOutputStream(file)
dataResized.writeTo(output)
output.flush()
@@ -431,9 +431,9 @@ fun saveImage(context: Context, image: Bitmap): String? {
}
}
-fun saveAnimImage(context: Context, uri: Uri): String? {
+fun saveAnimImage(uri: Uri): String? {
return try {
- val filename = getFileName(context, uri)?.lowercase()
+ val filename = getFileName(uri)?.lowercase()
var ext = when {
// remove everything but extension
filename?.contains(".") == true -> filename.replaceBeforeLast('.', "").replace(".", "")
@@ -441,10 +441,10 @@ fun saveAnimImage(context: Context, uri: Uri): String? {
}
// Just in case the image has a strange extension
if (ext.length < 3 || ext.length > 4) ext = "gif"
- val fileToSave = generateNewFileName(context, "IMG", ext)
- val file = File(getAppFilePath(context, fileToSave))
+ val fileToSave = generateNewFileName("IMG", ext)
+ val file = File(getAppFilePath(fileToSave))
val output = FileOutputStream(file)
- context.contentResolver.openInputStream(uri)!!.use { input ->
+ SimplexApp.context.contentResolver.openInputStream(uri)!!.use { input ->
output.use { output ->
input.copyTo(output)
}
@@ -460,7 +460,7 @@ fun saveTempImageUncompressed(image: Bitmap, asPng: Boolean): File? {
return try {
val ext = if (asPng) "png" else "jpg"
val tmpDir = SimplexApp.context.getDir("temp", Application.MODE_PRIVATE)
- return File(tmpDir.absolutePath + File.separator + generateNewFileName(SimplexApp.context, "IMG", ext)).apply {
+ return File(tmpDir.absolutePath + File.separator + generateNewFileName("IMG", ext)).apply {
outputStream().use { out ->
image.compress(if (asPng) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG, 85, out)
out.flush()
@@ -474,13 +474,13 @@ fun saveTempImageUncompressed(image: Bitmap, asPng: Boolean): File? {
}
}
-fun saveFileFromUri(context: Context, uri: Uri): String? {
+fun saveFileFromUri(uri: Uri): String? {
return try {
- val inputStream = context.contentResolver.openInputStream(uri)
- val fileToSave = getFileName(context, uri)
+ val inputStream = SimplexApp.context.contentResolver.openInputStream(uri)
+ val fileToSave = getFileName(uri)
if (inputStream != null && fileToSave != null) {
- val destFileName = uniqueCombine(context, fileToSave)
- val destFile = File(getAppFilePath(context, destFileName))
+ val destFileName = uniqueCombine(fileToSave)
+ val destFile = File(getAppFilePath(destFileName))
IOUtils.copy(inputStream, FileOutputStream(destFile))
destFileName
} else {
@@ -493,21 +493,21 @@ fun saveFileFromUri(context: Context, uri: Uri): String? {
}
}
-fun generateNewFileName(context: Context, prefix: String, ext: String): String {
+fun generateNewFileName(prefix: String, ext: String): String {
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US)
sdf.timeZone = TimeZone.getTimeZone("GMT")
val timestamp = sdf.format(Date())
- return uniqueCombine(context, "${prefix}_$timestamp.$ext")
+ return uniqueCombine("${prefix}_$timestamp.$ext")
}
-fun uniqueCombine(context: Context, fileName: String): String {
+fun uniqueCombine(fileName: String): String {
val orig = File(fileName)
val name = orig.nameWithoutExtension
val ext = orig.extension
fun tryCombine(n: Int): String {
val suffix = if (n == 0) "" else "_$n"
val f = "$name$suffix.$ext"
- return if (File(getAppFilePath(context, f)).exists()) tryCombine(n + 1) else f
+ return if (File(getAppFilePath(f)).exists()) tryCombine(n + 1) else f
}
return tryCombine(0)
}
@@ -530,8 +530,8 @@ fun formatBytes(bytes: Long): String {
}
}
-fun removeFile(context: Context, fileName: String): Boolean {
- val file = File(getAppFilePath(context, fileName))
+fun removeFile(fileName: String): Boolean {
+ val file = File(getAppFilePath(fileName))
val fileDeleted = file.delete()
if (!fileDeleted) {
Log.e(chat.simplex.app.TAG, "Util.kt removeFile error")
@@ -539,11 +539,11 @@ fun removeFile(context: Context, fileName: String): Boolean {
return fileDeleted
}
-fun deleteAppFiles(context: Context) {
- val dir = File(getAppFilesDirectory(context))
+fun deleteAppFiles() {
+ val dir = File(getAppFilesDirectory())
try {
dir.list()?.forEach {
- removeFile(context, it)
+ removeFile(it)
}
} catch (e: java.lang.Exception) {
Log.e(TAG, "Util deleteAppFiles error: ${e.stackTraceToString()}")
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
index dc0744a752..25f5d6aacf 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
@@ -24,7 +24,6 @@ class VideoPlayer private constructor(
private val defaultPreview: Bitmap,
defaultDuration: Long,
soundEnabled: Boolean,
- context: Context
) {
companion object {
private val players: MutableMap, VideoPlayer> = mutableMapOf()
@@ -36,9 +35,8 @@ class VideoPlayer private constructor(
defaultPreview: Bitmap,
defaultDuration: Long,
soundEnabled: Boolean,
- context: Context
): VideoPlayer =
- players.getOrPut(uri to gallery) { VideoPlayer(uri, gallery, defaultPreview, defaultDuration, soundEnabled, context) }
+ players.getOrPut(uri to gallery) { VideoPlayer(uri, gallery, defaultPreview, defaultDuration, soundEnabled) }
fun enableSound(enable: Boolean, fileName: String?, gallery: Boolean): Boolean =
player(fileName, gallery)?.enableSound(enable) == true
@@ -76,8 +74,8 @@ class VideoPlayer private constructor(
setPreviewAndDuration()
}
- val player = ExoPlayer.Builder(context,
- DefaultRenderersFactory(context))
+ val player = ExoPlayer.Builder(SimplexApp.context,
+ DefaultRenderersFactory(SimplexApp.context))
/*.setLoadControl(DefaultLoadControl.Builder()
.setPrioritizeTimeOverSizeThresholds(false) // Could probably save some megabytes in memory in case it will be needed
.createDefaultLoadControl())*/
@@ -108,7 +106,7 @@ class VideoPlayer private constructor(
}
private fun start(seek: Long? = null, onProgressUpdate: (position: Long?, state: TrackState) -> Unit): Boolean {
- val filepath = getAppFilePath(SimplexApp.context, uri)
+ val filepath = getAppFilePath(uri)
if (filepath == null || !File(filepath).exists()) {
Log.e(TAG, "No such file: $uri")
brokenVideo.value = true
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/LocalAuthView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/LocalAuthView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/localauth/LocalAuthView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/LocalAuthView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt
index 99eab4584d..cc5117bb9a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt
@@ -12,7 +12,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@@ -24,11 +23,10 @@ import chat.simplex.app.views.usersettings.SettingsActionItem
@Composable
fun AddContactView(connReqInvitation: String, connIncognito: Boolean) {
- val cxt = LocalContext.current
AddContactLayout(
connReq = connReqInvitation,
connIncognito = connIncognito,
- share = { shareText(cxt, connReqInvitation) },
+ share = { shareText(connReqInvitation) },
learnMore = {
ModalManager.shared.showModal {
Column(
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt
similarity index 96%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt
index fa7ec6f01f..50ad56a5eb 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt
@@ -11,7 +11,6 @@ import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@@ -45,7 +44,6 @@ fun ContactConnectionInfoView(
}
}
}
- val context = LocalContext.current
ContactConnectionInfoLayout(
connReq = connReqInvitation,
contactConnection,
@@ -53,7 +51,7 @@ fun ContactConnectionInfoView(
focusAlias,
deleteConnection = { deleteContactConnectionAlert(contactConnection, chatModel, close) },
onLocalAliasChanged = { setContactAlias(contactConnection, it, chatModel) },
- share = { if (connReqInvitation != null) shareText(context, connReqInvitation) },
+ share = { if (connReqInvitation != null) shareText(connReqInvitation) },
learnMore = {
ModalManager.shared.showModal {
Column(
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/QRCode.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/QRCode.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/QRCode.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/QRCode.kt
index 1f190b4216..62c1f4f72e 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/QRCode.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/QRCode.kt
@@ -27,7 +27,6 @@ fun QRCode(
tintColor: Color = Color(0xff062d56),
withLogo: Boolean = true
) {
- val context = LocalContext.current
val scope = rememberCoroutineScope()
BoxWithConstraints {
@@ -47,7 +46,7 @@ fun QRCode(
.let { if (withLogo) it.addLogo() else it }
val file = saveTempImageUncompressed(image, false)
if (file != null) {
- shareFile(context, "", file.absolutePath)
+ shareFile("", file.absolutePath)
}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/QRCodeScanner.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/QRCodeScanner.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/QRCodeScanner.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/QRCodeScanner.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/CreateSimpleXAddress.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/CreateSimpleXAddress.kt
similarity index 96%
rename from apps/android/app/src/main/java/chat/simplex/app/views/onboarding/CreateSimpleXAddress.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/CreateSimpleXAddress.kt
index 60dcb04838..f536039542 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/CreateSimpleXAddress.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/CreateSimpleXAddress.kt
@@ -9,7 +9,6 @@ import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@@ -24,16 +23,14 @@ import chat.simplex.app.views.newchat.QRCode
@Composable
fun CreateSimpleXAddress(m: ChatModel) {
- val context = LocalContext.current
var progressIndicator by remember { mutableStateOf(false) }
val userAddress = remember { m.userAddress }
CreateSimpleXAddressLayout(
userAddress.value,
- share = { address: String -> shareText(context, address) },
+ share = { address: String -> shareText(address) },
sendEmail = { address ->
sendEmail(
- context,
generalGetString(R.string.email_invite_subject),
generalGetString(R.string.email_invite_body).format(address.connReqContact)
)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/OnboardingView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/OnboardingView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/onboarding/OnboardingView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/OnboardingView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt
similarity index 80%
rename from apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt
index 8f08fe4cf4..ebb934ec75 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt
@@ -1,5 +1,7 @@
package chat.simplex.app.views.onboarding
+import android.Manifest
+import android.os.Build
import androidx.annotation.StringRes
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
@@ -15,11 +17,14 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
+import chat.simplex.app.SimplexApp
import chat.simplex.app.model.ChatModel
+import chat.simplex.app.model.NtfManager
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.NotificationsMode
import chat.simplex.app.views.usersettings.changeNotificationsMode
+import com.google.accompanist.permissions.rememberPermissionState
@Composable
fun SetNotificationsMode(m: ChatModel) {
@@ -47,8 +52,24 @@ fun SetNotificationsMode(m: ChatModel) {
}
Spacer(Modifier.fillMaxHeight().weight(1f))
}
- LaunchedEffect(Unit) {
- m.controller.ntfManager.createNtfChannelsMaybeShowAlert()
+ SetNotificationsModeAdditions()
+}
+
+@Composable
+fun SetNotificationsModeAdditions() {
+ if (Build.VERSION.SDK_INT >= 33) {
+ val notificationsPermissionState = rememberPermissionState(Manifest.permission.POST_NOTIFICATIONS)
+ LaunchedEffect(notificationsPermissionState.hasPermission) {
+ if (notificationsPermissionState.hasPermission) {
+ SimplexApp.context.chatModel.controller.ntfManager.createNtfChannelsMaybeShowAlert()
+ } else {
+ notificationsPermissionState.launchPermissionRequest()
+ }
+ }
+ } else {
+ LaunchedEffect(Unit) {
+ SimplexApp.context.chatModel.controller.ntfManager.createNtfChannelsMaybeShowAlert()
+ }
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt
index 8530394170..5233192e2d 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt
@@ -236,9 +236,8 @@ fun CustomizeThemeView(editColor: (ThemeColor, Color) -> Unit) {
}
SectionSpacer()
SectionView {
- val context = LocalContext.current
val theme = remember { mutableStateOf(null as String?) }
- val exportThemeLauncher = rememberSaveThemeLauncher(context, theme)
+ val exportThemeLauncher = rememberSaveThemeLauncher(theme)
SectionItemView({
val overrides = ThemeManager.currentThemeOverridesForExport(isInDarkTheme)
theme.value = yaml.encodeToString(overrides)
@@ -375,10 +374,11 @@ private fun DarkThemeSelector(state: State, onSelected: (String) -> Uni
//}
@Composable
-private fun rememberSaveThemeLauncher(cxt: Context, theme: MutableState): ManagedActivityResultLauncher =
+private fun rememberSaveThemeLauncher(theme: MutableState): ManagedActivityResultLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.CreateDocument(),
onResult = { destination ->
+ val cxt = SimplexApp.context
try {
destination?.let {
val theme = theme.value
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Cryptor.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Cryptor.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Cryptor.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Cryptor.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt
similarity index 99%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt
index e80283ecba..8bd917e7a5 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt
@@ -188,7 +188,7 @@ fun notificationPreviewModes(): List> {
fun changeNotificationsMode(mode: NotificationsMode, chatModel: ChatModel) {
chatModel.controller.appPrefs.notificationsMode.set(mode.name)
- if (mode.requiresIgnoringBattery && !chatModel.controller.isIgnoringBatteryOptimizations(chatModel.controller.appContext)) {
+ if (mode.requiresIgnoringBattery && !chatModel.controller.isIgnoringBatteryOptimizations()) {
chatModel.controller.appPrefs.backgroundServiceNoticeShown.set(false)
}
chatModel.notificationsMode.value = mode
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt
similarity index 97%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt
index c73bd6e7ce..b961ba58a2 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt
@@ -143,7 +143,7 @@ fun SimplexLockView(
} else {
generalGetString(R.string.chat_lock)
},
- generalGetString(R.string.change_lock_mode), activity = activity
+ generalGetString(R.string.change_lock_mode)
) { laResult ->
when (laResult) {
is LAResult.Error -> {
@@ -153,7 +153,7 @@ fun SimplexLockView(
LAResult.Success -> {
when (toLAMode) {
LAMode.SYSTEM -> {
- authenticate(generalGetString(R.string.auth_enable_simplex_lock), promptSubtitle = "", activity = activity, usingLAMode = toLAMode) { laResult ->
+ authenticate(generalGetString(R.string.auth_enable_simplex_lock), promptSubtitle = "", usingLAMode = toLAMode) { laResult ->
when (laResult) {
LAResult.Success -> {
currentLAMode.set(toLAMode)
@@ -189,7 +189,7 @@ fun SimplexLockView(
}
fun toggleSelfDestruct(selfDestruct: SharedPreference) {
- authenticate(generalGetString(R.string.la_current_app_passcode), generalGetString(R.string.change_self_destruct_mode), activity = activity) { laResult ->
+ authenticate(generalGetString(R.string.la_current_app_passcode), generalGetString(R.string.change_self_destruct_mode)) { laResult ->
when (laResult) {
is LAResult.Error -> laFailedAlert()
is LAResult.Failed -> { /* Can be called multiple times on every failure */ }
@@ -208,7 +208,7 @@ fun SimplexLockView(
}
fun changeLAPassword() {
- authenticate(generalGetString(R.string.la_current_app_passcode), generalGetString(R.string.la_change_app_passcode), activity = activity) { laResult ->
+ authenticate(generalGetString(R.string.la_current_app_passcode), generalGetString(R.string.la_change_app_passcode)) { laResult ->
when (laResult) {
LAResult.Success -> {
ModalManager.shared.showCustomModal { close ->
@@ -231,7 +231,7 @@ fun SimplexLockView(
}
fun changeSelfDestructPassword() {
- authenticate(generalGetString(R.string.la_current_app_passcode), generalGetString(R.string.change_self_destruct_passcode), activity = activity) { laResult ->
+ authenticate(generalGetString(R.string.la_current_app_passcode), generalGetString(R.string.change_self_destruct_passcode)) { laResult ->
when (laResult) {
LAResult.Success -> {
ModalManager.shared.showCustomModal { close ->
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ScanProtocolServer.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/ScanProtocolServer.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ScanProtocolServer.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/ScanProtocolServer.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
index 682c44a12a..2aae79fa8a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
@@ -6,7 +6,6 @@ import SectionItemView
import SectionItemViewWithIcon
import SectionView
import TextIconSpaced
-import android.content.*
import android.content.res.Configuration
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
@@ -45,7 +44,6 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
if (user != null) {
val requireAuth = remember { chatModel.controller.appPrefs.performLA.state }
- val context = LocalContext.current
SettingsLayout(
profile = user.profile,
stopped,
@@ -92,7 +90,7 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
LaunchedEffect(Unit) {
if (autoShow) {
autoShow = false
- runAuth(title, desc, context, onFinishAuth)
+ runAuth(title, desc, onFinishAuth)
}
}
Box(
@@ -103,7 +101,7 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
stringResource(R.string.auth_unlock),
icon = painterResource(R.drawable.ic_lock),
click = {
- runAuth(title, desc, context, onFinishAuth)
+ runAuth(title, desc, onFinishAuth)
}
)
}
@@ -481,11 +479,10 @@ fun PreferenceToggleWithIcon(
}
}
-private fun runAuth(title: String, desc: String, context: Context, onFinish: (success: Boolean) -> Unit) {
+private fun runAuth(title: String, desc: String, onFinish: (success: Boolean) -> Unit) {
authenticate(
title,
desc,
- activity = context as FragmentActivity,
completed = { laResult ->
onFinish(laResult == LAResult.Success || laResult is LAResult.Unavailable)
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt
similarity index 98%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt
index c9ce92f10b..8f4b467dab 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt
+++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt
@@ -16,7 +16,6 @@ import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@@ -36,7 +35,6 @@ fun UserAddressView(
shareViaProfile: Boolean = false,
close: () -> Unit
) {
- val context = LocalContext.current
val shareViaProfile = remember { mutableStateOf(shareViaProfile) }
var progressIndicator by remember { mutableStateOf(false) }
val onCloseHandler: MutableState<(close: () -> Unit) -> Unit> = remember { mutableStateOf({ _ -> }) }
@@ -94,10 +92,9 @@ fun UserAddressView(
}
}
},
- share = { userAddress: String -> shareText(context, userAddress) },
+ share = { userAddress: String -> shareText(userAddress) },
sendEmail = { userAddress ->
sendEmail(
- context,
generalGetString(R.string.email_invite_subject),
generalGetString(R.string.email_invite_body).format(userAddress.connReqContact)
)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt
similarity index 100%
rename from apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt
rename to apps/multiplatform/android/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt
diff --git a/apps/android/app/src/main/res/drawable-hdpi/decentralized.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/decentralized.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/decentralized.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/decentralized.png
diff --git a/apps/android/app/src/main/res/drawable-hdpi/decentralized_light.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/decentralized_light.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/decentralized_light.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/decentralized_light.png
diff --git a/apps/android/app/src/main/res/drawable-hdpi/icon.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/icon.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/icon.png
diff --git a/apps/android/app/src/main/res/drawable-hdpi/ntf_icon.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/ntf_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/ntf_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/ntf_icon.png
diff --git a/apps/android/app/src/main/res/drawable-hdpi/ntf_service_icon.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/ntf_service_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/ntf_service_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/ntf_service_icon.png
diff --git a/apps/android/app/src/main/res/drawable-hdpi/privacy.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/privacy.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/privacy.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/privacy.png
diff --git a/apps/android/app/src/main/res/drawable-hdpi/shield.png b/apps/multiplatform/android/src/main/res/drawable-hdpi/shield.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-hdpi/shield.png
rename to apps/multiplatform/android/src/main/res/drawable-hdpi/shield.png
diff --git a/apps/android/app/src/main/res/drawable-mdpi/decentralized.png b/apps/multiplatform/android/src/main/res/drawable-mdpi/decentralized.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-mdpi/decentralized.png
rename to apps/multiplatform/android/src/main/res/drawable-mdpi/decentralized.png
diff --git a/apps/android/app/src/main/res/drawable-mdpi/decentralized_light.png b/apps/multiplatform/android/src/main/res/drawable-mdpi/decentralized_light.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-mdpi/decentralized_light.png
rename to apps/multiplatform/android/src/main/res/drawable-mdpi/decentralized_light.png
diff --git a/apps/android/app/src/main/res/drawable-mdpi/ntf_icon.png b/apps/multiplatform/android/src/main/res/drawable-mdpi/ntf_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-mdpi/ntf_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-mdpi/ntf_icon.png
diff --git a/apps/android/app/src/main/res/drawable-mdpi/ntf_service_icon.png b/apps/multiplatform/android/src/main/res/drawable-mdpi/ntf_service_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-mdpi/ntf_service_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-mdpi/ntf_service_icon.png
diff --git a/apps/android/app/src/main/res/drawable-mdpi/privacy.png b/apps/multiplatform/android/src/main/res/drawable-mdpi/privacy.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-mdpi/privacy.png
rename to apps/multiplatform/android/src/main/res/drawable-mdpi/privacy.png
diff --git a/apps/android/app/src/main/res/drawable-mdpi/shield.png b/apps/multiplatform/android/src/main/res/drawable-mdpi/shield.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-mdpi/shield.png
rename to apps/multiplatform/android/src/main/res/drawable-mdpi/shield.png
diff --git a/apps/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/apps/multiplatform/android/src/main/res/drawable-v24/ic_launcher_foreground.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
rename to apps/multiplatform/android/src/main/res/drawable-v24/ic_launcher_foreground.xml
diff --git a/apps/android/app/src/main/res/drawable-xhdpi/decentralized.png b/apps/multiplatform/android/src/main/res/drawable-xhdpi/decentralized.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xhdpi/decentralized.png
rename to apps/multiplatform/android/src/main/res/drawable-xhdpi/decentralized.png
diff --git a/apps/android/app/src/main/res/drawable-xhdpi/decentralized_light.png b/apps/multiplatform/android/src/main/res/drawable-xhdpi/decentralized_light.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xhdpi/decentralized_light.png
rename to apps/multiplatform/android/src/main/res/drawable-xhdpi/decentralized_light.png
diff --git a/apps/android/app/src/main/res/drawable-xhdpi/ntf_icon.png b/apps/multiplatform/android/src/main/res/drawable-xhdpi/ntf_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xhdpi/ntf_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-xhdpi/ntf_icon.png
diff --git a/apps/android/app/src/main/res/drawable-xhdpi/ntf_service_icon.png b/apps/multiplatform/android/src/main/res/drawable-xhdpi/ntf_service_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xhdpi/ntf_service_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-xhdpi/ntf_service_icon.png
diff --git a/apps/android/app/src/main/res/drawable-xhdpi/privacy.png b/apps/multiplatform/android/src/main/res/drawable-xhdpi/privacy.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xhdpi/privacy.png
rename to apps/multiplatform/android/src/main/res/drawable-xhdpi/privacy.png
diff --git a/apps/android/app/src/main/res/drawable-xhdpi/shield.png b/apps/multiplatform/android/src/main/res/drawable-xhdpi/shield.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xhdpi/shield.png
rename to apps/multiplatform/android/src/main/res/drawable-xhdpi/shield.png
diff --git a/apps/android/app/src/main/res/drawable-xxhdpi/decentralized.png b/apps/multiplatform/android/src/main/res/drawable-xxhdpi/decentralized.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxhdpi/decentralized.png
rename to apps/multiplatform/android/src/main/res/drawable-xxhdpi/decentralized.png
diff --git a/apps/android/app/src/main/res/drawable-xxhdpi/decentralized_light.png b/apps/multiplatform/android/src/main/res/drawable-xxhdpi/decentralized_light.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxhdpi/decentralized_light.png
rename to apps/multiplatform/android/src/main/res/drawable-xxhdpi/decentralized_light.png
diff --git a/apps/android/app/src/main/res/drawable-xxhdpi/ntf_icon.png b/apps/multiplatform/android/src/main/res/drawable-xxhdpi/ntf_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxhdpi/ntf_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-xxhdpi/ntf_icon.png
diff --git a/apps/android/app/src/main/res/drawable-xxhdpi/ntf_service_icon.png b/apps/multiplatform/android/src/main/res/drawable-xxhdpi/ntf_service_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxhdpi/ntf_service_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-xxhdpi/ntf_service_icon.png
diff --git a/apps/android/app/src/main/res/drawable-xxhdpi/privacy.png b/apps/multiplatform/android/src/main/res/drawable-xxhdpi/privacy.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxhdpi/privacy.png
rename to apps/multiplatform/android/src/main/res/drawable-xxhdpi/privacy.png
diff --git a/apps/android/app/src/main/res/drawable-xxhdpi/shield.png b/apps/multiplatform/android/src/main/res/drawable-xxhdpi/shield.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxhdpi/shield.png
rename to apps/multiplatform/android/src/main/res/drawable-xxhdpi/shield.png
diff --git a/apps/android/app/src/main/res/drawable-xxxhdpi/decentralized.png b/apps/multiplatform/android/src/main/res/drawable-xxxhdpi/decentralized.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxxhdpi/decentralized.png
rename to apps/multiplatform/android/src/main/res/drawable-xxxhdpi/decentralized.png
diff --git a/apps/android/app/src/main/res/drawable-xxxhdpi/decentralized_light.png b/apps/multiplatform/android/src/main/res/drawable-xxxhdpi/decentralized_light.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxxhdpi/decentralized_light.png
rename to apps/multiplatform/android/src/main/res/drawable-xxxhdpi/decentralized_light.png
diff --git a/apps/android/app/src/main/res/drawable-xxxhdpi/ntf_icon.png b/apps/multiplatform/android/src/main/res/drawable-xxxhdpi/ntf_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxxhdpi/ntf_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-xxxhdpi/ntf_icon.png
diff --git a/apps/android/app/src/main/res/drawable-xxxhdpi/ntf_service_icon.png b/apps/multiplatform/android/src/main/res/drawable-xxxhdpi/ntf_service_icon.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxxhdpi/ntf_service_icon.png
rename to apps/multiplatform/android/src/main/res/drawable-xxxhdpi/ntf_service_icon.png
diff --git a/apps/android/app/src/main/res/drawable-xxxhdpi/privacy.png b/apps/multiplatform/android/src/main/res/drawable-xxxhdpi/privacy.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxxhdpi/privacy.png
rename to apps/multiplatform/android/src/main/res/drawable-xxxhdpi/privacy.png
diff --git a/apps/android/app/src/main/res/drawable-xxxhdpi/shield.png b/apps/multiplatform/android/src/main/res/drawable-xxxhdpi/shield.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable-xxxhdpi/shield.png
rename to apps/multiplatform/android/src/main/res/drawable-xxxhdpi/shield.png
diff --git a/apps/android/app/src/main/res/drawable/edit_text_cursor.xml b/apps/multiplatform/android/src/main/res/drawable/edit_text_cursor.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/edit_text_cursor.xml
rename to apps/multiplatform/android/src/main/res/drawable/edit_text_cursor.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_account_circle_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_account_circle_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_account_circle_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_account_circle_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_add.xml b/apps/multiplatform/android/src/main/res/drawable/ic_add.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_add.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_add.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_add_link.xml b/apps/multiplatform/android/src/main/res/drawable/ic_add_link.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_add_link.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_add_link.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_add_photo.xml b/apps/multiplatform/android/src/main/res/drawable/ic_add_photo.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_add_photo.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_add_photo.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_add_reaction.xml b/apps/multiplatform/android/src/main/res/drawable/ic_add_reaction.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_add_reaction.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_add_reaction.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_add_reaction_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_add_reaction_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_add_reaction_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_add_reaction_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_all_inclusive.xml b/apps/multiplatform/android/src/main/res/drawable/ic_all_inclusive.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_all_inclusive.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_all_inclusive.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_back_ios_new.xml b/apps/multiplatform/android/src/main/res/drawable/ic_arrow_back_ios_new.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_arrow_back_ios_new.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_arrow_back_ios_new.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_downward.xml b/apps/multiplatform/android/src/main/res/drawable/ic_arrow_downward.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_arrow_downward.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_arrow_downward.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_forward_ios.xml b/apps/multiplatform/android/src/main/res/drawable/ic_arrow_forward_ios.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_arrow_forward_ios.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_arrow_forward_ios.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_upward.xml b/apps/multiplatform/android/src/main/res/drawable/ic_arrow_upward.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_arrow_upward.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_arrow_upward.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_article.xml b/apps/multiplatform/android/src/main/res/drawable/ic_article.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_article.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_article.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_attach_file_filled_500.xml b/apps/multiplatform/android/src/main/res/drawable/ic_attach_file_filled_500.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_attach_file_filled_500.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_attach_file_filled_500.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_backspace.xml b/apps/multiplatform/android/src/main/res/drawable/ic_backspace.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_backspace.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_backspace.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_backup.xml b/apps/multiplatform/android/src/main/res/drawable/ic_backup.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_backup.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_backup.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_battery_2_bar.xml b/apps/multiplatform/android/src/main/res/drawable/ic_battery_2_bar.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_battery_2_bar.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_battery_2_bar.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_battery_3_bar.xml b/apps/multiplatform/android/src/main/res/drawable/ic_battery_3_bar.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_battery_3_bar.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_battery_3_bar.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_bolt.xml b/apps/multiplatform/android/src/main/res/drawable/ic_bolt.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_bolt.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_bolt.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_bolt_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_bolt_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_bolt_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_bolt_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_cable.xml b/apps/multiplatform/android/src/main/res/drawable/ic_cable.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_cable.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_cable.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_call.xml b/apps/multiplatform/android/src/main/res/drawable/ic_call.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_call.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_call.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_call_500.xml b/apps/multiplatform/android/src/main/res/drawable/ic_call_500.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_call_500.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_call_500.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_call_end.xml b/apps/multiplatform/android/src/main/res/drawable/ic_call_end.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_call_end.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_call_end.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_call_end_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_call_end_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_call_end_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_call_end_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_call_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_call_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_call_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_call_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_camera_enhance.xml b/apps/multiplatform/android/src/main/res/drawable/ic_camera_enhance.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_camera_enhance.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_camera_enhance.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_cancel_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_cancel_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_cancel_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_cancel_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_chat.xml b/apps/multiplatform/android/src/main/res/drawable/ic_chat.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_chat.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_chat.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_check.xml b/apps/multiplatform/android/src/main/res/drawable/ic_check.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_check.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_check.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_check_circle_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_check_circle_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_check_circle_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_check_circle_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_check_fill.xml b/apps/multiplatform/android/src/main/res/drawable/ic_check_fill.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_check_fill.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_check_fill.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_check_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_check_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_check_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_check_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_chevron_right.xml b/apps/multiplatform/android/src/main/res/drawable/ic_chevron_right.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_chevron_right.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_chevron_right.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_circle.xml b/apps/multiplatform/android/src/main/res/drawable/ic_circle.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_circle.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_circle.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_circle_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_circle_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_circle_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_circle_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_close.xml b/apps/multiplatform/android/src/main/res/drawable/ic_close.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_close.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_close.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_code.xml b/apps/multiplatform/android/src/main/res/drawable/ic_code.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_code.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_code.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_content_copy.xml b/apps/multiplatform/android/src/main/res/drawable/ic_content_copy.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_content_copy.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_content_copy.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_content_paste.xml b/apps/multiplatform/android/src/main/res/drawable/ic_content_paste.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_content_paste.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_content_paste.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_database.xml b/apps/multiplatform/android/src/main/res/drawable/ic_database.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_database.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_database.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_delete.xml b/apps/multiplatform/android/src/main/res/drawable/ic_delete.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_delete.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_delete.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_delete_forever.xml b/apps/multiplatform/android/src/main/res/drawable/ic_delete_forever.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_delete_forever.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_delete_forever.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_delete_forever_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_delete_forever_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_delete_forever_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_delete_forever_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_dns.xml b/apps/multiplatform/android/src/main/res/drawable/ic_dns.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_dns.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_dns.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_do_not_disturb_on.xml b/apps/multiplatform/android/src/main/res/drawable/ic_do_not_disturb_on.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_do_not_disturb_on.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_do_not_disturb_on.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_done_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_done_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_done_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_done_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_download.xml b/apps/multiplatform/android/src/main/res/drawable/ic_download.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_download.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_download.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_draft.xml b/apps/multiplatform/android/src/main/res/drawable/ic_draft.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_draft.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_draft.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_draft_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_draft_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_draft_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_draft_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_drive_folder_upload.xml b/apps/multiplatform/android/src/main/res/drawable/ic_drive_folder_upload.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_drive_folder_upload.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_drive_folder_upload.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_edit.xml b/apps/multiplatform/android/src/main/res/drawable/ic_edit.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_edit.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_edit.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_edit_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_edit_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_edit_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_edit_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_edit_note.xml b/apps/multiplatform/android/src/main/res/drawable/ic_edit_note.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_edit_note.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_edit_note.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_electrical_services.xml b/apps/multiplatform/android/src/main/res/drawable/ic_electrical_services.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_electrical_services.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_electrical_services.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_error.xml b/apps/multiplatform/android/src/main/res/drawable/ic_error.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_error.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_error.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_error_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_error_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_error_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_error_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_expand_less.xml b/apps/multiplatform/android/src/main/res/drawable/ic_expand_less.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_expand_less.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_expand_less.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_expand_more.xml b/apps/multiplatform/android/src/main/res/drawable/ic_expand_more.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_expand_more.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_expand_more.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_filter_list.xml b/apps/multiplatform/android/src/main/res/drawable/ic_filter_list.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_filter_list.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_filter_list.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_flag.xml b/apps/multiplatform/android/src/main/res/drawable/ic_flag.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_flag.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_flag.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_flip_camera_android_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_flip_camera_android_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_flip_camera_android_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_flip_camera_android_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_github.xml b/apps/multiplatform/android/src/main/res/drawable/ic_github.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_github.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_github.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_group.xml b/apps/multiplatform/android/src/main/res/drawable/ic_group.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_group.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_group.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_help.xml b/apps/multiplatform/android/src/main/res/drawable/ic_help.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_help.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_help.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_image.xml b/apps/multiplatform/android/src/main/res/drawable/ic_image.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_image.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_image.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_info.xml b/apps/multiplatform/android/src/main/res/drawable/ic_info.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_info.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_info.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_inventory_2.xml b/apps/multiplatform/android/src/main/res/drawable/ic_inventory_2.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_inventory_2.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_inventory_2.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_ios_share.xml b/apps/multiplatform/android/src/main/res/drawable/ic_ios_share.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_ios_share.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_ios_share.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard.xml b/apps/multiplatform/android/src/main/res/drawable/ic_keyboard.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_keyboard.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_keyboard.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml b/apps/multiplatform/android/src/main/res/drawable/ic_keyboard_arrow_down.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_keyboard_arrow_down.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard_voice.xml b/apps/multiplatform/android/src/main/res/drawable/ic_keyboard_voice.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_keyboard_voice.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_keyboard_voice.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard_voice_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_keyboard_voice_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_keyboard_voice_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_keyboard_voice_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_launcher_background.xml b/apps/multiplatform/android/src/main/res/drawable/ic_launcher_background.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_launcher_background.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_launcher_background.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_light_mode.xml b/apps/multiplatform/android/src/main/res/drawable/ic_light_mode.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_light_mode.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_light_mode.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_link.xml b/apps/multiplatform/android/src/main/res/drawable/ic_link.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_link.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_link.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_lock.xml b/apps/multiplatform/android/src/main/res/drawable/ic_lock.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_lock.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_lock.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_lock_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_lock_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_lock_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_lock_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_lock_open.xml b/apps/multiplatform/android/src/main/res/drawable/ic_lock_open.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_lock_open.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_lock_open.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_login.xml b/apps/multiplatform/android/src/main/res/drawable/ic_login.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_login.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_login.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_logout.xml b/apps/multiplatform/android/src/main/res/drawable/ic_logout.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_logout.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_logout.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_mail.xml b/apps/multiplatform/android/src/main/res/drawable/ic_mail.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_mail.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_mail.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_manage_accounts.xml b/apps/multiplatform/android/src/main/res/drawable/ic_manage_accounts.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_manage_accounts.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_manage_accounts.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_maps_ugc.xml b/apps/multiplatform/android/src/main/res/drawable/ic_maps_ugc.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_maps_ugc.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_maps_ugc.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_mark_chat_unread.xml b/apps/multiplatform/android/src/main/res/drawable/ic_mark_chat_unread.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_mark_chat_unread.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_mark_chat_unread.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_menu.xml b/apps/multiplatform/android/src/main/res/drawable/ic_menu.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_menu.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_menu.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_mic.xml b/apps/multiplatform/android/src/main/res/drawable/ic_mic.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_mic.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_mic.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_mic_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_mic_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_mic_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_mic_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_mic_off.xml b/apps/multiplatform/android/src/main/res/drawable/ic_mic_off.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_mic_off.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_mic_off.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_more_horiz.xml b/apps/multiplatform/android/src/main/res/drawable/ic_more_horiz.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_more_horiz.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_more_horiz.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_note_add.xml b/apps/multiplatform/android/src/main/res/drawable/ic_note_add.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_note_add.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_note_add.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_notifications.xml b/apps/multiplatform/android/src/main/res/drawable/ic_notifications.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_notifications.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_notifications.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_notifications_off.xml b/apps/multiplatform/android/src/main/res/drawable/ic_notifications_off.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_notifications_off.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_notifications_off.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_notifications_off_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_notifications_off_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_notifications_off_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_notifications_off_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_open_in_new.xml b/apps/multiplatform/android/src/main/res/drawable/ic_open_in_new.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_open_in_new.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_open_in_new.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_outline_terminal.xml b/apps/multiplatform/android/src/main/res/drawable/ic_outline_terminal.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_outline_terminal.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_outline_terminal.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_pause_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_pause_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_pause_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_pause_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_pending.xml b/apps/multiplatform/android/src/main/res/drawable/ic_pending.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_pending.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_pending.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_pending_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_pending_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_pending_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_pending_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_person.xml b/apps/multiplatform/android/src/main/res/drawable/ic_person.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_person.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_person.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_person_add.xml b/apps/multiplatform/android/src/main/res/drawable/ic_person_add.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_person_add.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_person_add.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_person_add_500.xml b/apps/multiplatform/android/src/main/res/drawable/ic_person_add_500.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_person_add_500.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_person_add_500.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_phone_in_talk_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_phone_in_talk_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_phone_in_talk_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_phone_in_talk_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_photo_camera.xml b/apps/multiplatform/android/src/main/res/drawable/ic_photo_camera.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_photo_camera.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_photo_camera.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_play_arrow_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_play_arrow_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_play_arrow_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_play_arrow_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_power_settings_new.xml b/apps/multiplatform/android/src/main/res/drawable/ic_power_settings_new.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_power_settings_new.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_power_settings_new.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_priority_high.xml b/apps/multiplatform/android/src/main/res/drawable/ic_priority_high.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_priority_high.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_priority_high.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_qr_code.xml b/apps/multiplatform/android/src/main/res/drawable/ic_qr_code.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_qr_code.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_qr_code.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_repeat_one.xml b/apps/multiplatform/android/src/main/res/drawable/ic_repeat_one.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_repeat_one.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_repeat_one.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_replay.xml b/apps/multiplatform/android/src/main/res/drawable/ic_replay.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_replay.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_replay.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_reply.xml b/apps/multiplatform/android/src/main/res/drawable/ic_reply.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_reply.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_reply.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_report_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_report_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_report_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_report_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_restart_alt.xml b/apps/multiplatform/android/src/main/res/drawable/ic_restart_alt.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_restart_alt.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_restart_alt.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_ring_volume.xml b/apps/multiplatform/android/src/main/res/drawable/ic_ring_volume.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_ring_volume.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_ring_volume.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_safety_divider.xml b/apps/multiplatform/android/src/main/res/drawable/ic_safety_divider.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_safety_divider.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_safety_divider.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_search.xml b/apps/multiplatform/android/src/main/res/drawable/ic_search.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_search.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_search.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_search_500.xml b/apps/multiplatform/android/src/main/res/drawable/ic_search_500.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_search_500.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_search_500.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_security.xml b/apps/multiplatform/android/src/main/res/drawable/ic_security.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_security.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_security.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_settings.xml b/apps/multiplatform/android/src/main/res/drawable/ic_settings.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_settings.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_settings.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_settings_backup_restore.xml b/apps/multiplatform/android/src/main/res/drawable/ic_settings_backup_restore.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_settings_backup_restore.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_settings_backup_restore.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_settings_ethernet.xml b/apps/multiplatform/android/src/main/res/drawable/ic_settings_ethernet.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_settings_ethernet.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_settings_ethernet.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_settings_phone.xml b/apps/multiplatform/android/src/main/res/drawable/ic_settings_phone.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_settings_phone.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_settings_phone.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_share.xml b/apps/multiplatform/android/src/main/res/drawable/ic_share.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_share.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_share.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_share_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_share_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_share_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_share_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_shield.xml b/apps/multiplatform/android/src/main/res/drawable/ic_shield.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_shield.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_shield.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_smart_display.xml b/apps/multiplatform/android/src/main/res/drawable/ic_smart_display.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_smart_display.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_smart_display.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_star.xml b/apps/multiplatform/android/src/main/res/drawable/ic_star.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_star.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_star.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_star_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_star_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_star_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_star_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_star_off.xml b/apps/multiplatform/android/src/main/res/drawable/ic_star_off.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_star_off.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_star_off.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_stop_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_stop_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_stop_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_stop_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_supervised_user_circle_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_supervised_user_circle_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_supervised_user_circle_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_supervised_user_circle_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle.xml b/apps/multiplatform/android/src/main/res/drawable/ic_swap_horizontal_circle.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_swap_horizontal_circle.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_tag.xml b/apps/multiplatform/android/src/main/res/drawable/ic_tag.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_tag.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_tag.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_task.xml b/apps/multiplatform/android/src/main/res/drawable/ic_task.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_task.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_task.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_theater_comedy.xml b/apps/multiplatform/android/src/main/res/drawable/ic_theater_comedy.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_theater_comedy.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_theater_comedy.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_theater_comedy_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_theater_comedy_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_theater_comedy_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_theater_comedy_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_timer.xml b/apps/multiplatform/android/src/main/res/drawable/ic_timer.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_timer.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_timer.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_timer_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_timer_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_timer_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_timer_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_toggle_on.xml b/apps/multiplatform/android/src/main/res/drawable/ic_toggle_on.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_toggle_on.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_toggle_on.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_translate.xml b/apps/multiplatform/android/src/main/res/drawable/ic_translate.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_translate.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_translate.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_travel_explore.xml b/apps/multiplatform/android/src/main/res/drawable/ic_travel_explore.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_travel_explore.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_travel_explore.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_upload_file.xml b/apps/multiplatform/android/src/main/res/drawable/ic_upload_file.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_upload_file.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_upload_file.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_verified_user.xml b/apps/multiplatform/android/src/main/res/drawable/ic_verified_user.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_verified_user.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_verified_user.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_videocam.xml b/apps/multiplatform/android/src/main/res/drawable/ic_videocam.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_videocam.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_videocam.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_videocam_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_videocam_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_videocam_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_videocam_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_videocam_off.xml b/apps/multiplatform/android/src/main/res/drawable/ic_videocam_off.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_videocam_off.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_videocam_off.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility.xml b/apps/multiplatform/android/src/main/res/drawable/ic_visibility.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_visibility.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_visibility.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_visibility_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_visibility_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_visibility_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility_off.xml b/apps/multiplatform/android/src/main/res/drawable/ic_visibility_off.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_visibility_off.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_visibility_off.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility_off_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_visibility_off_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_visibility_off_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_visibility_off_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_volume_down.xml b/apps/multiplatform/android/src/main/res/drawable/ic_volume_down.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_volume_down.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_volume_down.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_volume_up.xml b/apps/multiplatform/android/src/main/res/drawable/ic_volume_up.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_volume_up.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_volume_up.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_vpn_key_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_vpn_key_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_vpn_key_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_vpn_key_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_vpn_key_off_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_vpn_key_off_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_vpn_key_off_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_vpn_key_off_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_warning_filled.xml b/apps/multiplatform/android/src/main/res/drawable/ic_warning_filled.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_warning_filled.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_warning_filled.xml
diff --git a/apps/android/app/src/main/res/drawable/ic_wifi_tethering.xml b/apps/multiplatform/android/src/main/res/drawable/ic_wifi_tethering.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/ic_wifi_tethering.xml
rename to apps/multiplatform/android/src/main/res/drawable/ic_wifi_tethering.xml
diff --git a/apps/android/app/src/main/res/drawable/logo.png b/apps/multiplatform/android/src/main/res/drawable/logo.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable/logo.png
rename to apps/multiplatform/android/src/main/res/drawable/logo.png
diff --git a/apps/android/app/src/main/res/drawable/logo_light.png b/apps/multiplatform/android/src/main/res/drawable/logo_light.png
similarity index 100%
rename from apps/android/app/src/main/res/drawable/logo_light.png
rename to apps/multiplatform/android/src/main/res/drawable/logo_light.png
diff --git a/apps/android/app/src/main/res/drawable/send_msg_view_background.xml b/apps/multiplatform/android/src/main/res/drawable/send_msg_view_background.xml
similarity index 100%
rename from apps/android/app/src/main/res/drawable/send_msg_view_background.xml
rename to apps/multiplatform/android/src/main/res/drawable/send_msg_view_background.xml
diff --git a/apps/android/app/src/main/res/font/inter_bold.ttf b/apps/multiplatform/android/src/main/res/font/inter_bold.ttf
similarity index 100%
rename from apps/android/app/src/main/res/font/inter_bold.ttf
rename to apps/multiplatform/android/src/main/res/font/inter_bold.ttf
diff --git a/apps/android/app/src/main/res/font/inter_italic.ttf b/apps/multiplatform/android/src/main/res/font/inter_italic.ttf
similarity index 100%
rename from apps/android/app/src/main/res/font/inter_italic.ttf
rename to apps/multiplatform/android/src/main/res/font/inter_italic.ttf
diff --git a/apps/android/app/src/main/res/font/inter_light.ttf b/apps/multiplatform/android/src/main/res/font/inter_light.ttf
similarity index 100%
rename from apps/android/app/src/main/res/font/inter_light.ttf
rename to apps/multiplatform/android/src/main/res/font/inter_light.ttf
diff --git a/apps/android/app/src/main/res/font/inter_medium.ttf b/apps/multiplatform/android/src/main/res/font/inter_medium.ttf
similarity index 100%
rename from apps/android/app/src/main/res/font/inter_medium.ttf
rename to apps/multiplatform/android/src/main/res/font/inter_medium.ttf
diff --git a/apps/android/app/src/main/res/font/inter_regular.ttf b/apps/multiplatform/android/src/main/res/font/inter_regular.ttf
similarity index 100%
rename from apps/android/app/src/main/res/font/inter_regular.ttf
rename to apps/multiplatform/android/src/main/res/font/inter_regular.ttf
diff --git a/apps/android/app/src/main/res/font/inter_semi_bold.ttf b/apps/multiplatform/android/src/main/res/font/inter_semi_bold.ttf
similarity index 100%
rename from apps/android/app/src/main/res/font/inter_semi_bold.ttf
rename to apps/multiplatform/android/src/main/res/font/inter_semi_bold.ttf
diff --git a/apps/android/app/src/main/res/mipmap-anydpi-v26/icon.xml b/apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon.xml
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-anydpi-v26/icon.xml
rename to apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon.xml
diff --git a/apps/android/app/src/main/res/mipmap-anydpi-v26/icon_dark_blue.xml b/apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_dark_blue.xml
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-anydpi-v26/icon_dark_blue.xml
rename to apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_dark_blue.xml
diff --git a/apps/android/app/src/main/res/mipmap-anydpi-v26/icon_dark_blue_round.xml b/apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_dark_blue_round.xml
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-anydpi-v26/icon_dark_blue_round.xml
rename to apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_dark_blue_round.xml
diff --git a/apps/android/app/src/main/res/mipmap-anydpi-v26/icon_round.xml b/apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_round.xml
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-anydpi-v26/icon_round.xml
rename to apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_round.xml
diff --git a/apps/android/app/src/main/res/mipmap-anydpi-v26/icon_round_dark_blue.xml b/apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_round_dark_blue.xml
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-anydpi-v26/icon_round_dark_blue.xml
rename to apps/multiplatform/android/src/main/res/mipmap-anydpi-v26/icon_round_dark_blue.xml
diff --git a/apps/android/app/src/main/res/mipmap-hdpi/icon.png b/apps/multiplatform/android/src/main/res/mipmap-hdpi/icon.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-hdpi/icon.png
rename to apps/multiplatform/android/src/main/res/mipmap-hdpi/icon.png
diff --git a/apps/android/app/src/main/res/mipmap-hdpi/icon_dark_blue.png b/apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_dark_blue.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-hdpi/icon_dark_blue.png
rename to apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_dark_blue.png
diff --git a/apps/android/app/src/main/res/mipmap-hdpi/icon_dark_blue_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_dark_blue_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-hdpi/icon_dark_blue_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_dark_blue_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-hdpi/icon_dark_blue_round.png b/apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_dark_blue_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-hdpi/icon_dark_blue_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_dark_blue_round.png
diff --git a/apps/android/app/src/main/res/mipmap-hdpi/icon_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-hdpi/icon_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-hdpi/icon_round.png b/apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-hdpi/icon_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-hdpi/icon_round.png
diff --git a/apps/android/app/src/main/res/mipmap-mdpi/icon.png b/apps/multiplatform/android/src/main/res/mipmap-mdpi/icon.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-mdpi/icon.png
rename to apps/multiplatform/android/src/main/res/mipmap-mdpi/icon.png
diff --git a/apps/android/app/src/main/res/mipmap-mdpi/icon_dark_blue.png b/apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_dark_blue.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-mdpi/icon_dark_blue.png
rename to apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_dark_blue.png
diff --git a/apps/android/app/src/main/res/mipmap-mdpi/icon_dark_blue_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_dark_blue_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-mdpi/icon_dark_blue_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_dark_blue_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-mdpi/icon_dark_blue_round.png b/apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_dark_blue_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-mdpi/icon_dark_blue_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_dark_blue_round.png
diff --git a/apps/android/app/src/main/res/mipmap-mdpi/icon_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-mdpi/icon_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-mdpi/icon_round.png b/apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-mdpi/icon_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-mdpi/icon_round.png
diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/icon.png b/apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xhdpi/icon.png
rename to apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon.png
diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/icon_dark_blue.png b/apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_dark_blue.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xhdpi/icon_dark_blue.png
rename to apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_dark_blue.png
diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/icon_dark_blue_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_dark_blue_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xhdpi/icon_dark_blue_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_dark_blue_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/icon_dark_blue_round.png b/apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_dark_blue_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xhdpi/icon_dark_blue_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_dark_blue_round.png
diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/icon_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xhdpi/icon_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/icon_round.png b/apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xhdpi/icon_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-xhdpi/icon_round.png
diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/icon.png b/apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxhdpi/icon.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon.png
diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/icon_dark_blue.png b/apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_dark_blue.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxhdpi/icon_dark_blue.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_dark_blue.png
diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/icon_dark_blue_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_dark_blue_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxhdpi/icon_dark_blue_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_dark_blue_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/icon_dark_blue_round.png b/apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_dark_blue_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxhdpi/icon_dark_blue_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_dark_blue_round.png
diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/icon_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxhdpi/icon_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/icon_round.png b/apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxhdpi/icon_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxhdpi/icon_round.png
diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/icon.png b/apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxxhdpi/icon.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon.png
diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/icon_dark_blue.png b/apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_dark_blue.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxxhdpi/icon_dark_blue.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_dark_blue.png
diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/icon_dark_blue_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_dark_blue_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxxhdpi/icon_dark_blue_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_dark_blue_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/icon_dark_blue_round.png b/apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_dark_blue_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxxhdpi/icon_dark_blue_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_dark_blue_round.png
diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/icon_foreground.png b/apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_foreground.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxxhdpi/icon_foreground.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_foreground.png
diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/icon_round.png b/apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_round.png
similarity index 100%
rename from apps/android/app/src/main/res/mipmap-xxxhdpi/icon_round.png
rename to apps/multiplatform/android/src/main/res/mipmap-xxxhdpi/icon_round.png
diff --git a/apps/android/app/src/main/res/raw/ring_once.mp3 b/apps/multiplatform/android/src/main/res/raw/ring_once.mp3
similarity index 100%
rename from apps/android/app/src/main/res/raw/ring_once.mp3
rename to apps/multiplatform/android/src/main/res/raw/ring_once.mp3
diff --git a/apps/android/app/src/main/res/values-ar/strings.xml b/apps/multiplatform/android/src/main/res/values-ar/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-ar/strings.xml
rename to apps/multiplatform/android/src/main/res/values-ar/strings.xml
diff --git a/apps/android/app/src/main/res/values-cs/strings.xml b/apps/multiplatform/android/src/main/res/values-cs/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-cs/strings.xml
rename to apps/multiplatform/android/src/main/res/values-cs/strings.xml
diff --git a/apps/android/app/src/main/res/values-de/strings.xml b/apps/multiplatform/android/src/main/res/values-de/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-de/strings.xml
rename to apps/multiplatform/android/src/main/res/values-de/strings.xml
diff --git a/apps/android/app/src/main/res/values-el/strings.xml b/apps/multiplatform/android/src/main/res/values-el/strings.xml
similarity index 98%
rename from apps/android/app/src/main/res/values-el/strings.xml
rename to apps/multiplatform/android/src/main/res/values-el/strings.xml
index 6f31189d09..6926e0c891 100644
--- a/apps/android/app/src/main/res/values-el/strings.xml
+++ b/apps/multiplatform/android/src/main/res/values-el/strings.xml
@@ -42,7 +42,6 @@
Αποδοχή αιτήματος σύνδεσης;
αποδεκτή κλήση
Πρόσβαση στους διακομιστές μέσω SOCKS proxy στην πόρτα 9050; Ο διακομιστής μεσολάβησης (proxy server) πρέπει να είναι ενεργός πριν ενεργοποιηθεί αυτή η ρύθμιση.
- Αποδοχή αιτημάτων
Προσθήκη διακομιστή…
Προχωρημένες ρυθμίσεις δικτύου
Προσθήκη διακομιστών μέσω σάρωσης QR κωδικών.
diff --git a/apps/android/app/src/main/res/values-es/strings.xml b/apps/multiplatform/android/src/main/res/values-es/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-es/strings.xml
rename to apps/multiplatform/android/src/main/res/values-es/strings.xml
diff --git a/apps/android/app/src/main/res/values-fi/strings.xml b/apps/multiplatform/android/src/main/res/values-fi/strings.xml
similarity index 99%
rename from apps/android/app/src/main/res/values-fi/strings.xml
rename to apps/multiplatform/android/src/main/res/values-fi/strings.xml
index c4c7dc1aab..83c37137a0 100644
--- a/apps/android/app/src/main/res/values-fi/strings.xml
+++ b/apps/multiplatform/android/src/main/res/values-fi/strings.xml
@@ -54,7 +54,6 @@
Tietokannan salauksen tunnuslause päivitetään ja tallennetaan Keystoreen.
Poista keskusteluprofiili käyttäjälle
poistettu
- KEHITÄ
LAITE
%dh
Yhteysvirhe
diff --git a/apps/android/app/src/main/res/values-fr/strings.xml b/apps/multiplatform/android/src/main/res/values-fr/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-fr/strings.xml
rename to apps/multiplatform/android/src/main/res/values-fr/strings.xml
diff --git a/apps/android/app/src/main/res/values-hi/strings.xml b/apps/multiplatform/android/src/main/res/values-hi/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-hi/strings.xml
rename to apps/multiplatform/android/src/main/res/values-hi/strings.xml
diff --git a/apps/android/app/src/main/res/values-hr/strings.xml b/apps/multiplatform/android/src/main/res/values-hr/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-hr/strings.xml
rename to apps/multiplatform/android/src/main/res/values-hr/strings.xml
diff --git a/apps/android/app/src/main/res/values-it/strings.xml b/apps/multiplatform/android/src/main/res/values-it/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-it/strings.xml
rename to apps/multiplatform/android/src/main/res/values-it/strings.xml
diff --git a/apps/android/app/src/main/res/values-iw/strings.xml b/apps/multiplatform/android/src/main/res/values-iw/strings.xml
similarity index 99%
rename from apps/android/app/src/main/res/values-iw/strings.xml
rename to apps/multiplatform/android/src/main/res/values-iw/strings.xml
index cdda3579ba..ca8df0dfab 100644
--- a/apps/android/app/src/main/res/values-iw/strings.xml
+++ b/apps/multiplatform/android/src/main/res/values-iw/strings.xml
@@ -4,7 +4,6 @@
אשר
לאשר בקשת חיבור\?
אודות SimpleX Chat
- אשר בקשות
אודות SimpleX
ענה
שבוע
@@ -25,7 +24,6 @@
מראה
גרסת האפליקציה: v%s
גרסת אפליקציה: %s
- הודעת פתיחה
כל אנשי הקשר יישארו מחוברים.
תמיד להשתמש בממסר
ענה לשיחה
@@ -83,7 +81,6 @@
אימות
אימות נכשל
חזרה
- אוטומטית
מודגש
גיבוב הודעה שגוי
מזהה הודעה שגוי
@@ -228,7 +225,6 @@
תרומה
גרסת ליבה: v%s
צור כתובת
- בקשות ליצירת קשר
צור
צור פרופיל
יצירת הפרופיל שלך
diff --git a/apps/android/app/src/main/res/values-ja/strings.xml b/apps/multiplatform/android/src/main/res/values-ja/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-ja/strings.xml
rename to apps/multiplatform/android/src/main/res/values-ja/strings.xml
diff --git a/apps/android/app/src/main/res/values-ko/strings.xml b/apps/multiplatform/android/src/main/res/values-ko/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-ko/strings.xml
rename to apps/multiplatform/android/src/main/res/values-ko/strings.xml
diff --git a/apps/android/app/src/main/res/values-lt/strings.xml b/apps/multiplatform/android/src/main/res/values-lt/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-lt/strings.xml
rename to apps/multiplatform/android/src/main/res/values-lt/strings.xml
diff --git a/apps/android/app/src/main/res/values-ml/strings.xml b/apps/multiplatform/android/src/main/res/values-ml/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-ml/strings.xml
rename to apps/multiplatform/android/src/main/res/values-ml/strings.xml
diff --git a/apps/android/app/src/main/res/values-night/themes.xml b/apps/multiplatform/android/src/main/res/values-night/themes.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-night/themes.xml
rename to apps/multiplatform/android/src/main/res/values-night/themes.xml
diff --git a/apps/android/app/src/main/res/values-nl/strings.xml b/apps/multiplatform/android/src/main/res/values-nl/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-nl/strings.xml
rename to apps/multiplatform/android/src/main/res/values-nl/strings.xml
diff --git a/apps/android/app/src/main/res/values-pl/strings.xml b/apps/multiplatform/android/src/main/res/values-pl/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-pl/strings.xml
rename to apps/multiplatform/android/src/main/res/values-pl/strings.xml
diff --git a/apps/android/app/src/main/res/values-pt-rBR/strings.xml b/apps/multiplatform/android/src/main/res/values-pt-rBR/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-pt-rBR/strings.xml
rename to apps/multiplatform/android/src/main/res/values-pt-rBR/strings.xml
diff --git a/apps/android/app/src/main/res/values-pt/strings.xml b/apps/multiplatform/android/src/main/res/values-pt/strings.xml
similarity index 99%
rename from apps/android/app/src/main/res/values-pt/strings.xml
rename to apps/multiplatform/android/src/main/res/values-pt/strings.xml
index 4e19cdcd79..6c8bef2c55 100644
--- a/apps/android/app/src/main/res/values-pt/strings.xml
+++ b/apps/multiplatform/android/src/main/res/values-pt/strings.xml
@@ -7,7 +7,6 @@
Consola de conversa
Teste ao servidor falhou!
Usar proxy SOCKS
- Usar proxy SOCKS (porto 9050)
Usar proxy SOCKS\?
Porto
porto %d
@@ -15,7 +14,6 @@
Versão da aplicação
Todos os seus contatos permanecerão conectados.
Eliminar endereço
- Automaticamente
a + b
chamada perdida
Utilizar sempre o servidor de relay
@@ -129,7 +127,6 @@
Aceitar
Aceitar pedido de ligação\?
Aceitar modo anónimo
- Aceitar pedidos
Adicionar servidores pré-definidos
Aceder aos servidores via proxy SOCKS no porto %d\? O proxy tem de iniciar antes de ativar esta opção.
Adicionar a outro dispositivo
@@ -357,7 +354,6 @@
Conectado
conectando…
Tempo limite de conexão
- Pedidos de contato
Preferências de contato
Contato escondido:
O contato ainda não está conectado!
@@ -736,7 +732,6 @@
Erro de desencriptação
O código de acesso é substituído por um código auto-destrutivo.
ID da base de dados: %d
- DESENVOLVER
Nomes, avatares e isolamento de transporte diferentes.
Secundário adicional
Realce adicional
diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/multiplatform/android/src/main/res/values-ru/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-ru/strings.xml
rename to apps/multiplatform/android/src/main/res/values-ru/strings.xml
diff --git a/apps/android/app/src/main/res/values-th/strings.xml b/apps/multiplatform/android/src/main/res/values-th/strings.xml
similarity index 99%
rename from apps/android/app/src/main/res/values-th/strings.xml
rename to apps/multiplatform/android/src/main/res/values-th/strings.xml
index d604bcd42b..f19d43a145 100644
--- a/apps/android/app/src/main/res/values-th/strings.xml
+++ b/apps/multiplatform/android/src/main/res/values-th/strings.xml
@@ -401,7 +401,6 @@
เปิดใช้งานรหัสผ่านแบบทําลายตัวเอง
เปิดใช้งานการทำลายตัวเอง
ความช่วยเหลือ
- พัฒนา
เครื่องมือสำหรับนักพัฒนา
อุปกรณ์
คุณลักษณะสำหรับการทดลอง
diff --git a/apps/android/app/src/main/res/values-uk/strings.xml b/apps/multiplatform/android/src/main/res/values-uk/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-uk/strings.xml
rename to apps/multiplatform/android/src/main/res/values-uk/strings.xml
diff --git a/apps/android/app/src/main/res/values-zh-rCN/strings.xml b/apps/multiplatform/android/src/main/res/values-zh-rCN/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-zh-rCN/strings.xml
rename to apps/multiplatform/android/src/main/res/values-zh-rCN/strings.xml
diff --git a/apps/android/app/src/main/res/values-zh-rTW/strings.xml b/apps/multiplatform/android/src/main/res/values-zh-rTW/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values-zh-rTW/strings.xml
rename to apps/multiplatform/android/src/main/res/values-zh-rTW/strings.xml
diff --git a/apps/android/app/src/main/res/values/colors.xml b/apps/multiplatform/android/src/main/res/values/colors.xml
similarity index 100%
rename from apps/android/app/src/main/res/values/colors.xml
rename to apps/multiplatform/android/src/main/res/values/colors.xml
diff --git a/apps/android/app/src/main/res/values/icon_background.xml b/apps/multiplatform/android/src/main/res/values/icon_background.xml
similarity index 100%
rename from apps/android/app/src/main/res/values/icon_background.xml
rename to apps/multiplatform/android/src/main/res/values/icon_background.xml
diff --git a/apps/android/app/src/main/res/values/icon_dark_blue_background.xml b/apps/multiplatform/android/src/main/res/values/icon_dark_blue_background.xml
similarity index 100%
rename from apps/android/app/src/main/res/values/icon_dark_blue_background.xml
rename to apps/multiplatform/android/src/main/res/values/icon_dark_blue_background.xml
diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/multiplatform/android/src/main/res/values/strings.xml
similarity index 100%
rename from apps/android/app/src/main/res/values/strings.xml
rename to apps/multiplatform/android/src/main/res/values/strings.xml
diff --git a/apps/android/app/src/main/res/values/themes.xml b/apps/multiplatform/android/src/main/res/values/themes.xml
similarity index 100%
rename from apps/android/app/src/main/res/values/themes.xml
rename to apps/multiplatform/android/src/main/res/values/themes.xml
diff --git a/apps/android/app/src/main/res/xml/file_paths.xml b/apps/multiplatform/android/src/main/res/xml/file_paths.xml
similarity index 100%
rename from apps/android/app/src/main/res/xml/file_paths.xml
rename to apps/multiplatform/android/src/main/res/xml/file_paths.xml
diff --git a/apps/android/app/src/main/res/xml/locales_config.xml b/apps/multiplatform/android/src/main/res/xml/locales_config.xml
similarity index 100%
rename from apps/android/app/src/main/res/xml/locales_config.xml
rename to apps/multiplatform/android/src/main/res/xml/locales_config.xml
diff --git a/apps/android/app/src/test/java/chat/simplex/app/ExampleUnitTest.kt b/apps/multiplatform/android/src/test/java/chat/simplex/app/ExampleUnitTest.kt
similarity index 100%
rename from apps/android/app/src/test/java/chat/simplex/app/ExampleUnitTest.kt
rename to apps/multiplatform/android/src/test/java/chat/simplex/app/ExampleUnitTest.kt
diff --git a/apps/multiplatform/build.gradle.kts b/apps/multiplatform/build.gradle.kts
new file mode 100644
index 0000000000..94cecd1725
--- /dev/null
+++ b/apps/multiplatform/build.gradle.kts
@@ -0,0 +1,73 @@
+import org.gradle.initialization.Environment.Properties
+import java.io.File
+import java.io.FileInputStream
+
+buildscript {
+ val prop = java.util.Properties().apply {
+ try {
+ load(java.io.FileInputStream(File(rootProject.rootDir, "local.properties")))
+ } catch (e: Exception) {
+ // No file was created
+ }
+ }
+ extra.set("compose.version", prop["compose.version"] ?: extra["compose.version"])
+ extra.set("kotlin.version", prop["kotlin.version"] ?: extra["kotlin.version"])
+ extra.set("gradle.plugin.version", prop["gradle.plugin.version"] ?: extra["gradle.plugin.version"])
+ extra.set("abi_filter", prop["abi_filter"] ?: "arm64-v8a")
+ // Name that will be shown for debug build. By default, it is from strings
+ extra.set("app.name", prop["app.name"] ?: "@string/app_name")
+ // Whether the app is debuggable or not. Specify `false` if yo`u want good performance in debug builds
+ extra.set("enable_debuggable", prop["debuggable"] != "false")
+ // Ending part of package name.
+ // Provide, for example, `application_id.suffix=.debug` in local.properties
+ // to allow debug & release versions to coexist
+ extra.set("application_id.suffix", prop["application_id.suffix"] ?: "")
+ // Compression level for debug AND release apk. 0 = disable compression. Max is 9
+ extra.set("compression.level", (prop["compression.level"] as String?)?.toIntOrNull() ?: 0)
+ // NOTE: If you need a different version of something, provide it in `local.properties`
+ // like so: compose.version=123, or gradle.plugin.version=1.2.3, etc
+ repositories {
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath("com.android.tools.build:gradle:${rootProject.extra["gradle.plugin.version"]}")
+ classpath(kotlin("gradle-plugin", version = rootProject.extra["kotlin.version"] as String))
+ classpath("org.jetbrains.kotlin:kotlin-serialization:1.3.2")
+ classpath("dev.icerock.moko:resources-generator:0.22.3")
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}// Top-level build file where you can add configuration options common to all sub-projects/modules.
+/*plugins {
+ id "com.android.application" version "$gradle_plugin_version" apply false
+ id "com.android.library" version "$gradle_plugin_version" apply false
+ id "org.jetbrains.kotlin.android" version "$kotlin_version" apply false
+ id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
+}*/
+
+group = "chat.simplex"
+version = extra["android.version_name"] as String
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+ maven("https://jitpack.io")
+ }
+}
+
+plugins {
+ kotlin("multiplatform") apply false
+ kotlin("android") apply false
+ id("com.android.application") apply false
+ id("com.android.library") apply false
+ id("org.jetbrains.compose") apply false
+ id("org.jetbrains.kotlin.plugin.serialization") apply false
+}
+
+tasks.register("clean", Delete::class) {
+ delete(rootProject.buildDir)
+}
diff --git a/apps/multiplatform/common/build.gradle.kts b/apps/multiplatform/common/build.gradle.kts
new file mode 100644
index 0000000000..c3474f451d
--- /dev/null
+++ b/apps/multiplatform/common/build.gradle.kts
@@ -0,0 +1,140 @@
+plugins {
+ kotlin("multiplatform")
+ id("org.jetbrains.compose")
+ id("com.android.library")
+ id("org.jetbrains.kotlin.plugin.serialization")
+ id("dev.icerock.mobile.multiplatform-resources")
+ id("com.github.gmazzo.buildconfig") version "4.0.4"
+}
+
+group = "chat.simplex"
+version = extra["android.version_name"] as String
+
+kotlin {
+ android()
+ jvm("desktop") {
+ jvmToolchain(11)
+ }
+ sourceSets {
+ all {
+ languageSettings {
+ optIn("kotlinx.coroutines.DelicateCoroutinesApi")
+ optIn("androidx.compose.foundation.ExperimentalFoundationApi")
+ optIn("androidx.compose.ui.text.ExperimentalTextApi")
+ optIn("androidx.compose.material.ExperimentalMaterialApi")
+ optIn("com.arkivanov.decompose.ExperimentalDecomposeApi")
+ optIn("kotlinx.serialization.InternalSerializationApi")
+ optIn("kotlinx.serialization.ExperimentalSerializationApi")
+ optIn("androidx.compose.ui.ExperimentalComposeUiApi")
+ optIn("com.google.accompanist.permissions.ExperimentalPermissionsApi")
+ }
+ }
+
+ val commonMain by getting {
+ kotlin.srcDir("./build/generated/moko/commonMain/src/")
+ dependencies {
+ api(compose.runtime)
+ api(compose.foundation)
+ api(compose.material)
+ api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
+ api("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2")
+ api("com.russhwolf:multiplatform-settings:1.0.0")
+ api("com.charleskorn.kaml:kaml:0.43.0")
+ api("dev.icerock.moko:resources-compose:0.22.3")
+ api("org.jetbrains.compose.ui:ui-text:${rootProject.extra["compose.version"] as String}")
+ implementation("org.jetbrains.compose.components:components-animatedimage:${rootProject.extra["compose.version"] as String}")
+ //Barcode
+ api("org.boofcv:boofcv-core:0.40.1")
+ implementation("com.godaddy.android.colorpicker:compose-color-picker-jvm:0.7.0")
+ // Link Previews
+ implementation("org.jsoup:jsoup:1.13.1")
+ }
+ }
+ val commonTest by getting {
+ dependencies {
+ implementation(kotlin("test"))
+ }
+ }
+ // LALAL CHANGE TO IMPLEMENTATION
+ val androidMain by getting {
+ dependencies {
+ api("androidx.appcompat:appcompat:1.5.1")
+ api("androidx.core:core-ktx:1.9.0")
+ api("androidx.activity:activity-compose:1.5.0")
+ val work_version = "2.7.1"
+ api("androidx.work:work-runtime-ktx:$work_version")
+ api("androidx.work:work-multiprocess:$work_version")
+ api("com.google.accompanist:accompanist-insets:0.23.0")
+ api("dev.icerock.moko:resources:0.22.3")
+
+ // Video support
+ api("com.google.android.exoplayer:exoplayer:2.17.1")
+
+ // Biometric authentication
+ api("androidx.biometric:biometric:1.2.0-alpha04")
+
+ //Barcode
+ api("org.boofcv:boofcv-android:0.40.1")
+
+ //Camera Permission
+ api("com.google.accompanist:accompanist-permissions:0.23.0")
+
+ api("androidx.webkit:webkit:1.4.0")
+
+ // GIFs support
+ api("io.coil-kt:coil-compose:2.1.0")
+ api("io.coil-kt:coil-gif:2.1.0")
+
+ api("com.jakewharton:process-phoenix:2.1.2")
+
+ val camerax_version = "1.1.0-beta01"
+ api("androidx.camera:camera-core:${camerax_version}")
+ api("androidx.camera:camera-camera2:${camerax_version}")
+ api("androidx.camera:camera-lifecycle:${camerax_version}")
+ api("androidx.camera:camera-view:${camerax_version}")
+
+ // LALAL REPLACE IT WITH SOURCE
+ // Wheel picker
+ api("com.github.zj565061763:compose-wheel-picker:1.0.0-alpha10")
+
+ // LALAL REMOVE
+ api("org.jsoup:jsoup:1.13.1")
+ api("com.godaddy.android.colorpicker:compose-color-picker-jvm:0.7.0")
+ api("androidx.compose.ui:ui-tooling-preview:${extra["compose.version"]}")
+ }
+ }
+ val desktopMain by getting {
+ dependencies {
+ implementation("dev.icerock.moko:resources:0.22.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.7.1")
+ }
+ }
+ val desktopTest by getting
+ }
+}
+
+android {
+ compileSdkVersion(33)
+ sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
+ defaultConfig {
+ minSdkVersion(26)
+ targetSdkVersion(33)
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+}
+
+multiplatformResources {
+ multiplatformResourcesPackage = "com.icerockdev.library"
+ // multiplatformResourcesClassName = "MR"
+}
+
+buildConfig {
+ forClass("BuildConfigCommon") {
+ buildConfigField("String", "ANDROID_VERSION_NAME", "\"${extra["android.version_name"]}\"")
+ buildConfigField("int", "ANDROID_VERSION_CODE", "${extra["android.version_code"]}")
+ buildConfigField("String", "DESKTOP_VERSION_NAME", "\"${extra["desktop.version_name"]}\"")
+ }
+}
diff --git a/apps/multiplatform/common/src/androidMain/AndroidManifest.xml b/apps/multiplatform/common/src/androidMain/AndroidManifest.xml
new file mode 100644
index 0000000000..74520465ae
--- /dev/null
+++ b/apps/multiplatform/common/src/androidMain/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/apps/android/app/src/main/cpp/CMakeLists.txt b/apps/multiplatform/common/src/commonMain/cpp/android/CMakeLists.txt
similarity index 99%
rename from apps/android/app/src/main/cpp/CMakeLists.txt
rename to apps/multiplatform/common/src/commonMain/cpp/android/CMakeLists.txt
index de688975c6..44cb31d424 100644
--- a/apps/android/app/src/main/cpp/CMakeLists.txt
+++ b/apps/multiplatform/common/src/commonMain/cpp/android/CMakeLists.txt
@@ -64,4 +64,4 @@ target_link_libraries( # Specifies the target library.
# Links the target library to the log library
# included in the NDK.
- ${log-lib})
\ No newline at end of file
+ ${log-lib})
diff --git a/apps/android/app/src/main/cpp/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c
similarity index 100%
rename from apps/android/app/src/main/cpp/simplex-api.c
rename to apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt b/apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt
new file mode 100644
index 0000000000..2f8f119d75
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt
@@ -0,0 +1,92 @@
+# Manually downloaded headers because `find_package(JNI REQUIRED)` doesn't work while cross-compiling:
+
+# https://raw.githubusercontent.com/openjdk/jdk/master/src/java.base/share/native/include/jni.h
+include_directories(${CMAKE_SOURCE_DIR}/include)
+if(UNIX)
+ # https://raw.githubusercontent.com/openjdk/jdk/master/src/java.base/unix/native/include/jni_md.h
+ include_directories(${CMAKE_SOURCE_DIR}/include/unix)
+elseif(WIN32)
+ # https://raw.githubusercontent.com/openjdk/jdk/master/src/java.base/windows/native/include/jni_md.h
+ include_directories(${CMAKE_SOURCE_DIR}/include/windows)
+endif()
+
+# Sets the minimum version of CMake required to build the native library.
+cmake_minimum_required(VERSION 3.10.2)
+
+# Declares and names the project.
+project("app")
+
+if(UNIX AND NOT APPLE)
+ set(OS_LIB_PATH "linux")
+ set(OS_LIB_EXT "so")
+elseif(WIN32)
+ set(OS_LIB_PATH "windows")
+ set(OS_LIB_EXT "dll")
+else()
+ set(OS_LIB_PATH "mac")
+ set(OS_LIB_EXT "dylib")
+ set(CMAKE_MACOSX_RPATH 1)
+ set(CMAKE_BUILD_RPATH "@loader_path")
+endif()
+
+if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "amd64")
+ set(OS_LIB_ARCH "x86_64")
+elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64")
+ set(OS_LIB_ARCH "aarch64")
+else()
+ set(OS_LIB_ARCH "${CMAKE_SYSTEM_PROCESSOR}")
+endif()
+
+# Makes ld search libs in the same dir as libapp-lib, not in system dirs
+#set(CMAKE_BUILD_RPATH "$ORIGIN")
+
+# Creates and names a library, sets it as either STATIC
+# or SHARED, and provides the relative paths to its source code.
+# You can define multiple libraries, and CMake builds them for you.
+# Gradle automatically packages shared libraries with your APK.
+
+add_library( # Sets the name of the library.
+ app-lib
+
+ # Sets the library as a shared library.
+ SHARED
+
+ # Provides a relative path to your source file(s).
+ simplex-api.c)
+
+add_library( simplex SHARED IMPORTED )
+# Lib has different name because of version, find it
+FILE(GLOB SIMPLEXLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libHSsimplex-chat-*.${OS_LIB_EXT})
+set_target_properties( simplex PROPERTIES IMPORTED_LOCATION ${SIMPLEXLIB})
+
+
+# Specifies libraries CMake should link to your target library. You
+# can link multiple libraries, such as libraries you define in this
+# build script, prebuilt third-party libraries, or system libraries.
+if(NOT APPLE)
+ target_link_libraries(app-lib simplex)
+else()
+ # Without direct linking it can't find hs_init in linking step
+ add_library( rts SHARED IMPORTED )
+ FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/deps/libHSrts_thr-*.${OS_LIB_EXT})
+ set_target_properties( rts PROPERTIES IMPORTED_LOCATION ${RTSLIB})
+
+ target_link_libraries(app-lib rts simplex)
+endif()
+
+
+
+# Trying to copy resulting files into needed directory, but none of these work for some reason. This could allow to
+# remove gradle's copy hooks
+#add_custom_target(lalal)
+#MACRO(POST_BUILD_COPY src_files dest_path)
+# ADD_CUSTOM_COMMAND(TARGET lalal POST_BUILD
+# COMMAND ${CMAKE_COMMAND} -E copy ${src_files} ${dest_path})
+#ENDMACRO(POST_BUILD_COPY src_files dest_path)
+
+#file(COPY "${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libsimplex.${OS_LIB_EXT}" DESTINATION "../../resources/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libsimplex.${OS_LIB_EXT}")
+#POST_BUILD_COPY("${CMAKE_BINARY_DIR}/libapp-lib.${OS_LIB_EXT}" "../resources/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/")
+
+#add_custom_command(TARGET lalal POST_BUILD
+# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/libapp-lib.${OS_LIB_EXT} "../../resources/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libapp-lib.${OS_LIB_EXT}"
+#)
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h
new file mode 100644
index 0000000000..c85da1bc67
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h
@@ -0,0 +1,2001 @@
+/*
+ * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include
+#include
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+ and jlong */
+
+#include "jni_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK 0 /* success */
+#define JNI_ERR (-1) /* unknown error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* not enough memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+ char *name;
+ char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ void *reserved3;
+ jint (JNICALL *GetVersion)(JNIEnv *env);
+
+ jclass (JNICALL *DefineClass)
+ (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len);
+ jclass (JNICALL *FindClass)
+ (JNIEnv *env, const char *name);
+
+ jmethodID (JNICALL *FromReflectedMethod)
+ (JNIEnv *env, jobject method);
+ jfieldID (JNICALL *FromReflectedField)
+ (JNIEnv *env, jobject field);
+
+ jobject (JNICALL *ToReflectedMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+ jclass (JNICALL *GetSuperclass)
+ (JNIEnv *env, jclass sub);
+ jboolean (JNICALL *IsAssignableFrom)
+ (JNIEnv *env, jclass sub, jclass sup);
+
+ jobject (JNICALL *ToReflectedField)
+ (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (JNICALL *Throw)
+ (JNIEnv *env, jthrowable obj);
+ jint (JNICALL *ThrowNew)
+ (JNIEnv *env, jclass clazz, const char *msg);
+ jthrowable (JNICALL *ExceptionOccurred)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionDescribe)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionClear)
+ (JNIEnv *env);
+ void (JNICALL *FatalError)
+ (JNIEnv *env, const char *msg);
+
+ jint (JNICALL *PushLocalFrame)
+ (JNIEnv *env, jint capacity);
+ jobject (JNICALL *PopLocalFrame)
+ (JNIEnv *env, jobject result);
+
+ jobject (JNICALL *NewGlobalRef)
+ (JNIEnv *env, jobject lobj);
+ void (JNICALL *DeleteGlobalRef)
+ (JNIEnv *env, jobject gref);
+ void (JNICALL *DeleteLocalRef)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsSameObject)
+ (JNIEnv *env, jobject obj1, jobject obj2);
+ jobject (JNICALL *NewLocalRef)
+ (JNIEnv *env, jobject ref);
+ jint (JNICALL *EnsureLocalCapacity)
+ (JNIEnv *env, jint capacity);
+
+ jobject (JNICALL *AllocObject)
+ (JNIEnv *env, jclass clazz);
+ jobject (JNICALL *NewObject)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *NewObjectV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *NewObjectA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (JNICALL *GetObjectClass)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsInstanceOf)
+ (JNIEnv *env, jobject obj, jclass clazz);
+
+ jmethodID (JNICALL *GetMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallObjectMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (JNICALL *CallObjectMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallObjectMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jboolean (JNICALL *CallBooleanMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (JNICALL *CallBooleanMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallBooleanMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jbyte (JNICALL *CallByteMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (JNICALL *CallByteMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallByteMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallCharMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (JNICALL *CallCharMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallCharMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallShortMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (JNICALL *CallShortMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallShortMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallIntMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (JNICALL *CallIntMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jint (JNICALL *CallIntMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallLongMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (JNICALL *CallLongMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallLongMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallFloatMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (JNICALL *CallFloatMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallFloatMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallDoubleMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (JNICALL *CallDoubleMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallDoubleMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallVoidMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (JNICALL *CallVoidMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ void (JNICALL *CallVoidMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jobject (JNICALL *CallNonvirtualObjectMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallNonvirtualObjectMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jobject (JNICALL *CallNonvirtualObjectMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jboolean (JNICALL *CallNonvirtualBooleanMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jbyte (JNICALL *CallNonvirtualByteMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallNonvirtualByteMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jbyte (JNICALL *CallNonvirtualByteMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jchar (JNICALL *CallNonvirtualCharMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallNonvirtualCharMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jchar (JNICALL *CallNonvirtualCharMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jshort (JNICALL *CallNonvirtualShortMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallNonvirtualShortMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jshort (JNICALL *CallNonvirtualShortMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jint (JNICALL *CallNonvirtualIntMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallNonvirtualIntMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jint (JNICALL *CallNonvirtualIntMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jlong (JNICALL *CallNonvirtualLongMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallNonvirtualLongMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jlong (JNICALL *CallNonvirtualLongMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jfloat (JNICALL *CallNonvirtualFloatMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallNonvirtualFloatMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jfloat (JNICALL *CallNonvirtualFloatMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jdouble (JNICALL *CallNonvirtualDoubleMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ void (JNICALL *CallNonvirtualVoidMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ void (JNICALL *CallNonvirtualVoidMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ void (JNICALL *CallNonvirtualVoidMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jfieldID (JNICALL *GetFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *GetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (JNICALL *GetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (JNICALL *GetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (JNICALL *GetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (JNICALL *GetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (JNICALL *GetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (JNICALL *GetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (JNICALL *GetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (JNICALL *GetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (JNICALL *SetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (JNICALL *SetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (JNICALL *SetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (JNICALL *SetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (JNICALL *SetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (JNICALL *SetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (JNICALL *SetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (JNICALL *SetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (JNICALL *SetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (JNICALL *GetStaticMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallStaticObjectMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallStaticObjectMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallStaticObjectMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jboolean (JNICALL *CallStaticBooleanMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallStaticBooleanMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallStaticBooleanMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jbyte (JNICALL *CallStaticByteMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallStaticByteMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallStaticByteMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallStaticCharMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallStaticCharMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallStaticCharMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallStaticShortMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallStaticShortMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallStaticShortMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallStaticIntMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallStaticIntMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jint (JNICALL *CallStaticIntMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallStaticLongMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallStaticLongMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallStaticLongMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallStaticFloatMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallStaticFloatMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallStaticFloatMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallStaticDoubleMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallStaticDoubleMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallStaticDoubleMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallStaticVoidMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+ void (JNICALL *CallStaticVoidMethodV)
+ (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+ void (JNICALL *CallStaticVoidMethodA)
+ (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+ jfieldID (JNICALL *GetStaticFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+ jobject (JNICALL *GetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (JNICALL *GetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (JNICALL *GetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (JNICALL *GetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (JNICALL *GetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (JNICALL *GetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (JNICALL *GetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (JNICALL *GetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (JNICALL *GetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (JNICALL *SetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+ void (JNICALL *SetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+ void (JNICALL *SetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+ void (JNICALL *SetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+ void (JNICALL *SetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+ void (JNICALL *SetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+ void (JNICALL *SetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+ void (JNICALL *SetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+ void (JNICALL *SetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+ jstring (JNICALL *NewString)
+ (JNIEnv *env, const jchar *unicode, jsize len);
+ jsize (JNICALL *GetStringLength)
+ (JNIEnv *env, jstring str);
+ const jchar *(JNICALL *GetStringChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringChars)
+ (JNIEnv *env, jstring str, const jchar *chars);
+
+ jstring (JNICALL *NewStringUTF)
+ (JNIEnv *env, const char *utf);
+ jsize (JNICALL *GetStringUTFLength)
+ (JNIEnv *env, jstring str);
+ const char* (JNICALL *GetStringUTFChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringUTFChars)
+ (JNIEnv *env, jstring str, const char* chars);
+
+
+ jsize (JNICALL *GetArrayLength)
+ (JNIEnv *env, jarray array);
+
+ jobjectArray (JNICALL *NewObjectArray)
+ (JNIEnv *env, jsize len, jclass clazz, jobject init);
+ jobject (JNICALL *GetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index);
+ void (JNICALL *SetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (JNICALL *NewBooleanArray)
+ (JNIEnv *env, jsize len);
+ jbyteArray (JNICALL *NewByteArray)
+ (JNIEnv *env, jsize len);
+ jcharArray (JNICALL *NewCharArray)
+ (JNIEnv *env, jsize len);
+ jshortArray (JNICALL *NewShortArray)
+ (JNIEnv *env, jsize len);
+ jintArray (JNICALL *NewIntArray)
+ (JNIEnv *env, jsize len);
+ jlongArray (JNICALL *NewLongArray)
+ (JNIEnv *env, jsize len);
+ jfloatArray (JNICALL *NewFloatArray)
+ (JNIEnv *env, jsize len);
+ jdoubleArray (JNICALL *NewDoubleArray)
+ (JNIEnv *env, jsize len);
+
+ jboolean * (JNICALL *GetBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte * (JNICALL *GetByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar * (JNICALL *GetCharArrayElements)
+ (JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort * (JNICALL *GetShortArrayElements)
+ (JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint * (JNICALL *GetIntArrayElements)
+ (JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong * (JNICALL *GetLongArrayElements)
+ (JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat * (JNICALL *GetFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble * (JNICALL *GetDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (JNICALL *ReleaseBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+ void (JNICALL *ReleaseByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+ void (JNICALL *ReleaseCharArrayElements)
+ (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+ void (JNICALL *ReleaseShortArrayElements)
+ (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+ void (JNICALL *ReleaseIntArrayElements)
+ (JNIEnv *env, jintArray array, jint *elems, jint mode);
+ void (JNICALL *ReleaseLongArrayElements)
+ (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+ void (JNICALL *ReleaseFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+ void (JNICALL *ReleaseDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+ void (JNICALL *GetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+ void (JNICALL *GetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+ void (JNICALL *GetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+ void (JNICALL *GetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+ void (JNICALL *GetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+ void (JNICALL *GetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+ void (JNICALL *GetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+ void (JNICALL *SetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+ void (JNICALL *SetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+ void (JNICALL *SetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+ void (JNICALL *SetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+ void (JNICALL *SetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+ void (JNICALL *SetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+ void (JNICALL *SetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+ void (JNICALL *SetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+ jint (JNICALL *RegisterNatives)
+ (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (JNICALL *UnregisterNatives)
+ (JNIEnv *env, jclass clazz);
+
+ jint (JNICALL *MonitorEnter)
+ (JNIEnv *env, jobject obj);
+ jint (JNICALL *MonitorExit)
+ (JNIEnv *env, jobject obj);
+
+ jint (JNICALL *GetJavaVM)
+ (JNIEnv *env, JavaVM **vm);
+
+ void (JNICALL *GetStringRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetStringUTFRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void * (JNICALL *GetPrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, jboolean *isCopy);
+ void (JNICALL *ReleasePrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar * (JNICALL *GetStringCritical)
+ (JNIEnv *env, jstring string, jboolean *isCopy);
+ void (JNICALL *ReleaseStringCritical)
+ (JNIEnv *env, jstring string, const jchar *cstring);
+
+ jweak (JNICALL *NewWeakGlobalRef)
+ (JNIEnv *env, jobject obj);
+ void (JNICALL *DeleteWeakGlobalRef)
+ (JNIEnv *env, jweak ref);
+
+ jboolean (JNICALL *ExceptionCheck)
+ (JNIEnv *env);
+
+ jobject (JNICALL *NewDirectByteBuffer)
+ (JNIEnv* env, void* address, jlong capacity);
+ void* (JNICALL *GetDirectBufferAddress)
+ (JNIEnv* env, jobject buf);
+ jlong (JNICALL *GetDirectBufferCapacity)
+ (JNIEnv* env, jobject buf);
+
+ /* New JNI 1.6 Features */
+
+ jobjectRefType (JNICALL *GetObjectRefType)
+ (JNIEnv* env, jobject obj);
+
+ /* Module Features */
+
+ jobject (JNICALL *GetModule)
+ (JNIEnv* env, jclass clazz);
+
+ /* Virtual threads */
+
+ jboolean (JNICALL *IsVirtualThread)
+ (JNIEnv* env, jobject obj);
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ * env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ * (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+ const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint GetVersion() {
+ return functions->GetVersion(this);
+ }
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize len) {
+ return functions->DefineClass(this, name, loader, buf, len);
+ }
+ jclass FindClass(const char *name) {
+ return functions->FindClass(this, name);
+ }
+ jmethodID FromReflectedMethod(jobject method) {
+ return functions->FromReflectedMethod(this,method);
+ }
+ jfieldID FromReflectedField(jobject field) {
+ return functions->FromReflectedField(this,field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass sub) {
+ return functions->GetSuperclass(this, sub);
+ }
+ jboolean IsAssignableFrom(jclass sub, jclass sup) {
+ return functions->IsAssignableFrom(this, sub, sup);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+ return functions->ToReflectedField(this,cls,fieldID,isStatic);
+ }
+
+ jint Throw(jthrowable obj) {
+ return functions->Throw(this, obj);
+ }
+ jint ThrowNew(jclass clazz, const char *msg) {
+ return functions->ThrowNew(this, clazz, msg);
+ }
+ jthrowable ExceptionOccurred() {
+ return functions->ExceptionOccurred(this);
+ }
+ void ExceptionDescribe() {
+ functions->ExceptionDescribe(this);
+ }
+ void ExceptionClear() {
+ functions->ExceptionClear(this);
+ }
+ void FatalError(const char *msg) {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity) {
+ return functions->PushLocalFrame(this,capacity);
+ }
+ jobject PopLocalFrame(jobject result) {
+ return functions->PopLocalFrame(this,result);
+ }
+
+ jobject NewGlobalRef(jobject lobj) {
+ return functions->NewGlobalRef(this,lobj);
+ }
+ void DeleteGlobalRef(jobject gref) {
+ functions->DeleteGlobalRef(this,gref);
+ }
+ void DeleteLocalRef(jobject obj) {
+ functions->DeleteLocalRef(this, obj);
+ }
+
+ jboolean IsSameObject(jobject obj1, jobject obj2) {
+ return functions->IsSameObject(this,obj1,obj2);
+ }
+
+ jobject NewLocalRef(jobject ref) {
+ return functions->NewLocalRef(this,ref);
+ }
+ jint EnsureLocalCapacity(jint capacity) {
+ return functions->EnsureLocalCapacity(this,capacity);
+ }
+
+ jobject AllocObject(jclass clazz) {
+ return functions->AllocObject(this,clazz);
+ }
+ jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args, methodID);
+ result = functions->NewObjectV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject NewObjectV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->NewObjectV(this,clazz,methodID,args);
+ }
+ jobject NewObjectA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->NewObjectA(this,clazz,methodID,args);
+ }
+
+ jclass GetObjectClass(jobject obj) {
+ return functions->GetObjectClass(this,obj);
+ }
+ jboolean IsInstanceOf(jobject obj, jclass clazz) {
+ return functions->IsInstanceOf(this,obj,clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallObjectMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallObjectMethodV(this,obj,methodID,args);
+ }
+ jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallObjectMethodA(this,obj,methodID,args);
+ }
+
+ jboolean CallBooleanMethod(jobject obj,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallBooleanMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallBooleanMethodV(this,obj,methodID,args);
+ }
+ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallBooleanMethodA(this,obj,methodID, args);
+ }
+
+ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallByteMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallByteMethodV(this,obj,methodID,args);
+ }
+ jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallByteMethodA(this,obj,methodID,args);
+ }
+
+ jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallCharMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallCharMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallCharMethodV(this,obj,methodID,args);
+ }
+ jchar CallCharMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallCharMethodA(this,obj,methodID,args);
+ }
+
+ jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallShortMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallShortMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallShortMethodV(this,obj,methodID,args);
+ }
+ jshort CallShortMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallShortMethodA(this,obj,methodID,args);
+ }
+
+ jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallIntMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallIntMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallIntMethodV(this,obj,methodID,args);
+ }
+ jint CallIntMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallIntMethodA(this,obj,methodID,args);
+ }
+
+ jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallLongMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallLongMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallLongMethodV(this,obj,methodID,args);
+ }
+ jlong CallLongMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallLongMethodA(this,obj,methodID,args);
+ }
+
+ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallFloatMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallFloatMethodV(this,obj,methodID,args);
+ }
+ jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallFloatMethodA(this,obj,methodID,args);
+ }
+
+ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallDoubleMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallDoubleMethodV(this,obj,methodID,args);
+ }
+ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallDoubleMethodA(this,obj,methodID,args);
+ }
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallVoidMethodA(this,obj,methodID,args);
+ }
+
+ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+ methodID, args);
+ }
+
+ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetFieldID(this,clazz,name,sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID) {
+ return functions->GetObjectField(this,obj,fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+ return functions->GetBooleanField(this,obj,fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID) {
+ return functions->GetByteField(this,obj,fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID) {
+ return functions->GetCharField(this,obj,fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID) {
+ return functions->GetShortField(this,obj,fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID) {
+ return functions->GetIntField(this,obj,fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID) {
+ return functions->GetLongField(this,obj,fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+ return functions->GetFloatField(this,obj,fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+ return functions->GetDoubleField(this,obj,fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+ functions->SetObjectField(this,obj,fieldID,val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID,
+ jboolean val) {
+ functions->SetBooleanField(this,obj,fieldID,val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID,
+ jbyte val) {
+ functions->SetByteField(this,obj,fieldID,val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID,
+ jchar val) {
+ functions->SetCharField(this,obj,fieldID,val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID,
+ jshort val) {
+ functions->SetShortField(this,obj,fieldID,val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID,
+ jint val) {
+ functions->SetIntField(this,obj,fieldID,val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID,
+ jlong val) {
+ functions->SetLongField(this,obj,fieldID,val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID,
+ jfloat val) {
+ functions->SetFloatField(this,obj,fieldID,val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID,
+ jdouble val) {
+ functions->SetDoubleField(this,obj,fieldID,val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+ ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ }
+ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+ }
+
+ jboolean CallStaticBooleanMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallStaticBooleanMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ }
+ jboolean CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+ }
+
+ jbyte CallStaticByteMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallStaticByteMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ }
+ jbyte CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+ }
+
+ jchar CallStaticCharMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallStaticCharMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ }
+ jchar CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+ }
+
+ jshort CallStaticShortMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallStaticShortMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ }
+ jshort CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+ }
+
+ jint CallStaticIntMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallStaticIntMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ }
+ jint CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+ }
+
+ jlong CallStaticLongMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallStaticLongMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ }
+ jlong CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+ }
+
+ jfloat CallStaticFloatMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallStaticFloatMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ }
+ jfloat CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+ }
+
+ jdouble CallStaticDoubleMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallStaticDoubleMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ }
+ jdouble CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+ }
+
+ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+ va_list args) {
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ }
+ void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallStaticVoidMethodA(this,cls,methodID,args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticFieldID(this,clazz,name,sig);
+ }
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticObjectField(this,clazz,fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticBooleanField(this,clazz,fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticByteField(this,clazz,fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticCharField(this,clazz,fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticShortField(this,clazz,fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticIntField(this,clazz,fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticLongField(this,clazz,fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticFloatField(this,clazz,fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticDoubleField(this,clazz,fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+ jobject value) {
+ functions->SetStaticObjectField(this,clazz,fieldID,value);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+ jboolean value) {
+ functions->SetStaticBooleanField(this,clazz,fieldID,value);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID,
+ jbyte value) {
+ functions->SetStaticByteField(this,clazz,fieldID,value);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID,
+ jchar value) {
+ functions->SetStaticCharField(this,clazz,fieldID,value);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID,
+ jshort value) {
+ functions->SetStaticShortField(this,clazz,fieldID,value);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID,
+ jint value) {
+ functions->SetStaticIntField(this,clazz,fieldID,value);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID,
+ jlong value) {
+ functions->SetStaticLongField(this,clazz,fieldID,value);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+ jfloat value) {
+ functions->SetStaticFloatField(this,clazz,fieldID,value);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+ jdouble value) {
+ functions->SetStaticDoubleField(this,clazz,fieldID,value);
+ }
+
+ jstring NewString(const jchar *unicode, jsize len) {
+ return functions->NewString(this,unicode,len);
+ }
+ jsize GetStringLength(jstring str) {
+ return functions->GetStringLength(this,str);
+ }
+ const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringChars(this,str,isCopy);
+ }
+ void ReleaseStringChars(jstring str, const jchar *chars) {
+ functions->ReleaseStringChars(this,str,chars);
+ }
+
+ jstring NewStringUTF(const char *utf) {
+ return functions->NewStringUTF(this,utf);
+ }
+ jsize GetStringUTFLength(jstring str) {
+ return functions->GetStringUTFLength(this,str);
+ }
+ const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringUTFChars(this,str,isCopy);
+ }
+ void ReleaseStringUTFChars(jstring str, const char* chars) {
+ functions->ReleaseStringUTFChars(this,str,chars);
+ }
+
+ jsize GetArrayLength(jarray array) {
+ return functions->GetArrayLength(this,array);
+ }
+
+ jobjectArray NewObjectArray(jsize len, jclass clazz,
+ jobject init) {
+ return functions->NewObjectArray(this,len,clazz,init);
+ }
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+ return functions->GetObjectArrayElement(this,array,index);
+ }
+ void SetObjectArrayElement(jobjectArray array, jsize index,
+ jobject val) {
+ functions->SetObjectArrayElement(this,array,index,val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize len) {
+ return functions->NewBooleanArray(this,len);
+ }
+ jbyteArray NewByteArray(jsize len) {
+ return functions->NewByteArray(this,len);
+ }
+ jcharArray NewCharArray(jsize len) {
+ return functions->NewCharArray(this,len);
+ }
+ jshortArray NewShortArray(jsize len) {
+ return functions->NewShortArray(this,len);
+ }
+ jintArray NewIntArray(jsize len) {
+ return functions->NewIntArray(this,len);
+ }
+ jlongArray NewLongArray(jsize len) {
+ return functions->NewLongArray(this,len);
+ }
+ jfloatArray NewFloatArray(jsize len) {
+ return functions->NewFloatArray(this,len);
+ }
+ jdoubleArray NewDoubleArray(jsize len) {
+ return functions->NewDoubleArray(this,len);
+ }
+
+ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+ return functions->GetBooleanArrayElements(this,array,isCopy);
+ }
+ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+ return functions->GetByteArrayElements(this,array,isCopy);
+ }
+ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+ return functions->GetCharArrayElements(this,array,isCopy);
+ }
+ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+ return functions->GetShortArrayElements(this,array,isCopy);
+ }
+ jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+ return functions->GetIntArrayElements(this,array,isCopy);
+ }
+ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+ return functions->GetLongArrayElements(this,array,isCopy);
+ }
+ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+ return functions->GetFloatArrayElements(this,array,isCopy);
+ }
+ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+ return functions->GetDoubleArrayElements(this,array,isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean *elems,
+ jint mode) {
+ functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array,
+ jbyte *elems,
+ jint mode) {
+ functions->ReleaseByteArrayElements(this,array,elems,mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array,
+ jchar *elems,
+ jint mode) {
+ functions->ReleaseCharArrayElements(this,array,elems,mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array,
+ jshort *elems,
+ jint mode) {
+ functions->ReleaseShortArrayElements(this,array,elems,mode);
+ }
+ void ReleaseIntArrayElements(jintArray array,
+ jint *elems,
+ jint mode) {
+ functions->ReleaseIntArrayElements(this,array,elems,mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array,
+ jlong *elems,
+ jint mode) {
+ functions->ReleaseLongArrayElements(this,array,elems,mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array,
+ jfloat *elems,
+ jint mode) {
+ functions->ReleaseFloatArrayElements(this,array,elems,mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble *elems,
+ jint mode) {
+ functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array,
+ jsize start, jsize len, jboolean *buf) {
+ functions->GetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void GetByteArrayRegion(jbyteArray array,
+ jsize start, jsize len, jbyte *buf) {
+ functions->GetByteArrayRegion(this,array,start,len,buf);
+ }
+ void GetCharArrayRegion(jcharArray array,
+ jsize start, jsize len, jchar *buf) {
+ functions->GetCharArrayRegion(this,array,start,len,buf);
+ }
+ void GetShortArrayRegion(jshortArray array,
+ jsize start, jsize len, jshort *buf) {
+ functions->GetShortArrayRegion(this,array,start,len,buf);
+ }
+ void GetIntArrayRegion(jintArray array,
+ jsize start, jsize len, jint *buf) {
+ functions->GetIntArrayRegion(this,array,start,len,buf);
+ }
+ void GetLongArrayRegion(jlongArray array,
+ jsize start, jsize len, jlong *buf) {
+ functions->GetLongArrayRegion(this,array,start,len,buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array,
+ jsize start, jsize len, jfloat *buf) {
+ functions->GetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array,
+ jsize start, jsize len, jdouble *buf) {
+ functions->GetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf) {
+ functions->SetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf) {
+ functions->SetByteArrayRegion(this,array,start,len,buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf) {
+ functions->SetCharArrayRegion(this,array,start,len,buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf) {
+ functions->SetShortArrayRegion(this,array,start,len,buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf) {
+ functions->SetIntArrayRegion(this,array,start,len,buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf) {
+ functions->SetLongArrayRegion(this,array,start,len,buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf) {
+ functions->SetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf) {
+ functions->SetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ return functions->RegisterNatives(this,clazz,methods,nMethods);
+ }
+ jint UnregisterNatives(jclass clazz) {
+ return functions->UnregisterNatives(this,clazz);
+ }
+
+ jint MonitorEnter(jobject obj) {
+ return functions->MonitorEnter(this,obj);
+ }
+ jint MonitorExit(jobject obj) {
+ return functions->MonitorExit(this,obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm) {
+ return functions->GetJavaVM(this,vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+ functions->GetStringRegion(this,str,start,len,buf);
+ }
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+ functions->GetStringUTFRegion(this,str,start,len,buf);
+ }
+
+ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+ return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+ }
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+ functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+ }
+
+ const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+ return functions->GetStringCritical(this,string,isCopy);
+ }
+ void ReleaseStringCritical(jstring string, const jchar *cstring) {
+ functions->ReleaseStringCritical(this,string,cstring);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj) {
+ return functions->NewWeakGlobalRef(this,obj);
+ }
+ void DeleteWeakGlobalRef(jweak ref) {
+ functions->DeleteWeakGlobalRef(this,ref);
+ }
+
+ jboolean ExceptionCheck() {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void* address, jlong capacity) {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+ void* GetDirectBufferAddress(jobject buf) {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+ jlong GetDirectBufferCapacity(jobject buf) {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+ jobjectRefType GetObjectRefType(jobject obj) {
+ return functions->GetObjectRefType(this, obj);
+ }
+
+ /* Module Features */
+
+ jobject GetModule(jclass clazz) {
+ return functions->GetModule(this, clazz);
+ }
+
+ /* Virtual threads */
+
+ jboolean IsVirtualThread(jobject obj) {
+ return functions->IsVirtualThread(this, obj);
+ }
+
+#endif /* __cplusplus */
+};
+
+/*
+ * optionString may be any option accepted by the JVM, or one of the
+ * following:
+ *
+ * -D= Set a system property.
+ * -verbose[:class|gc|jni] Enable verbose output, comma-separated. E.g.
+ * "-verbose:class" or "-verbose:gc,class"
+ * Standard names include: gc, class, and jni.
+ * All nonstandard (VM-specific) names must begin
+ * with "X".
+ * vfprintf extraInfo is a pointer to the vfprintf hook.
+ * exit extraInfo is a pointer to the exit hook.
+ * abort extraInfo is a pointer to the abort hook.
+ */
+typedef struct JavaVMOption {
+ char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+ jint version;
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+ jint version;
+
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
+/* These will be VM-specific. */
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+ jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+ jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+ jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+ jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+ const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(void **penv, void *args) {
+ return functions->AttachCurrentThread(this, penv, args);
+ }
+ jint DetachCurrentThread() {
+ return functions->DetachCurrentThread(this);
+ }
+
+ jint GetEnv(void **penv, jint version) {
+ return functions->GetEnv(this, penv, version);
+ }
+ jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+ return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+ }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+#define JNI_VERSION_1_8 0x00010008
+#define JNI_VERSION_9 0x00090000
+#define JNI_VERSION_10 0x000a0000
+#define JNI_VERSION_19 0x00130000
+#define JNI_VERSION_20 0x00140000
+#define JNI_VERSION_21 0x00150000
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h
new file mode 100644
index 0000000000..6e583da714
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+
+#ifndef JNIEXPORT
+ #if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #ifdef ARM
+ #define JNIEXPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIEXPORT __attribute__((visibility("default")))
+ #endif
+ #else
+ #define JNIEXPORT
+ #endif
+#endif
+
+#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #ifdef ARM
+ #define JNIIMPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIIMPORT __attribute__((visibility("default")))
+ #endif
+#else
+ #define JNIIMPORT
+#endif
+
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h
new file mode 100644
index 0000000000..b8c144fb04
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef JNIEXPORT
+ #define JNIEXPORT __declspec(dllexport)
+#endif
+#define JNIIMPORT __declspec(dllimport)
+#define JNICALL __stdcall
+
+// 'long' is always 32 bit on windows so this matches what jdk expects
+typedef long jint;
+typedef __int64 jlong;
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c
new file mode 100644
index 0000000000..e772adffa2
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c
@@ -0,0 +1,98 @@
+#include
+
+// from the RTS
+void hs_init(int * argc, char **argv[]);
+
+//extern void __svfscanf(void){};
+//extern void __vfwscanf(void){};
+//extern void __memset_chk_fail(void){};
+//extern void __strcpy_chk_generic(void){};
+//extern void __strcat_chk_generic(void){};
+//extern void __libc_globals(void){};
+//extern void __rel_iplt_start(void){};
+
+// Android 9 only, not 13
+//extern void reallocarray(void){};
+
+JNIEXPORT void JNICALL
+Java_chat_simplex_common_platform_BackendKt_initHS(JNIEnv *env, jclass clazz) {
+ hs_init(NULL, NULL);
+}
+
+// from simplex-chat
+typedef long* chat_ctrl;
+
+extern char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl);
+extern char *chat_send_cmd(chat_ctrl ctrl, const char *cmd);
+extern char *chat_recv_msg(chat_ctrl ctrl); // deprecated
+extern char *chat_recv_msg_wait(chat_ctrl ctrl, const int wait);
+extern char *chat_parse_markdown(const char *str);
+extern char *chat_parse_server(const char *str);
+extern char *chat_password_hash(const char *pwd, const char *salt);
+
+JNIEXPORT jobjectArray JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatMigrateInit(JNIEnv *env, jclass clazz, jstring dbPath, jstring dbKey, jstring confirm) {
+ const char *_dbPath = (*env)->GetStringUTFChars(env, dbPath, JNI_FALSE);
+ const char *_dbKey = (*env)->GetStringUTFChars(env, dbKey, JNI_FALSE);
+ const char *_confirm = (*env)->GetStringUTFChars(env, confirm, JNI_FALSE);
+ jlong _ctrl = (jlong) 0;
+ jstring res = (*env)->NewStringUTF(env, chat_migrate_init(_dbPath, _dbKey, _confirm, &_ctrl));
+ (*env)->ReleaseStringUTFChars(env, dbPath, _dbPath);
+ (*env)->ReleaseStringUTFChars(env, dbKey, _dbKey);
+ (*env)->ReleaseStringUTFChars(env, dbKey, _confirm);
+
+ // Creating array of Object's (boxed values can be passed, eg. Long instead of long)
+ jobjectArray ret = (jobjectArray)(*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "java/lang/Object"), NULL);
+ // Java's String
+ (*env)->SetObjectArrayElement(env, ret, 0, res);
+ // Java's Long
+ (*env)->SetObjectArrayElement(env, ret, 1,
+ (*env)->NewObject(env, (*env)->FindClass(env, "java/lang/Long"),
+ (*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Long"), "", "(J)V"),
+ _ctrl));
+ return ret;
+}
+
+JNIEXPORT jstring JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatSendCmd(JNIEnv *env, jclass clazz, jlong controller, jstring msg) {
+ const char *_msg = (*env)->GetStringUTFChars(env, msg, JNI_FALSE);
+ jstring res = (*env)->NewStringUTF(env, chat_send_cmd((void*)controller, _msg));
+ (*env)->ReleaseStringUTFChars(env, msg, _msg);
+ return res;
+}
+
+JNIEXPORT jstring JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatRecvMsg(JNIEnv *env, jclass clazz, jlong controller) {
+ return (*env)->NewStringUTF(env, chat_recv_msg((void*)controller));
+}
+
+JNIEXPORT jstring JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatRecvMsgWait(JNIEnv *env, jclass clazz, jlong controller, jint wait) {
+ return (*env)->NewStringUTF(env, chat_recv_msg_wait((void*)controller, wait));
+}
+
+JNIEXPORT jstring JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatParseMarkdown(JNIEnv *env, jclass clazz, jstring str) {
+ const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE);
+ jstring res = (*env)->NewStringUTF(env, chat_parse_markdown(_str));
+ (*env)->ReleaseStringUTFChars(env, str, _str);
+ return res;
+}
+
+JNIEXPORT jstring JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatParseServer(JNIEnv *env, jclass clazz, jstring str) {
+ const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE);
+ jstring res = (*env)->NewStringUTF(env, chat_parse_server(_str));
+ (*env)->ReleaseStringUTFChars(env, str, _str);
+ return res;
+}
+
+JNIEXPORT jstring JNICALL
+Java_chat_simplex_common_platform_BackendKt_chatPasswordHash(JNIEnv *env, jclass clazz, jstring pwd, jstring salt) {
+ const char *_pwd = (*env)->GetStringUTFChars(env, pwd, JNI_FALSE);
+ const char *_salt = (*env)->GetStringUTFChars(env, salt, JNI_FALSE);
+ jstring res = (*env)->NewStringUTF(env, chat_password_hash(_pwd, _salt));
+ (*env)->ReleaseStringUTFChars(env, pwd, _pwd);
+ (*env)->ReleaseStringUTFChars(env, salt, _salt);
+ return res;
+}
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake
new file mode 100644
index 0000000000..4dd58aabf0
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake
@@ -0,0 +1,20 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR aarch64)
+
+set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
+set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")
+set(CMAKE_AR "aarch64-linux-gnu-ar" CACHE FILEPATH Archiver)
+set(CMAKE_RANLIB "aarch64-linux-gnu-ranlib" CACHE FILEPATH Indexer)
+
+set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+set(CMAKE_C_FLAGS "-march=armv8-a")
+set(CMAKE_CXX_FLAGS "-march=armv8-a")
+
+# cache flags
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake
new file mode 100644
index 0000000000..f69e17306f
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake
@@ -0,0 +1,17 @@
+set(CMAKE_SYSTEM_NAME Darwin)
+set(CMAKE_SYSTEM_PROCESSOR aarch64)
+
+set(CMAKE_C_COMPILER "gcc-13")
+set(CMAKE_CXX_COMPILER "g++-13")
+set(CMAKE_AR "gcc-ar-13" CACHE FILEPATH Archiver)
+set(CMAKE_RANLIB "gcc-ranlib-13" CACHE FILEPATH Indexer)
+
+set(CMAKE_FIND_ROOT_PATH /usr/)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# cache flags
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake
new file mode 100644
index 0000000000..e5dba46894
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake
@@ -0,0 +1,17 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR amd64)
+
+set(CMAKE_C_COMPILER "x86_64-linux-gnu-gcc")
+set(CMAKE_CXX_COMPILER "x86_64-linux-gnu-g++")
+set(CMAKE_AR "x86_64-linux-gnu-gcc-ar" CACHE FILEPATH Archiver)
+set(CMAKE_RANLIB "x86_64-linux-gnu-gcc-ranlib" CACHE FILEPATH Indexer)
+
+set(CMAKE_FIND_ROOT_PATH /usr/x86_64-linux-gnu)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# cache flags
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake
new file mode 100644
index 0000000000..a28b89d8af
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake
@@ -0,0 +1,17 @@
+set(CMAKE_SYSTEM_NAME Darwin)
+set(CMAKE_SYSTEM_PROCESSOR amd64)
+
+set(CMAKE_C_COMPILER "gcc-13")
+set(CMAKE_CXX_COMPILER "g++-13")
+set(CMAKE_AR "gcc-ar-13" CACHE FILEPATH Archiver)
+set(CMAKE_RANLIB "gcc-ranlib-13" CACHE FILEPATH Indexer)
+
+set(CMAKE_FIND_ROOT_PATH /usr/)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# cache flags
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake
new file mode 100644
index 0000000000..e34e871b18
--- /dev/null
+++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake
@@ -0,0 +1,17 @@
+set(CMAKE_SYSTEM_NAME Windows)
+set(CMAKE_SYSTEM_PROCESSOR amd64)
+
+set(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc")
+set(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++")
+set(CMAKE_AR "x86_64-w64-mingw32-ar" CACHE FILEPATH Archiver)
+set(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib" CACHE FILEPATH Indexer)
+
+set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# cache flags
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
diff --git a/apps/multiplatform/desktop/build.gradle.kts b/apps/multiplatform/desktop/build.gradle.kts
new file mode 100644
index 0000000000..95a4908dbd
--- /dev/null
+++ b/apps/multiplatform/desktop/build.gradle.kts
@@ -0,0 +1,169 @@
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
+
+plugins {
+ kotlin("multiplatform")
+ id("org.jetbrains.compose")
+ id("io.github.tomtzook.gradle-cmake") version "1.2.2"
+}
+
+group = "chat.simplex"
+version = extra["desktop.version_name"] as String
+
+
+kotlin {
+ jvm {
+ jvmToolchain(11)
+ withJava()
+ }
+ sourceSets {
+ val jvmMain by getting {
+ dependencies {
+ implementation(project(":common"))
+ implementation(compose.desktop.currentOs)
+ }
+ }
+ val jvmTest by getting
+ }
+}
+
+// https://github.com/JetBrains/compose-multiplatform/tree/master/tutorials/Native_distributions_and_local_execution
+compose {
+ desktop {
+ application {
+ mainClass = "MainKt"
+ nativeDistributions {
+ modules("jdk.zipfs")
+ //includeAllModules = true
+ outputBaseDir.set(project.file("../release"))
+ targetFormats(
+ TargetFormat.Deb, TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Exe
+ //, TargetFormat.AppImage // Gradle doesn't sync on Mac with it
+ )
+ linux {
+ iconFile.set(project.file("../common/src/commonMain/resources/distribute/simplex.png"))
+ appCategory = "Messenger"
+ }
+ windows {
+ // LALAL
+ iconFile.set(project.file("../common/src/commonMain/resources/distribute/simplex.ico"))
+ console = true
+ perUserInstall = true
+ dirChooser = true
+ }
+ macOS {
+ // LALAL
+ //iconFile.set(project.file("../common/src/commonMain/resources/distribute/simplex.icns"))
+ appCategory = "public.app-category.social-networking"
+ bundleID = "chat.simplex.app"
+ }
+ packageName = "simplex"
+ // Packaging requires to have version like MAJOR.MINOR.PATCH
+ var adjustedVersion = rootProject.extra["desktop.version_name"] as String
+ adjustedVersion = adjustedVersion.replace(Regex("[^0-9.]"), "")
+ if (adjustedVersion.split(".").size != 3) {
+ adjustedVersion += ".0"
+ }
+ version = adjustedVersion
+ }
+ }
+ }
+}
+
+val cppPath = "../common/src/commonMain/cpp"
+cmake {
+ // Run this command to make build for all targets:
+ // ./gradlew common:cmakeBuild -PcrossCompile
+ if (project.hasProperty("crossCompile")) {
+ machines.customMachines.register("linux-amd64") {
+ toolchainFile.set(project.file("$cppPath/toolchains/x86_64-linux-gnu-gcc.cmake"))
+ }
+ /*machines.customMachines.register("linux-aarch64") {
+ toolchainFile.set(project.file("$cppPath/toolchains/aarch64-linux-gnu-gcc.cmake"))
+ }*/
+ machines.customMachines.register("win-amd64") {
+ toolchainFile.set(project.file("$cppPath/toolchains/x86_64-windows-mingw32-gcc.cmake"))
+ }
+ if (machines.host.name == "mac-amd64") {
+ machines.customMachines.register("mac-amd64") {
+ toolchainFile.set(project.file("$cppPath/toolchains/x86_64-mac-apple-darwin-gcc.cmake"))
+ }
+ }
+ if (machines.host.name == "mac-aarch64") {
+ machines.customMachines.register("mac-aarch64") {
+ toolchainFile.set(project.file("$cppPath/toolchains/aarch64-mac-apple-darwin-gcc.cmake"))
+ }
+ }
+ }
+ val compileMachineTargets = arrayListOf(machines.host)
+ compileMachineTargets.addAll(machines.customMachines)
+ targets {
+ val main by creating {
+ cmakeLists.set(file("$cppPath/desktop/CMakeLists.txt"))
+ targetMachines.addAll(compileMachineTargets.toSet())
+ }
+ }
+}
+
+tasks.named("clean") {
+ dependsOn("cmakeClean")
+}
+tasks.named("compileJava") {
+ dependsOn("cmakeBuildAndCopy")
+}
+afterEvaluate {
+ tasks.create("cmakeBuildAndCopy") {
+ dependsOn("cmakeBuild")
+ doLast {
+ copy {
+ from("${project(":desktop").buildDir}/cmake/main/linux-amd64", "$cppPath/desktop/libs/linux-x86_64", "$cppPath/desktop/libs/linux-x86_64/deps")
+ into("../common/src/commonMain/resources/libs/linux-x86_64")
+ include("*.so")
+ eachFile {
+ path = name
+ }
+ includeEmptyDirs = false
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+ }
+ copy {
+ from("${project(":desktop").buildDir}/cmake/main/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64/deps")
+ into("../common/src/commonMain/resources/libs/linux-aarch64")
+ include("*.so")
+ eachFile {
+ path = name
+ }
+ includeEmptyDirs = false
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+ }
+ copy {
+ from("${project(":desktop").buildDir}/cmake/main/win-amd64", "$cppPath/desktop/libs/windows-x86_64", "$cppPath/desktop/libs/windows-x86_64/deps")
+ into("../common/src/commonMain/resources/libs/windows-x86_64")
+ include("*.dll")
+ eachFile {
+ path = name
+ }
+ includeEmptyDirs = false
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+ }
+ copy {
+ from("${project(":desktop").buildDir}/cmake/main/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64/deps")
+ into("../common/src/commonMain/resources/libs/mac-x86_64")
+ include("*.dylib")
+ eachFile {
+ path = name
+ }
+ includeEmptyDirs = false
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+ }
+ copy {
+ from("${project(":desktop").buildDir}/cmake/main/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64/deps")
+ into("../common/src/commonMain/resources/libs/mac-aarch64")
+ include("*.dylib")
+ eachFile {
+ path = name
+ }
+ includeEmptyDirs = false
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+ }
+ }
+ }
+}
diff --git a/apps/android/gradle.properties b/apps/multiplatform/gradle.properties
similarity index 87%
rename from apps/android/gradle.properties
rename to apps/multiplatform/gradle.properties
index cbbffa0869..ac73c373a4 100644
--- a/apps/android/gradle.properties
+++ b/apps/multiplatform/gradle.properties
@@ -23,3 +23,13 @@ kotlin.code.style=official
android.nonTransitiveRClass=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
+kotlin.mpp.androidSourceSetLayoutVersion=2
+
+android.version_name=5.2-beta.0
+android.version_code=129
+
+desktop.version_name=1.0
+
+kotlin.version=1.8.20
+gradle.plugin.version=7.4.2
+compose.version=1.4.0
diff --git a/apps/android/gradle/wrapper/gradle-wrapper.jar b/apps/multiplatform/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from apps/android/gradle/wrapper/gradle-wrapper.jar
rename to apps/multiplatform/gradle/wrapper/gradle-wrapper.jar
diff --git a/apps/android/gradle/wrapper/gradle-wrapper.properties b/apps/multiplatform/gradle/wrapper/gradle-wrapper.properties
similarity index 93%
rename from apps/android/gradle/wrapper/gradle-wrapper.properties
rename to apps/multiplatform/gradle/wrapper/gradle-wrapper.properties
index 88ac00ff11..00c09d815c 100644
--- a/apps/android/gradle/wrapper/gradle-wrapper.properties
+++ b/apps/multiplatform/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Mon Feb 14 14:23:51 GMT 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/apps/android/gradlew b/apps/multiplatform/gradlew
similarity index 100%
rename from apps/android/gradlew
rename to apps/multiplatform/gradlew
diff --git a/apps/android/gradlew.bat b/apps/multiplatform/gradlew.bat
similarity index 100%
rename from apps/android/gradlew.bat
rename to apps/multiplatform/gradlew.bat
diff --git a/apps/multiplatform/settings.gradle.kts b/apps/multiplatform/settings.gradle.kts
new file mode 100644
index 0000000000..ba047edf1e
--- /dev/null
+++ b/apps/multiplatform/settings.gradle.kts
@@ -0,0 +1,21 @@
+pluginManagement {
+ repositories {
+ google()
+ gradlePluginPortal()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+ }
+
+ plugins {
+ kotlin("multiplatform").version(extra["kotlin.version"] as String)
+ kotlin("android").version(extra["kotlin.version"] as String)
+ id("com.android.application").version(extra["gradle.plugin.version"] as String)
+ id("com.android.library").version(extra["gradle.plugin.version"] as String)
+ id("org.jetbrains.compose").version(extra["compose.version"] as String)
+ id("org.jetbrains.kotlin.plugin.serialization").version(extra["kotlin.version"] as String)
+ }
+}
+
+rootProject.name = "app"
+
+include(":android", ":desktop", ":common")
diff --git a/cabal.project b/cabal.project
index 1119f593e6..82e9949a58 100644
--- a/cabal.project
+++ b/cabal.project
@@ -7,7 +7,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
- tag: 3a74558e8449faa65dd6c72f01d3856d748f8102
+ tag: 54dc8d42e7594632daeadf0a0f115936b17165af
source-repository-package
type: git
diff --git a/docs/THEMES.md b/docs/THEMES.md
index 6b06a18fd2..693d0c311a 100644
--- a/docs/THEMES.md
+++ b/docs/THEMES.md
@@ -8,7 +8,7 @@ You can contribute your themes to the repository by creating a pull request.
1. Once you have configured your theme in the app, export it to a file and give it a descriptive name – e.g., `example.theme`
-2. Export your app database, and import a [sample chat database](./themes/simplex-chat.sample.zip).
+2. Export your app database, and import a [sample chat database](./themes/simplex-chat.sample.zip) - the passphrase is `passphrase`.
3. Make three screenshots - the list of conversations with opened profile picker, conversation and privacy settings.
diff --git a/packages/simplex-chat-webrtc/copy b/packages/simplex-chat-webrtc/copy
index 1b766264fb..4991cdef45 100755
--- a/packages/simplex-chat-webrtc/copy
+++ b/packages/simplex-chat-webrtc/copy
@@ -8,7 +8,7 @@ cp ./src/webcall.html ./dist/webcall.html
cp ./src/ui.js ./dist/ui.js
# copy to android app
-cp ./src/call.html ../../apps/android/app/src/main/assets/www/call.html
-cp ./src/style.css ../../apps/android/app/src/main/assets/www/style.css
-cp ./dist/call.js ../../apps/android/app/src/main/assets/www/call.js
-cp ./node_modules/lz-string/libs/lz-string.min.js ../../apps/android/app/src/main/assets/www/lz-string.min.js
+cp ./src/call.html ../../apps/multiplatform/android/src/main/assets/www/call.html
+cp ./src/style.css ../../apps/multiplatform/android/src/main/assets/www/style.css
+cp ./dist/call.js ../../apps/multiplatform/android/src/main/assets/www/call.js
+cp ./node_modules/lz-string/libs/lz-string.min.js ../../apps/multiplatform/android/src/main/assets/www/lz-string.min.js
diff --git a/scripts/android/build-android-bundle.sh b/scripts/android/build-android-bundle.sh
index 18aa03145a..554e64edff 100755
--- a/scripts/android/build-android-bundle.sh
+++ b/scripts/android/build-android-bundle.sh
@@ -15,13 +15,13 @@ git clone https://github.com/simplex-chat/simplex-chat "$tmp/simplex-chat"
git -C "$tmp/simplex-chat" checkout "$commit"
# Create missing folders
-mkdir -p "$tmp/simplex-chat/apps/android/app/src/main/cpp/libs/arm64-v8a"
+mkdir -p "$tmp/simplex-chat/apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a"
curl -sSf "$libsim" -o "$tmp/libsimplex.zip"
-unzip -o "$tmp/libsimplex.zip" -d "$tmp/simplex-chat/apps/android/app/src/main/cpp/libs/arm64-v8a"
+unzip -o "$tmp/libsimplex.zip" -d "$tmp/simplex-chat/apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a"
curl -sSf "$libsup" -o "$tmp/libsupport.zip"
-unzip -o "$tmp/libsupport.zip" -d "$tmp/simplex-chat/apps/android/app/src/main/cpp/libs/arm64-v8a"
+unzip -o "$tmp/libsupport.zip" -d "$tmp/simplex-chat/apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a"
-gradle -p "$tmp/simplex-chat/apps/android/" clean build
-cp "$tmp/simplex-chat/apps/android/app/build/outputs/apk/release/app-release-unsigned.apk" "$PWD/simplex-chat.apk"
+gradle -p "$tmp/simplex-chat/apps/multiplatform/" clean build
+cp "$tmp/simplex-chat/apps/multiplatform/android/build/outputs/apk/release/android-release-unsigned.apk" "$PWD/simplex-chat.apk"
diff --git a/scripts/android/build-android.sh b/scripts/android/build-android.sh
index 87f9776b1b..90916a96fe 100755
--- a/scripts/android/build-android.sh
+++ b/scripts/android/build-android.sh
@@ -81,21 +81,21 @@ checks() {
build() {
# Build preparations
- sed -i.bak 's/${extract_native_libs}/true/' "$folder/apps/android/app/src/main/AndroidManifest.xml"
- sed -i.bak '/android {/a lint {abortOnError false}' "$folder/apps/android/app/build.gradle"
+ sed -i.bak 's/${extract_native_libs}/true/' "$folder/apps/multiplatform/android/src/main/AndroidManifest.xml"
+ sed -i.bak '/android {/a lint {abortOnError false}' "$folder/apps/multiplatform/android/build.gradle.kts"
for arch in $arches; do
android_simplex_lib="${folder}#hydraJobs.${arch}-android:lib:simplex-chat.x86_64-linux"
android_support_lib="${folder}#hydraJobs.${arch}-android:lib:support.x86_64-linux"
android_simplex_lib_output="${PWD}/result/pkg-${arch}-android-libsimplex.zip"
android_support_lib_output="${PWD}/result/pkg-${arch}-android-libsupport.zip"
-
+
arch_map "$arch"
android_tmp_folder="${tmp}/android-${arch}"
- android_apk_output="${folder}/apps/android/app/build/outputs/apk/release/app-${android_arch}-release-unsigned.apk"
+ android_apk_output="${folder}/apps/multiplatform/android/build/outputs/apk/release/android-${android_arch}-release-unsigned.apk"
android_apk_output_final="simplex-chat-${android_arch}.apk"
- libs_folder="$folder/apps/android/app/src/main/cpp/libs"
+ libs_folder="$folder/apps/multiplatform/common/src/commonMain/cpp/android/libs"
# Create missing folders
mkdir -p "$libs_folder/$android_arch"
@@ -107,12 +107,12 @@ build() {
unzip -o "$android_support_lib_output" -d "$libs_folder/$android_arch"
# Build only one arch
- sed -i.bak "s/include '.*/include '${android_arch}'/" "$folder/apps/android/app/build.gradle"
- gradle -p "$folder/apps/android/" clean assembleRelease
-
+ sed -i.bak "s/include '.*/include '${android_arch}'/" "$folder/apps/multiplatform/android/build.gradle.kts"
+ gradle -p "$folder/apps/multiplatform/" clean assembleRelease
+
mkdir -p "$android_tmp_folder"
unzip -oqd "$android_tmp_folder" "$android_apk_output"
-
+
(
cd "$android_tmp_folder" && \
zip -rq5 "$tmp/$android_apk_output_final" . && \
diff --git a/scripts/android/compress-and-sign-apk.sh b/scripts/android/compress-and-sign-apk.sh
index 586511cdfa..e46b8a54f1 100755
--- a/scripts/android/compress-and-sign-apk.sh
+++ b/scripts/android/compress-and-sign-apk.sh
@@ -23,7 +23,7 @@ touch remove_this_file remove_this_FILE
#echo Case-insensitive file system: $case_insensitive
rm remove_this_file remove_this_FILE 2> /dev/null || true
-ORIG_NAMES=( $(echo app*.apk) )
+ORIG_NAMES=( $(echo android*.apk) )
for ORIG_NAME in "${ORIG_NAMES[@]}"; do
unzip -o -q -d apk $ORIG_NAME
ORIG_NAME_COPY=$ORIG_NAME-copy
diff --git a/scripts/android/download-libs.sh b/scripts/android/download-libs.sh
index dd1b1fb2d1..f67cc397a7 100755
--- a/scripts/android/download-libs.sh
+++ b/scripts/android/download-libs.sh
@@ -33,7 +33,7 @@ root_dir="$(dirname "$(dirname "$(readlink "$0")")")"
for ((i = 0 ; i < ${#arches[@]}; i++)); do
arch="${arches[$i]}"
output_arch="${output_arches[$i]}"
- output_dir="$root_dir/apps/android/app/src/main/cpp/libs/$output_arch/"
+ output_dir="$root_dir/apps/multiplatform/common/src/commonMain/cpp/android/libs/$output_arch/"
mkdir -p "$output_dir" 2> /dev/null
diff --git a/scripts/android/prepare.sh b/scripts/android/prepare.sh
index 4947d0c2b3..683d9cbf87 100755
--- a/scripts/android/prepare.sh
+++ b/scripts/android/prepare.sh
@@ -1,12 +1,12 @@
#!/bin/sh
# libsimplex.so and libsupport.so binaries should be in ~/Downloads folder in their directories based on archive name
-mkdir -p ./apps/android/app/src/main/cpp/libs/arm64-v8a/
-rm ./apps/android/app/src/main/cpp/libs/arm64-v8a/*
-unzip -o ~/Downloads/pkg-aarch64-android-libsupport.zip -d ./apps/android/app/src/main/cpp/libs/arm64-v8a
-unzip -o ~/Downloads/pkg-aarch64-android-libsimplex.zip -d ./apps/android/app/src/main/cpp/libs/arm64-v8a/
+mkdir -p ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a/
+rm ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a/*
+unzip -o ~/Downloads/pkg-aarch64-android-libsupport.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a
+unzip -o ~/Downloads/pkg-aarch64-android-libsimplex.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a/
-mkdir -p ./apps/android/app/src/main/cpp/libs/armeabi-v7a/
-rm ./apps/android/app/src/main/cpp/libs/armeabi-v7a/*
-unzip -o ~/Downloads/pkg-armv7a-android-libsupport.zip -d ./apps/android/app/src/main/cpp/libs/armeabi-v7a/
-unzip -o ~/Downloads/pkg-armv7a-android-libsimplex.zip -d ./apps/android/app/src/main/cpp/libs/armeabi-v7a/
+mkdir -p ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/
+rm ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/*
+unzip -o ~/Downloads/pkg-armv7a-android-libsupport.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/
+unzip -o ~/Downloads/pkg-armv7a-android-libsimplex.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/
diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix
index e1198e4c81..679b55456a 100644
--- a/scripts/nix/sha256map.nix
+++ b/scripts/nix/sha256map.nix
@@ -1,5 +1,5 @@
{
- "https://github.com/simplex-chat/simplexmq.git"."3a74558e8449faa65dd6c72f01d3856d748f8102" = "1i1g01ipbvb0ajws7k1n1p03wv4ldf63y3zny6c76vpazxbflcpc";
+ "https://github.com/simplex-chat/simplexmq.git"."54dc8d42e7594632daeadf0a0f115936b17165af" = "02lhlnwcyr3zmr11drmfwwmn6a54s7id9qzsdlqvi16dr5va245d";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb";
"https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd";
diff --git a/stack.yaml b/stack.yaml
index 9802cd4654..12a92c8fdc 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -49,7 +49,7 @@ extra-deps:
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
# - ../simplexmq
- github: simplex-chat/simplexmq
- commit: 3a74558e8449faa65dd6c72f01d3856d748f8102
+ commit: 54dc8d42e7594632daeadf0a0f115936b17165af
- github: kazu-yamamoto/http2
commit: b5a1b7200cf5bc7044af34ba325284271f6dff25
# - ../direct-sqlcipher
diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs
index 13eb391f00..8970c6304d 100644
--- a/tests/ChatClient.hs
+++ b/tests/ChatClient.hs
@@ -37,6 +37,7 @@ import Simplex.Messaging.Client (ProtocolClientConfig (..), defaultNetworkConfig
import Simplex.Messaging.Server (runSMPServerBlocking)
import Simplex.Messaging.Server.Env.STM
import Simplex.Messaging.Transport
+import Simplex.Messaging.Transport.Server (defaultTransportServerConfig)
import Simplex.Messaging.Version
import System.Directory (createDirectoryIfMissing, removeDirectoryRecursive)
import System.FilePath ((>))
@@ -125,7 +126,7 @@ testAgentCfgV1 =
testAgentCfg
{ smpClientVRange = mkVersionRange 1 1,
smpAgentVRange = mkVersionRange 1 1,
- smpCfg = (smpCfg testAgentCfg) {smpServerVRange = mkVersionRange 1 1}
+ smpCfg = (smpCfg testAgentCfg) {serverVRange = mkVersionRange 1 1}
}
testCfgV1 :: ChatConfig
@@ -318,7 +319,7 @@ serverCfg =
serverStatsLogFile = "tests/smp-server-stats.daily.log",
serverStatsBackupFile = Nothing,
smpServerVRange = supportedSMPServerVRange,
- logTLSErrors = True
+ transportConfig = defaultTransportServerConfig
}
withSmpServer :: IO () -> IO ()
@@ -349,7 +350,7 @@ xftpServerConfig =
logStatsStartTime = 0,
serverStatsLogFile = "tests/tmp/xftp-server-stats.daily.log",
serverStatsBackupFile = Nothing,
- logTLSErrors = True
+ transportConfig = defaultTransportServerConfig
}
withXFTPServer :: IO () -> IO ()
diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs
index 0fee08f79a..941fa2aff2 100644
--- a/tests/ChatTests/Direct.hs
+++ b/tests/ChatTests/Direct.hs
@@ -86,7 +86,7 @@ chatDirectTests = do
it "mark contact verified" testMarkContactVerified
it "mark group member verified" testMarkGroupMemberVerified
describe "message errors" $ do
- it "show message decryption error and update count" testMsgDecryptError
+ xit "show message decryption error and update count" testMsgDecryptError
describe "message reactions" $ do
it "set message reactions" testSetMessageReactions
diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs
index 1f89dd3df9..1e724ce007 100644
--- a/tests/ChatTests/Groups.hs
+++ b/tests/ChatTests/Groups.hs
@@ -56,7 +56,7 @@ chatGroupTests = do
it "group link member role" testGroupLinkMemberRole
it "leaving and deleting the group joined via link should NOT delete previously existing direct contacts" testGroupLinkLeaveDelete
describe "group message errors" $ do
- it "show message decryption error and update count" testGroupMsgDecryptError
+ xit "show message decryption error and update count" testGroupMsgDecryptError
describe "message reactions" $ do
it "set group message reactions" testSetGroupMessageReactions
diff --git a/website/src/css/demo.css b/website/src/css/demo.css
new file mode 100644
index 0000000000..d4995d2cd7
--- /dev/null
+++ b/website/src/css/demo.css
@@ -0,0 +1,226 @@
+#demo {
+ padding-top: 3.5rem;
+ padding-bottom: 2.5rem;
+ text-align: center;
+}
+
+#demo .all-users {
+ position: relative;
+ height: 640px;
+}
+
+#demo .user {
+ position: absolute;
+}
+
+#demo h3 {
+ position: absolute;
+ top: -60px;
+ text-align: left;
+ padding: 0 0 5px 7px;
+ color: #ffffbb;
+ mix-blend-mode: difference;
+ font-size: 1.5rem;
+ margin-bottom: 2rem;
+}
+
+#demo .user .terminal {
+ text-align: left;
+ position: relative;
+ background-color: rgba(0, 0, 0, 0.8);
+ border-radius: 10px;
+ box-sizing: border-box;
+ padding: 10px 10px;
+ color: white;
+ overflow-y: hidden;
+}
+
+#demo .user .terminal:before {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ height: 20px;
+ background: #666 url(/img/topbar.svg) no-repeat 8px center;
+ border-radius: 10px 10px 0 0;
+ z-index: 2;
+}
+
+#demo .user .terminal input,
+#demo .user .terminal .input,
+#demo .user .terminal .display {
+ font-family: Menlo, "Lucida Console", Monaco, monospace;
+ font-size: 14px;
+ letter-spacing: 0.27px;
+ line-height: 28px;
+ position: absolute;
+ left: 10px;
+ right: 10px;
+}
+
+#demo .user .terminal input,
+#demo .user .terminal .input {
+ color: white;
+ display: block;
+ height: 30px;
+ bottom: 0;
+}
+
+#demo .user .terminal input {
+ background-color: transparent;
+ display: none;
+ left: 25px;
+ width: calc(100% - 30px);
+}
+
+#demo .user .terminal .display {
+ color: white;
+ text-align: left;
+ bottom: 30px;
+ z-index: 1;
+ overflow-x: hidden;
+ word-wrap: break-word;
+}
+
+#demo .user .terminal .display .info {
+ color: white;
+}
+
+#demo .user .terminal .display .error {
+ color: #ff6347;
+}
+
+#demo .user .terminal .display .sent span.group {
+ color: cyan;
+}
+
+#demo .user .terminal .display .received span.group {
+ color: yellow;
+}
+
+#demo .user .terminal .display span {
+ font-family: Menlo, Monaco, "Lucida Console", monospace;
+ text-align: left;
+ margin: 0 0;
+}
+
+#demo .user .terminal .display span.recipient {
+ color: cyan;
+}
+
+#demo .user .terminal .display span.sender {
+ color: yellow;
+}
+
+#demo .user .terminal .display span.secret {
+ color: rgba(0, 0, 0, 0.4);
+ background-color: rgba(0, 0, 0, 0.4);
+}
+
+#demo .alice {
+ left: -30px;
+ top: 102px;
+}
+
+#demo .bob {
+ left: 425px;
+ top: 0px;
+}
+
+#demo .tom {
+ left: 425px;
+ top: 378px;
+}
+
+#demo .all-users .terminal {
+ width: 410px;
+}
+
+#demo .alice .terminal {
+ height: 340px;
+}
+
+#demo .bob .terminal {
+ height: 305px;
+}
+
+#demo .tom .terminal {
+ height: 280px;
+}
+
+
+/* Demo buttons */
+#demo button {
+ position: absolute;
+ width: 140px;
+ height: 40px;
+ bottom: 85px;
+ font-size: 16px;
+ border-radius: 34px;
+ color: white;
+ font-weight: 500;
+ letter-spacing: 0.02em;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 1.25rem;
+ padding-right: 1.25rem;
+ background-color: #0053d0;
+}
+
+.dark #demo button {
+ color: black;
+ background-color: #70f0f9;
+}
+
+#demo button:disabled {
+ filter: brightness(75%);
+}
+
+#demo .run-demo {
+ left: 20px;
+}
+
+#demo .run-faster {
+ left: 20px;
+ display: none;
+}
+
+#demo .try-it {
+ left: 180px;
+}
+
+@media (max-width: 1240px) {
+ #demo .all-users {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ #demo .alice {
+ position: relative !important;
+ top: 0;
+ left: 0;
+ }
+
+ #demo button,
+ #demo .bob,
+ #demo .tom {
+ display: none;
+ }
+}
+
+@media (max-width: 570px) {
+ #demo .alice .terminal {
+ width: 400px;
+ }
+}
+
+@media (max-width: 440px) {
+ #demo .alice .terminal {
+ width: 330px;
+ height: 420px;
+ }
+}
\ No newline at end of file
diff --git a/website/src/js/demo.js b/website/src/js/demo.js
new file mode 100644
index 0000000000..21beec97f4
--- /dev/null
+++ b/website/src/js/demo.js
@@ -0,0 +1,347 @@
+(async function () {
+ let DELAY = 0;
+ const DISTR = 0.33;
+
+ class User {
+ constructor(name) {
+ this.userWindow = document.querySelector(`#demo .user.${name}`);
+ this.terminal = this.userWindow.querySelector(`.terminal`);
+ this.input = this.terminal.querySelector(".input");
+ this.demoInput = this.terminal.querySelector("input");
+ this.resetInput();
+ this.setupDemo();
+ this.group = [];
+ this.display = this.terminal.querySelector(".display");
+ this.setupMoveWindow();
+ this.name = name;
+ }
+
+ reset() {
+ this.resetInput();
+ this.display.innerHTML = "";
+ }
+
+ setGroup(groupName, users) {
+ this.users = users;
+ this.group = users.filter((u) => u !== this);
+ this.groupName = groupName;
+ }
+
+ tryDemo() {
+ this.reset();
+ show(this.demoInput);
+ this.demoInput.value = "";
+ }
+
+ async send(to, message, typeTo, paste, secret) {
+ await this._sendMsg(`@${to.name}`, message, typeTo, paste, secret);
+ await to.receive(this, toSecret(secret, message));
+ await delay(20);
+ }
+
+ async sendGroup(message, typeTo, paste) {
+ await this._sendMsg(`#${this.groupName}`, message, typeTo, paste);
+ await this.receiveGroup(message);
+ await delay(10);
+ }
+
+ async _sendMsg(toStr, message, typeTo, paste, secret) {
+ await this.type(`${toStr} `, !typeTo);
+ if (secret) await this.type("#");
+ await this.type(message, paste);
+ if (secret) await this.type("#");
+ await delay(10);
+ this.resetInput();
+ this.show("sent", `${toStr} ${toSecret(secret, message)}`);
+ }
+
+ async type(str, paste) {
+ if (paste) {
+ await delay(10);
+ this.input.insertAdjacentHTML("beforeend", str);
+ } else {
+ for (const char of str) {
+ await delay(isAlpha(char) ? 1 : 2);
+ this.input.insertAdjacentHTML("beforeend", char);
+ }
+ }
+ await delay(2);
+ }
+
+ resetInput() {
+ this.input.innerHTML = "> ";
+ show(this.demoInput, false);
+ }
+
+ async receive(from, message, edit, group) {
+ await delay(10);
+ let g = group ? `#${this.groupName} ` : "";
+ this.show("received", `${g}${from.name}> ${message}`, edit);
+ }
+
+ async receiveGroup(message, edit) {
+ await Promise.all(this.group.map((u) => u.receive(this, message, edit, true)));
+ }
+
+ show(mode, str, edit) {
+ if (edit && this.lastMessage) {
+ this.lastMessage.innerHTML = highlight(str);
+ return;
+ }
+ this.display.insertAdjacentHTML("beforeend", `${highlight(str)}
`);
+ }
+
+ setupDemo() {
+ if (!this.demoInput) return;
+ let editMode = false;
+
+ on("keypress", this.demoInput, async ({ key }) => {
+ if (key === "Enter") {
+ const edit = editMode;
+ editMode = false;
+ const [to, ...words] = this.demoInput.value.trim().split(" ");
+ const message = words.join(" ");
+ switch (to[0]) {
+ case undefined:
+ if (message !== "") {
+ this.show("error", "Message should start with @user or #group");
+ }
+ break;
+ case "@":
+ await this.sendInput(to.slice(1), message, edit);
+ break;
+ case "#":
+ await this.sendInputGroup(to.slice(1), message, edit);
+ break;
+ default:
+ this.show("error", "Message should start with @user or #group");
+ }
+ } else if (this.demoInput.value === "" && key !== "@" && key !== "#") {
+ const channel = this.currentChannel();
+ if (channel) this.demoInput.value = channel + " ";
+ }
+ });
+ on("keydown", this.demoInput, async (e) => {
+ switch (e.key) {
+ case "ArrowUp":
+ if (this.demoInput.value === "" && this.lastMessage) {
+ const str = (this.demoInput.value = this.lastMessage.innerText);
+ editMode = true;
+ await delay(0);
+ this.demoInput.selectionStart = str.length;
+ }
+ break;
+ case "Tab": {
+ e.preventDefault();
+ const userIndex = this.users.indexOf(this);
+ const nextIndex = (userIndex + 1) % this.users.length;
+ this.users[nextIndex].demoInput.focus();
+ }
+ }
+ });
+ }
+
+ async sendInput(name, message, edit) {
+ if (name === this.name) {
+ this.show("error", "Can't send message to yourself");
+ return;
+ }
+ const recipient = this.group.find((u) => u.name === name);
+ if (recipient === undefined) {
+ const knownNames = this.group.map((u) => `@${u.name}`).join(", ") + ` or @${this.name}`;
+ this.show("error", `Unknown recipient @${name} (try ${knownNames})`);
+ return;
+ }
+ this.show("sent", `@${name} ${message}`, edit);
+ this.demoInput.value = "";
+ await recipient.receive(this, message, edit);
+ }
+
+ async sendInputGroup(name, message, edit) {
+ if (name !== this.groupName) {
+ this.show("error", `Unknown group #${name} (try #team)`);
+ return;
+ }
+ this.show("sent", `#${name} ${message}`, edit);
+ this.demoInput.value = "";
+ await this.receiveGroup(message, edit);
+ }
+
+ get lastMessage() {
+ const messages = this.display.childNodes;
+ return messages[messages.length - 1];
+ }
+
+ currentChannel() {
+ return this.lastMessage && toContact(this.lastMessage.childNodes[0].innerHTML);
+ }
+
+ setupMoveWindow() {
+ let moving = false;
+ let startX, startY;
+ const user = this.userWindow;
+ const parent = user.parentNode;
+
+ on("mousedown", this.terminal, (e) => {
+ if (e.clientY - this.terminal.getBoundingClientRect().top > 20) return;
+ moving = true;
+ startX = user.offsetLeft - e.clientX;
+ startY = user.offsetTop - e.clientY;
+ parent.removeChild(user);
+ parent.appendChild(user);
+ });
+ on("mouseup", this.terminal, () => (moving = false));
+ on("mouseleave", this.terminal, () => (moving = false));
+ on("mousemove", this.terminal, (e) => {
+ if (!moving) return;
+ user.style.left = e.clientX + startX + "px";
+ user.style.top = e.clientY + startY + "px";
+ });
+ }
+ }
+
+ function toContact(str) {
+ return str.endsWith(">") ? "@" + str.slice(0, -4) : str;
+ }
+
+ function setGroup(groupName, users) {
+ users.forEach((u) => u.setGroup(groupName, users));
+ }
+
+ const alice = new User("alice");
+ const bob = new User("bob");
+ const tom = new User("tom");
+ const team = [alice, bob, tom];
+ setGroup("team", team);
+
+ async function chatDemo() {
+ team.forEach((u) => u.reset());
+ await alice.sendGroup("please review my PR project/site#72", true);
+ await tom.sendGroup("anybody got application key 🔑?");
+ await bob.sendGroup("looking at it now @alice 👀");
+ await alice.sendGroup("thanks @bob!");
+ await alice.sendGroup("will DM @tom");
+ await alice.send(tom, "w3@o6CewoZx#%$SQETXbWnus", true, true, true);
+ await tom.send(alice, "you're the savior 🙏!");
+ await alice.send(bob, "please check the tests too", true);
+ await bob.send(alice, "all looks good 👍");
+ await alice.send(bob, "thank you!");
+ DELAY = 80;
+ }
+
+ const invitation =
+ "smp::example.com:5223#1XNE1m2E1m0lm92WGKet9CL6+lO742Vy5G6nsrkvgs8=::St9hPY+k6nfrbaXj::rsa:MIIBoTANBgkqhkiG9w0BAQEFAAOCAY4AMIIBiQKCAQEA03XGpEqh3faDNGl06pPhaT==";
+
+ async function establishConnection() {
+ team.forEach((u) => u.reset());
+ await alice.type("/add bob");
+ await delay(10);
+ alice.resetInput();
+ // alice.show("/add bob");
+ alice.show("sent", "pass this invitation to your contact (via any channel):");
+ alice.show("sent", " ");
+ alice.show("sent", invitation);
+ alice.show("sent", " ");
+ alice.show("sent", "and ask them to connect:");
+ alice.show("sent", "/c name_for_you invitation_above");
+ await delay(20);
+ await bob.type("/connect alice ");
+ await bob.type(invitation, true);
+ await delay(20);
+ bob.resetInput();
+ await bob.show("received", "/connect alice " + invitation);
+ await delay(10);
+ bob.show("received", "@alice connected");
+ await delay(2);
+ alice.show("received", "@bob connected");
+ await alice.send(bob, "hello bob");
+ await bob.send(alice, "hi alice");
+ }
+
+ await chatDemo();
+ const RUN_DEMO = "#demo .run-demo";
+ const RUN_FASTER = "#demo .run-faster";
+ const TRY_IT = "#demo .try-it";
+ onClick(RUN_DEMO, runChatDemo);
+ // onClick(RUN_DEMO, establishConnection);
+ onClick(RUN_FASTER, () => (DELAY /= 2));
+ onClick(TRY_IT, tryChatDemo);
+
+ async function runChatDemo() {
+ show(RUN_DEMO, false);
+ show(RUN_FASTER);
+ enable(TRY_IT, false);
+ await chatDemo();
+ show(RUN_DEMO);
+ show(RUN_FASTER, false);
+ enable(TRY_IT);
+ }
+
+ function tryChatDemo() {
+ team.forEach((u) => u.tryDemo());
+ alice.demoInput.focus();
+ }
+
+ async function delay(units) {
+ // delay is random with `1 +/- DISTR` range
+ const ms = units * DELAY * (1 - DISTR + 2 * DISTR * Math.random());
+ return new Promise((resolve) => setTimeout(resolve, ms));
+ }
+
+ function highlight(str) {
+ return str
+ .replace(/(@[a-z]+)([^0-9]|$)/gi, `$1$2`)
+ .replace(/([a-z]+>)([^0-9]|$)/gi, `$1$2`)
+ .replace(/(#[a-z]+)([^0-9]|$)/gi, `$1$2`)
+ .replace(/#([^\s]+)#([\s]|$)/gi, `#$1#$2`);
+ }
+
+ function toSecret(secret, message) {
+ return secret ? `#${message}#` : message;
+ }
+
+ function isAlpha(c) {
+ c = c.toUpperCase();
+ return c >= "A" && c <= "Z";
+ }
+
+ let flipper = setInterval(flipProblem, 10000);
+
+ onClick("#problem .pagination", () => {
+ clearInterval(flipper);
+ flipper = setInterval(flipProblem, 20000);
+ });
+
+ function flipProblem() {
+ if (isElementInViewport(document.getElementById("problem"))) {
+ window.location.hash =
+ window.location.hash === "#problem-explained" ? "#problem-intro" : "#problem-explained";
+ }
+ }
+
+ function isElementInViewport(el) {
+ if (!el) return false;
+ const r = el.getBoundingClientRect();
+ return r.bottom >= 0 && r.top <= window.innerHeight;
+ }
+
+ function onClick(selector, handler, enable = true) {
+ const el = document.querySelector(selector);
+ if (el) on("click", el, handler, enable);
+ }
+
+ function on(event, el, handler, enable = true) {
+ const method = enable ? "addEventListener" : "removeEventListener";
+ el[method](event, handler);
+ }
+
+ function show(selector, visible = true) {
+ const el = typeof selector === "string" ? document.querySelector(selector) : selector;
+ if (el) el.style.display = visible ? "block" : "none";
+ }
+
+ function enable(selector, enabled = true) {
+ const el = document.querySelector(selector);
+ el.disabled = enabled ? "" : "true";
+ }
+})();
diff --git a/website/src/js/docs.js b/website/src/js/docs.js
index 4535fb5ea9..137923482c 100644
--- a/website/src/js/docs.js
+++ b/website/src/js/docs.js
@@ -1,4 +1,51 @@
document.addEventListener("DOMContentLoaded", function () {
+ if (window.location.pathname.endsWith('cli.html')) {
+ const cliHeader = document.querySelector('h1')
+ const demoSection = document.createElement('section')
+ demoSection.id = 'demo'
+ demoSection.innerHTML = `
+
+
+
+
+
+
+
+
+ `
+ cliHeader.parentNode.insertBefore(demoSection, cliHeader.nextSibling)
+
+ const demoScript = document.createElement('script')
+ demoScript.src = '/js/demo.js'
+ document.body.appendChild(demoScript)
+
+ const demoStyles = document.createElement('link')
+ demoStyles.rel = 'stylesheet'
+ demoStyles.href = '/css/demo.css'
+ document.head.appendChild(demoStyles)
+ }
+
const imgs = document.querySelectorAll('p img')
imgs.forEach(img => {
console.log(img.height)