react-native-expo-cropper 1.0.29 → 1.0.30
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/.babelrc +7 -0
- package/App.js +27 -0
- package/app.json +3 -0
- package/dist/CustomCamera.js +276 -0
- package/dist/ImageCropper.js +352 -0
- package/dist/ImageCropperStyles.js +177 -0
- package/dist/ImageProcessor.js +53 -0
- package/index.js +6 -0
- package/package.json +2 -9
- package/src/CustomCamera.js +41 -6
- package/src/ImageCropper.js +46 -20
package/.babelrc
ADDED
package/App.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SafeAreaView, StatusBar, StyleSheet } from 'react-native';
|
|
3
|
+
import ImageCropper from './src/ImageCropper';
|
|
4
|
+
|
|
5
|
+
const App = () => {
|
|
6
|
+
const handleCrop = (uri) => {
|
|
7
|
+
console.log('Cropped Image URI:', uri);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<StatusBar backgroundColor="black" barStyle="light-content" />
|
|
13
|
+
<SafeAreaView style={styles.container}>
|
|
14
|
+
<ImageCropper onCrop={handleCrop} />
|
|
15
|
+
</SafeAreaView>
|
|
16
|
+
</>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const styles = StyleSheet.create({
|
|
21
|
+
container: {
|
|
22
|
+
flex: 1,
|
|
23
|
+
backgroundColor: 'black',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export default App;
|
package/app.json
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = CustomCamera;
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _reactNative = require("react-native");
|
|
10
|
+
var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
|
|
11
|
+
var _expoCamera = require("expo-camera");
|
|
12
|
+
var ImageManipulator = _interopRequireWildcard(require("expo-image-manipulator"));
|
|
13
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t3 in e) "default" !== _t3 && {}.hasOwnProperty.call(e, _t3) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t3)) && (i.get || i.set) ? o(f, _t3, i) : f[_t3] = e[_t3]); return f; })(e, t); }
|
|
14
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
16
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
17
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
18
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
19
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
20
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
21
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
22
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
23
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
24
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
25
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
26
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
27
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
28
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
29
|
+
var _Dimensions$get = _reactNative.Dimensions.get('window'),
|
|
30
|
+
width = _Dimensions$get.width;
|
|
31
|
+
function CustomCamera(_ref) {
|
|
32
|
+
var onPhotoCaptured = _ref.onPhotoCaptured;
|
|
33
|
+
var _useState = (0, _react.useState)(false),
|
|
34
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
35
|
+
isReady = _useState2[0],
|
|
36
|
+
setIsReady = _useState2[1];
|
|
37
|
+
var _useState3 = (0, _react.useState)(false),
|
|
38
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
39
|
+
loadingBeforeCapture = _useState4[0],
|
|
40
|
+
setLoadingBeforeCapture = _useState4[1];
|
|
41
|
+
var _useState5 = (0, _react.useState)(null),
|
|
42
|
+
_useState6 = _slicedToArray(_useState5, 1),
|
|
43
|
+
setHasPermission = _useState6[0];
|
|
44
|
+
var cameraRef = (0, _react.useRef)(null);
|
|
45
|
+
var insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
|
|
46
|
+
(0, _react.useEffect)(function () {
|
|
47
|
+
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
48
|
+
var _yield$Camera$request, status;
|
|
49
|
+
return _regenerator().w(function (_context) {
|
|
50
|
+
while (1) switch (_context.n) {
|
|
51
|
+
case 0:
|
|
52
|
+
_context.n = 1;
|
|
53
|
+
return _expoCamera.Camera.requestCameraPermissionsAsync();
|
|
54
|
+
case 1:
|
|
55
|
+
_yield$Camera$request = _context.v;
|
|
56
|
+
status = _yield$Camera$request.status;
|
|
57
|
+
setHasPermission(status === 'granted');
|
|
58
|
+
case 2:
|
|
59
|
+
return _context.a(2);
|
|
60
|
+
}
|
|
61
|
+
}, _callee);
|
|
62
|
+
}))();
|
|
63
|
+
}, []);
|
|
64
|
+
|
|
65
|
+
// Helper function to wait for multiple render cycles (works on iOS)
|
|
66
|
+
var waitForRender = function waitForRender() {
|
|
67
|
+
var cycles = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;
|
|
68
|
+
return new Promise(function (resolve) {
|
|
69
|
+
var count = 0;
|
|
70
|
+
var _tick = function tick() {
|
|
71
|
+
count++;
|
|
72
|
+
if (count >= cycles) {
|
|
73
|
+
resolve();
|
|
74
|
+
} else {
|
|
75
|
+
setImmediate(_tick);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
setImmediate(_tick);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Helper function to fix image orientation (removes EXIF orientation)
|
|
83
|
+
var fixImageOrientation = /*#__PURE__*/function () {
|
|
84
|
+
var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(uri) {
|
|
85
|
+
var fixedImage, _t;
|
|
86
|
+
return _regenerator().w(function (_context2) {
|
|
87
|
+
while (1) switch (_context2.p = _context2.n) {
|
|
88
|
+
case 0:
|
|
89
|
+
_context2.p = 0;
|
|
90
|
+
_context2.n = 1;
|
|
91
|
+
return ImageManipulator.manipulateAsync(uri, [], {
|
|
92
|
+
compress: 1,
|
|
93
|
+
format: ImageManipulator.SaveFormat.PNG
|
|
94
|
+
});
|
|
95
|
+
case 1:
|
|
96
|
+
fixedImage = _context2.v;
|
|
97
|
+
return _context2.a(2, fixedImage.uri);
|
|
98
|
+
case 2:
|
|
99
|
+
_context2.p = 2;
|
|
100
|
+
_t = _context2.v;
|
|
101
|
+
console.error("Error fixing image orientation:", _t);
|
|
102
|
+
return _context2.a(2, uri);
|
|
103
|
+
}
|
|
104
|
+
}, _callee2, null, [[0, 2]]);
|
|
105
|
+
}));
|
|
106
|
+
return function fixImageOrientation(_x) {
|
|
107
|
+
return _ref3.apply(this, arguments);
|
|
108
|
+
};
|
|
109
|
+
}();
|
|
110
|
+
var takePicture = /*#__PURE__*/function () {
|
|
111
|
+
var _ref4 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
112
|
+
var photo, fixedUri, _t2;
|
|
113
|
+
return _regenerator().w(function (_context3) {
|
|
114
|
+
while (1) switch (_context3.p = _context3.n) {
|
|
115
|
+
case 0:
|
|
116
|
+
if (!cameraRef.current) {
|
|
117
|
+
_context3.n = 6;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
_context3.p = 1;
|
|
121
|
+
// Show loading after a delay (using setImmediate for iOS compatibility)
|
|
122
|
+
waitForRender(20).then(function () {
|
|
123
|
+
setLoadingBeforeCapture(true);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Wait a bit before taking picture (works on iOS)
|
|
127
|
+
_context3.n = 2;
|
|
128
|
+
return waitForRender(3);
|
|
129
|
+
case 2:
|
|
130
|
+
_context3.n = 3;
|
|
131
|
+
return cameraRef.current.takePictureAsync({
|
|
132
|
+
quality: 1,
|
|
133
|
+
shutterSound: false
|
|
134
|
+
});
|
|
135
|
+
case 3:
|
|
136
|
+
photo = _context3.v;
|
|
137
|
+
_context3.n = 4;
|
|
138
|
+
return fixImageOrientation(photo.uri);
|
|
139
|
+
case 4:
|
|
140
|
+
fixedUri = _context3.v;
|
|
141
|
+
onPhotoCaptured(fixedUri);
|
|
142
|
+
setLoadingBeforeCapture(false);
|
|
143
|
+
_context3.n = 6;
|
|
144
|
+
break;
|
|
145
|
+
case 5:
|
|
146
|
+
_context3.p = 5;
|
|
147
|
+
_t2 = _context3.v;
|
|
148
|
+
setLoadingBeforeCapture(false);
|
|
149
|
+
_reactNative.Alert.alert("Erreur");
|
|
150
|
+
case 6:
|
|
151
|
+
return _context3.a(2);
|
|
152
|
+
}
|
|
153
|
+
}, _callee3, null, [[1, 5]]);
|
|
154
|
+
}));
|
|
155
|
+
return function takePicture() {
|
|
156
|
+
return _ref4.apply(this, arguments);
|
|
157
|
+
};
|
|
158
|
+
}();
|
|
159
|
+
return /*#__PURE__*/_react["default"].createElement(_reactNative.SafeAreaView, {
|
|
160
|
+
style: styles.outerContainer
|
|
161
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
162
|
+
style: styles.cameraWrapper
|
|
163
|
+
}, /*#__PURE__*/_react["default"].createElement(_expoCamera.CameraView, {
|
|
164
|
+
style: styles.camera,
|
|
165
|
+
facing: "back",
|
|
166
|
+
ref: cameraRef,
|
|
167
|
+
onCameraReady: function onCameraReady() {
|
|
168
|
+
return setIsReady(true);
|
|
169
|
+
}
|
|
170
|
+
}), loadingBeforeCapture && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
171
|
+
style: styles.loadingOverlay
|
|
172
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.Image, {
|
|
173
|
+
source: require('../src/assets/loadingCamera.gif'),
|
|
174
|
+
style: styles.loadingGif,
|
|
175
|
+
resizeMode: "contain"
|
|
176
|
+
})), /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
177
|
+
style: styles.touchBlocker,
|
|
178
|
+
pointerEvents: "auto"
|
|
179
|
+
})), /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
180
|
+
style: styles.scanFrame
|
|
181
|
+
})), /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
182
|
+
style: [styles.buttonContainer, {
|
|
183
|
+
bottom: ((insets === null || insets === void 0 ? void 0 : insets.bottom) || 0) + 16,
|
|
184
|
+
marginBottom: 0
|
|
185
|
+
}]
|
|
186
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.TouchableOpacity, {
|
|
187
|
+
style: styles.button,
|
|
188
|
+
onPress: takePicture,
|
|
189
|
+
disabled: !isReady || loadingBeforeCapture
|
|
190
|
+
})));
|
|
191
|
+
}
|
|
192
|
+
var PRIMARY_GREEN = '#198754';
|
|
193
|
+
var DEEP_BLACK = '#0B0B0B';
|
|
194
|
+
var GLOW_WHITE = 'rgba(255, 255, 255, 0.85)';
|
|
195
|
+
var styles = _reactNative.StyleSheet.create({
|
|
196
|
+
outerContainer: {
|
|
197
|
+
flex: 1,
|
|
198
|
+
backgroundColor: DEEP_BLACK,
|
|
199
|
+
justifyContent: 'center',
|
|
200
|
+
alignItems: 'center'
|
|
201
|
+
},
|
|
202
|
+
cameraWrapper: {
|
|
203
|
+
width: width,
|
|
204
|
+
aspectRatio: 9 / 16,
|
|
205
|
+
borderRadius: 30,
|
|
206
|
+
overflow: 'hidden',
|
|
207
|
+
alignItems: 'center',
|
|
208
|
+
justifyContent: 'center',
|
|
209
|
+
position: 'relative'
|
|
210
|
+
},
|
|
211
|
+
camera: _objectSpread({}, _reactNative.StyleSheet.absoluteFillObject),
|
|
212
|
+
scanFrame: {
|
|
213
|
+
position: 'absolute',
|
|
214
|
+
width: '95%',
|
|
215
|
+
height: '80%',
|
|
216
|
+
borderWidth: 4,
|
|
217
|
+
borderColor: PRIMARY_GREEN,
|
|
218
|
+
borderRadius: 5,
|
|
219
|
+
backgroundColor: 'rgba(0, 0, 0, 0.1)'
|
|
220
|
+
},
|
|
221
|
+
loadingOverlay: _objectSpread(_objectSpread({}, _reactNative.StyleSheet.absoluteFillObject), {}, {
|
|
222
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
223
|
+
zIndex: 20,
|
|
224
|
+
justifyContent: 'center',
|
|
225
|
+
alignItems: 'center'
|
|
226
|
+
}),
|
|
227
|
+
loadingGif: {
|
|
228
|
+
width: 100,
|
|
229
|
+
height: 100
|
|
230
|
+
},
|
|
231
|
+
touchBlocker: _objectSpread(_objectSpread({}, _reactNative.StyleSheet.absoluteFillObject), {}, {
|
|
232
|
+
zIndex: 21,
|
|
233
|
+
backgroundColor: 'transparent'
|
|
234
|
+
}),
|
|
235
|
+
cancelIcon: {
|
|
236
|
+
position: 'absolute',
|
|
237
|
+
top: 20,
|
|
238
|
+
left: 20,
|
|
239
|
+
backgroundColor: PRIMARY_GREEN,
|
|
240
|
+
borderRadius: 5,
|
|
241
|
+
padding: 8
|
|
242
|
+
},
|
|
243
|
+
buttonContainer: {
|
|
244
|
+
position: 'absolute',
|
|
245
|
+
bottom: 0,
|
|
246
|
+
marginBottom: 20,
|
|
247
|
+
flexDirection: 'row',
|
|
248
|
+
justifyContent: 'center'
|
|
249
|
+
},
|
|
250
|
+
button: {
|
|
251
|
+
width: 80,
|
|
252
|
+
height: 80,
|
|
253
|
+
borderRadius: 50,
|
|
254
|
+
backgroundColor: GLOW_WHITE,
|
|
255
|
+
borderWidth: 5,
|
|
256
|
+
borderColor: PRIMARY_GREEN,
|
|
257
|
+
alignItems: 'center',
|
|
258
|
+
justifyContent: 'center'
|
|
259
|
+
},
|
|
260
|
+
text: {
|
|
261
|
+
fontSize: 18,
|
|
262
|
+
color: GLOW_WHITE
|
|
263
|
+
},
|
|
264
|
+
container: {
|
|
265
|
+
flex: 1,
|
|
266
|
+
backgroundColor: DEEP_BLACK,
|
|
267
|
+
justifyContent: 'center',
|
|
268
|
+
alignItems: 'center',
|
|
269
|
+
padding: 20
|
|
270
|
+
},
|
|
271
|
+
iconText: {
|
|
272
|
+
fontSize: 18,
|
|
273
|
+
color: GLOW_WHITE,
|
|
274
|
+
fontWeight: '600'
|
|
275
|
+
}
|
|
276
|
+
});
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = void 0;
|
|
8
|
+
var _ImageCropperStyles = _interopRequireDefault(require("./ImageCropperStyles"));
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _reactNative = require("react-native");
|
|
11
|
+
var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
|
|
12
|
+
var _reactNativeViewShot = require("react-native-view-shot");
|
|
13
|
+
var _CustomCamera = _interopRequireDefault(require("./CustomCamera"));
|
|
14
|
+
var _ImageProcessor = require("./ImageProcessor");
|
|
15
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t2 in e) "default" !== _t2 && {}.hasOwnProperty.call(e, _t2) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t2)) && (i.get || i.set) ? o(f, _t2, i) : f[_t2] = e[_t2]); return f; })(e, t); }
|
|
16
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
17
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
18
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
19
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
20
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
21
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
22
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
23
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
24
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
25
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
26
|
+
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
27
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
28
|
+
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
29
|
+
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
30
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
31
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
32
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
33
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
34
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
35
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
36
|
+
var ImageCropper = function ImageCropper(_ref) {
|
|
37
|
+
var onConfirm = _ref.onConfirm,
|
|
38
|
+
openCameraFirst = _ref.openCameraFirst,
|
|
39
|
+
initialImage = _ref.initialImage,
|
|
40
|
+
addheight = _ref.addheight;
|
|
41
|
+
var _useState = (0, _react.useState)(null),
|
|
42
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
43
|
+
image = _useState2[0],
|
|
44
|
+
setImage = _useState2[1];
|
|
45
|
+
var _useState3 = (0, _react.useState)([]),
|
|
46
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
47
|
+
points = _useState4[0],
|
|
48
|
+
setPoints = _useState4[1];
|
|
49
|
+
var _useState5 = (0, _react.useState)(false),
|
|
50
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
51
|
+
showResult = _useState6[0],
|
|
52
|
+
setShowResult = _useState6[1];
|
|
53
|
+
var _useState7 = (0, _react.useState)(false),
|
|
54
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
55
|
+
showCustomCamera = _useState8[0],
|
|
56
|
+
setShowCustomCamera = _useState8[1];
|
|
57
|
+
var viewRef = (0, _react.useRef)(null);
|
|
58
|
+
var imageMeasure = (0, _react.useRef)({
|
|
59
|
+
x: 0,
|
|
60
|
+
y: 0,
|
|
61
|
+
width: 0,
|
|
62
|
+
height: 0
|
|
63
|
+
});
|
|
64
|
+
var selectedPointIndex = (0, _react.useRef)(null);
|
|
65
|
+
var lastTap = (0, _react.useRef)(null);
|
|
66
|
+
var _useState9 = (0, _react.useState)(false),
|
|
67
|
+
_useState0 = _slicedToArray(_useState9, 2),
|
|
68
|
+
isLoading = _useState0[0],
|
|
69
|
+
setIsLoading = _useState0[1];
|
|
70
|
+
var _useState1 = (0, _react.useState)(false),
|
|
71
|
+
_useState10 = _slicedToArray(_useState1, 2),
|
|
72
|
+
showFullScreenCapture = _useState10[0],
|
|
73
|
+
setShowFullScreenCapture = _useState10[1];
|
|
74
|
+
var lastValidPosition = (0, _react.useRef)(null);
|
|
75
|
+
(0, _react.useEffect)(function () {
|
|
76
|
+
if (openCameraFirst) {
|
|
77
|
+
setShowCustomCamera(true);
|
|
78
|
+
} else if (initialImage) {
|
|
79
|
+
setImage(initialImage);
|
|
80
|
+
}
|
|
81
|
+
}, [openCameraFirst, initialImage]);
|
|
82
|
+
(0, _react.useEffect)(function () {
|
|
83
|
+
if (!image) return;
|
|
84
|
+
_reactNative.Image.getSize(image, function (imgWidth, imgHeight) {
|
|
85
|
+
var screenRatio = SCREEN_WIDTH / SCREEN_HEIGHT;
|
|
86
|
+
var imageRatio = imgWidth / imgHeight;
|
|
87
|
+
if (imageRatio > screenRatio) {
|
|
88
|
+
imageMeasure.current = {
|
|
89
|
+
width: SCREEN_WIDTH,
|
|
90
|
+
height: SCREEN_WIDTH / imageRatio
|
|
91
|
+
};
|
|
92
|
+
} else {
|
|
93
|
+
imageMeasure.current = {
|
|
94
|
+
width: SCREEN_HEIGHT * imageRatio,
|
|
95
|
+
height: SCREEN_HEIGHT
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}, [image]);
|
|
100
|
+
var initializeCropBox = function initializeCropBox() {
|
|
101
|
+
var _imageMeasure$current = imageMeasure.current,
|
|
102
|
+
width = _imageMeasure$current.width,
|
|
103
|
+
height = _imageMeasure$current.height;
|
|
104
|
+
// if (width === 0 || height === 0 || points.length > 0) return;
|
|
105
|
+
var boxWidth = width * 0.8;
|
|
106
|
+
var boxHeight = height * 0.8;
|
|
107
|
+
var centerX = width / 2;
|
|
108
|
+
var centerY = height / 2;
|
|
109
|
+
setPoints([{
|
|
110
|
+
x: centerX - boxWidth / 2,
|
|
111
|
+
y: centerY - boxHeight / 2
|
|
112
|
+
}, {
|
|
113
|
+
x: centerX + boxWidth / 2,
|
|
114
|
+
y: centerY - boxHeight / 2
|
|
115
|
+
}, {
|
|
116
|
+
x: centerX + boxWidth / 2,
|
|
117
|
+
y: centerY + boxHeight / 2
|
|
118
|
+
}, {
|
|
119
|
+
x: centerX - boxWidth / 2,
|
|
120
|
+
y: centerY + boxHeight / 2
|
|
121
|
+
}]);
|
|
122
|
+
};
|
|
123
|
+
var onImageLayout = function onImageLayout(e) {
|
|
124
|
+
var layout = e.nativeEvent.layout;
|
|
125
|
+
imageMeasure.current = {
|
|
126
|
+
x: layout.x,
|
|
127
|
+
y: layout.y,
|
|
128
|
+
width: layout.width,
|
|
129
|
+
height: layout.height
|
|
130
|
+
};
|
|
131
|
+
initializeCropBox();
|
|
132
|
+
};
|
|
133
|
+
var createPath = function createPath() {
|
|
134
|
+
if (points.length < 1) return '';
|
|
135
|
+
var path = "M ".concat(points[0].x, " ").concat(points[0].y, " ");
|
|
136
|
+
points.forEach(function (point) {
|
|
137
|
+
return path += "L ".concat(point.x, " ").concat(point.y, " ");
|
|
138
|
+
});
|
|
139
|
+
return path + 'Z';
|
|
140
|
+
};
|
|
141
|
+
var handleTap = function handleTap(e) {
|
|
142
|
+
if (!image || showResult) return;
|
|
143
|
+
var now = Date.now();
|
|
144
|
+
var _e$nativeEvent = e.nativeEvent,
|
|
145
|
+
tapX = _e$nativeEvent.locationX,
|
|
146
|
+
tapY = _e$nativeEvent.locationY;
|
|
147
|
+
if (lastTap.current && now - lastTap.current < 300) {
|
|
148
|
+
var exists = points.some(function (p) {
|
|
149
|
+
return Math.abs(p.x - tapX) < 15 && Math.abs(p.y - tapY) < 15;
|
|
150
|
+
});
|
|
151
|
+
if (!exists) setPoints([].concat(_toConsumableArray(points), [{
|
|
152
|
+
x: tapX,
|
|
153
|
+
y: tapY
|
|
154
|
+
}]));
|
|
155
|
+
lastTap.current = null;
|
|
156
|
+
} else {
|
|
157
|
+
var index = points.findIndex(function (p) {
|
|
158
|
+
return Math.abs(p.x - tapX) < 20 && Math.abs(p.y - tapY) < 20;
|
|
159
|
+
});
|
|
160
|
+
if (index !== -1) {
|
|
161
|
+
selectedPointIndex.current = index;
|
|
162
|
+
lastValidPosition.current = _objectSpread({}, points[index]); // store original position before move
|
|
163
|
+
}
|
|
164
|
+
lastTap.current = now;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
var handleMove = function handleMove(e) {
|
|
168
|
+
if (showResult || selectedPointIndex.current === null) return;
|
|
169
|
+
var _e$nativeEvent2 = e.nativeEvent,
|
|
170
|
+
moveX = _e$nativeEvent2.locationX,
|
|
171
|
+
moveY = _e$nativeEvent2.locationY;
|
|
172
|
+
var width = imageMeasure.current.width;
|
|
173
|
+
var height = imageMeasure.current.height;
|
|
174
|
+
var boundedX = Math.max(0, Math.min(moveX, width));
|
|
175
|
+
var boundedY = Math.max(0, Math.min(moveY, height));
|
|
176
|
+
var edgeThreshold = 10;
|
|
177
|
+
var isNearTopOrBottomEdge = boundedY <= edgeThreshold || boundedY >= height - edgeThreshold;
|
|
178
|
+
var isNearLeftOrRightEdge = boundedX <= edgeThreshold || boundedX >= width - edgeThreshold;
|
|
179
|
+
if (isNearTopOrBottomEdge || isNearLeftOrRightEdge) {
|
|
180
|
+
// Reset point to last known position
|
|
181
|
+
if (lastValidPosition.current && selectedPointIndex.current !== null) {
|
|
182
|
+
setPoints(function (prev) {
|
|
183
|
+
return prev.map(function (p, i) {
|
|
184
|
+
return i === selectedPointIndex.current ? lastValidPosition.current : p;
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
selectedPointIndex.current = null;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Valid move — update point and store as new last valid position
|
|
193
|
+
var updatedPoint = {
|
|
194
|
+
x: boundedX,
|
|
195
|
+
y: boundedY
|
|
196
|
+
};
|
|
197
|
+
lastValidPosition.current = updatedPoint;
|
|
198
|
+
setPoints(function (prev) {
|
|
199
|
+
return prev.map(function (p, i) {
|
|
200
|
+
return i === selectedPointIndex.current ? updatedPoint : p;
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
var handleRelease = function handleRelease() {
|
|
205
|
+
selectedPointIndex.current = null;
|
|
206
|
+
};
|
|
207
|
+
var handleReset = function handleReset() {
|
|
208
|
+
// setPoints([]);
|
|
209
|
+
initializeCropBox();
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Helper function to wait for multiple render cycles (works on iOS)
|
|
213
|
+
var waitForRender = function waitForRender() {
|
|
214
|
+
var cycles = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;
|
|
215
|
+
return new Promise(function (resolve) {
|
|
216
|
+
var count = 0;
|
|
217
|
+
var _tick = function tick() {
|
|
218
|
+
count++;
|
|
219
|
+
if (count >= cycles) {
|
|
220
|
+
resolve();
|
|
221
|
+
} else {
|
|
222
|
+
setImmediate(_tick);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
setImmediate(_tick);
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
return /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
229
|
+
style: _ImageCropperStyles["default"].container
|
|
230
|
+
}, showCustomCamera ? /*#__PURE__*/_react["default"].createElement(_CustomCamera["default"], {
|
|
231
|
+
onPhotoCaptured: function onPhotoCaptured(uri) {
|
|
232
|
+
setImage(uri);
|
|
233
|
+
setShowCustomCamera(false);
|
|
234
|
+
},
|
|
235
|
+
onCancel: function onCancel() {
|
|
236
|
+
return setShowCustomCamera(false);
|
|
237
|
+
}
|
|
238
|
+
}) : /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, !showResult && /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
239
|
+
style: image ? _ImageCropperStyles["default"].buttonContainer : _ImageCropperStyles["default"].centerButtonsContainer
|
|
240
|
+
}, image && /*#__PURE__*/_react["default"].createElement(_reactNative.TouchableOpacity, {
|
|
241
|
+
style: _ImageCropperStyles["default"].button,
|
|
242
|
+
onPress: handleReset
|
|
243
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.Text, {
|
|
244
|
+
style: _ImageCropperStyles["default"].buttonText
|
|
245
|
+
}, "Reset")), image && /*#__PURE__*/_react["default"].createElement(_reactNative.TouchableOpacity, {
|
|
246
|
+
style: _ImageCropperStyles["default"].button,
|
|
247
|
+
onPress: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
248
|
+
var capturedUri, enhancedUri, name, _t;
|
|
249
|
+
return _regenerator().w(function (_context) {
|
|
250
|
+
while (1) switch (_context.p = _context.n) {
|
|
251
|
+
case 0:
|
|
252
|
+
// setShowFullScreenCapture(true);
|
|
253
|
+
setIsLoading(true);
|
|
254
|
+
setShowResult(true);
|
|
255
|
+
_context.p = 1;
|
|
256
|
+
_context.n = 2;
|
|
257
|
+
return waitForRender(8);
|
|
258
|
+
case 2:
|
|
259
|
+
console.log("Starting capture...");
|
|
260
|
+
_context.n = 3;
|
|
261
|
+
return (0, _reactNativeViewShot.captureRef)(viewRef, {
|
|
262
|
+
format: 'png',
|
|
263
|
+
quality: 1
|
|
264
|
+
});
|
|
265
|
+
case 3:
|
|
266
|
+
capturedUri = _context.v;
|
|
267
|
+
console.log("Capture successful:", capturedUri);
|
|
268
|
+
if (capturedUri) {
|
|
269
|
+
_context.n = 4;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
throw new Error("Capture returned empty URI");
|
|
273
|
+
case 4:
|
|
274
|
+
console.log("Enhancing image...");
|
|
275
|
+
_context.n = 5;
|
|
276
|
+
return (0, _ImageProcessor.enhanceImage)(capturedUri, addheight);
|
|
277
|
+
case 5:
|
|
278
|
+
enhancedUri = _context.v;
|
|
279
|
+
console.log("Image enhanced:", enhancedUri);
|
|
280
|
+
name = "IMAGE XTK".concat(Date.now(), ".png");
|
|
281
|
+
if (onConfirm) {
|
|
282
|
+
console.log("Calling onConfirm with:", enhancedUri, name);
|
|
283
|
+
onConfirm(enhancedUri, name);
|
|
284
|
+
}
|
|
285
|
+
_context.n = 7;
|
|
286
|
+
break;
|
|
287
|
+
case 6:
|
|
288
|
+
_context.p = 6;
|
|
289
|
+
_t = _context.v;
|
|
290
|
+
console.error("Erreur lors de la capture :", _t);
|
|
291
|
+
alert("Erreur lors de la capture ! " + _t.message);
|
|
292
|
+
case 7:
|
|
293
|
+
_context.p = 7;
|
|
294
|
+
setShowResult(false);
|
|
295
|
+
setIsLoading(false);
|
|
296
|
+
setShowFullScreenCapture(false);
|
|
297
|
+
return _context.f(7);
|
|
298
|
+
case 8:
|
|
299
|
+
return _context.a(2);
|
|
300
|
+
}
|
|
301
|
+
}, _callee, null, [[1, 6, 7, 8]]);
|
|
302
|
+
}))
|
|
303
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.Text, {
|
|
304
|
+
style: _ImageCropperStyles["default"].buttonText
|
|
305
|
+
}, "Confirm"))), image && /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
306
|
+
ref: viewRef,
|
|
307
|
+
collapsable: false,
|
|
308
|
+
style: showFullScreenCapture ? _ImageCropperStyles["default"].fullscreenImageContainer : _ImageCropperStyles["default"].imageContainer,
|
|
309
|
+
onStartShouldSetResponder: function onStartShouldSetResponder() {
|
|
310
|
+
return true;
|
|
311
|
+
},
|
|
312
|
+
onResponderStart: handleTap,
|
|
313
|
+
onResponderMove: handleMove,
|
|
314
|
+
onResponderRelease: handleRelease
|
|
315
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.Image, {
|
|
316
|
+
source: {
|
|
317
|
+
uri: image
|
|
318
|
+
},
|
|
319
|
+
style: _ImageCropperStyles["default"].image,
|
|
320
|
+
onLayout: onImageLayout
|
|
321
|
+
}), /*#__PURE__*/_react["default"].createElement(_reactNativeSvg["default"], {
|
|
322
|
+
style: _ImageCropperStyles["default"].overlay
|
|
323
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNativeSvg.Path, {
|
|
324
|
+
d: "M 0 0 H ".concat(imageMeasure.current.width, " V ").concat(imageMeasure.current.height, " H 0 Z ").concat(createPath()),
|
|
325
|
+
fill: showResult ? 'white' : 'rgba(0, 0, 0, 0.8)',
|
|
326
|
+
fillRule: "evenodd"
|
|
327
|
+
}), !showResult && points.length > 0 && /*#__PURE__*/_react["default"].createElement(_reactNativeSvg.Path, {
|
|
328
|
+
d: createPath(),
|
|
329
|
+
fill: "transparent",
|
|
330
|
+
stroke: "white",
|
|
331
|
+
strokeWidth: 2
|
|
332
|
+
}), !showResult && points.map(function (point, index) {
|
|
333
|
+
return /*#__PURE__*/_react["default"].createElement(_reactNativeSvg.Circle, {
|
|
334
|
+
key: index,
|
|
335
|
+
cx: point.x,
|
|
336
|
+
cy: point.y,
|
|
337
|
+
r: 10,
|
|
338
|
+
fill: "white"
|
|
339
|
+
});
|
|
340
|
+
})))), /*#__PURE__*/_react["default"].createElement(_reactNative.Modal, {
|
|
341
|
+
visible: isLoading,
|
|
342
|
+
transparent: true,
|
|
343
|
+
animationType: "fade"
|
|
344
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.View, {
|
|
345
|
+
style: _ImageCropperStyles["default"].loadingOverlay
|
|
346
|
+
}, /*#__PURE__*/_react["default"].createElement(_reactNative.Image, {
|
|
347
|
+
source: require('../src/assets/loadingCamera.gif'),
|
|
348
|
+
style: _ImageCropperStyles["default"].loadingGif,
|
|
349
|
+
resizeMode: "contain"
|
|
350
|
+
}))));
|
|
351
|
+
};
|
|
352
|
+
var _default = exports["default"] = ImageCropper;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _Dimensions$get = _reactNative.Dimensions.get('window'),
|
|
9
|
+
SCREEN_WIDTH = _Dimensions$get.width,
|
|
10
|
+
SCREEN_HEIGHT = _Dimensions$get.height;
|
|
11
|
+
var IMAGE_HEIGHT = SCREEN_HEIGHT;
|
|
12
|
+
var IMAGE_WIDTH = SCREEN_WIDTH;
|
|
13
|
+
var PRIMARY_GREEN = '#198754';
|
|
14
|
+
var DEEP_BLACK = '#0B0B0B';
|
|
15
|
+
var GLOW_WHITE = 'rgba(255, 255, 255, 0.85)';
|
|
16
|
+
var styles = _reactNative.StyleSheet.create({
|
|
17
|
+
container: {
|
|
18
|
+
flex: 1,
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
backgroundColor: DEEP_BLACK
|
|
21
|
+
},
|
|
22
|
+
buttonContainer: {
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
bottom: 50,
|
|
25
|
+
left: 0,
|
|
26
|
+
right: 0,
|
|
27
|
+
flexDirection: 'row',
|
|
28
|
+
flexWrap: 'wrap',
|
|
29
|
+
justifyContent: 'center',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
paddingHorizontal: 10,
|
|
32
|
+
zIndex: 10
|
|
33
|
+
},
|
|
34
|
+
button: {
|
|
35
|
+
flex: 1,
|
|
36
|
+
width: "100%",
|
|
37
|
+
padding: 10,
|
|
38
|
+
alignItems: "center",
|
|
39
|
+
justifyContent: "center",
|
|
40
|
+
backgroundColor: "#549433",
|
|
41
|
+
borderRadius: 5,
|
|
42
|
+
marginBottom: 20,
|
|
43
|
+
marginRight: 5
|
|
44
|
+
},
|
|
45
|
+
buttonText: {
|
|
46
|
+
color: 'white',
|
|
47
|
+
fontSize: 18,
|
|
48
|
+
fontWeight: '600',
|
|
49
|
+
textAlign: 'center'
|
|
50
|
+
},
|
|
51
|
+
iconText: {
|
|
52
|
+
color: PRIMARY_GREEN,
|
|
53
|
+
fontSize: 16,
|
|
54
|
+
fontWeight: '600',
|
|
55
|
+
textAlign: 'center'
|
|
56
|
+
},
|
|
57
|
+
imageContainer: {
|
|
58
|
+
width: IMAGE_WIDTH,
|
|
59
|
+
height: "80%",
|
|
60
|
+
justifyContent: 'center',
|
|
61
|
+
alignItems: 'center',
|
|
62
|
+
overflow: 'hidden',
|
|
63
|
+
backgroundColor: 'black'
|
|
64
|
+
},
|
|
65
|
+
image: {
|
|
66
|
+
width: '100%',
|
|
67
|
+
height: '100%',
|
|
68
|
+
resizeMode: 'contain'
|
|
69
|
+
},
|
|
70
|
+
overlay: {
|
|
71
|
+
position: 'absolute',
|
|
72
|
+
top: 0,
|
|
73
|
+
left: 0,
|
|
74
|
+
width: '100%',
|
|
75
|
+
height: '100%',
|
|
76
|
+
zIndex: 1
|
|
77
|
+
},
|
|
78
|
+
croppedImage: {
|
|
79
|
+
width: IMAGE_WIDTH,
|
|
80
|
+
height: IMAGE_HEIGHT,
|
|
81
|
+
resizeMode: 'cover',
|
|
82
|
+
marginTop: 10,
|
|
83
|
+
borderWidth: 2,
|
|
84
|
+
borderColor: 'white',
|
|
85
|
+
borderRadius: 10
|
|
86
|
+
},
|
|
87
|
+
fixedButtonContainer: {
|
|
88
|
+
position: 'absolute',
|
|
89
|
+
bottom: 100,
|
|
90
|
+
left: 0,
|
|
91
|
+
right: 0,
|
|
92
|
+
flexDirection: 'row',
|
|
93
|
+
justifyContent: 'center',
|
|
94
|
+
flexWrap: 'wrap',
|
|
95
|
+
gap: 10,
|
|
96
|
+
paddingHorizontal: 10
|
|
97
|
+
},
|
|
98
|
+
fixedButton: {
|
|
99
|
+
backgroundColor: PRIMARY_GREEN,
|
|
100
|
+
paddingVertical: 18,
|
|
101
|
+
paddingHorizontal: 30,
|
|
102
|
+
borderRadius: 12,
|
|
103
|
+
margin: 6,
|
|
104
|
+
alignItems: 'center',
|
|
105
|
+
justifyContent: 'center',
|
|
106
|
+
borderWidth: 0,
|
|
107
|
+
width: SCREEN_WIDTH * 0.4,
|
|
108
|
+
height: 60
|
|
109
|
+
},
|
|
110
|
+
centerButtonsContainer: {
|
|
111
|
+
position: 'absolute',
|
|
112
|
+
bottom: 20,
|
|
113
|
+
left: 0,
|
|
114
|
+
right: 0,
|
|
115
|
+
alignItems: 'center',
|
|
116
|
+
justifyContent: 'center',
|
|
117
|
+
zIndex: 10,
|
|
118
|
+
gap: 10
|
|
119
|
+
},
|
|
120
|
+
welcomeText: {
|
|
121
|
+
position: 'absolute',
|
|
122
|
+
top: '40%',
|
|
123
|
+
left: 20,
|
|
124
|
+
right: 20,
|
|
125
|
+
textAlign: 'center',
|
|
126
|
+
color: GLOW_WHITE,
|
|
127
|
+
fontSize: 40,
|
|
128
|
+
fontWeight: '800',
|
|
129
|
+
zIndex: 10
|
|
130
|
+
},
|
|
131
|
+
startButton: {
|
|
132
|
+
backgroundColor: PRIMARY_GREEN,
|
|
133
|
+
paddingVertical: 18,
|
|
134
|
+
paddingHorizontal: 30,
|
|
135
|
+
borderRadius: 12,
|
|
136
|
+
margin: 6,
|
|
137
|
+
alignItems: 'center',
|
|
138
|
+
justifyContent: 'center',
|
|
139
|
+
borderWidth: 0,
|
|
140
|
+
width: SCREEN_WIDTH * 0.9,
|
|
141
|
+
height: 70
|
|
142
|
+
},
|
|
143
|
+
startButtonText: {
|
|
144
|
+
color: 'white',
|
|
145
|
+
fontSize: 18,
|
|
146
|
+
fontWeight: '600',
|
|
147
|
+
textAlign: 'center'
|
|
148
|
+
},
|
|
149
|
+
loadingOverlay: {
|
|
150
|
+
flex: 1,
|
|
151
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
152
|
+
justifyContent: 'center',
|
|
153
|
+
alignItems: 'center',
|
|
154
|
+
position: 'absolute',
|
|
155
|
+
top: 0,
|
|
156
|
+
bottom: 0,
|
|
157
|
+
left: 0,
|
|
158
|
+
right: 0,
|
|
159
|
+
zIndex: 9999
|
|
160
|
+
},
|
|
161
|
+
loadingGif: {
|
|
162
|
+
width: 120,
|
|
163
|
+
height: 120
|
|
164
|
+
},
|
|
165
|
+
fullscreenImageContainer: {
|
|
166
|
+
position: 'absolute',
|
|
167
|
+
top: 0,
|
|
168
|
+
left: 0,
|
|
169
|
+
width: SCREEN_WIDTH,
|
|
170
|
+
height: SCREEN_HEIGHT,
|
|
171
|
+
backgroundColor: 'black',
|
|
172
|
+
justifyContent: 'center',
|
|
173
|
+
alignItems: 'center',
|
|
174
|
+
zIndex: 9999
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
var _default = exports["default"] = styles;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.enhanceImage = void 0;
|
|
8
|
+
var ImageManipulator = _interopRequireWildcard(require("expo-image-manipulator"));
|
|
9
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t2 in e) "default" !== _t2 && {}.hasOwnProperty.call(e, _t2) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t2)) && (i.get || i.set) ? o(f, _t2, i) : f[_t2] = e[_t2]); return f; })(e, t); }
|
|
10
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
11
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
12
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
13
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
14
|
+
var enhanceImage = exports.enhanceImage = /*#__PURE__*/function () {
|
|
15
|
+
var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(uri, addheight) {
|
|
16
|
+
var imageInfo, ratio, maxHeight, newWidth, newHeight, result, _t;
|
|
17
|
+
return _regenerator().w(function (_context) {
|
|
18
|
+
while (1) switch (_context.p = _context.n) {
|
|
19
|
+
case 0:
|
|
20
|
+
_context.p = 0;
|
|
21
|
+
_context.n = 1;
|
|
22
|
+
return ImageManipulator.manipulateAsync(uri, []);
|
|
23
|
+
case 1:
|
|
24
|
+
imageInfo = _context.v;
|
|
25
|
+
ratio = imageInfo.height / imageInfo.width;
|
|
26
|
+
maxHeight = addheight;
|
|
27
|
+
newWidth = Math.round(maxHeight / ratio);
|
|
28
|
+
newHeight = Math.round(newWidth * ratio);
|
|
29
|
+
_context.n = 2;
|
|
30
|
+
return ImageManipulator.manipulateAsync(uri, [{
|
|
31
|
+
resize: {
|
|
32
|
+
width: newWidth,
|
|
33
|
+
height: newHeight
|
|
34
|
+
}
|
|
35
|
+
}], {
|
|
36
|
+
compress: 1,
|
|
37
|
+
format: ImageManipulator.SaveFormat.PNG
|
|
38
|
+
});
|
|
39
|
+
case 2:
|
|
40
|
+
result = _context.v;
|
|
41
|
+
return _context.a(2, result.uri);
|
|
42
|
+
case 3:
|
|
43
|
+
_context.p = 3;
|
|
44
|
+
_t = _context.v;
|
|
45
|
+
console.error("Erreur T404K:", _t);
|
|
46
|
+
return _context.a(2, uri);
|
|
47
|
+
}
|
|
48
|
+
}, _callee, null, [[0, 3]]);
|
|
49
|
+
}));
|
|
50
|
+
return function enhanceImage(_x, _x2) {
|
|
51
|
+
return _ref.apply(this, arguments);
|
|
52
|
+
};
|
|
53
|
+
}();
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-expo-cropper",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "Recadrage polygonal d'images.",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "index.js",
|
|
6
6
|
"author": "PCS AGRI",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"keywords": [
|
|
@@ -50,12 +50,5 @@
|
|
|
50
50
|
"@babel/core": "^7.28.5",
|
|
51
51
|
"@babel/preset-env": "^7.28.5",
|
|
52
52
|
"@babel/preset-react": "^7.28.5"
|
|
53
|
-
},
|
|
54
|
-
"files": [
|
|
55
|
-
"src",
|
|
56
|
-
"README.MD"
|
|
57
|
-
],
|
|
58
|
-
"publishConfig": {
|
|
59
|
-
"access": "public"
|
|
60
53
|
}
|
|
61
54
|
}
|
package/src/CustomCamera.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from 'react-native';
|
|
12
12
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
13
13
|
import { Camera, CameraView } from 'expo-camera';
|
|
14
|
+
import * as ImageManipulator from 'expo-image-manipulator';
|
|
14
15
|
const { width } = Dimensions.get('window');
|
|
15
16
|
|
|
16
17
|
export default function CustomCamera({ onPhotoCaptured}) {
|
|
@@ -31,23 +32,57 @@ useEffect(() => {
|
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
|
|
35
|
+
// Helper function to wait for multiple render cycles (works on iOS)
|
|
36
|
+
const waitForRender = (cycles = 5) => {
|
|
37
|
+
return new Promise((resolve) => {
|
|
38
|
+
let count = 0;
|
|
39
|
+
const tick = () => {
|
|
40
|
+
count++;
|
|
41
|
+
if (count >= cycles) {
|
|
42
|
+
resolve();
|
|
43
|
+
} else {
|
|
44
|
+
setImmediate(tick);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
setImmediate(tick);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Helper function to fix image orientation (removes EXIF orientation)
|
|
52
|
+
const fixImageOrientation = async (uri) => {
|
|
53
|
+
try {
|
|
54
|
+
// Use manipulateAsync with empty array to fix orientation based on EXIF data
|
|
55
|
+
const fixedImage = await ImageManipulator.manipulateAsync(uri, [], {
|
|
56
|
+
compress: 1,
|
|
57
|
+
format: ImageManipulator.SaveFormat.PNG
|
|
58
|
+
});
|
|
59
|
+
return fixedImage.uri;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error("Error fixing image orientation:", error);
|
|
62
|
+
return uri; // Return original if fixing fails
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
34
66
|
const takePicture = async () => {
|
|
35
67
|
if (cameraRef.current) {
|
|
36
68
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
// Show loading after a delay (using setImmediate for iOS compatibility)
|
|
70
|
+
waitForRender(20).then(() => {
|
|
39
71
|
setLoadingBeforeCapture(true);
|
|
40
|
-
}
|
|
72
|
+
});
|
|
41
73
|
|
|
42
|
-
|
|
74
|
+
// Wait a bit before taking picture (works on iOS)
|
|
75
|
+
await waitForRender(3);
|
|
43
76
|
|
|
44
77
|
const photo = await cameraRef.current.takePictureAsync({
|
|
45
78
|
quality: 1,
|
|
46
79
|
shutterSound: false,
|
|
47
80
|
});
|
|
48
81
|
|
|
82
|
+
// Fix orientation to preserve vertical/horizontal position as taken
|
|
83
|
+
const fixedUri = await fixImageOrientation(photo.uri);
|
|
49
84
|
|
|
50
|
-
onPhotoCaptured(
|
|
85
|
+
onPhotoCaptured(fixedUri);
|
|
51
86
|
|
|
52
87
|
setLoadingBeforeCapture(false);
|
|
53
88
|
} catch (error) {
|
|
@@ -127,7 +162,7 @@ const styles = StyleSheet.create({
|
|
|
127
162
|
borderWidth: 4,
|
|
128
163
|
borderColor: PRIMARY_GREEN,
|
|
129
164
|
borderRadius: 5,
|
|
130
|
-
backgroundColor: 'rgba(
|
|
165
|
+
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
|
131
166
|
},
|
|
132
167
|
loadingOverlay: {
|
|
133
168
|
...StyleSheet.absoluteFillObject,
|
package/src/ImageCropper.js
CHANGED
|
@@ -60,8 +60,8 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
|
|
|
60
60
|
const initializeCropBox = () => {
|
|
61
61
|
const { width, height } = imageMeasure.current;
|
|
62
62
|
// if (width === 0 || height === 0 || points.length > 0) return;
|
|
63
|
-
const boxWidth = width * 0.
|
|
64
|
-
const boxHeight = height * 0.
|
|
63
|
+
const boxWidth = width * 0.8;
|
|
64
|
+
const boxHeight = height * 0.8;
|
|
65
65
|
const centerX = width / 2;
|
|
66
66
|
const centerY = height / 2;
|
|
67
67
|
setPoints([
|
|
@@ -160,6 +160,22 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
|
|
|
160
160
|
initializeCropBox();
|
|
161
161
|
};
|
|
162
162
|
|
|
163
|
+
// Helper function to wait for multiple render cycles (works on iOS)
|
|
164
|
+
const waitForRender = (cycles = 5) => {
|
|
165
|
+
return new Promise((resolve) => {
|
|
166
|
+
let count = 0;
|
|
167
|
+
const tick = () => {
|
|
168
|
+
count++;
|
|
169
|
+
if (count >= cycles) {
|
|
170
|
+
resolve();
|
|
171
|
+
} else {
|
|
172
|
+
setImmediate(tick);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
setImmediate(tick);
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
163
179
|
|
|
164
180
|
return (
|
|
165
181
|
<View style={styles.container}>
|
|
@@ -187,29 +203,39 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
|
|
|
187
203
|
setIsLoading(true);
|
|
188
204
|
setShowResult(true);
|
|
189
205
|
try {
|
|
190
|
-
|
|
206
|
+
// Wait for UI to render - give React time to update the SVG with white fill
|
|
207
|
+
await waitForRender(8);
|
|
208
|
+
|
|
209
|
+
console.log("Starting capture...");
|
|
191
210
|
const capturedUri = await captureRef(viewRef, {
|
|
192
211
|
format: 'png',
|
|
193
212
|
quality: 1,
|
|
194
213
|
});
|
|
214
|
+
console.log("Capture successful:", capturedUri);
|
|
195
215
|
|
|
216
|
+
if (!capturedUri) {
|
|
217
|
+
throw new Error("Capture returned empty URI");
|
|
218
|
+
}
|
|
196
219
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
220
|
+
console.log("Enhancing image...");
|
|
221
|
+
const enhancedUri = await enhanceImage(capturedUri, addheight);
|
|
222
|
+
console.log("Image enhanced:", enhancedUri);
|
|
223
|
+
|
|
224
|
+
const name = `IMAGE XTK${Date.now()}.png`;
|
|
225
|
+
|
|
226
|
+
if (onConfirm) {
|
|
227
|
+
console.log("Calling onConfirm with:", enhancedUri, name);
|
|
228
|
+
onConfirm(enhancedUri, name);
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error("Erreur lors de la capture :", error);
|
|
232
|
+
alert("Erreur lors de la capture ! " + error.message);
|
|
233
|
+
} finally {
|
|
234
|
+
setShowResult(false);
|
|
235
|
+
setIsLoading(false);
|
|
236
|
+
setShowFullScreenCapture(false);
|
|
237
|
+
}
|
|
238
|
+
}}
|
|
213
239
|
>
|
|
214
240
|
<Text style={styles.buttonText}>Confirm</Text>
|
|
215
241
|
</TouchableOpacity>
|
|
@@ -233,7 +259,7 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
|
|
|
233
259
|
<Svg style={styles.overlay}>
|
|
234
260
|
<Path
|
|
235
261
|
d={`M 0 0 H ${imageMeasure.current.width} V ${imageMeasure.current.height} H 0 Z ${createPath()}`}
|
|
236
|
-
fill={showResult ? 'white' : 'rgba(
|
|
262
|
+
fill={showResult ? 'white' : 'rgba(0, 0, 0, 0.8)'}
|
|
237
263
|
fillRule="evenodd"
|
|
238
264
|
/>
|
|
239
265
|
{!showResult && points.length > 0 && (
|