react-native-nitro-country-picker 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/NitroCountryPicker.podspec +37 -0
- package/README.md +164 -0
- package/android/CMakeLists.txt +24 -0
- package/android/build.gradle +149 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/nitrocountrypicker/CountryPickerActivity.kt +95 -0
- package/android/src/main/java/com/margelo/nitro/nitrocountrypicker/NitroCountryPicker.kt +132 -0
- package/android/src/main/java/com/margelo/nitro/nitrocountrypicker/NitroCountryPickerPackage.kt +36 -0
- package/ios/NitroCountryPicker.swift +94 -0
- package/lib/module/NitroCountryPicker.nitro.js +4 -0
- package/lib/module/NitroCountryPicker.nitro.js.map +1 -0
- package/lib/module/index.js +11 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NitroCountryPicker.nitro.d.ts +17 -0
- package/lib/typescript/src/NitroCountryPicker.nitro.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/nitro.json +23 -0
- package/nitrogen/generated/android/c++/JHybridNitroCountryPickerSpec.cpp +83 -0
- package/nitrogen/generated/android/c++/JHybridNitroCountryPickerSpec.hpp +64 -0
- package/nitrogen/generated/android/c++/JIPickedCountry.hpp +65 -0
- package/nitrogen/generated/android/c++/JPickCountryOptions.hpp +58 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_IPickedCountry.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_IPickedCountry.hpp +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocountrypicker/HybridNitroCountryPickerSpec.kt +60 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocountrypicker/IPickedCountry.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocountrypicker/PickCountryOptions.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocountrypicker/Variant_NullType_IPickedCountry.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocountrypicker/nitrocountrypickerOnLoad.kt +35 -0
- package/nitrogen/generated/android/nitrocountrypicker+autolinking.cmake +82 -0
- package/nitrogen/generated/android/nitrocountrypicker+autolinking.gradle +27 -0
- package/nitrogen/generated/android/nitrocountrypickerOnLoad.cpp +54 -0
- package/nitrogen/generated/android/nitrocountrypickerOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/NitroCountryPicker+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroCountryPicker-Swift-Cxx-Bridge.cpp +49 -0
- package/nitrogen/generated/ios/NitroCountryPicker-Swift-Cxx-Bridge.hpp +188 -0
- package/nitrogen/generated/ios/NitroCountryPicker-Swift-Cxx-Umbrella.hpp +54 -0
- package/nitrogen/generated/ios/NitroCountryPickerAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroCountryPickerAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridNitroCountryPickerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroCountryPickerSpecSwift.hpp +99 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__IPickedCountry_.swift +58 -0
- package/nitrogen/generated/ios/swift/HybridNitroCountryPickerSpec.swift +56 -0
- package/nitrogen/generated/ios/swift/HybridNitroCountryPickerSpec_cxx.swift +171 -0
- package/nitrogen/generated/ios/swift/IPickedCountry.swift +39 -0
- package/nitrogen/generated/ios/swift/PickCountryOptions.swift +42 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_IPickedCountry.swift +18 -0
- package/nitrogen/generated/shared/c++/HybridNitroCountryPickerSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridNitroCountryPickerSpec.hpp +71 -0
- package/nitrogen/generated/shared/c++/IPickedCountry.hpp +91 -0
- package/nitrogen/generated/shared/c++/PickCountryOptions.hpp +84 -0
- package/package.json +175 -0
- package/src/NitroCountryPicker.nitro.ts +20 -0
- package/src/index.tsx +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Quan Pham
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "NitroCountryPicker"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/Doko-Demo-Doa/react-native-nitro-country-picker.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
s.source_files = [
|
|
18
|
+
"ios/**/*.{swift}",
|
|
19
|
+
"ios/**/*.{m,mm}",
|
|
20
|
+
"cpp/**/*.{hpp,cpp}",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
s.dependency 'React-jsi'
|
|
24
|
+
s.dependency 'React-callinvoker'
|
|
25
|
+
s.dependency 'CountryPickerAKS'
|
|
26
|
+
|
|
27
|
+
load 'nitrogen/generated/ios/NitroCountryPicker+autolinking.rb'
|
|
28
|
+
add_nitrogen_files(s)
|
|
29
|
+
|
|
30
|
+
# Ensure generated shared C++ headers are exported to Pods/Headers/Public.
|
|
31
|
+
current_public_headers = Array(s.attributes_hash['public_header_files'])
|
|
32
|
+
s.public_header_files = current_public_headers + [
|
|
33
|
+
'nitrogen/generated/shared/c++/*.hpp',
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
install_modules_dependencies(s)
|
|
37
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# react-native-nitro-country-picker
|
|
2
|
+
|
|
3
|
+
A native country picker for React Native, powered by Nitro Modules.
|
|
4
|
+
|
|
5
|
+
This library provides a single async API that opens a native picker and returns structured country data.
|
|
6
|
+
|
|
7
|
+
- Android native implementation: [CountryCodePickerCompose](https://github.com/ahmmedrejowan/CountryCodePickerCompose)
|
|
8
|
+
- iOS native implementation: [CountryPickerAKS](https://github.com/aksamitsah/CountryPickerAKS)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Native picker UI on both iOS and Android
|
|
13
|
+
- Promise-based API: `pickCountry(options?)`
|
|
14
|
+
- Typed result object with `name`, `dialCode`, and `code`
|
|
15
|
+
- `null` result when user dismisses without selection
|
|
16
|
+
- Last selection cache via `getLastPickedCountry()`
|
|
17
|
+
- Optional picker title input: `headerTitle` (currently applied on Android)
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
| Platform | Minimum |
|
|
22
|
+
| -------- | ------- |
|
|
23
|
+
| iOS | 15.1+ |
|
|
24
|
+
| Android | API 24+ |
|
|
25
|
+
|
|
26
|
+
> Note: This package depends on [react-native-nitro-modules](https://nitro.margelo.com/).
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install react-native-nitro-country-picker react-native-nitro-modules
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
or
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
yarn add react-native-nitro-country-picker react-native-nitro-modules
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### iOS setup
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cd ios && pod install
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { pickCountry } from 'react-native-nitro-country-picker';
|
|
50
|
+
|
|
51
|
+
const country = await pickCountry();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### With options
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { pickCountry } from 'react-native-nitro-country-picker';
|
|
58
|
+
|
|
59
|
+
const country = await pickCountry({
|
|
60
|
+
headerTitle: 'Select your country',
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Returned Data Examples
|
|
65
|
+
|
|
66
|
+
### 1) Handle selected vs dismissed
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { pickCountry } from 'react-native-nitro-country-picker';
|
|
70
|
+
|
|
71
|
+
const picked = await pickCountry();
|
|
72
|
+
|
|
73
|
+
if (picked) {
|
|
74
|
+
console.log('Country name:', picked.name);
|
|
75
|
+
console.log('Dial code:', picked.dialCode);
|
|
76
|
+
console.log('ISO code:', picked.code);
|
|
77
|
+
} else {
|
|
78
|
+
console.log('Picker dismissed without selection');
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 2) Build display text from returned data
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import { pickCountry } from 'react-native-nitro-country-picker';
|
|
86
|
+
|
|
87
|
+
const picked = await pickCountry();
|
|
88
|
+
const label = picked
|
|
89
|
+
? `${picked.name} (${picked.dialCode}, ${picked.code})`
|
|
90
|
+
: 'No country selected';
|
|
91
|
+
|
|
92
|
+
console.log(label);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 3) Read last picked country
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import {
|
|
99
|
+
getLastPickedCountry,
|
|
100
|
+
pickCountry,
|
|
101
|
+
} from 'react-native-nitro-country-picker';
|
|
102
|
+
|
|
103
|
+
await pickCountry();
|
|
104
|
+
|
|
105
|
+
const last = getLastPickedCountry();
|
|
106
|
+
if (last) {
|
|
107
|
+
console.log('Last picked:', last.name, last.dialCode, last.code);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## API
|
|
112
|
+
|
|
113
|
+
### `pickCountry(options?) => Promise<IPickedCountry | null>`
|
|
114
|
+
|
|
115
|
+
Opens the native picker and resolves with:
|
|
116
|
+
|
|
117
|
+
- `IPickedCountry` when user selects a country
|
|
118
|
+
- `null` when user dismisses/cancels
|
|
119
|
+
|
|
120
|
+
Options:
|
|
121
|
+
|
|
122
|
+
- `headerTitle?: string`
|
|
123
|
+
|
|
124
|
+
### `getLastPickedCountry() => IPickedCountry | null`
|
|
125
|
+
|
|
126
|
+
Returns the most recent selected country for the current app runtime session.
|
|
127
|
+
|
|
128
|
+
## Type Shapes
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
type IPickedCountry = {
|
|
132
|
+
name: string;
|
|
133
|
+
dialCode: string;
|
|
134
|
+
code: string;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
type PickCountryOptions = {
|
|
138
|
+
headerTitle?: string;
|
|
139
|
+
};
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Example App
|
|
143
|
+
|
|
144
|
+
To run the included example app:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
cd example
|
|
148
|
+
yarn install
|
|
149
|
+
yarn ios
|
|
150
|
+
# or
|
|
151
|
+
yarn android
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Contributing
|
|
155
|
+
|
|
156
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development workflow and contribution guidelines.
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
project(nitrocountrypicker)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set(PACKAGE_NAME nitrocountrypicker)
|
|
5
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
7
|
+
|
|
8
|
+
# Define C++ library and add all sources
|
|
9
|
+
add_library(${PACKAGE_NAME} SHARED src/main/cpp/cpp-adapter.cpp)
|
|
10
|
+
|
|
11
|
+
# Add Nitrogen specs :)
|
|
12
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/nitrocountrypicker+autolinking.cmake)
|
|
13
|
+
|
|
14
|
+
# Set up local includes
|
|
15
|
+
include_directories("src/main/cpp" "../cpp")
|
|
16
|
+
|
|
17
|
+
find_library(LOG_LIB log)
|
|
18
|
+
|
|
19
|
+
# Link all libraries together
|
|
20
|
+
target_link_libraries(
|
|
21
|
+
${PACKAGE_NAME}
|
|
22
|
+
${LOG_LIB}
|
|
23
|
+
android # <-- Android core
|
|
24
|
+
)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.getExtOrDefault = {name ->
|
|
3
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['NitroCountryPicker_' + name]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
maven { url 'https://jitpack.io' }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
dependencies {
|
|
13
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
14
|
+
// noinspection DifferentKotlinGradleVersion
|
|
15
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
16
|
+
classpath "org.jetbrains.kotlin:compose-compiler-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def reactNativeArchitectures() {
|
|
21
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
22
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
apply plugin: "com.android.library"
|
|
26
|
+
apply plugin: "kotlin-android"
|
|
27
|
+
apply plugin: "org.jetbrains.kotlin.plugin.compose"
|
|
28
|
+
apply from: '../nitrogen/generated/android/nitrocountrypicker+autolinking.gradle'
|
|
29
|
+
|
|
30
|
+
apply plugin: "com.facebook.react"
|
|
31
|
+
|
|
32
|
+
def getExtOrIntegerDefault(name) {
|
|
33
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroCountryPicker_" + name]).toInteger()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
android {
|
|
37
|
+
namespace "com.margelo.nitro.nitrocountrypicker"
|
|
38
|
+
|
|
39
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
40
|
+
|
|
41
|
+
defaultConfig {
|
|
42
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
43
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
44
|
+
|
|
45
|
+
externalNativeBuild {
|
|
46
|
+
cmake {
|
|
47
|
+
cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
|
|
48
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
49
|
+
abiFilters (*reactNativeArchitectures())
|
|
50
|
+
|
|
51
|
+
buildTypes {
|
|
52
|
+
debug {
|
|
53
|
+
cppFlags "-O1 -g"
|
|
54
|
+
}
|
|
55
|
+
release {
|
|
56
|
+
cppFlags "-O2"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
externalNativeBuild {
|
|
64
|
+
cmake {
|
|
65
|
+
path "CMakeLists.txt"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
packagingOptions {
|
|
70
|
+
excludes = [
|
|
71
|
+
"META-INF",
|
|
72
|
+
"META-INF/**",
|
|
73
|
+
"**/libc++_shared.so",
|
|
74
|
+
"**/libfbjni.so",
|
|
75
|
+
"**/libjsi.so",
|
|
76
|
+
"**/libfolly_json.so",
|
|
77
|
+
"**/libfolly_runtime.so",
|
|
78
|
+
"**/libglog.so",
|
|
79
|
+
"**/libhermes.so",
|
|
80
|
+
"**/libhermes-executor-debug.so",
|
|
81
|
+
"**/libhermes_executor.so",
|
|
82
|
+
"**/libreactnative.so",
|
|
83
|
+
"**/libreactnativejni.so",
|
|
84
|
+
"**/libturbomodulejsijni.so",
|
|
85
|
+
"**/libreact_nativemodule_core.so",
|
|
86
|
+
"**/libjscexecutor.so"
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
buildFeatures {
|
|
91
|
+
buildConfig true
|
|
92
|
+
prefab true
|
|
93
|
+
compose true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
buildTypes {
|
|
97
|
+
release {
|
|
98
|
+
minifyEnabled false
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
lintOptions {
|
|
103
|
+
disable "GradleCompatible"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
compileOptions {
|
|
107
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
108
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
kotlinOptions {
|
|
112
|
+
jvmTarget = "17"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
sourceSets {
|
|
116
|
+
main {
|
|
117
|
+
java.srcDirs += [
|
|
118
|
+
"generated/java",
|
|
119
|
+
"generated/jni"
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
repositories {
|
|
126
|
+
mavenCentral()
|
|
127
|
+
maven { url 'https://jitpack.io' }
|
|
128
|
+
google()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
132
|
+
def appcompat_version = "1.7.1"
|
|
133
|
+
def compose_bom_version = "2024.12.01"
|
|
134
|
+
def activity_compose_version = "1.13.0"
|
|
135
|
+
|
|
136
|
+
dependencies {
|
|
137
|
+
implementation "com.facebook.react:react-android"
|
|
138
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
139
|
+
implementation project(":react-native-nitro-modules")
|
|
140
|
+
|
|
141
|
+
implementation "com.rejowan:ccpc:1.0.1"
|
|
142
|
+
implementation platform("androidx.compose:compose-bom:$compose_bom_version")
|
|
143
|
+
implementation "androidx.activity:activity-compose:$activity_compose_version"
|
|
144
|
+
implementation "androidx.compose.ui:ui"
|
|
145
|
+
implementation "androidx.compose.runtime:runtime"
|
|
146
|
+
implementation "androidx.compose.material3:material3"
|
|
147
|
+
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
|
148
|
+
implementation "com.google.android.material:material:1.12.0"
|
|
149
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrocountrypicker
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
import android.widget.Toast
|
|
7
|
+
import androidx.activity.ComponentActivity
|
|
8
|
+
import androidx.activity.compose.setContent
|
|
9
|
+
import androidx.compose.material3.MaterialTheme
|
|
10
|
+
import androidx.compose.runtime.getValue
|
|
11
|
+
import androidx.compose.runtime.mutableStateOf
|
|
12
|
+
import androidx.compose.runtime.remember
|
|
13
|
+
import androidx.compose.runtime.setValue
|
|
14
|
+
import com.rejowan.ccpc.CCPUtils
|
|
15
|
+
import com.rejowan.ccpc.Country
|
|
16
|
+
import com.rejowan.ccpc.CountryPickerDialog
|
|
17
|
+
import com.rejowan.ccpc.PickerCustomization
|
|
18
|
+
|
|
19
|
+
class CountryPickerActivity : ComponentActivity() {
|
|
20
|
+
companion object {
|
|
21
|
+
const val EXTRA_HEADER_TITLE = "com.margelo.nitro.nitrocountrypicker.HEADER_TITLE"
|
|
22
|
+
private const val EXTRA_RESULT_NAME = "com.margelo.nitro.nitrocountrypicker.RESULT_NAME"
|
|
23
|
+
private const val EXTRA_RESULT_DIAL_CODE = "com.margelo.nitro.nitrocountrypicker.RESULT_DIAL_CODE"
|
|
24
|
+
private const val EXTRA_RESULT_CODE = "com.margelo.nitro.nitrocountrypicker.RESULT_CODE"
|
|
25
|
+
|
|
26
|
+
fun intentResultToPickedCountry(resultCode: Int, data: Intent?): IPickedCountry? {
|
|
27
|
+
if (resultCode != Activity.RESULT_OK || data == null) {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
val name = data.getStringExtra(EXTRA_RESULT_NAME) ?: return null
|
|
32
|
+
val dialCode = data.getStringExtra(EXTRA_RESULT_DIAL_CODE) ?: return null
|
|
33
|
+
val code = data.getStringExtra(EXTRA_RESULT_CODE) ?: return null
|
|
34
|
+
return IPickedCountry(name = name, dialCode = dialCode, code = code)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private var hasCompletedPick = false
|
|
39
|
+
|
|
40
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
41
|
+
super.onCreate(savedInstanceState)
|
|
42
|
+
val headerTitle = intent.getStringExtra(EXTRA_HEADER_TITLE)?.trim()?.takeIf { it.isNotEmpty() }
|
|
43
|
+
val pickerCustomization = if (headerTitle == null) {
|
|
44
|
+
PickerCustomization()
|
|
45
|
+
} else {
|
|
46
|
+
PickerCustomization(headerTitleText = headerTitle)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setContent {
|
|
50
|
+
MaterialTheme {
|
|
51
|
+
var selectedCountry by remember {
|
|
52
|
+
mutableStateOf(
|
|
53
|
+
CCPUtils.getCountryAutomatically(this@CountryPickerActivity)
|
|
54
|
+
?: Country.UnitedStates
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
CountryPickerDialog(
|
|
59
|
+
onDismissRequest = {
|
|
60
|
+
hasCompletedPick = true
|
|
61
|
+
setResult(Activity.RESULT_CANCELED)
|
|
62
|
+
finish()
|
|
63
|
+
},
|
|
64
|
+
onItemClicked = { country ->
|
|
65
|
+
selectedCountry = country
|
|
66
|
+
hasCompletedPick = true
|
|
67
|
+
val resultIntent = Intent().apply {
|
|
68
|
+
putExtra(EXTRA_RESULT_NAME, country.countryName)
|
|
69
|
+
putExtra(EXTRA_RESULT_DIAL_CODE, country.countryCode)
|
|
70
|
+
putExtra(EXTRA_RESULT_CODE, country.countryIso)
|
|
71
|
+
}
|
|
72
|
+
setResult(Activity.RESULT_OK, resultIntent)
|
|
73
|
+
Toast.makeText(
|
|
74
|
+
this@CountryPickerActivity,
|
|
75
|
+
country.countryName,
|
|
76
|
+
Toast.LENGTH_SHORT
|
|
77
|
+
).show()
|
|
78
|
+
finish()
|
|
79
|
+
},
|
|
80
|
+
listOfCountry = Country.getAllCountries(),
|
|
81
|
+
selectedCountry = selectedCountry,
|
|
82
|
+
pickerCustomization = pickerCustomization
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
override fun onDestroy() {
|
|
89
|
+
super.onDestroy()
|
|
90
|
+
if (!hasCompletedPick) {
|
|
91
|
+
setResult(Activity.RESULT_CANCELED)
|
|
92
|
+
hasCompletedPick = true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrocountrypicker
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import androidx.activity.ComponentActivity
|
|
5
|
+
import androidx.activity.result.ActivityResultLauncher
|
|
6
|
+
import androidx.activity.result.contract.ActivityResultContracts
|
|
7
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
8
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
9
|
+
import com.margelo.nitro.NitroModules
|
|
10
|
+
import com.margelo.nitro.core.NullType
|
|
11
|
+
import com.margelo.nitro.core.Promise
|
|
12
|
+
import java.util.concurrent.atomic.AtomicInteger
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@DoNotStrip
|
|
16
|
+
class NitroCountryPicker : HybridNitroCountryPickerSpec() {
|
|
17
|
+
companion object {
|
|
18
|
+
const val NAME = "NitroCountryPicker"
|
|
19
|
+
|
|
20
|
+
@Volatile
|
|
21
|
+
private var lastPickedCountry: IPickedCountry? = null
|
|
22
|
+
|
|
23
|
+
@Volatile
|
|
24
|
+
private var pendingPickPromise: Promise<Variant_NullType_IPickedCountry>? = null
|
|
25
|
+
|
|
26
|
+
private val launcherCounter = AtomicInteger(0)
|
|
27
|
+
|
|
28
|
+
private fun setLastPickedCountry(country: IPickedCountry) {
|
|
29
|
+
lastPickedCountry = country
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Synchronized
|
|
33
|
+
private fun resolvePendingPick(country: IPickedCountry?) {
|
|
34
|
+
val promise = pendingPickPromise ?: return
|
|
35
|
+
pendingPickPromise = null
|
|
36
|
+
val result = if (country == null) {
|
|
37
|
+
Variant_NullType_IPickedCountry.create(NullType.NULL)
|
|
38
|
+
} else {
|
|
39
|
+
Variant_NullType_IPickedCountry.create(country)
|
|
40
|
+
}
|
|
41
|
+
promise.resolve(result)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Synchronized
|
|
45
|
+
private fun setPendingPickPromise(promise: Promise<Variant_NullType_IPickedCountry>): Boolean {
|
|
46
|
+
if (pendingPickPromise != null) {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
pendingPickPromise = promise
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Synchronized
|
|
54
|
+
private fun rejectPendingPick(error: Throwable) {
|
|
55
|
+
val promise = pendingPickPromise ?: return
|
|
56
|
+
pendingPickPromise = null
|
|
57
|
+
promise.reject(error)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private fun nextLauncherKey(): String {
|
|
61
|
+
return "NitroCountryPicker#${launcherCounter.incrementAndGet()}"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override fun pickCountry(options: PickCountryOptions?): Promise<Variant_NullType_IPickedCountry> {
|
|
66
|
+
val activity = NitroModules.applicationContext?.currentActivity
|
|
67
|
+
?: return Promise.rejected<Variant_NullType_IPickedCountry>(
|
|
68
|
+
IllegalStateException("No current Activity available to present country picker.")
|
|
69
|
+
)
|
|
70
|
+
val componentActivity = activity as? ComponentActivity
|
|
71
|
+
?: return Promise.rejected<Variant_NullType_IPickedCountry>(
|
|
72
|
+
IllegalStateException("Current Activity must be a ComponentActivity to register for activity results.")
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
val promise = Promise<Variant_NullType_IPickedCountry>()
|
|
76
|
+
val accepted = setPendingPickPromise(promise)
|
|
77
|
+
if (!accepted) {
|
|
78
|
+
return Promise.rejected<Variant_NullType_IPickedCountry>(
|
|
79
|
+
IllegalStateException("Country picker is already open.")
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
UiThreadUtil.runOnUiThread {
|
|
84
|
+
var launcher: ActivityResultLauncher<Intent>? = null
|
|
85
|
+
try {
|
|
86
|
+
val intent = Intent(activity, CountryPickerActivity::class.java)
|
|
87
|
+
val headerTitle = options?.headerTitle?.trim()?.takeIf { it.isNotEmpty() }
|
|
88
|
+
if (headerTitle != null) {
|
|
89
|
+
intent.putExtra(CountryPickerActivity.EXTRA_HEADER_TITLE, headerTitle)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
launcher = componentActivity.activityResultRegistry.register(
|
|
93
|
+
nextLauncherKey(),
|
|
94
|
+
ActivityResultContracts.StartActivityForResult()
|
|
95
|
+
) { result ->
|
|
96
|
+
try {
|
|
97
|
+
val picked = CountryPickerActivity.intentResultToPickedCountry(result.resultCode, result.data)
|
|
98
|
+
if (picked != null) {
|
|
99
|
+
setLastPickedCountry(picked)
|
|
100
|
+
}
|
|
101
|
+
resolvePendingPick(picked)
|
|
102
|
+
} catch (error: Throwable) {
|
|
103
|
+
rejectPendingPick(error)
|
|
104
|
+
} finally {
|
|
105
|
+
launcher?.unregister()
|
|
106
|
+
launcher = null
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
launcher?.launch(intent)
|
|
111
|
+
} catch (error: Throwable) {
|
|
112
|
+
try {
|
|
113
|
+
launcher?.unregister()
|
|
114
|
+
} catch (_: Throwable) {
|
|
115
|
+
// Ignore cleanup errors while handling the original failure.
|
|
116
|
+
}
|
|
117
|
+
rejectPendingPick(error)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return promise
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
override fun getLastPickedCountry(): Variant_NullType_IPickedCountry {
|
|
125
|
+
val picked = lastPickedCountry
|
|
126
|
+
return if (picked == null) {
|
|
127
|
+
Variant_NullType_IPickedCountry.create(NullType.NULL)
|
|
128
|
+
} else {
|
|
129
|
+
Variant_NullType_IPickedCountry.create(picked)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
package/android/src/main/java/com/margelo/nitro/nitrocountrypicker/NitroCountryPickerPackage.kt
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrocountrypicker
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.BaseReactPackage
|
|
5
|
+
import com.facebook.react.bridge.NativeModule
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
8
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
9
|
+
|
|
10
|
+
class NitroCountryPickerPackage : BaseReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
16
|
+
return ReactModuleInfoProvider {
|
|
17
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
18
|
+
moduleInfos[NitroCountryPicker.NAME] = ReactModuleInfo(
|
|
19
|
+
NitroCountryPicker.NAME,
|
|
20
|
+
NitroCountryPicker.NAME,
|
|
21
|
+
false,
|
|
22
|
+
needsEagerInit = true,
|
|
23
|
+
isCxxModule = false,
|
|
24
|
+
isTurboModule = true
|
|
25
|
+
)
|
|
26
|
+
moduleInfos
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
companion object {
|
|
31
|
+
init {
|
|
32
|
+
System.loadLibrary("nitrocountrypicker")
|
|
33
|
+
Log.d(NitroCountryPicker.NAME, "Hello from init")
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|