cordova-plugin-mserviceinterface-2.0 1.0.93 → 1.0.95
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/package.json +1 -1
- package/plugin.xml +1 -4
- package/src/android/mInterface.java +297 -198
- package/src/ios/mInterface.h +1 -0
- package/src/ios/mInterface.m +336 -1
package/package.json
CHANGED
package/plugin.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
3
|
-
xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-mserviceinterface-2.0" version="1.0.
|
|
3
|
+
xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-mserviceinterface-2.0" version="1.0.95">
|
|
4
4
|
<name>mserviceinterface-2.0</name>
|
|
5
5
|
<description>This plugin establishes the connection to the native interface and performs the requested task.</description>
|
|
6
6
|
<author>selfservit@gmail.com</author>
|
|
@@ -47,14 +47,11 @@
|
|
|
47
47
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
48
48
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
49
49
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
50
|
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
51
|
-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
52
50
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
53
51
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
54
52
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
|
55
53
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
|
56
54
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
57
|
-
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
|
58
55
|
<queries>
|
|
59
56
|
<intent>
|
|
60
57
|
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
|
@@ -486,11 +486,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
486
486
|
} else if (action.equals("CheckLocationPermission")) {
|
|
487
487
|
checkLocationPermission(args, callbackContext);
|
|
488
488
|
return true;
|
|
489
|
-
} else if (action.equals("GetMediaImagePermission")) {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
489
|
+
} else if (action.equals("CheckMediaImagePermission") || action.equals("GetMediaImagePermission")) {
|
|
490
|
+
try {
|
|
491
|
+
callbackContext.success("not_required");
|
|
492
|
+
} catch (Exception e) {
|
|
493
|
+
callbackContext.error(e.getMessage());
|
|
494
|
+
}
|
|
494
495
|
return true;
|
|
495
496
|
} else if (action.equals("AppVersion")) {
|
|
496
497
|
appVersion(callbackContext);
|
|
@@ -1606,40 +1607,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1606
1607
|
}
|
|
1607
1608
|
}
|
|
1608
1609
|
|
|
1609
|
-
private void checkMediaImagePermission(JSONArray args, CallbackContext
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
Context context = cordova.getActivity().getApplicationContext();
|
|
1615
|
-
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1616
|
-
if (permissions[0].equalsIgnoreCase("android.permission.READ_MEDIA_IMAGES")) {
|
|
1617
|
-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
1618
|
-
checkPermission = false;
|
|
1619
|
-
}
|
|
1620
|
-
}
|
|
1621
|
-
if (checkPermission) {
|
|
1622
|
-
list = new ArrayList<String>(Arrays.asList(permissions));
|
|
1623
|
-
permissions = list.toArray(new String[0]);
|
|
1624
|
-
|
|
1625
|
-
for (int i = 0; i < permissions.length; i++) {
|
|
1626
|
-
if (ActivityCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
|
|
1627
|
-
permissionGranted = false;
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
if (!permissionGranted) {
|
|
1631
|
-
callback.error("failure");
|
|
1632
|
-
} else {
|
|
1633
|
-
callback.success("success");
|
|
1634
|
-
}
|
|
1635
|
-
} else {
|
|
1636
|
-
callback.success("success");
|
|
1637
|
-
}
|
|
1638
|
-
} catch (Exception e) {
|
|
1639
|
-
e.printStackTrace();
|
|
1640
|
-
}
|
|
1610
|
+
private void checkMediaImagePermission(JSONArray args, CallbackContext cb) {
|
|
1611
|
+
try { cb.success("not_required"); } catch (Exception e) { cb.error(e.getMessage()); }
|
|
1612
|
+
}
|
|
1613
|
+
private void getMediaImagePermission(JSONArray args, CallbackContext cb) {
|
|
1614
|
+
try { cb.success("not_required"); } catch (Exception e) { cb.error(e.getMessage()); }
|
|
1641
1615
|
}
|
|
1642
|
-
|
|
1643
1616
|
|
|
1644
1617
|
private void getLocationPermission(JSONArray args, CallbackContext callbackContext) {
|
|
1645
1618
|
boolean permissionGranted = true;
|
|
@@ -1665,30 +1638,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1665
1638
|
e.printStackTrace();
|
|
1666
1639
|
}
|
|
1667
1640
|
}
|
|
1668
|
-
|
|
1669
|
-
boolean permissionGranted = true;
|
|
1670
|
-
List<String> list;
|
|
1671
|
-
try {
|
|
1672
|
-
callback = callbackContext;
|
|
1673
|
-
Context context = cordova.getActivity().getApplicationContext();
|
|
1674
|
-
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1675
|
-
list = new ArrayList<String>(Arrays.asList(permissions));
|
|
1676
|
-
permissions = list.toArray(new String[0]);
|
|
1677
|
-
|
|
1678
|
-
for (int i = 0; i < permissions.length; i++) {
|
|
1679
|
-
if (ActivityCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
|
|
1680
|
-
permissionGranted = false;
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
if (!permissionGranted) {
|
|
1684
|
-
PermissionHelper.requestPermissions(this, 111, permissions);
|
|
1685
|
-
} else {
|
|
1686
|
-
callback.success("success");
|
|
1687
|
-
}
|
|
1688
|
-
} catch (Exception e) {
|
|
1689
|
-
e.printStackTrace();
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1641
|
+
|
|
1692
1642
|
private void getPermissions(JSONArray args, CallbackContext callbackContext) {
|
|
1693
1643
|
boolean permissionGranted = true;
|
|
1694
1644
|
List<String> list;
|
|
@@ -1760,29 +1710,33 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1760
1710
|
pluginResult.setKeepCallback(true);
|
|
1761
1711
|
callbackContext.sendPluginResult(pluginResult);
|
|
1762
1712
|
}
|
|
1763
|
-
|
|
1713
|
+
|
|
1714
|
+
void pickImageFromGallery(CallbackContext callbackContext) {
|
|
1764
1715
|
try {
|
|
1765
|
-
Intent
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
1770
|
-
// Use the ACTION_OPEN_DOCUMENT intent for Android 13 and higher
|
|
1771
|
-
openFile = new Intent(MediaStore.ACTION_PICK_IMAGES);
|
|
1772
|
-
openFile.setType("image/*");
|
|
1716
|
+
Intent i;
|
|
1717
|
+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
|
|
1718
|
+
i = new Intent(MediaStore.ACTION_PICK_IMAGES);
|
|
1719
|
+
i.setType("image/*");
|
|
1773
1720
|
} else {
|
|
1774
|
-
|
|
1775
|
-
|
|
1721
|
+
i = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
1722
|
+
i.addCategory(Intent.CATEGORY_OPENABLE);
|
|
1723
|
+
i.setType("image/*");
|
|
1724
|
+
i.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
1776
1725
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
callbackContext.sendPluginResult(
|
|
1726
|
+
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
1727
|
+
this.callback = callbackContext;
|
|
1728
|
+
PluginResult pr = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
1729
|
+
pr.setKeepCallback(true);
|
|
1730
|
+
callbackContext.sendPluginResult(pr);
|
|
1731
|
+
cordova.startActivityForResult(this, i, PICK_IMAGE_FROM_GALLERY);
|
|
1732
|
+
|
|
1733
|
+
|
|
1782
1734
|
} catch (Exception e) {
|
|
1783
1735
|
callbackContext.error("pickImageFromGallery failed, exception is : " + e.getMessage());
|
|
1784
1736
|
}
|
|
1785
1737
|
}
|
|
1738
|
+
|
|
1739
|
+
|
|
1786
1740
|
|
|
1787
1741
|
private String getMimeType(String path, Uri uri) {
|
|
1788
1742
|
String mimeType = null;
|
|
@@ -2117,6 +2071,198 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2117
2071
|
return "";
|
|
2118
2072
|
}
|
|
2119
2073
|
|
|
2074
|
+
|
|
2075
|
+
private String safeGetDisplayName(@NonNull ContentResolver cr, @NonNull Uri uri, @NonNull String defaultExt) {
|
|
2076
|
+
String name = null;
|
|
2077
|
+
try (Cursor c = cr.query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null)) {
|
|
2078
|
+
if (c != null && c.moveToFirst()) {
|
|
2079
|
+
int idx = c.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
2080
|
+
if (idx != -1) name = c.getString(idx);
|
|
2081
|
+
}
|
|
2082
|
+
} catch (Throwable t) {
|
|
2083
|
+
android.util.Log.w("mInterface", "safeGetDisplayName query failed: " + t.getMessage());
|
|
2084
|
+
}
|
|
2085
|
+
if (name == null || name.trim().isEmpty()) {
|
|
2086
|
+
String ts = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new java.util.Date());
|
|
2087
|
+
name = "FILE_" + ts + (defaultExt.startsWith(".") ? defaultExt : "." + defaultExt);
|
|
2088
|
+
}
|
|
2089
|
+
return name;
|
|
2090
|
+
}
|
|
2091
|
+
private void postSuccess(final CallbackContext cb, final org.json.JSONObject out) {
|
|
2092
|
+
if (cb == null) return;
|
|
2093
|
+
final PluginResult pr = new PluginResult(PluginResult.Status.OK, out);
|
|
2094
|
+
pr.setKeepCallback(false);
|
|
2095
|
+
cordova.getActivity().runOnUiThread(new Runnable() {
|
|
2096
|
+
@Override public void run() { cb.sendPluginResult(pr); }
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
private void postSuccess(final CallbackContext cb, final String s) {
|
|
2101
|
+
if (cb == null) return;
|
|
2102
|
+
final PluginResult pr = new PluginResult(PluginResult.Status.OK, s);
|
|
2103
|
+
pr.setKeepCallback(false);
|
|
2104
|
+
cordova.getActivity().runOnUiThread(new Runnable() {
|
|
2105
|
+
@Override public void run() { cb.sendPluginResult(pr); }
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
private void postError(final CallbackContext cb, final String msg) {
|
|
2110
|
+
if (cb == null) return;
|
|
2111
|
+
final PluginResult pr = new PluginResult(PluginResult.Status.ERROR, msg);
|
|
2112
|
+
pr.setKeepCallback(false);
|
|
2113
|
+
cordova.getActivity().runOnUiThread(new Runnable() {
|
|
2114
|
+
@Override public void run() { cb.sendPluginResult(pr); }
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
private int calcInSampleSize(BitmapFactory.Options o, int reqW, int reqH) {
|
|
2119
|
+
int inSample = 1, h = o.outHeight, w = o.outWidth;
|
|
2120
|
+
while ((h / inSample) > reqH || (w / inSample) > reqW) inSample <<= 1;
|
|
2121
|
+
return Math.max(1, inSample);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
/**
|
|
2125
|
+
* Async version that mirrors the sync behavior:
|
|
2126
|
+
* - "camera"/"gallery": returns base64 string
|
|
2127
|
+
* - "compress": returns JSON { filePath, fileName, fileSize, fileExtension, thumbnail }
|
|
2128
|
+
*/
|
|
2129
|
+
private void convertImageTo64BaseStringAsync(final CallbackContext cb,
|
|
2130
|
+
final String imageSourcePath,
|
|
2131
|
+
final String imgSrcType,
|
|
2132
|
+
final String destinationPath) {
|
|
2133
|
+
cordova.getThreadPool().execute(new Runnable() {
|
|
2134
|
+
@Override public void run() {
|
|
2135
|
+
InputStream srcFileReader = null;
|
|
2136
|
+
OutputStream desFileWriter = null;
|
|
2137
|
+
ByteArrayOutputStream baos = null;
|
|
2138
|
+
Bitmap bitmap = null;
|
|
2139
|
+
try {
|
|
2140
|
+
// Common bits
|
|
2141
|
+
final String[] parts = imageSourcePath.split("/");
|
|
2142
|
+
String baseName = parts.length > 0 ? parts[parts.length - 1] : "IMG";
|
|
2143
|
+
if (baseName.indexOf(".") > 0) {
|
|
2144
|
+
baseName = baseName.substring(0, baseName.lastIndexOf("."));
|
|
2145
|
+
}
|
|
2146
|
+
final String extFromSource = "." + imageSourcePath.substring(imageSourcePath.lastIndexOf(".") + 1).toLowerCase();
|
|
2147
|
+
final String thumbnail = getFileThumbnail(imageSourcePath, extFromSource);
|
|
2148
|
+
|
|
2149
|
+
if ("compress".equalsIgnoreCase(imgSrcType)) {
|
|
2150
|
+
// === COMPRESS: write JPEG to destination and return file properties ===
|
|
2151
|
+
File fileToCompress = new File(imageSourcePath);
|
|
2152
|
+
File compressedImageFile = new Compressor(cordova.getActivity())
|
|
2153
|
+
.setQuality(15)
|
|
2154
|
+
.setCompressFormat(Bitmap.CompressFormat.JPEG)
|
|
2155
|
+
.compressToFile(fileToCompress);
|
|
2156
|
+
|
|
2157
|
+
String timeStamp = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new java.util.Date());
|
|
2158
|
+
final String baseDir = (destinationPath != null && !destinationPath.isEmpty())
|
|
2159
|
+
? (mInterfaceUtil.rootDirectory + "/" + destinationPath)
|
|
2160
|
+
: (mInterfaceUtil.rootDirectory + "/" + mInterfaceUtil.packageName + "/images");
|
|
2161
|
+
final String outName = baseName + "_" + timeStamp + ".jpg";
|
|
2162
|
+
final String outFullPath = baseDir + "/" + outName;
|
|
2163
|
+
|
|
2164
|
+
File outDir = new File(baseDir);
|
|
2165
|
+
if (!outDir.exists()) outDir.mkdirs();
|
|
2166
|
+
|
|
2167
|
+
// Copy compressed temp → final path
|
|
2168
|
+
if (compressedImageFile.exists()) {
|
|
2169
|
+
srcFileReader = new FileInputStream(compressedImageFile);
|
|
2170
|
+
desFileWriter = new FileOutputStream(new File(outFullPath));
|
|
2171
|
+
byte[] buf = new byte[64 * 1024];
|
|
2172
|
+
int n;
|
|
2173
|
+
while ((n = srcFileReader.read(buf)) > 0) {
|
|
2174
|
+
desFileWriter.write(buf, 0, n);
|
|
2175
|
+
}
|
|
2176
|
+
desFileWriter.flush();
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
// (Optional) load to normalize EXIF rotation like the sync version did
|
|
2180
|
+
try { bitmap = handleImageRotation(outFullPath); } catch (Throwable ignore) {}
|
|
2181
|
+
|
|
2182
|
+
// Build properties
|
|
2183
|
+
File outFile = new File(outFullPath);
|
|
2184
|
+
org.json.JSONObject fileProps = new org.json.JSONObject();
|
|
2185
|
+
fileProps.put("filePath", outFile.getParent());
|
|
2186
|
+
fileProps.put("fileName", outFile.getName());
|
|
2187
|
+
fileProps.put("fileSize", outFile.length());
|
|
2188
|
+
fileProps.put("fileExtension", ".jpg");
|
|
2189
|
+
fileProps.put("thumbnail", thumbnail);
|
|
2190
|
+
|
|
2191
|
+
// Match original behavior: clear attachmentDestPath if you rely on that global
|
|
2192
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2193
|
+
|
|
2194
|
+
postSuccess(cb, fileProps);
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
// === CAMERA / GALLERY → return BASE64 string ===
|
|
2199
|
+
// Decode with downsampling and fix rotation
|
|
2200
|
+
BitmapFactory.Options o = new BitmapFactory.Options();
|
|
2201
|
+
o.inJustDecodeBounds = true; BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2202
|
+
o.inSampleSize = calcInSampleSize(o, 1920, 1920);
|
|
2203
|
+
o.inJustDecodeBounds = false;
|
|
2204
|
+
|
|
2205
|
+
// Prefer your rotation-aware helper (handles EXIF)
|
|
2206
|
+
try {
|
|
2207
|
+
bitmap = handleImageRotation(imageSourcePath);
|
|
2208
|
+
if (bitmap == null) bitmap = BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2209
|
+
} catch (Throwable t) {
|
|
2210
|
+
bitmap = BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2211
|
+
}
|
|
2212
|
+
if (bitmap == null) {
|
|
2213
|
+
postError(cb, "decode_failed");
|
|
2214
|
+
return;
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
baos = new ByteArrayOutputStream(1024 * 1024);
|
|
2218
|
+
bitmap.compress(Bitmap.CompressFormat.JPEG, 15, baos);
|
|
2219
|
+
String encodedImage = android.util.Base64.encodeToString(baos.toByteArray(), android.util.Base64.NO_WRAP);
|
|
2220
|
+
|
|
2221
|
+
// Match original behavior: delete camera temp + clear dest flag
|
|
2222
|
+
if ("camera".equalsIgnoreCase(imgSrcType)) {
|
|
2223
|
+
try {
|
|
2224
|
+
File f = new File(imageSourcePath);
|
|
2225
|
+
if (f.exists()) f.delete();
|
|
2226
|
+
} catch (Throwable ignore) {}
|
|
2227
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2228
|
+
} else if ("gallery".equalsIgnoreCase(imgSrcType)) {
|
|
2229
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
postSuccess(cb, encodedImage);
|
|
2233
|
+
} catch (Exception e) {
|
|
2234
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2235
|
+
postError(cb, "convertImageTo64BaseStringAsync failed: " + e.getMessage());
|
|
2236
|
+
} finally {
|
|
2237
|
+
try { if (srcFileReader != null) srcFileReader.close(); } catch (Exception ignore) {}
|
|
2238
|
+
try { if (desFileWriter != null) desFileWriter.close(); } catch (Exception ignore) {}
|
|
2239
|
+
try { if (baos != null) baos.close(); } catch (Exception ignore) {}
|
|
2240
|
+
try { if (bitmap != null) bitmap.recycle(); } catch (Exception ignore) {}
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
});
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
|
|
2247
|
+
private String copyFileFromUriFast(Context ctx, Uri uri, String destName, String destDir) {
|
|
2248
|
+
java.io.File dir = (destDir!=null && !destDir.isEmpty())
|
|
2249
|
+
? new java.io.File(ctx.getFilesDir(), destDir)
|
|
2250
|
+
: ctx.getFilesDir();
|
|
2251
|
+
if (!dir.exists() && !dir.mkdirs()) return null;
|
|
2252
|
+
java.io.File out = new java.io.File(dir, destName);
|
|
2253
|
+
try (java.io.InputStream in = ctx.getContentResolver().openInputStream(uri);
|
|
2254
|
+
java.io.OutputStream os = new java.io.FileOutputStream(out)) {
|
|
2255
|
+
if (in == null) return null;
|
|
2256
|
+
byte[] buf = new byte[64 * 1024];
|
|
2257
|
+
int n; while ((n = in.read(buf)) != -1) os.write(buf, 0, n);
|
|
2258
|
+
os.flush();
|
|
2259
|
+
return out.getAbsolutePath();
|
|
2260
|
+
} catch (Exception e) {
|
|
2261
|
+
android.util.Log.e("mInterface", "copyFileFromUriFast", e);
|
|
2262
|
+
return null;
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2120
2266
|
@Override
|
|
2121
2267
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
2122
2268
|
try {
|
|
@@ -2158,136 +2304,89 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2158
2304
|
SCANCODEINT = 0;
|
|
2159
2305
|
callback.error(resultCode);
|
|
2160
2306
|
}
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
if (new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) != null) {
|
|
2190
|
-
storageDefinition = new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) + "/" + path;
|
|
2191
|
-
file = new File(storageDefinition);
|
|
2192
|
-
if (file.exists() && file.canRead()) {
|
|
2193
|
-
getfilePath = storageDefinition;
|
|
2194
|
-
}
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { // DownloadsProvider
|
|
2199
|
-
id = DocumentsContract.getDocumentId(uri);
|
|
2200
|
-
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
|
|
2201
|
-
getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, null, null);
|
|
2202
|
-
} else if ("com.android.providers.media.documents".equals(uri.getAuthority())) { // MediaProvider
|
|
2203
|
-
docId = DocumentsContract.getDocumentId(uri);
|
|
2204
|
-
split = docId.split(":");
|
|
2205
|
-
type = split[0];
|
|
2206
|
-
Uri contentUri = null;
|
|
2207
|
-
if ("image".equals(type)) {
|
|
2208
|
-
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
|
2209
|
-
} else if ("video".equals(type)) {
|
|
2210
|
-
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
|
2211
|
-
} else if ("audio".equals(type)) {
|
|
2212
|
-
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
|
2213
|
-
}
|
|
2214
|
-
final String selection = "_id=?";
|
|
2215
|
-
final String[] selectionArgs = new String[]{
|
|
2216
|
-
split[1]
|
|
2217
|
-
};
|
|
2218
|
-
getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, selection, selectionArgs);
|
|
2219
|
-
}
|
|
2220
|
-
// *** API Level 19 and Above (To Get FileName,FileExtension and FileSize)**** //
|
|
2221
|
-
cursor = cordova.getActivity().getContentResolver().query(uri, null, null, null, null, null);
|
|
2307
|
+
}else if (requestCode == PICK_IMAGE_FROM_GALLERY) {
|
|
2308
|
+
final CallbackContext cb = this.callback;
|
|
2309
|
+
this.callback = null;
|
|
2310
|
+
if (cb == null) return;
|
|
2311
|
+
|
|
2312
|
+
try {
|
|
2313
|
+
if (resultCode != RESULT_OK || data == null) {
|
|
2314
|
+
cb.error("canceled");
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
// Photo Picker may return via getData() or ClipData
|
|
2319
|
+
Uri uri = data.getData();
|
|
2320
|
+
if (uri == null && data.getClipData() != null && data.getClipData().getItemCount() > 0) {
|
|
2321
|
+
uri = data.getClipData().getItemAt(0).getUri();
|
|
2322
|
+
}
|
|
2323
|
+
if (uri == null) {
|
|
2324
|
+
cb.error("no_file_selected");
|
|
2325
|
+
return;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
final Uri selectedUri = uri;
|
|
2329
|
+
final String destPath = attachmentDestPath; // capture current dest
|
|
2330
|
+
final String galleryInd = String.valueOf(galleryAttachmentInd);
|
|
2331
|
+
|
|
2332
|
+
// Offload ALL heavy work (resolver, copy, bitmap/encode) to Cordova thread pool
|
|
2333
|
+
cordova.getThreadPool().execute(new Runnable() {
|
|
2334
|
+
@Override public void run() {
|
|
2222
2335
|
try {
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2336
|
+
ContentResolver cr = cordova.getActivity().getContentResolver();
|
|
2337
|
+
|
|
2338
|
+
String mime = null;
|
|
2339
|
+
try { mime = cr.getType(selectedUri); } catch (Throwable ignore) {}
|
|
2340
|
+
|
|
2341
|
+
String defExt = (mime != null && mime.contains("/"))
|
|
2342
|
+
? mime.substring(mime.indexOf('/') + 1).toLowerCase()
|
|
2343
|
+
: "jpg";
|
|
2344
|
+
|
|
2345
|
+
// Get a display name if provider allows; otherwise build a sane fallback
|
|
2346
|
+
String fileName = safeGetDisplayName(cr, selectedUri, defExt);
|
|
2347
|
+
String ext = fileName.contains(".")
|
|
2348
|
+
? fileName.substring(fileName.lastIndexOf('.')).toLowerCase()
|
|
2349
|
+
: ("." + defExt);
|
|
2350
|
+
|
|
2351
|
+
// Copy the user-selected URI into app-private storage (no READ_MEDIA_* needed)
|
|
2352
|
+
String localPath = copyFileFromUriFast(
|
|
2353
|
+
cordova.getActivity().getApplicationContext(),
|
|
2354
|
+
selectedUri, fileName, destPath);
|
|
2355
|
+
|
|
2356
|
+
if (localPath == null) {
|
|
2357
|
+
cb.error("copy_failed");
|
|
2358
|
+
return;
|
|
2230
2359
|
}
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
};
|
|
2242
|
-
cursor = cordova.getActivity().getContentResolver().query(uri, projection, null, null, null);
|
|
2243
|
-
if (cursor.moveToFirst()) {
|
|
2244
|
-
getfilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
|
|
2245
|
-
fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
|
|
2360
|
+
|
|
2361
|
+
// Accept only image-like picks (by MIME or extension)
|
|
2362
|
+
boolean imageLike =
|
|
2363
|
+
(mime != null && mime.startsWith("image/")) ||
|
|
2364
|
+
ext.equals(".jpg") || ext.equals(".jpeg") ||
|
|
2365
|
+
ext.equals(".png") || ext.equals(".heic");
|
|
2366
|
+
|
|
2367
|
+
if (!imageLike) {
|
|
2368
|
+
cb.error("Only JPEG/PNG/HEIC images are allowed.");
|
|
2369
|
+
return;
|
|
2246
2370
|
}
|
|
2247
|
-
cursor.close();
|
|
2248
|
-
// API LEVEL 19 BELOW AND SAMSUNG (TO GET FILE PROPERTIES OF NORMAL FILES(EX:txt,.pdf,etc..,))
|
|
2249
|
-
} else {
|
|
2250
|
-
getfilePath = data.getData().getPath();
|
|
2251
|
-
filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
|
|
2252
|
-
getFileName = new File(getfilePath);
|
|
2253
|
-
fileName = getFileName.getName();
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
|
|
2257
|
-
fileExtension = "." + getfilePath.substring(getfilePath.lastIndexOf(".") + 1).toLowerCase();
|
|
2258
|
-
if (filePath != null) {
|
|
2259
|
-
try {
|
|
2260
|
-
if (fileExtension.equals(".heic")) {
|
|
2261
|
-
if (galleryAttachmentInd.equals("true")) {
|
|
2262
|
-
convertImageTo64BaseString(callback, filePath + "/" + fileName, "compress", attachmentDestPath);
|
|
2263
|
-
} else {
|
|
2264
|
-
convertImageTo64BaseString(callback, filePath + "/" + fileName, "gallery", "");
|
|
2265
|
-
}
|
|
2266
2371
|
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
} else {
|
|
2271
|
-
convertImageTo64BaseString(callback, filePath + "/" + fileName, "gallery", "");
|
|
2272
|
-
}
|
|
2372
|
+
// Run your existing conversion on a worker too (non-blocking)
|
|
2373
|
+
if ("true".equals(galleryInd)) {
|
|
2374
|
+
convertImageTo64BaseStringAsync(cb, localPath, "compress", destPath);
|
|
2273
2375
|
} else {
|
|
2274
|
-
|
|
2376
|
+
convertImageTo64BaseStringAsync(cb, localPath, "gallery", "");
|
|
2275
2377
|
}
|
|
2276
2378
|
} catch (Exception e) {
|
|
2277
|
-
|
|
2379
|
+
cb.error("PICK_IMAGE_FROM_GALLERY: " + e.getMessage());
|
|
2278
2380
|
}
|
|
2279
|
-
} else {
|
|
2280
|
-
callback.error("File path was null");
|
|
2281
2381
|
}
|
|
2282
|
-
}
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
} else {
|
|
2288
|
-
callback.error(resultCode);
|
|
2382
|
+
});
|
|
2383
|
+
return; // IMPORTANT: stop here so no other branch falls through
|
|
2384
|
+
} catch (Exception e) {
|
|
2385
|
+
cb.error("PICK_IMAGE_FROM_GALLERY dispatch failed: " + e.getMessage());
|
|
2386
|
+
return;
|
|
2289
2387
|
}
|
|
2290
|
-
}
|
|
2388
|
+
}
|
|
2389
|
+
else if (requestCode == NEW_FILE_PICK_REQUEST && callback != null) {
|
|
2291
2390
|
try {
|
|
2292
2391
|
Uri uri = data.getData();
|
|
2293
2392
|
String fileName, extension, filePath;
|
package/src/ios/mInterface.h
CHANGED
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
UIInterfaceOrientation _lastOrientation;
|
|
44
44
|
}
|
|
45
45
|
@property(strong) NSString* callbackID;
|
|
46
|
+
- (void)GetConfigCascade:(CDVInvokedUrlCommand*)command;
|
|
46
47
|
- (void)ScanBarCode:(CDVInvokedUrlCommand*)command;
|
|
47
48
|
- (void)ScanQRCode:(CDVInvokedUrlCommand*)command;
|
|
48
49
|
- (void)viewRoute:(CDVInvokedUrlCommand*)command;
|
package/src/ios/mInterface.m
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
#import "OneSignalPush.h"
|
|
14
14
|
#import <objc/runtime.h>
|
|
15
15
|
#import <AVFoundation/AVFoundation.h>
|
|
16
|
+
#import <Cordova/CDV.h>
|
|
16
17
|
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
|
17
18
|
@import UserNotifications;
|
|
18
19
|
#endif
|
|
@@ -20,7 +21,14 @@
|
|
|
20
21
|
#ifndef NSFoundationVersionNumber_iOS_9_x_Max
|
|
21
22
|
#define NSFoundationVersionNumber_iOS_9_x_Max 1299
|
|
22
23
|
#endif
|
|
23
|
-
|
|
24
|
+
/*** TOP-LEVEL helper (NOT inside @implementation mInterface) ***/
|
|
25
|
+
@interface ResolveResult : NSObject
|
|
26
|
+
@property (nonatomic, strong) NSURL *fileURL;
|
|
27
|
+
@property (nonatomic, copy) NSString *ext;
|
|
28
|
+
@end
|
|
29
|
+
|
|
30
|
+
@implementation ResolveResult
|
|
31
|
+
@end
|
|
24
32
|
@implementation mInterface
|
|
25
33
|
@synthesize btnGallery;
|
|
26
34
|
@synthesize indicator = _indicator;
|
|
@@ -29,6 +37,333 @@
|
|
|
29
37
|
@synthesize callbackID;
|
|
30
38
|
|
|
31
39
|
|
|
40
|
+
|
|
41
|
+
- (void)GetConfigCascade:(CDVInvokedUrlCommand*)command {
|
|
42
|
+
// Declarations first
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@try {
|
|
46
|
+
[self.commandDelegate runInBackground:^{
|
|
47
|
+
@try {
|
|
48
|
+
// --- parse input
|
|
49
|
+
NSDictionary *p = (command.arguments.count > 0 && [command.arguments[0] isKindOfClass:[NSDictionary class]]) ? command.arguments[0] : @{};
|
|
50
|
+
NSString *kind = p[@"configType"] ?: @"controller";
|
|
51
|
+
NSString *identifier = p[@"id"] ?: @"";
|
|
52
|
+
NSString *clientId = p[@"clientId"] ?: @"";
|
|
53
|
+
NSString *countryCode = p[@"countryCode"] ?: @"";
|
|
54
|
+
NSString *clientGroup = p[@"clientGroup"] ?: @"";
|
|
55
|
+
NSString *vertical = p[@"vertical"] ?: @"";
|
|
56
|
+
NSString *solution = p[@"solution"] ?: @"";
|
|
57
|
+
NSString *scope = p[@"scope"] ?: kind;
|
|
58
|
+
NSString *transNo = p[@"transNo"] ?: @"";
|
|
59
|
+
NSString *rootPrefix = p[@"root"] ?: @"";
|
|
60
|
+
NSString *localeId = p[@"localeId"] ?: @"";
|
|
61
|
+
|
|
62
|
+
// --- base dir
|
|
63
|
+
NSFileManager *fm = [NSFileManager defaultManager];
|
|
64
|
+
NSURL *baseDir = [[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
|
|
65
|
+
if (!baseDir) baseDir = [[fm URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] firstObject];
|
|
66
|
+
|
|
67
|
+
// --- roots
|
|
68
|
+
NSArray<NSURL *> *roots = [self buildRootsWithBase:baseDir
|
|
69
|
+
rootPrefix:rootPrefix
|
|
70
|
+
clientGroup:clientGroup
|
|
71
|
+
clientId:clientId
|
|
72
|
+
countryCode:countryCode];
|
|
73
|
+
|
|
74
|
+
// --- keys (label is locale-aware)
|
|
75
|
+
NSMutableArray<NSString *> *keys = [NSMutableArray array];
|
|
76
|
+
if ([kind isEqualToString:@"label"] && localeId.length > 0) {
|
|
77
|
+
if (clientId.length && countryCode.length) [keys addObject:[NSString stringWithFormat:@"%@_%@_%@_%@", identifier, clientId, countryCode, localeId]];
|
|
78
|
+
if (clientId.length) [keys addObject:[NSString stringWithFormat:@"%@_%@_%@", identifier, clientId, localeId]];
|
|
79
|
+
if (clientGroup.length) [keys addObject:[NSString stringWithFormat:@"%@_%@_%@", identifier, clientGroup, localeId]];
|
|
80
|
+
if (vertical.length) [keys addObject:[NSString stringWithFormat:@"%@_%@_%@", identifier, vertical, localeId]];
|
|
81
|
+
if (solution.length) [keys addObject:[NSString stringWithFormat:@"%@_%@_%@", identifier, solution, localeId]];
|
|
82
|
+
[keys addObject:[NSString stringWithFormat:@"%@_%@", identifier, localeId]];
|
|
83
|
+
} else {
|
|
84
|
+
if (clientId.length && countryCode.length) [keys addObject:[NSString stringWithFormat:@"%@_%@_%@", identifier, clientId, countryCode]];
|
|
85
|
+
if (clientId.length) [keys addObject:[NSString stringWithFormat:@"%@_%@", identifier, clientId]];
|
|
86
|
+
if (clientGroup.length) [keys addObject:[NSString stringWithFormat:@"%@_%@", identifier, clientGroup]];
|
|
87
|
+
if (vertical.length) [keys addObject:[NSString stringWithFormat:@"%@_%@", identifier, vertical]];
|
|
88
|
+
if (solution.length) [keys addObject:[NSString stringWithFormat:@"%@_%@", identifier, solution]];
|
|
89
|
+
[keys addObject:identifier ?: @""];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --- scopes
|
|
93
|
+
NSMutableArray<NSString *> *scopesToTry = [NSMutableArray array];
|
|
94
|
+
if ([scope isEqualToString:@"containR"]) {
|
|
95
|
+
[scopesToTry addObject:@"containR"];
|
|
96
|
+
[scopesToTry addObject:kind];
|
|
97
|
+
} else {
|
|
98
|
+
[scopesToTry addObject:kind];
|
|
99
|
+
[scopesToTry addObject:@"containR"];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// --- search
|
|
103
|
+
BOOL found = NO;
|
|
104
|
+
NSString *resolvedKey = nil; NSString *usedExt = nil; NSString *absPath = nil; NSString *content = nil;
|
|
105
|
+
|
|
106
|
+
for (NSString *key in keys) {
|
|
107
|
+
for (NSString *sc in scopesToTry) {
|
|
108
|
+
ResolveResult *rr = [self resolveGenericFileWithRoots:roots
|
|
109
|
+
scope:sc
|
|
110
|
+
kind:kind
|
|
111
|
+
id:identifier
|
|
112
|
+
transNo:transNo
|
|
113
|
+
key:key];
|
|
114
|
+
if (rr && rr.fileURL) {
|
|
115
|
+
NSString *tryPath = rr.fileURL.path;
|
|
116
|
+
NSLog(@"mInterface: Trying: %@", tryPath);
|
|
117
|
+
BOOL isDir = NO;
|
|
118
|
+
if ([fm fileExistsAtPath:tryPath isDirectory:&isDir] && !isDir) {
|
|
119
|
+
NSError *readErr = nil;
|
|
120
|
+
NSString *txt = [NSString stringWithContentsOfURL:rr.fileURL
|
|
121
|
+
encoding:NSUTF8StringEncoding
|
|
122
|
+
error:&readErr];
|
|
123
|
+
if (!readErr && txt != nil) {
|
|
124
|
+
content = txt;
|
|
125
|
+
resolvedKey = key;
|
|
126
|
+
usedExt = rr.ext ?: @"";
|
|
127
|
+
absPath = tryPath;
|
|
128
|
+
found = YES;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (found) break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// --- respond
|
|
138
|
+
if (found) {
|
|
139
|
+
NSDictionary *payload = @{
|
|
140
|
+
@"configType": kind ?: @"",
|
|
141
|
+
@"srcKey": resolvedKey ?: @"",
|
|
142
|
+
@"ext": usedExt ?: @"",
|
|
143
|
+
@"path": absPath ?: @"",
|
|
144
|
+
@"content": content ?: @""
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
NSError *jsonError = nil; // declare inside the block
|
|
148
|
+
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
|
|
149
|
+
options:0
|
|
150
|
+
error:&jsonError];
|
|
151
|
+
NSString *jsonStr = [[NSString alloc] initWithData:jsonData
|
|
152
|
+
encoding:NSUTF8StringEncoding];
|
|
153
|
+
|
|
154
|
+
CDVPluginResult *ok = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
|
|
155
|
+
messageAsString:jsonStr ?: @"{}"];
|
|
156
|
+
[self.commandDelegate sendPluginResult:ok callbackId:command.callbackId];
|
|
157
|
+
} else {
|
|
158
|
+
CDVPluginResult *errRes = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
|
|
159
|
+
messageAsString:@"NOT_FOUND"];
|
|
160
|
+
[self.commandDelegate sendPluginResult:errRes callbackId:command.callbackId];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
} @catch (NSException *ex) {
|
|
164
|
+
CDVPluginResult *errRes = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"GetConfigCascade failed: %@", ex.reason ?: @""]];
|
|
165
|
+
[self.commandDelegate sendPluginResult:errRes callbackId:command.callbackId];
|
|
166
|
+
}
|
|
167
|
+
}];
|
|
168
|
+
} @catch (NSException *exOuter) {
|
|
169
|
+
CDVPluginResult *errRes = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"GetConfigCascade failed: %@", exOuter.reason ?: @""]];
|
|
170
|
+
[self.commandDelegate sendPluginResult:errRes callbackId:command.callbackId];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
#pragma mark - Helpers
|
|
175
|
+
|
|
176
|
+
- (NSArray<NSURL*> *)buildRootsWithBase:(NSURL *)baseDir
|
|
177
|
+
rootPrefix:(NSString *)rootPrefix
|
|
178
|
+
clientGroup:(NSString *)clientGroup
|
|
179
|
+
clientId:(NSString *)clientId
|
|
180
|
+
countryCode:(NSString *)countryCode {
|
|
181
|
+
NSMutableArray<NSURL*> *roots = [NSMutableArray array];
|
|
182
|
+
NSMutableSet<NSString*> *seen = [NSMutableSet set];
|
|
183
|
+
|
|
184
|
+
void (^addIfUnique)(NSURL *) = ^(NSURL *u){
|
|
185
|
+
if (!u) return;
|
|
186
|
+
NSString *p = u.path;
|
|
187
|
+
if (p.length && ![seen containsObject:p]) { [roots addObject:u]; [seen addObject:p]; }
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
@try {
|
|
191
|
+
NSURL *r1 = [[[baseDir URLByAppendingPathComponent:rootPrefix isDirectory:YES]
|
|
192
|
+
URLByAppendingPathComponent:clientId isDirectory:YES]
|
|
193
|
+
URLByAppendingPathComponent:countryCode isDirectory:YES];
|
|
194
|
+
addIfUnique(r1);
|
|
195
|
+
|
|
196
|
+
NSURL *r2 = [[[[baseDir URLByAppendingPathComponent:rootPrefix isDirectory:YES]
|
|
197
|
+
URLByAppendingPathComponent:clientId isDirectory:YES]
|
|
198
|
+
URLByAppendingPathComponent:clientId isDirectory:YES]
|
|
199
|
+
URLByAppendingPathComponent:countryCode isDirectory:YES];
|
|
200
|
+
addIfUnique(r2);
|
|
201
|
+
|
|
202
|
+
if (clientGroup.length) {
|
|
203
|
+
NSURL *r3 = [[[[baseDir URLByAppendingPathComponent:rootPrefix isDirectory:YES]
|
|
204
|
+
URLByAppendingPathComponent:clientGroup isDirectory:YES]
|
|
205
|
+
URLByAppendingPathComponent:clientId isDirectory:YES]
|
|
206
|
+
URLByAppendingPathComponent:countryCode isDirectory:YES];
|
|
207
|
+
addIfUnique(r3);
|
|
208
|
+
}
|
|
209
|
+
} @catch (__unused NSException *e) {}
|
|
210
|
+
return roots;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
- (NSString *)prefixForKind:(NSString *)kind {
|
|
214
|
+
if ([kind isEqualToString:@"controller"]) return @"controller_";
|
|
215
|
+
if ([kind isEqualToString:@"label"]) return @"label_";
|
|
216
|
+
if ([kind isEqualToString:@"rule"]) return @"rule_";
|
|
217
|
+
if ([kind isEqualToString:@"template"]) return @"template_";
|
|
218
|
+
if ([kind isEqualToString:@"ui"]) return @"ui_";
|
|
219
|
+
return [kind stringByAppendingString:@"_"];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
- (NSArray<NSString*> *)extensionsForKind:(NSString *)kind {
|
|
223
|
+
if ([kind isEqualToString:@"controller"]) return @[ @"json" ];
|
|
224
|
+
if ([kind isEqualToString:@"label"]) return @[ @"json", @"txt" ];
|
|
225
|
+
if ([kind isEqualToString:@"rule"]) return @[ @"txt", @"json" ];
|
|
226
|
+
if ([kind isEqualToString:@"template"]) return @[ @"html", @"json" ];
|
|
227
|
+
if ([kind isEqualToString:@"ui"]) return @[ @"html", @"json" ];
|
|
228
|
+
return @[ @"json" ];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
- (ResolveResult *)resolveGenericFileWithRoots:(NSArray<NSURL*> *)roots
|
|
232
|
+
scope:(NSString *)scope
|
|
233
|
+
kind:(NSString *)kind
|
|
234
|
+
id:(NSString *)identifier
|
|
235
|
+
transNo:(NSString *)transNo
|
|
236
|
+
key:(NSString *)key {
|
|
237
|
+
NSArray<NSString*> *exts = [self extensionsForKind:kind];
|
|
238
|
+
NSString *prefix = [self prefixForKind:kind];
|
|
239
|
+
|
|
240
|
+
NSArray<NSString*> *nameVariants = [kind isEqualToString:@"label"]
|
|
241
|
+
? @[ [prefix stringByAppendingString:key], key ]
|
|
242
|
+
: @[ [prefix stringByAppendingString:key] ];
|
|
243
|
+
|
|
244
|
+
NSFileManager *fm = [NSFileManager defaultManager];
|
|
245
|
+
|
|
246
|
+
@try {
|
|
247
|
+
for (NSURL *root in roots) {
|
|
248
|
+
if (!root) continue;
|
|
249
|
+
|
|
250
|
+
for (NSString *ext in exts) {
|
|
251
|
+
|
|
252
|
+
if ([scope isEqualToString:@"containR"]) {
|
|
253
|
+
NSURL *containRDir = [root URLByAppendingPathComponent:@"containR" isDirectory:YES];
|
|
254
|
+
NSURL *screenDir = [containRDir URLByAppendingPathComponent:identifier isDirectory:YES];
|
|
255
|
+
|
|
256
|
+
if (transNo.length) {
|
|
257
|
+
NSURL *transDir = [screenDir URLByAppendingPathComponent:transNo isDirectory:YES];
|
|
258
|
+
|
|
259
|
+
if ([kind isEqualToString:@"label"]) {
|
|
260
|
+
NSURL *labelDir = [transDir URLByAppendingPathComponent:@"label" isDirectory:YES];
|
|
261
|
+
NSURL *labelsDir = [transDir URLByAppendingPathComponent:@"labels" isDirectory:YES];
|
|
262
|
+
|
|
263
|
+
for (NSString *nv in nameVariants) {
|
|
264
|
+
NSArray<NSURL*> *cands = @[
|
|
265
|
+
[labelDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
266
|
+
[labelsDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
267
|
+
[transDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]]
|
|
268
|
+
];
|
|
269
|
+
for (NSURL *u in cands) {
|
|
270
|
+
if ([fm fileExistsAtPath:u.path isDirectory:NULL]) {
|
|
271
|
+
ResolveResult *rr = [ResolveResult new]; rr.fileURL = u; rr.ext = ext; return rr;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
NSURL *typeDir = [transDir URLByAppendingPathComponent:kind isDirectory:YES];
|
|
277
|
+
NSURL *f1 = [typeDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
278
|
+
NSURL *f2 = [transDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
279
|
+
if ([fm fileExistsAtPath:f1.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f1; rr.ext=ext; return rr; }
|
|
280
|
+
if ([fm fileExistsAtPath:f2.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f2; rr.ext=ext; return rr; }
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if ([kind isEqualToString:@"label"]) {
|
|
285
|
+
NSURL *labelDirNT = [screenDir URLByAppendingPathComponent:@"label" isDirectory:YES];
|
|
286
|
+
NSURL *labelsDirNT = [screenDir URLByAppendingPathComponent:@"labels" isDirectory:YES];
|
|
287
|
+
for (NSString *nv in nameVariants) {
|
|
288
|
+
NSArray<NSURL*> *cands = @[
|
|
289
|
+
[labelDirNT URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
290
|
+
[labelsDirNT URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
291
|
+
[screenDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]]
|
|
292
|
+
];
|
|
293
|
+
for (NSURL *u in cands) {
|
|
294
|
+
if ([fm fileExistsAtPath:u.path isDirectory:NULL]) {
|
|
295
|
+
ResolveResult *rr = [ResolveResult new]; rr.fileURL = u; rr.ext = ext; return rr;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
NSURL *typeDirNT = [screenDir URLByAppendingPathComponent:kind isDirectory:YES];
|
|
301
|
+
NSURL *f1 = [typeDirNT URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
302
|
+
NSURL *f2 = [screenDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
303
|
+
if ([fm fileExistsAtPath:f1.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f1; rr.ext=ext; return rr; }
|
|
304
|
+
if ([fm fileExistsAtPath:f2.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f2; rr.ext=ext; return rr; }
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
} else {
|
|
308
|
+
NSURL *cfg = [root URLByAppendingPathComponent:@"configuration_package" isDirectory:YES];
|
|
309
|
+
|
|
310
|
+
if ([kind isEqualToString:@"label"]) {
|
|
311
|
+
NSURL *labelDir = [cfg URLByAppendingPathComponent:@"label" isDirectory:YES];
|
|
312
|
+
NSURL *labelsDir = [cfg URLByAppendingPathComponent:@"labels" isDirectory:YES];
|
|
313
|
+
|
|
314
|
+
for (NSString *nv in nameVariants) {
|
|
315
|
+
NSArray<NSURL*> *cands1 = @[
|
|
316
|
+
[labelDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
317
|
+
[labelsDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]]
|
|
318
|
+
];
|
|
319
|
+
for (NSURL *u in cands1) {
|
|
320
|
+
if ([fm fileExistsAtPath:u.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=u; rr.ext=ext; return rr; }
|
|
321
|
+
}
|
|
322
|
+
NSArray<NSURL*> *cands2 = @[
|
|
323
|
+
[[labelDir URLByAppendingPathComponent:identifier isDirectory:YES] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
324
|
+
[[labelsDir URLByAppendingPathComponent:identifier isDirectory:YES] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]]
|
|
325
|
+
];
|
|
326
|
+
for (NSURL *u in cands2) {
|
|
327
|
+
if ([fm fileExistsAtPath:u.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=u; rr.ext=ext; return rr; }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
NSURL *cfg2 = [root URLByAppendingPathComponent:@"configuration" isDirectory:YES];
|
|
332
|
+
NSURL *label2 = [cfg2 URLByAppendingPathComponent:@"label" isDirectory:YES];
|
|
333
|
+
NSURL *labels2 = [cfg2 URLByAppendingPathComponent:@"labels" isDirectory:YES];
|
|
334
|
+
for (NSString *nv in nameVariants) {
|
|
335
|
+
NSArray<NSURL*> *cands3 = @[
|
|
336
|
+
[label2 URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
337
|
+
[labels2 URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
338
|
+
[[label2 URLByAppendingPathComponent:identifier isDirectory:YES] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]],
|
|
339
|
+
[[labels2 URLByAppendingPathComponent:identifier isDirectory:YES] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", nv, ext]]
|
|
340
|
+
];
|
|
341
|
+
for (NSURL *u in cands3) {
|
|
342
|
+
if ([fm fileExistsAtPath:u.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=u; rr.ext=ext; return rr; }
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
} else {
|
|
347
|
+
NSURL *typeDir = [cfg URLByAppendingPathComponent:kind isDirectory:YES];
|
|
348
|
+
NSURL *f1 = [typeDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
349
|
+
NSURL *f2 = [[typeDir URLByAppendingPathComponent:identifier isDirectory:YES] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
350
|
+
if ([fm fileExistsAtPath:f1.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f1; rr.ext=ext; return rr; }
|
|
351
|
+
if ([fm fileExistsAtPath:f2.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f2; rr.ext=ext; return rr; }
|
|
352
|
+
|
|
353
|
+
NSURL *cfg2 = [root URLByAppendingPathComponent:@"configuration" isDirectory:YES];
|
|
354
|
+
NSURL *type2 = [cfg2 URLByAppendingPathComponent:kind isDirectory:YES];
|
|
355
|
+
NSURL *f3 = [type2 URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
356
|
+
NSURL *f4 = [[type2 URLByAppendingPathComponent:identifier isDirectory:YES] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [prefix stringByAppendingString:key], ext]];
|
|
357
|
+
if ([fm fileExistsAtPath:f3.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f3; rr.ext=ext; return rr; }
|
|
358
|
+
if ([fm fileExistsAtPath:f4.path isDirectory:NULL]) { ResolveResult *rr=[ResolveResult new]; rr.fileURL=f4; rr.ext=ext; return rr; }
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} @catch (__unused NSException *e) {}
|
|
364
|
+
return nil;
|
|
365
|
+
}
|
|
366
|
+
|
|
32
367
|
|
|
33
368
|
// Inside the @implementation block
|
|
34
369
|
- (void)ScanBarCode:(CDVInvokedUrlCommand*)command {
|