@momo-kits/calculator-keyboard 0.167.1-beta.10 → 0.167.1-beta.14

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.
Files changed (17) hide show
  1. package/android/app/app.iml +11 -0
  2. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/NativeInputCalculatorManagerDelegate.java +67 -0
  3. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/NativeInputCalculatorManagerInterface.java +28 -0
  4. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/ComponentDescriptors.cpp +22 -0
  5. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/ComponentDescriptors.h +24 -0
  6. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/EventEmitters.cpp +69 -0
  7. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/EventEmitters.h +55 -0
  8. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/Props.cpp +32 -0
  9. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/Props.h +66 -0
  10. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/ShadowNodes.cpp +17 -0
  11. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/ShadowNodes.h +32 -0
  12. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/States.cpp +16 -0
  13. package/android/app/build/generated/source/codegen/jni/react/renderer/components/CalculatorKeyboardSpecs/States.h +29 -0
  14. package/android/src/main/java/com/momokits/calculatorkeyboard/native/CustomKeyboardView.kt +34 -0
  15. package/ios/CalculatorKeyboardView.mm +76 -18
  16. package/ios/InputCalculator.mm +8 -2
  17. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="JAVA_MODULE" version="4">
3
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
4
+ <exclude-output />
5
+ <content url="file://$MODULE_DIR$">
6
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/codegen/java" isTestSource="false" />
7
+ </content>
8
+ <orderEntry type="inheritedJdk" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ </component>
11
+ </module>
@@ -0,0 +1,67 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaDelegate.js
8
+ */
9
+
10
+ package com.facebook.react.viewmanagers;
11
+
12
+ import android.view.View;
13
+ import androidx.annotation.Nullable;
14
+ import com.facebook.react.bridge.ReadableArray;
15
+ import com.facebook.react.bridge.ReadableMap;
16
+ import com.facebook.react.uimanager.BaseViewManager;
17
+ import com.facebook.react.uimanager.BaseViewManagerDelegate;
18
+ import com.facebook.react.uimanager.LayoutShadowNode;
19
+
20
+ public class NativeInputCalculatorManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NativeInputCalculatorManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
21
+ public NativeInputCalculatorManagerDelegate(U viewManager) {
22
+ super(viewManager);
23
+ }
24
+ @Override
25
+ public void setProperty(T view, String propName, @Nullable Object value) {
26
+ switch (propName) {
27
+ case "value":
28
+ mViewManager.setValue(view, value == null ? null : (String) value);
29
+ break;
30
+ case "textAttributes":
31
+ mViewManager.setTextAttributes(view, (ReadableMap) value);
32
+ break;
33
+ case "mode":
34
+ mViewManager.setMode(view, value == null ? null : (String) value);
35
+ break;
36
+ case "selectionColor":
37
+ mViewManager.setSelectionColor(view, value == null ? null : (String) value);
38
+ break;
39
+ case "customKeyText":
40
+ mViewManager.setCustomKeyText(view, value == null ? null : (String) value);
41
+ break;
42
+ case "customKeyBackground":
43
+ mViewManager.setCustomKeyBackground(view, value == null ? null : (String) value);
44
+ break;
45
+ case "customKeyTextColor":
46
+ mViewManager.setCustomKeyTextColor(view, value == null ? null : (String) value);
47
+ break;
48
+ case "customKeyState":
49
+ mViewManager.setCustomKeyState(view, value == null ? null : (String) value);
50
+ break;
51
+ default:
52
+ super.setProperty(view, propName, value);
53
+ }
54
+ }
55
+
56
+ @Override
57
+ public void receiveCommand(T view, String commandName, @Nullable ReadableArray args) {
58
+ switch (commandName) {
59
+ case "focus":
60
+ mViewManager.focus(view);
61
+ break;
62
+ case "blur":
63
+ mViewManager.blur(view);
64
+ break;
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaInterface.js
8
+ */
9
+
10
+ package com.facebook.react.viewmanagers;
11
+
12
+ import android.view.View;
13
+ import androidx.annotation.Nullable;
14
+ import com.facebook.react.bridge.ReadableMap;
15
+ import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;
16
+
17
+ public interface NativeInputCalculatorManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {
18
+ void setValue(T view, @Nullable String value);
19
+ void setTextAttributes(T view, @Nullable ReadableMap value);
20
+ void setMode(T view, @Nullable String value);
21
+ void setSelectionColor(T view, @Nullable String value);
22
+ void setCustomKeyText(T view, @Nullable String value);
23
+ void setCustomKeyBackground(T view, @Nullable String value);
24
+ void setCustomKeyTextColor(T view, @Nullable String value);
25
+ void setCustomKeyState(T view, @Nullable String value);
26
+ void focus(T view);
27
+ void blur(T view);
28
+ }
@@ -0,0 +1,22 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateComponentDescriptorCpp.js
9
+ */
10
+
11
+ #include <react/renderer/components/CalculatorKeyboardSpecs/ComponentDescriptors.h>
12
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
13
+ #include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
14
+
15
+ namespace facebook::react {
16
+
17
+ void CalculatorKeyboardSpecs_registerComponentDescriptorsFromCodegen(
18
+ std::shared_ptr<const ComponentDescriptorProviderRegistry> registry) {
19
+ registry->add(concreteComponentDescriptorProvider<NativeInputCalculatorComponentDescriptor>());
20
+ }
21
+
22
+ } // namespace facebook::react
@@ -0,0 +1,24 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateComponentDescriptorH.js
9
+ */
10
+
11
+ #pragma once
12
+
13
+ #include <react/renderer/components/CalculatorKeyboardSpecs/ShadowNodes.h>
14
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
15
+ #include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
16
+
17
+ namespace facebook::react {
18
+
19
+ using NativeInputCalculatorComponentDescriptor = ConcreteComponentDescriptor<NativeInputCalculatorShadowNode>;
20
+
21
+ void CalculatorKeyboardSpecs_registerComponentDescriptorsFromCodegen(
22
+ std::shared_ptr<const ComponentDescriptorProviderRegistry> registry);
23
+
24
+ } // namespace facebook::react
@@ -0,0 +1,69 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateEventEmitterCpp.js
9
+ */
10
+
11
+ #include <react/renderer/components/CalculatorKeyboardSpecs/EventEmitters.h>
12
+
13
+
14
+ namespace facebook::react {
15
+
16
+ void NativeInputCalculatorEventEmitter::onChange(OnChange event) const {
17
+ dispatchEvent("change", [event=std::move(event)](jsi::Runtime &runtime) {
18
+ auto payload = jsi::Object(runtime);
19
+ payload.setProperty(runtime, "text", event.text);
20
+ return payload;
21
+ });
22
+ }
23
+
24
+
25
+ void NativeInputCalculatorEventEmitter::onKeyPress(OnKeyPress event) const {
26
+ dispatchEvent("keyPress", [event=std::move(event)](jsi::Runtime &runtime) {
27
+ auto payload = jsi::Object(runtime);
28
+ payload.setProperty(runtime, "key", event.key);
29
+ return payload;
30
+ });
31
+ }
32
+
33
+
34
+ void NativeInputCalculatorEventEmitter::onResult(OnResult event) const {
35
+ dispatchEvent("result", [event=std::move(event)](jsi::Runtime &runtime) {
36
+ auto payload = jsi::Object(runtime);
37
+ payload.setProperty(runtime, "result", event.result);
38
+ return payload;
39
+ });
40
+ }
41
+
42
+
43
+ void NativeInputCalculatorEventEmitter::onBlur(OnBlur event) const {
44
+ dispatchEvent("blur", [](jsi::Runtime &runtime) {
45
+ auto payload = jsi::Object(runtime);
46
+
47
+ return payload;
48
+ });
49
+ }
50
+
51
+
52
+ void NativeInputCalculatorEventEmitter::onFocus(OnFocus event) const {
53
+ dispatchEvent("focus", [](jsi::Runtime &runtime) {
54
+ auto payload = jsi::Object(runtime);
55
+
56
+ return payload;
57
+ });
58
+ }
59
+
60
+
61
+ void NativeInputCalculatorEventEmitter::onCustomKeyEvent(OnCustomKeyEvent event) const {
62
+ dispatchEvent("customKeyEvent", [](jsi::Runtime &runtime) {
63
+ auto payload = jsi::Object(runtime);
64
+
65
+ return payload;
66
+ });
67
+ }
68
+
69
+ } // namespace facebook::react
@@ -0,0 +1,55 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateEventEmitterH.js
9
+ */
10
+ #pragma once
11
+
12
+ #include <react/renderer/components/view/ViewEventEmitter.h>
13
+
14
+
15
+ namespace facebook::react {
16
+ class NativeInputCalculatorEventEmitter : public ViewEventEmitter {
17
+ public:
18
+ using ViewEventEmitter::ViewEventEmitter;
19
+
20
+ struct OnChange {
21
+ std::string text;
22
+ };
23
+
24
+ struct OnKeyPress {
25
+ std::string key;
26
+ };
27
+
28
+ struct OnResult {
29
+ std::string result;
30
+ };
31
+
32
+ struct OnBlur {
33
+
34
+ };
35
+
36
+ struct OnFocus {
37
+
38
+ };
39
+
40
+ struct OnCustomKeyEvent {
41
+
42
+ };
43
+ void onChange(OnChange value) const;
44
+
45
+ void onKeyPress(OnKeyPress value) const;
46
+
47
+ void onResult(OnResult value) const;
48
+
49
+ void onBlur(OnBlur value) const;
50
+
51
+ void onFocus(OnFocus value) const;
52
+
53
+ void onCustomKeyEvent(OnCustomKeyEvent value) const;
54
+ };
55
+ } // namespace facebook::react
@@ -0,0 +1,32 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GeneratePropsCpp.js
9
+ */
10
+
11
+ #include <react/renderer/components/CalculatorKeyboardSpecs/Props.h>
12
+ #include <react/renderer/core/PropsParserContext.h>
13
+ #include <react/renderer/core/propsConversions.h>
14
+
15
+ namespace facebook::react {
16
+
17
+ NativeInputCalculatorProps::NativeInputCalculatorProps(
18
+ const PropsParserContext &context,
19
+ const NativeInputCalculatorProps &sourceProps,
20
+ const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
21
+
22
+ value(convertRawProp(context, rawProps, "value", sourceProps.value, {})),
23
+ textAttributes(convertRawProp(context, rawProps, "textAttributes", sourceProps.textAttributes, {})),
24
+ mode(convertRawProp(context, rawProps, "mode", sourceProps.mode, {})),
25
+ selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
26
+ customKeyText(convertRawProp(context, rawProps, "customKeyText", sourceProps.customKeyText, {})),
27
+ customKeyBackground(convertRawProp(context, rawProps, "customKeyBackground", sourceProps.customKeyBackground, {})),
28
+ customKeyTextColor(convertRawProp(context, rawProps, "customKeyTextColor", sourceProps.customKeyTextColor, {})),
29
+ customKeyState(convertRawProp(context, rawProps, "customKeyState", sourceProps.customKeyState, {}))
30
+ {}
31
+
32
+ } // namespace facebook::react
@@ -0,0 +1,66 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GeneratePropsH.js
9
+ */
10
+ #pragma once
11
+
12
+ #include <react/renderer/components/view/ViewProps.h>
13
+ #include <react/renderer/core/PropsParserContext.h>
14
+ #include <react/renderer/core/propsConversions.h>
15
+
16
+ namespace facebook::react {
17
+
18
+ struct NativeInputCalculatorTextAttributesStruct {
19
+ Float fontSize{0.0};
20
+ std::string fontWeight{};
21
+ std::string placeholder{};
22
+ std::string placeholderTextColor{};
23
+ };
24
+
25
+ static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, NativeInputCalculatorTextAttributesStruct &result) {
26
+ auto map = (std::unordered_map<std::string, RawValue>)value;
27
+
28
+ auto tmp_fontSize = map.find("fontSize");
29
+ if (tmp_fontSize != map.end()) {
30
+ fromRawValue(context, tmp_fontSize->second, result.fontSize);
31
+ }
32
+ auto tmp_fontWeight = map.find("fontWeight");
33
+ if (tmp_fontWeight != map.end()) {
34
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
35
+ }
36
+ auto tmp_placeholder = map.find("placeholder");
37
+ if (tmp_placeholder != map.end()) {
38
+ fromRawValue(context, tmp_placeholder->second, result.placeholder);
39
+ }
40
+ auto tmp_placeholderTextColor = map.find("placeholderTextColor");
41
+ if (tmp_placeholderTextColor != map.end()) {
42
+ fromRawValue(context, tmp_placeholderTextColor->second, result.placeholderTextColor);
43
+ }
44
+ }
45
+
46
+ static inline std::string toString(const NativeInputCalculatorTextAttributesStruct &value) {
47
+ return "[Object NativeInputCalculatorTextAttributesStruct]";
48
+ }
49
+ class NativeInputCalculatorProps final : public ViewProps {
50
+ public:
51
+ NativeInputCalculatorProps() = default;
52
+ NativeInputCalculatorProps(const PropsParserContext& context, const NativeInputCalculatorProps &sourceProps, const RawProps &rawProps);
53
+
54
+ #pragma mark - Props
55
+
56
+ std::string value{};
57
+ NativeInputCalculatorTextAttributesStruct textAttributes{};
58
+ std::string mode{};
59
+ std::string selectionColor{};
60
+ std::string customKeyText{};
61
+ std::string customKeyBackground{};
62
+ std::string customKeyTextColor{};
63
+ std::string customKeyState{};
64
+ };
65
+
66
+ } // namespace facebook::react
@@ -0,0 +1,17 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateShadowNodeCpp.js
9
+ */
10
+
11
+ #include <react/renderer/components/CalculatorKeyboardSpecs/ShadowNodes.h>
12
+
13
+ namespace facebook::react {
14
+
15
+ extern const char NativeInputCalculatorComponentName[] = "NativeInputCalculator";
16
+
17
+ } // namespace facebook::react
@@ -0,0 +1,32 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateShadowNodeH.js
9
+ */
10
+
11
+ #pragma once
12
+
13
+ #include <react/renderer/components/CalculatorKeyboardSpecs/EventEmitters.h>
14
+ #include <react/renderer/components/CalculatorKeyboardSpecs/Props.h>
15
+ #include <react/renderer/components/CalculatorKeyboardSpecs/States.h>
16
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
17
+ #include <jsi/jsi.h>
18
+
19
+ namespace facebook::react {
20
+
21
+ JSI_EXPORT extern const char NativeInputCalculatorComponentName[];
22
+
23
+ /*
24
+ * `ShadowNode` for <NativeInputCalculator> component.
25
+ */
26
+ using NativeInputCalculatorShadowNode = ConcreteViewShadowNode<
27
+ NativeInputCalculatorComponentName,
28
+ NativeInputCalculatorProps,
29
+ NativeInputCalculatorEventEmitter,
30
+ NativeInputCalculatorState>;
31
+
32
+ } // namespace facebook::react
@@ -0,0 +1,16 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateStateCpp.js
9
+ */
10
+ #include <react/renderer/components/CalculatorKeyboardSpecs/States.h>
11
+
12
+ namespace facebook::react {
13
+
14
+
15
+
16
+ } // namespace facebook::react
@@ -0,0 +1,29 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GenerateStateH.js
8
+ */
9
+ #pragma once
10
+
11
+ #ifdef ANDROID
12
+ #include <folly/dynamic.h>
13
+ #endif
14
+
15
+ namespace facebook::react {
16
+
17
+ class NativeInputCalculatorState {
18
+ public:
19
+ NativeInputCalculatorState() = default;
20
+
21
+ #ifdef ANDROID
22
+ NativeInputCalculatorState(NativeInputCalculatorState const &previousState, folly::dynamic data){};
23
+ folly::dynamic getDynamic() const {
24
+ return {};
25
+ };
26
+ #endif
27
+ };
28
+
29
+ } // namespace facebook::react
@@ -3,9 +3,12 @@ package com.momokits.calculatorkeyboard.native
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
5
  import android.content.res.ColorStateList
6
+ import android.graphics.Bitmap
7
+ import android.graphics.BitmapFactory
6
8
  import android.graphics.Color
7
9
  import android.graphics.drawable.GradientDrawable
8
10
  import android.text.Editable
11
+ import android.util.DisplayMetrics
9
12
  import android.view.Gravity
10
13
  import android.view.MotionEvent
11
14
  import android.widget.Button
@@ -17,6 +20,8 @@ import androidx.core.graphics.toColorInt
17
20
  import com.momokits.calculatorkeyboard.native.utils.CalculatorEngine
18
21
  import com.momokits.calculatorkeyboard.native.utils.CalculatorFormatter
19
22
  import com.momokits.calculatorkeyboard.R
23
+ import java.net.URL
24
+ import kotlin.concurrent.thread
20
25
 
21
26
  @SuppressLint("SetTextI18n", "ViewConstructor")
22
27
  class CustomKeyboardView(
@@ -181,6 +186,26 @@ class CustomKeyboardView(
181
186
  setImageTintList(ColorStateList.valueOf(Color.BLACK))
182
187
  setOnClickListener { onKeyPress(key, false) }
183
188
  applyImagePressedOpacity()
189
+ loadBackIcon()
190
+ }
191
+ }
192
+
193
+ // Swap the bundled fallback icon for the design-system icon once it's downloaded
194
+ private fun ImageButton.loadBackIcon() {
195
+ backIconCache?.let { return setImageBitmap(it) }
196
+
197
+ thread {
198
+ val bitmap = runCatching {
199
+ URL(BACK_ICON_URL).openConnection().apply {
200
+ connectTimeout = BACK_ICON_TIMEOUT_MS
201
+ readTimeout = BACK_ICON_TIMEOUT_MS
202
+ }.getInputStream().use(BitmapFactory::decodeStream)
203
+ }.getOrNull() ?: return@thread
204
+
205
+ // Density makes the drawable render at BACK_ICON_SIZE_DP without resampling the bitmap
206
+ bitmap.density = bitmap.width * DisplayMetrics.DENSITY_DEFAULT / BACK_ICON_SIZE_DP
207
+ backIconCache = bitmap
208
+ post { setImageBitmap(bitmap) }
184
209
  }
185
210
  }
186
211
 
@@ -400,4 +425,13 @@ class CustomKeyboardView(
400
425
  }
401
426
  customKeyButton?.setTextColor(textColor)
402
427
  }
428
+
429
+ companion object {
430
+ private const val BACK_ICON_URL = "https://img.mservice.com.vn/app/img/kits/chat_back_space.png"
431
+ private const val BACK_ICON_SIZE_DP = 24
432
+ private const val BACK_ICON_TIMEOUT_MS = 10_000
433
+
434
+ @Volatile
435
+ private var backIconCache: Bitmap? = null
436
+ }
403
437
  }
@@ -1,6 +1,10 @@
1
1
  #import "CalculatorKeyboardView.h"
2
2
  #import "Utils.h"
3
3
 
4
+ static NSString *const kBackIconURL = @"https://img.mservice.com.vn/app/img/kits/chat_back_space.png";
5
+ static const CGFloat kBackIconSize = 24;
6
+ static UIImage *sBackIcon;
7
+
4
8
  @interface CalculatorKeyboardView ()
5
9
  @property (nonatomic, strong) NSArray<NSArray<NSString *> *> *numWithCTAKeys;
6
10
  @property (nonatomic, strong) NSArray<NSArray<NSString *> *> *defaultKeys;
@@ -10,6 +14,8 @@
10
14
 
11
15
  @implementation CalculatorKeyboardView {
12
16
  CGFloat _separatorWidth;
17
+ UIView *_contentView;
18
+ NSArray<NSArray<UIButton *> *> *_buttonRows;
13
19
  }
14
20
 
15
21
  - (instancetype)initWithFrame:(CGRect)frame
@@ -85,28 +91,26 @@
85
91
 
86
92
  self.backgroundColor = [Utils colorFromHex:@"#f2f2f6"];
87
93
 
88
- CGFloat buttonWidth = (UIScreen.mainScreen.bounds.size.width - _separatorWidth * 2 - 4 * _separatorWidth) / 5;
89
- CGFloat buttonHeight = (240 - _separatorWidth * 2 - 3 * _separatorWidth) / 4;
90
-
91
94
  // Create content view
92
95
  UIView *contentView = [[UIView alloc] init];
93
96
  contentView.translatesAutoresizingMaskIntoConstraints = NO;
94
97
  [self addSubview:contentView];
98
+ _contentView = contentView;
95
99
 
96
- // Set contentView constraints
100
+ // Set contentView constraints, keeping clear of the side safe area (landscape, iPhone Duo)
97
101
  [NSLayoutConstraint activateConstraints:@[
98
- [contentView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:_separatorWidth],
99
- [contentView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-_separatorWidth],
102
+ [contentView.leadingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leadingAnchor constant:_separatorWidth],
103
+ [contentView.trailingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.trailingAnchor constant:-_separatorWidth],
100
104
  [contentView.topAnchor constraintEqualToAnchor:self.topAnchor constant:_separatorWidth],
101
105
  [contentView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-_separatorWidth]
102
106
  ]];
103
107
 
104
- CGFloat yOffset = 0;
108
+ NSMutableArray<NSArray<UIButton *> *> *buttonRows = [NSMutableArray array];
105
109
  NSArray<NSArray<NSString *> *> *keys = [_keyboardMode isEqualToString:@"NumDefault"] ? _defaultKeys : _numWithCTAKeys;
106
110
 
107
111
  for (NSInteger rowIndex = 0; rowIndex < keys.count; rowIndex++) {
108
112
  NSArray<NSString *> *row = keys[rowIndex];
109
- CGFloat xOffset = 0;
113
+ NSMutableArray<UIButton *> *buttonRow = [NSMutableArray array];
110
114
 
111
115
  for (NSInteger colIndex = 0; colIndex < row.count; colIndex++) {
112
116
  NSString *key = row[colIndex];
@@ -124,22 +128,13 @@
124
128
  button.accessibilityIdentifier = key;
125
129
  button.tag = isMainCTAKey ? 1 : 0;
126
130
 
127
- CGRect buttonFrame = CGRectMake(xOffset, yOffset, buttonWidth, buttonHeight);
128
- if (isMainKey) {
129
- buttonFrame.size.height = buttonHeight * 2 + _separatorWidth;
130
- }
131
- if ([key isEqualToString:@"000"]) {
132
- buttonFrame.size.width = buttonWidth * 2 + _separatorWidth;
133
- }
134
-
135
- button.frame = buttonFrame;
136
-
137
131
  if ([key isEqualToString:@"back"]) {
138
132
  [button setTitle:@"" forState:UIControlStateNormal];
139
133
  UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:24 weight:UIImageSymbolWeightBold];
140
134
  UIImage *image = [UIImage systemImageNamed:@"delete.backward" withConfiguration:config];
141
135
  [button setImage:image forState:UIControlStateNormal];
142
136
  button.tintColor = UIColor.blackColor;
137
+ [self loadBackIconForButton:button];
143
138
  }
144
139
 
145
140
  if ([_specialKeys containsObject:key] || isMainKey) {
@@ -153,7 +148,44 @@
153
148
 
154
149
  [button addTarget:self action:@selector(keyPressed:) forControlEvents:UIControlEventTouchUpInside];
155
150
  [contentView addSubview:button];
151
+ [buttonRow addObject:button];
152
+ }
153
+
154
+ [buttonRows addObject:buttonRow];
155
+ }
156
+
157
+ _buttonRows = buttonRows;
158
+ [self setNeedsLayout];
159
+ }
160
+
161
+ // Size the keys from the live keyboard width, which follows the window through
162
+ // rotation, fold and unfold, instead of the screen width at setup
163
+ - (void)layoutSubviews
164
+ {
165
+ [super layoutSubviews];
166
+
167
+ CGFloat buttonWidth = (_contentView.bounds.size.width - 4 * _separatorWidth) / 5;
168
+ CGFloat buttonHeight = (240 - _separatorWidth * 2 - 3 * _separatorWidth) / 4;
169
+ CGFloat yOffset = 0;
170
+
171
+ for (NSInteger rowIndex = 0; rowIndex < _buttonRows.count; rowIndex++) {
172
+ NSArray<UIButton *> *row = _buttonRows[rowIndex];
173
+ CGFloat xOffset = 0;
174
+
175
+ for (NSInteger colIndex = 0; colIndex < row.count; colIndex++) {
176
+ UIButton *button = row[colIndex];
177
+ NSString *key = button.accessibilityIdentifier;
178
+ BOOL isMainKey = (colIndex == 4 && rowIndex == 2);
156
179
 
180
+ CGRect buttonFrame = CGRectMake(xOffset, yOffset, buttonWidth, buttonHeight);
181
+ if (isMainKey) {
182
+ buttonFrame.size.height = buttonHeight * 2 + _separatorWidth;
183
+ }
184
+ if ([key isEqualToString:@"000"]) {
185
+ buttonFrame.size.width = buttonWidth * 2 + _separatorWidth;
186
+ }
187
+
188
+ button.frame = buttonFrame;
157
189
  xOffset += buttonFrame.size.width + _separatorWidth;
158
190
  }
159
191
 
@@ -161,6 +193,32 @@
161
193
  }
162
194
  }
163
195
 
196
+ - (void)loadBackIconForButton:(UIButton *)button
197
+ {
198
+ if (sBackIcon) {
199
+ [button setImage:sBackIcon forState:UIControlStateNormal];
200
+ return;
201
+ }
202
+
203
+ __weak UIButton *weakButton = button;
204
+ [[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:kBackIconURL]
205
+ completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
206
+ CGImageRef cgImage = [UIImage imageWithData:data].CGImage;
207
+ if (!cgImage) return;
208
+
209
+ // Scale makes the image size kBackIconSize points without redrawing it
210
+ UIImage *icon = [[UIImage imageWithCGImage:cgImage
211
+ scale:CGImageGetWidth(cgImage) / kBackIconSize
212
+ orientation:UIImageOrientationUp]
213
+ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
214
+
215
+ dispatch_async(dispatch_get_main_queue(), ^{
216
+ sBackIcon = icon;
217
+ [weakButton setImage:icon forState:UIControlStateNormal];
218
+ });
219
+ }] resume];
220
+ }
221
+
164
222
  - (void)updateCustomKeyTitle
165
223
  {
166
224
  if (!self.customKeyButton || !_customKeyText) {
@@ -3,6 +3,7 @@
3
3
 
4
4
  #import <React/RCTConversions.h>
5
5
  #import <React/RCTFabricComponentsPlugins.h>
6
+ #import <React/RCTUtils.h>
6
7
  #import <react/renderer/components/InputCalculatorSpec/InputCalculatorComponentDescriptor.h>
7
8
  #import <react/renderer/components/InputCalculatorSpec/EventEmitters.h>
8
9
  #import <react/renderer/components/InputCalculatorSpec/Props.h>
@@ -45,9 +46,13 @@ typedef struct {
45
46
  _textField.delegate = (id<UITextFieldDelegate>)self;
46
47
 
47
48
  // Create keyboard view
49
+ // UIKit sizes the input view to the keyboard width; the keys follow it in layoutSubviews
50
+ UIWindow *window = RCTKeyWindow();
51
+ CGFloat keyboardWidth = window ? window.bounds.size.width : UIScreen.mainScreen.bounds.size.width;
48
52
  CGFloat bottomInset = [self getBottomInset];
49
- CGRect keyboardFrame = CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 240 + bottomInset);
53
+ CGRect keyboardFrame = CGRectMake(0, 0, keyboardWidth, 240 + bottomInset);
50
54
  _keyboardView = [[CalculatorKeyboardView alloc] initWithFrame:keyboardFrame];
55
+ _keyboardView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
51
56
  _keyboardView.input = (id)self; // Bridge pattern
52
57
 
53
58
  // Set custom keyboard
@@ -94,7 +99,8 @@ typedef struct {
94
99
 
95
100
  - (CGFloat)getBottomInset
96
101
  {
97
- UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
102
+ // key window of the active scene; windows.firstObject is unreliable with the UIScene life cycle
103
+ UIWindow *window = RCTKeyWindow();
98
104
  CGFloat bottom = window.safeAreaInsets.bottom > 0 ? 21 : 0;
99
105
  return bottom;
100
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/calculator-keyboard",
3
- "version": "0.167.1-beta.10",
3
+ "version": "0.167.1-beta.14",
4
4
  "description": "react native calculator keyboard",
5
5
  "main": "./src/index.tsx",
6
6
  "files": [