anyline-ocr-react-native-module 42.2.0 → 43.0.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/android/build.gradle +7 -3
- package/android/src/main/AndroidManifest.xml +9 -8
- package/android/src/main/assets/cow_tag_scanner.ale +46 -0
- package/android/src/main/java/com/anyline/reactnative/AnylinePackage.java +1 -2
- package/android/src/main/java/com/anyline/reactnative/AnylineSDKPlugin.java +25 -71
- package/android/src/main/java/com/anyline/reactnative/RotateButtonConfig.java +12 -2
- package/android/src/main/java/com/anyline/reactnative/ScanActivity.java +206 -0
- package/android/src/main/res/drawable/rotate_screen_background.xml +18 -0
- package/android/src/main/res/drawable/rotate_screen_white.png +0 -0
- package/android/src/main/res/layout/activity_scan.xml +27 -0
- package/android/src/main/res/values/anyline_sdk_plugin_strings.xml +2 -28
- package/ios/ALJsonUIConfiguration.h +29 -36
- package/ios/ALJsonUIConfiguration.m +136 -76
- package/ios/ALNFCScanViewController.h +3 -16
- package/ios/ALNFCScanViewController.m +361 -232
- package/ios/ALPluginHelper.h +19 -62
- package/ios/ALPluginHelper.m +208 -529
- package/ios/ALPluginScanViewController.h +5 -32
- package/ios/ALPluginScanViewController.m +339 -287
- package/ios/AnylineReact.podspec +4 -3
- package/ios/AnylineSDKPlugin.m +39 -82
- package/package.json +8 -8
- package/android/.gradle/6.7/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/6.7/fileChanges/last-build.bin +0 -0
- package/android/.gradle/6.7/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/6.7/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/6.7/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
- package/android/.gradle/checksums/checksums.lock +0 -0
- package/android/.gradle/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/configuration-cache/gc.properties +0 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/compiler.xml +0 -6
- package/android/.idea/gradle.xml +0 -18
- package/android/.idea/jarRepositories.xml +0 -35
- package/android/.idea/misc.xml +0 -10
- package/android/.idea/vcs.xml +0 -6
- package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/local.properties +0 -8
- package/android/src/main/java/com/anyline/reactnative/Anyline4Activity.java +0 -621
- package/android/src/main/java/com/anyline/reactnative/AnylineBaseActivity.java +0 -267
- package/android/src/main/java/com/anyline/reactnative/AnylinePluginHelper.java +0 -324
- package/android/src/main/java/com/anyline/reactnative/AnylineUIConfig.java +0 -88
- package/android/src/main/java/com/anyline/reactnative/Document4Activity.java +0 -595
- package/android/src/main/res/layout/activity_scan_document.xml +0 -63
- package/android/src/main/res/layout/activity_scan_scanview.xml +0 -52
- package/android/src/main/res/values/com_crashlytics_export_strings.xml +0 -10
|
@@ -1,52 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
// ALPluginScanViewController.m
|
|
3
|
-
// Anyline React-Native Example
|
|
4
|
-
//
|
|
5
|
-
// Created by Daniel Albertini on 30.10.18.
|
|
6
|
-
//
|
|
1
|
+
#import <Anyline/Anyline.h>
|
|
7
2
|
|
|
8
3
|
#import "ALPluginScanViewController.h"
|
|
9
|
-
#import <Anyline/Anyline.h>
|
|
10
4
|
#import "ALPluginHelper.h"
|
|
11
5
|
#import "ALRoundedView.h"
|
|
12
6
|
|
|
7
|
+
@interface ALPluginScanViewController () <ALScanPluginDelegate, ALViewPluginCompositeDelegate, ALScanViewDelegate>
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
// ACO should it have the `assign` attribute?
|
|
10
|
+
@property (nonatomic, strong) ALPluginCallback callback;
|
|
15
11
|
|
|
16
|
-
@property (nonatomic, strong) NSDictionary *
|
|
17
|
-
@property (nonatomic, weak) id<ALPluginScanViewControllerDelegate> delegate;
|
|
18
|
-
@property (nonatomic, strong) NSString *licensekey;
|
|
19
|
-
@property (nonatomic, strong) ALJsonUIConfiguration *uiConfig;
|
|
12
|
+
@property (nonatomic, strong) NSDictionary *config;
|
|
20
13
|
|
|
21
|
-
@property (nonatomic,
|
|
22
|
-
@property (nonatomic,strong) UILabel *scannedLabel;
|
|
14
|
+
@property (nonatomic, copy) NSString *licenseKey;
|
|
23
15
|
|
|
24
|
-
@property (nonatomic, strong)
|
|
16
|
+
@property (nonatomic, strong) ALJSONUIConfiguration *uiConfig;
|
|
17
|
+
|
|
18
|
+
@property (nonatomic, strong) ALScanView *scanView;
|
|
19
|
+
|
|
20
|
+
@property (nonatomic, strong) UIButton *doneButton;
|
|
21
|
+
|
|
22
|
+
@property (nonatomic, strong) UILabel *scannedLabel;
|
|
25
23
|
|
|
26
24
|
@property (nonatomic, strong) ALRoundedView *roundedView;
|
|
27
|
-
@property (nonatomic, assign) BOOL showingLabel;
|
|
28
25
|
|
|
29
|
-
@property (nonatomic, strong)
|
|
26
|
+
@property (nonatomic, strong) UISegmentedControl *segment;
|
|
30
27
|
|
|
31
28
|
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *detectedBarcodes;
|
|
32
29
|
|
|
30
|
+
@property (nonatomic, strong) NSLayoutConstraint *labelHorizontalOffsetConstraint;
|
|
31
|
+
|
|
32
|
+
@property (nonatomic, strong) NSLayoutConstraint *labelVerticalOffsetConstraint;
|
|
33
|
+
|
|
34
|
+
/// Applicable to non-composites (otherwise null)
|
|
35
|
+
@property (nonatomic, readonly, nullable) ALPluginConfig *pluginConfig;
|
|
36
|
+
|
|
33
37
|
@end
|
|
34
38
|
|
|
39
|
+
|
|
35
40
|
@implementation ALPluginScanViewController
|
|
36
41
|
|
|
37
|
-
- (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
- (void)dealloc {
|
|
43
|
+
// NSLog(@"ACO dealloc ALPluginScanViewController");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (instancetype)initWithLicensekey:(NSString *)licenseKey
|
|
47
|
+
configuration:(NSDictionary *)config
|
|
48
|
+
uiConfiguration:(ALJSONUIConfiguration *)JSONUIConfig
|
|
49
|
+
finished:(ALPluginCallback)callback {
|
|
50
|
+
|
|
51
|
+
if (self = [super init]) {
|
|
52
|
+
_licenseKey = licenseKey;
|
|
53
|
+
_callback = callback;
|
|
54
|
+
_config = config;
|
|
55
|
+
_uiConfig = JSONUIConfig;
|
|
47
56
|
|
|
48
57
|
self.quality = 100;
|
|
49
|
-
self.nativeBarcodeEnabled = NO;
|
|
50
58
|
self.cropAndTransformErrorMessage = @"";
|
|
51
59
|
}
|
|
52
60
|
return self;
|
|
@@ -56,327 +64,371 @@
|
|
|
56
64
|
[super viewDidLoad];
|
|
57
65
|
|
|
58
66
|
NSError *error = nil;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
|
|
68
|
+
self.view.backgroundColor = [UIColor blackColor];
|
|
69
|
+
|
|
70
|
+
// ACO is there an equivalent place to that of an AppDelegate on which this could be added?
|
|
71
|
+
[AnylineSDK setupWithLicenseKey:self.licenseKey error:&error];
|
|
72
|
+
|
|
73
|
+
if ([self showErrorAlertIfNeeded:error]) {
|
|
66
74
|
return;
|
|
67
75
|
}
|
|
68
|
-
|
|
69
|
-
self.scanView = [ALScanView scanViewForFrame:self.view.bounds
|
|
70
|
-
configDict:self.anylineConfig
|
|
71
|
-
delegate:self
|
|
72
|
-
error:&error];
|
|
73
|
-
|
|
74
|
-
if ([self.scanView.scanViewPlugin isKindOfClass:[ALDocumentScanViewPlugin class]]) {
|
|
75
|
-
[(ALDocumentScanViewPlugin *)self.scanView.scanViewPlugin addScanViewPluginDelegate:self];
|
|
76
|
-
[((ALDocumentScanViewPlugin *)self.scanView.scanViewPlugin).documentScanPlugin addInfoDelegate:self];
|
|
77
|
-
|
|
78
|
-
((ALDocumentScanViewPlugin *)self.scanView.scanViewPlugin).documentScanPlugin.justDetectCornersIfPossible = NO;
|
|
79
|
-
[((ALDocumentScanViewPlugin *)self.scanView.scanViewPlugin) setValue:self forKey:@"tmpOutlineDelegate"];
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
self.roundedView = [ALPluginHelper createRoundedViewForViewController:self];
|
|
83
|
-
|
|
84
|
-
self.scanView.cameraConfig = [ALCameraConfig defaultCameraConfig];
|
|
85
|
-
}
|
|
86
76
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if(
|
|
92
|
-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Could not start scanning" message:error.localizedDescription delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
|
|
93
|
-
[alert show];
|
|
94
|
-
|
|
77
|
+
self.scanView = [ALScanViewFactory withJSONDictionary:self.config
|
|
78
|
+
delegate:self
|
|
79
|
+
error:&error];
|
|
80
|
+
|
|
81
|
+
if ([self showErrorAlertIfNeeded:error]) {
|
|
95
82
|
return;
|
|
96
83
|
}
|
|
97
|
-
|
|
98
|
-
[self.scanView startCamera];
|
|
99
|
-
|
|
84
|
+
|
|
100
85
|
[self.view addSubview:self.scanView];
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (self.nativeBarcodeEnabled) {
|
|
112
|
-
error = nil;
|
|
113
|
-
BOOL success = [self.scanView.captureDeviceManager addBarcodeDelegate:self error:&error];
|
|
114
|
-
|
|
115
|
-
if(!success) {
|
|
116
|
-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Could not start scanning" message:error.localizedDescription delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
|
|
117
|
-
[alert show];
|
|
118
|
-
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
86
|
+
|
|
87
|
+
self.scanView.translatesAutoresizingMaskIntoConstraints = false;
|
|
88
|
+
[self.scanView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
|
|
89
|
+
[self.scanView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES;
|
|
90
|
+
[self.scanView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor].active = YES;
|
|
91
|
+
[self.scanView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
|
|
92
|
+
|
|
93
|
+
self.scanView.supportedNativeBarcodeFormats = self.uiConfig.nativeBarcodeFormats;
|
|
94
|
+
self.scanView.delegate = self;
|
|
123
95
|
self.detectedBarcodes = [NSMutableArray array];
|
|
124
|
-
|
|
96
|
+
|
|
125
97
|
self.doneButton = [ALPluginHelper createButtonForViewController:self config:self.uiConfig];
|
|
126
|
-
|
|
98
|
+
|
|
127
99
|
self.scannedLabel = [ALPluginHelper createLabelForView:self.view];
|
|
100
|
+
|
|
101
|
+
[self configureLabel:self.scannedLabel config:self.uiConfig];
|
|
102
|
+
|
|
103
|
+
[self configureSegmentControl];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)viewWillAppear:(BOOL)animated {
|
|
107
|
+
[super viewWillAppear:animated];
|
|
108
|
+
[self.scanView startCamera];
|
|
128
109
|
}
|
|
129
110
|
|
|
130
111
|
- (void)viewDidAppear:(BOOL)animated {
|
|
131
112
|
[super viewDidAppear:animated];
|
|
132
|
-
|
|
113
|
+
|
|
114
|
+
// avoid allowing the app to be put to sleep after a long period without touch events
|
|
133
115
|
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
|
134
|
-
|
|
116
|
+
|
|
135
117
|
NSError *error;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Could not start scanning" message:error.localizedDescription delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
|
|
139
|
-
[alert show];
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if(self.uiConfig.segmentModes){
|
|
144
|
-
self.segment.frame = CGRectMake(self.scanView.scanViewPlugin.cutoutRect.origin.x + self.uiConfig.segmentXPositionOffset/2,
|
|
145
|
-
self.scanView.scanViewPlugin.cutoutRect.origin.y + self.uiConfig.segmentYPositionOffset/2,
|
|
146
|
-
self.view.frame.size.width - 2*(self.scanView.scanViewPlugin.cutoutRect.origin.x + self.uiConfig.segmentXPositionOffset/2),
|
|
147
|
-
self.segment.frame.size.height);
|
|
148
|
-
self.segment.hidden = NO;
|
|
149
|
-
}
|
|
150
|
-
|
|
118
|
+
[self.scanView.scanViewPlugin startWithError:&error];
|
|
119
|
+
[self showErrorAlertIfNeeded:error];
|
|
151
120
|
}
|
|
152
121
|
|
|
153
122
|
- (void)viewDidDisappear:(BOOL)animated {
|
|
154
123
|
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
|
124
|
+
[super viewDidDisappear:animated];
|
|
155
125
|
}
|
|
156
126
|
|
|
157
127
|
- (BOOL)shouldAutorotate {
|
|
158
128
|
return NO;
|
|
159
129
|
}
|
|
160
130
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}];
|
|
165
|
-
}
|
|
131
|
+
/// The segment control contains a list of scan modes each of which, when selected, reloads the scan view with
|
|
132
|
+
/// the appropriate scan mode for the active plugin (keeping everything else the same)
|
|
133
|
+
- (void)configureSegmentControl {
|
|
166
134
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
}
|
|
135
|
+
NSString *scanMode = [self currentScanMode];
|
|
136
|
+
if (!scanMode) {
|
|
137
|
+
// Do nothing else: our plugin does not support scan modes.
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
173
140
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (
|
|
178
|
-
|
|
141
|
+
NSLog(@"The scan mode: %@", scanMode);
|
|
142
|
+
|
|
143
|
+
// At this point, you can safely create segment controls.
|
|
144
|
+
if (!self.uiConfig.segmentModes) {
|
|
145
|
+
return;
|
|
179
146
|
}
|
|
180
|
-
}
|
|
181
147
|
|
|
182
|
-
|
|
148
|
+
if (![self segmentModesAreValid]) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
183
151
|
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
152
|
+
// Give it the current scanmode that's initially defined already in the config JSON
|
|
153
|
+
self.segment = [ALPluginHelper createSegmentForViewController:self
|
|
154
|
+
config:self.uiConfig
|
|
155
|
+
initialScanMode:scanMode];
|
|
189
156
|
|
|
157
|
+
self.segment.hidden = NO;
|
|
158
|
+
self.segment.translatesAutoresizingMaskIntoConstraints = NO;
|
|
159
|
+
[self.segment.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
|
|
160
|
+
[self.segment.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor
|
|
161
|
+
constant:self.uiConfig.segmentYPositionOffset].active = YES;
|
|
190
162
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
didFindResult:(ALIDResult * _Nonnull)scanResult {
|
|
194
|
-
NSDictionary *dictResult = [ALPluginHelper dictionaryForIDResult:scanResult
|
|
195
|
-
detectedBarcodes:self.detectedBarcodes
|
|
196
|
-
outline:self.scanView.scanViewPlugin.outline
|
|
197
|
-
quality:self.quality];
|
|
198
|
-
|
|
199
|
-
[self handleResult:dictResult result:scanResult];
|
|
163
|
+
// NOTE: uncomment this to show the segment full width
|
|
164
|
+
[self.segment.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:10].active = YES;
|
|
200
165
|
}
|
|
201
166
|
|
|
202
|
-
- (void)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
167
|
+
- (void)configureLabel:(UILabel *)label config:(ALJSONUIConfiguration *)config {
|
|
168
|
+
|
|
169
|
+
if (config.labelText.length < 1) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
label.alpha = 1;
|
|
174
|
+
label.text = config.labelText;
|
|
175
|
+
label.font = [UIFont fontWithName:@"HelveticaNeue" size:config.labelSize];
|
|
176
|
+
label.textColor = config.labelColor;
|
|
177
|
+
label.translatesAutoresizingMaskIntoConstraints = NO;
|
|
178
|
+
|
|
179
|
+
[label.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:10].active = YES;
|
|
180
|
+
|
|
181
|
+
self.labelHorizontalOffsetConstraint = [label.centerXAnchor
|
|
182
|
+
constraintEqualToAnchor:self.view.centerXAnchor constant:0];
|
|
183
|
+
self.labelVerticalOffsetConstraint = [label.bottomAnchor
|
|
184
|
+
constraintEqualToAnchor:self.view.topAnchor
|
|
185
|
+
constant:0];
|
|
186
|
+
|
|
187
|
+
self.labelHorizontalOffsetConstraint.active = YES;
|
|
188
|
+
self.labelVerticalOffsetConstraint.active = YES;
|
|
210
189
|
}
|
|
211
190
|
|
|
212
|
-
- (void)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
191
|
+
- (void)handleResult:(id _Nullable)resultObj {
|
|
192
|
+
|
|
193
|
+
NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionaryWithDictionary:resultObj];
|
|
194
|
+
|
|
195
|
+
if (self.detectedBarcodes.count) {
|
|
196
|
+
resultDictionary[@"nativeBarcodesDetected"] = self.detectedBarcodes;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// dismiss the view controller, if cancelOnResult for the config is true
|
|
200
|
+
NSObject<ALScanViewPluginBase> *scanViewPluginBase = self.scanView.scanViewPlugin;
|
|
201
|
+
if ([scanViewPluginBase isKindOfClass:ALScanViewPlugin.class]) {
|
|
202
|
+
ALScanViewPlugin *scanViewPlugin = (ALScanViewPlugin *)scanViewPluginBase;
|
|
203
|
+
BOOL cancelOnResult = scanViewPlugin.scanPlugin.scanPluginConfig.cancelOnResult;
|
|
204
|
+
if (cancelOnResult) {
|
|
205
|
+
__weak __block typeof(self) weakSelf = self;
|
|
206
|
+
[self dismissViewControllerAnimated:YES completion:^{
|
|
207
|
+
weakSelf.callback(resultDictionary, nil);
|
|
208
|
+
}];
|
|
209
|
+
}
|
|
210
|
+
} else if ([scanViewPluginBase isKindOfClass:ALViewPluginComposite.class]) {
|
|
211
|
+
// for composites, the cancelOnResult values for each child don't matter
|
|
212
|
+
[self dismissViewControllerAnimated:YES completion:nil];
|
|
213
|
+
self.callback(resultDictionary, nil);
|
|
214
|
+
}
|
|
219
215
|
}
|
|
220
216
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
217
|
+
// MARK: - ALScanPluginDelegate
|
|
218
|
+
|
|
219
|
+
- (void)scanPlugin:(ALScanPlugin *)scanPlugin resultReceived:(ALScanResult *)scanResult {
|
|
220
|
+
|
|
221
|
+
CGFloat compressionQuality = self.quality / 100.0f;
|
|
222
|
+
|
|
223
|
+
NSMutableDictionary *resultDictMutable = [NSMutableDictionary dictionaryWithDictionary:scanResult.resultDictionary];
|
|
224
|
+
|
|
225
|
+
NSString *imagePath = [ALPluginHelper saveImageToFileSystem:scanResult.croppedImage
|
|
226
|
+
compressionQuality:compressionQuality];
|
|
227
|
+
resultDictMutable[@"imagePath"] = imagePath;
|
|
228
|
+
|
|
229
|
+
imagePath = [ALPluginHelper saveImageToFileSystem:scanResult.fullSizeImage
|
|
230
|
+
compressionQuality:compressionQuality];
|
|
231
|
+
|
|
232
|
+
resultDictMutable[@"fullImagePath"] = imagePath;
|
|
233
|
+
|
|
234
|
+
[self handleResult:resultDictMutable];
|
|
229
235
|
}
|
|
230
236
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
|
|
238
|
+
// MARK: - ALViewPluginCompositeDelegate
|
|
239
|
+
|
|
240
|
+
- (void)viewPluginComposite:(ALViewPluginComposite *)viewPluginComposite
|
|
241
|
+
allResultsReceived:(NSArray<ALScanResult *> *)scanResults {
|
|
242
|
+
// combine all into an array and create a string version of it.
|
|
243
|
+
NSMutableDictionary *results = [NSMutableDictionary dictionaryWithCapacity:scanResults.count];
|
|
244
|
+
CGFloat compressionQuality = self.quality / 100.0f;
|
|
245
|
+
|
|
246
|
+
for (ALScanResult *scanResult in scanResults) {
|
|
247
|
+
NSMutableDictionary *resultDictMutable = [NSMutableDictionary dictionaryWithDictionary:scanResult.resultDictionary];
|
|
248
|
+
NSString *imagePath = [ALPluginHelper saveImageToFileSystem:scanResult.croppedImage
|
|
249
|
+
compressionQuality:compressionQuality];
|
|
250
|
+
resultDictMutable[@"imagePath"] = imagePath;
|
|
251
|
+
imagePath = [ALPluginHelper saveImageToFileSystem:scanResult.fullSizeImage
|
|
252
|
+
compressionQuality:compressionQuality];
|
|
253
|
+
resultDictMutable[@"fullImagePath"] = imagePath;
|
|
254
|
+
results[scanResult.pluginID] = resultDictMutable;
|
|
255
|
+
}
|
|
256
|
+
[self handleResult:results];
|
|
239
257
|
}
|
|
240
258
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
259
|
+
// MARK: - ALScanViewDelegate
|
|
260
|
+
|
|
261
|
+
- (void)scanView:(ALScanView *)scanView updatedCutoutWithPluginID:(NSString *)pluginID frame:(CGRect)frame {
|
|
262
|
+
|
|
263
|
+
if (CGRectIsEmpty(frame)) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
CGFloat xOffset = self.uiConfig.labelXPositionOffset;
|
|
268
|
+
CGFloat yOffset = self.uiConfig.labelYPositionOffset;
|
|
269
|
+
|
|
270
|
+
// takes into account that frame reported for a cutout is in relation to
|
|
271
|
+
// its scan view's coordinate system
|
|
272
|
+
yOffset += [self.scanView convertRect:frame toView:self.scanView.superview].origin.y;
|
|
273
|
+
|
|
274
|
+
self.labelHorizontalOffsetConstraint.constant = xOffset;
|
|
275
|
+
|
|
276
|
+
self.labelVerticalOffsetConstraint.constant = yOffset;
|
|
252
277
|
}
|
|
253
278
|
|
|
254
|
-
- (void)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
quality:self.quality];
|
|
259
|
-
|
|
260
|
-
[self handleResult:dictResult result:nil];
|
|
261
|
-
|
|
279
|
+
- (void)scanView:(ALScanView *)scanView didReceiveNativeBarcodeResult:(ALScanResult *)scanResult {
|
|
280
|
+
// for this implementation we just take the last detected (we can show a list of it)
|
|
281
|
+
[self.detectedBarcodes removeAllObjects];
|
|
282
|
+
[self.detectedBarcodes addObject:scanResult.resultDictionary];
|
|
262
283
|
}
|
|
263
284
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
[
|
|
285
|
+
// MARK: - Getters and Setters
|
|
286
|
+
|
|
287
|
+
- (ALPluginConfig * _Nullable)pluginConfig {
|
|
288
|
+
// applic. only to non-composites
|
|
289
|
+
NSObject<ALScanViewPluginBase> *scanVwPluginBase = self.scanView.scanViewPlugin;
|
|
290
|
+
if ([scanVwPluginBase isKindOfClass:ALScanViewPlugin.class]) {
|
|
291
|
+
return ((ALScanViewPlugin *)scanVwPluginBase).scanPlugin.scanPluginConfig.pluginConfig;
|
|
292
|
+
}
|
|
293
|
+
return nil;
|
|
270
294
|
}
|
|
271
295
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
[self.
|
|
276
|
-
|
|
277
|
-
|
|
296
|
+
// MARK: - Selector Actions
|
|
297
|
+
|
|
298
|
+
- (void)doneButtonPressed:(id)sender {
|
|
299
|
+
[self.scanView.scanViewPlugin stop];
|
|
300
|
+
|
|
301
|
+
__weak __block typeof(self) weakSelf = self;
|
|
302
|
+
[self dismissViewControllerAnimated:YES completion:^{
|
|
303
|
+
weakSelf.callback(nil, @"Canceled");
|
|
304
|
+
}];
|
|
278
305
|
}
|
|
279
306
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
-(void)anylineDocumentScanPlugin:(ALDocumentScanPlugin *)anylineDocumentScanPlugin reportsPictureProcessingFailure:(ALDocumentError)error {
|
|
284
|
-
[self showUserLabel:error];
|
|
307
|
+
- (void)segmentChange:(id)sender {
|
|
308
|
+
NSString *newMode = self.uiConfig.segmentModes[((UISegmentedControl *)sender).selectedSegmentIndex];
|
|
309
|
+
[self updateScanModeWithValue:newMode];
|
|
285
310
|
}
|
|
286
311
|
|
|
287
|
-
|
|
288
|
-
This method receives errors that occured during the scan.
|
|
289
|
-
*/
|
|
312
|
+
// MARK: - Handle scan mode switching
|
|
290
313
|
|
|
291
|
-
-(void)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
314
|
+
- (void)updateScanModeWithValue:(NSString *)modeString {
|
|
315
|
+
ALPluginConfig *pluginConfig = self.pluginConfig;
|
|
316
|
+
|
|
317
|
+
id key = [ALPluginHelper confPropKeyWithScanModeForPluginConfig:pluginConfig];
|
|
318
|
+
|
|
319
|
+
// obj is something like an ALMeterConfig instance, that you can call scanMode: (or setScanMode:) on
|
|
320
|
+
id obj = [self.pluginConfig valueForKey:key];
|
|
321
|
+
NSAssert(obj, @"obj shouldn't be nil!");
|
|
322
|
+
|
|
323
|
+
id scanModeObj = [obj valueForKey:@"scanMode"];
|
|
324
|
+
NSString *newScanMode;
|
|
325
|
+
|
|
326
|
+
// does the equivalent of +[ALConfigMeterScanMode withValue:modeString],
|
|
327
|
+
// (or whatever scan mode object gets evaluated) avoiding warnings:
|
|
328
|
+
// https://stackoverflow.com/a/20058585
|
|
329
|
+
SEL selector = NSSelectorFromString(@"withValue:");
|
|
330
|
+
IMP imp = [[scanModeObj class] methodForSelector:selector];
|
|
331
|
+
NSString *(*func)(id, SEL, NSString *) = (void *)imp;
|
|
332
|
+
newScanMode = func([scanModeObj class], selector, modeString);
|
|
333
|
+
|
|
334
|
+
NSAssert(newScanMode, @"newScanMode is not nil!");
|
|
335
|
+
|
|
336
|
+
// like obj, pluginSubConfig should be the the plugin-specific config object
|
|
337
|
+
// (e.g. ALLicensePlateConfig) which responds to setScanMode:.
|
|
338
|
+
selector = NSSelectorFromString(@"setScanMode:");
|
|
339
|
+
imp = [obj methodForSelector:selector];
|
|
340
|
+
id (*func2)(id, SEL, id) = (void *)imp;
|
|
341
|
+
id pluginSubConfig = func2(obj, selector, newScanMode);
|
|
342
|
+
|
|
343
|
+
[pluginConfig setValue:pluginSubConfig forKey:key];
|
|
344
|
+
|
|
345
|
+
NSError *error;
|
|
346
|
+
BOOL success = [self updatePluginConfig:pluginConfig error:&error];
|
|
347
|
+
|
|
348
|
+
if (!success) {
|
|
349
|
+
// check error
|
|
350
|
+
NSLog(@"there was an error changing the scan mode: %@", error.localizedDescription);
|
|
323
351
|
}
|
|
324
352
|
}
|
|
325
353
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
354
|
+
// assume that pluginConfig carries the updated scanMode or whatever value that you wish to refresh.
|
|
355
|
+
- (BOOL)updatePluginConfig:(ALPluginConfig *)pluginConfig error:(NSError * _Nullable * _Nullable)error {
|
|
356
|
+
|
|
357
|
+
ALScanPluginConfig *scanPluginConfig = [[ALScanPluginConfig alloc] initWithPluginConfig:pluginConfig];
|
|
358
|
+
ALScanViewPluginConfig *origSVPConfig = ((ALScanViewPlugin *)self.scanView.scanViewPlugin).scanViewPluginConfig;
|
|
359
|
+
ALScanViewPluginConfig *scanViewPluginConfig = [ALScanViewPluginConfig withScanPluginConfig:scanPluginConfig
|
|
360
|
+
cutoutConfig:origSVPConfig.cutoutConfig
|
|
361
|
+
scanFeedbackConfig:origSVPConfig.scanFeedbackConfig];
|
|
362
|
+
ALScanViewPlugin *newScanViewPlugin = [[ALScanViewPlugin alloc] initWithConfig:scanViewPluginConfig error:error];
|
|
363
|
+
if (!newScanViewPlugin) {
|
|
364
|
+
return NO;
|
|
329
365
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
[self dismissViewControllerAnimated:YES completion:NULL];
|
|
366
|
+
|
|
367
|
+
newScanViewPlugin.scanPlugin.delegate = self;
|
|
368
|
+
|
|
369
|
+
BOOL success = [self.scanView setScanViewPlugin:newScanViewPlugin error:error];
|
|
370
|
+
if (!success) {
|
|
371
|
+
return NO;
|
|
337
372
|
}
|
|
338
|
-
|
|
373
|
+
|
|
374
|
+
success = [[self.scanView scanViewPlugin] startWithError:error];
|
|
375
|
+
if (!success) {
|
|
376
|
+
// check error
|
|
377
|
+
return NO;
|
|
378
|
+
}
|
|
379
|
+
return YES;
|
|
339
380
|
}
|
|
340
381
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
break;
|
|
350
|
-
case ALDocumentErrorImageTooDark:
|
|
351
|
-
helpString = @"Too Dark";
|
|
352
|
-
break;
|
|
353
|
-
case ALDocumentErrorShakeDetected:
|
|
354
|
-
helpString = @"Too much shaking";
|
|
355
|
-
break;
|
|
356
|
-
default:
|
|
357
|
-
break;
|
|
382
|
+
|
|
383
|
+
/// If the running plugin supports a scan mode, this returns the string representation of it.
|
|
384
|
+
- (NSString * _Nullable)currentScanMode {
|
|
385
|
+
// Does our running plugin contain a property named something like `XXXConfig`?
|
|
386
|
+
// If yes, is there a `scanMode` inside?
|
|
387
|
+
NSString * _Nullable pluginConfigPropertyWithScanMode = [ALPluginHelper confPropKeyWithScanModeForPluginConfig:self.pluginConfig];
|
|
388
|
+
if (!pluginConfigPropertyWithScanMode) {
|
|
389
|
+
return nil;
|
|
358
390
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
391
|
+
// obj is something like an ALMeterConfig instance
|
|
392
|
+
id obj = [self.pluginConfig valueForKey:pluginConfigPropertyWithScanMode];
|
|
393
|
+
NSAssert(obj, @"obj shouldn't be nil!");
|
|
394
|
+
id scanModeObj = [obj valueForKey:@"scanMode"];
|
|
395
|
+
return [scanModeObj valueForKey:@"value"];
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Check whether the scan modes indicated in options > segmentConfig are valid.
|
|
399
|
+
// Otherwise, the segment control is not shown.
|
|
400
|
+
- (BOOL)segmentModesAreValid {
|
|
401
|
+
if (self.uiConfig.segmentModes.count < 1) {
|
|
402
|
+
return NO;
|
|
363
403
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
self.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
[
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
404
|
+
|
|
405
|
+
// easy question first: is there an identical number of segModes and segTitles?
|
|
406
|
+
if (self.uiConfig.segmentModes.count != self.uiConfig.segmentTitles.count) {
|
|
407
|
+
NSLog(@"Error: should have the same number of segment modes and segment titles!");
|
|
408
|
+
return NO;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
NSString *propKey = [ALPluginHelper confPropKeyWithScanModeForPluginConfig:self.pluginConfig];
|
|
412
|
+
id obj = [self.pluginConfig valueForKey:propKey];
|
|
413
|
+
NSAssert(obj, @"obj shouldn't be nil!");
|
|
414
|
+
|
|
415
|
+
// go through each self.segmentMode. Each call below should be non-nil.
|
|
416
|
+
// NOTE: for now (24.01.2023) TIN and Container scanModes should be named in the JSON config
|
|
417
|
+
// in all UPPERCASE (because the schema demands it to be so).
|
|
418
|
+
for (NSString *scanModeStr in self.uiConfig.segmentModes) {
|
|
419
|
+
if (![[[obj scanMode] class] withValue:scanModeStr]) {
|
|
420
|
+
NSLog(@"Error: %@ is not a valid scan mode for the current plugin", scanModeStr);
|
|
421
|
+
return NO;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return YES;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// MARK: - Miscellaneous
|
|
429
|
+
|
|
430
|
+
- (BOOL)showErrorAlertIfNeeded:(NSError *)error {
|
|
431
|
+
return [ALPluginHelper showErrorAlertIfNeeded:error pluginCallback:self.callback];
|
|
380
432
|
}
|
|
381
433
|
|
|
382
434
|
@end
|