html2apk 0.4.0 → 0.7.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.
@@ -492,6 +492,7 @@ h2 {
492
492
  }
493
493
 
494
494
  .icon-field,
495
+ .keystore-field,
495
496
  .onesignal-field,
496
497
  .permissions-field {
497
498
  grid-column: span 2;
@@ -569,6 +570,24 @@ h2 {
569
570
  gap: 10px;
570
571
  }
571
572
 
573
+ .keystore-grid {
574
+ display: grid;
575
+ grid-template-columns: repeat(2, minmax(0, 1fr));
576
+ gap: 12px;
577
+ }
578
+
579
+ .keystore-grid label {
580
+ display: grid;
581
+ gap: 8px;
582
+ }
583
+
584
+ .inline-picker {
585
+ display: grid;
586
+ grid-template-columns: minmax(0, 1fr) auto;
587
+ gap: 10px;
588
+ align-items: center;
589
+ }
590
+
572
591
  .validation-panel {
573
592
  margin-top: 16px;
574
593
  border: 1px solid color-mix(in srgb, var(--red) 42%, var(--line));
@@ -621,6 +640,165 @@ h2 {
621
640
  color: var(--muted);
622
641
  }
623
642
 
643
+ .file-editor-layout {
644
+ display: grid;
645
+ grid-template-columns: minmax(220px, 290px) minmax(0, 1fr);
646
+ gap: 16px;
647
+ min-height: 620px;
648
+ }
649
+
650
+ .file-tree-panel,
651
+ .file-editor-panel {
652
+ border: 1px solid var(--line);
653
+ background: var(--panel);
654
+ border-radius: 8px;
655
+ box-shadow: var(--shadow);
656
+ }
657
+
658
+ .file-tree-panel {
659
+ padding: 14px;
660
+ overflow: auto;
661
+ }
662
+
663
+ .file-tree-panel > strong {
664
+ display: block;
665
+ margin-bottom: 12px;
666
+ }
667
+
668
+ .file-tree {
669
+ display: grid;
670
+ gap: 4px;
671
+ }
672
+
673
+ .file-tree-empty {
674
+ color: var(--muted);
675
+ line-height: 1.45;
676
+ }
677
+
678
+ .file-row {
679
+ width: 100%;
680
+ min-height: 34px;
681
+ border: 0;
682
+ border-radius: 7px;
683
+ padding: 0 8px;
684
+ background: transparent;
685
+ color: var(--text);
686
+ display: flex;
687
+ align-items: center;
688
+ gap: 8px;
689
+ text-align: left;
690
+ }
691
+
692
+ .file-row:hover,
693
+ .file-row.active {
694
+ background: var(--blue-soft);
695
+ color: var(--blue);
696
+ }
697
+
698
+ .file-row:disabled {
699
+ cursor: not-allowed;
700
+ color: var(--muted);
701
+ opacity: .62;
702
+ }
703
+
704
+ .folder-row {
705
+ margin-top: 8px;
706
+ min-height: 28px;
707
+ color: var(--muted);
708
+ font-size: 12px;
709
+ font-weight: 800;
710
+ text-transform: uppercase;
711
+ }
712
+
713
+ .file-editor-panel {
714
+ display: grid;
715
+ grid-template-rows: auto minmax(280px, 1fr) minmax(180px, 240px);
716
+ overflow: hidden;
717
+ }
718
+
719
+ .file-editor-meta {
720
+ min-height: 50px;
721
+ border-bottom: 1px solid var(--line);
722
+ padding: 12px 14px;
723
+ display: flex;
724
+ align-items: center;
725
+ justify-content: space-between;
726
+ gap: 12px;
727
+ }
728
+
729
+ .file-editor-meta strong {
730
+ overflow: hidden;
731
+ text-overflow: ellipsis;
732
+ white-space: nowrap;
733
+ }
734
+
735
+ #fileLanguageBadge {
736
+ flex: 0 0 auto;
737
+ min-width: 46px;
738
+ min-height: 26px;
739
+ padding: 5px 9px;
740
+ border-radius: 8px;
741
+ background: var(--blue-soft);
742
+ color: var(--blue);
743
+ text-align: center;
744
+ font-size: 12px;
745
+ font-weight: 800;
746
+ }
747
+
748
+ #fileEditorInput {
749
+ width: 100%;
750
+ min-height: 0;
751
+ resize: none;
752
+ border: 0;
753
+ border-bottom: 1px solid var(--line);
754
+ outline: none;
755
+ padding: 16px;
756
+ background: var(--bg);
757
+ color: var(--text);
758
+ font: 13px/1.55 ui-monospace, SFMono-Regular, Consolas, monospace;
759
+ tab-size: 2;
760
+ }
761
+
762
+ .syntax-preview-wrap {
763
+ min-height: 0;
764
+ display: grid;
765
+ grid-template-rows: auto minmax(0, 1fr);
766
+ background: color-mix(in srgb, var(--panel-soft) 55%, var(--panel));
767
+ }
768
+
769
+ .syntax-preview-wrap > strong {
770
+ padding: 10px 14px 0;
771
+ color: var(--muted);
772
+ font-size: 12px;
773
+ }
774
+
775
+ .syntax-preview {
776
+ margin: 0;
777
+ padding: 12px 14px 16px;
778
+ overflow: auto;
779
+ color: var(--text);
780
+ font: 12px/1.55 ui-monospace, SFMono-Regular, Consolas, monospace;
781
+ }
782
+
783
+ .syntax-token-tag,
784
+ .syntax-token-keyword {
785
+ color: var(--blue);
786
+ font-weight: 800;
787
+ }
788
+
789
+ .syntax-token-string {
790
+ color: var(--green);
791
+ }
792
+
793
+ .syntax-token-comment {
794
+ color: var(--muted);
795
+ font-style: italic;
796
+ }
797
+
798
+ .syntax-token-number {
799
+ color: var(--amber);
800
+ }
801
+
624
802
  .preference-row {
625
803
  min-height: 112px;
626
804
  padding: 20px;
@@ -1340,11 +1518,22 @@ body.logs-visible .bottom-log-bar {
1340
1518
  }
1341
1519
 
1342
1520
  .icon-field,
1521
+ .keystore-field,
1343
1522
  .onesignal-field,
1344
1523
  .permissions-field {
1345
1524
  grid-column: span 1;
1346
1525
  }
1347
1526
 
1527
+ .keystore-grid,
1528
+ .inline-picker,
1529
+ .file-editor-layout {
1530
+ grid-template-columns: 1fr;
1531
+ }
1532
+
1533
+ .file-editor-layout {
1534
+ min-height: 820px;
1535
+ }
1536
+
1348
1537
  .view-header,
1349
1538
  .result-panel,
1350
1539
  .progress-panel,
@@ -27,6 +27,7 @@
27
27
  <config-file target="AndroidManifest.xml" parent="/manifest/application">
28
28
  <service android:name="dev.html2apk.bridge.FloatingIconService" android:exported="false" />
29
29
  <receiver android:name="dev.html2apk.bridge.NotificationReceiver" android:exported="false" />
30
+ <receiver android:name="dev.html2apk.bridge.NotificationClickReceiver" android:exported="false" />
30
31
  <receiver android:name="dev.html2apk.bridge.BootReceiver" android:enabled="true" android:exported="true">
31
32
  <intent-filter>
32
33
  <action android:name="android.intent.action.BOOT_COMPLETED" />
@@ -38,6 +39,7 @@
38
39
  <source-file src="src/android/Html2ApkBridge.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
39
40
  <source-file src="src/android/FloatingIconService.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
40
41
  <source-file src="src/android/NotificationReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
42
+ <source-file src="src/android/NotificationClickReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
41
43
  <source-file src="src/android/BootReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
42
44
  <source-file src="src/android/NotificationStore.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
43
45
  <framework src="androidx.core:core:1.12.0" />
@@ -73,6 +73,7 @@ public class Html2ApkBridge extends CordovaPlugin {
73
73
  private static final int REQUEST_PICK_FOLDER = 7413;
74
74
  private static final String PREFS_NAME = "html2apk_bridge";
75
75
  private static final String PREF_PERMISSION_PREFIX = "permission_requested_";
76
+ private static Html2ApkBridge activeBridge;
76
77
 
77
78
  private CallbackContext notificationPermissionCallback;
78
79
  private CallbackContext cameraPermissionCallback;
@@ -100,6 +101,7 @@ public class Html2ApkBridge extends CordovaPlugin {
100
101
  @Override
101
102
  public void initialize(CordovaInterface cordova, CordovaWebView webView) {
102
103
  super.initialize(cordova, webView);
104
+ activeBridge = this;
103
105
  handleNotificationIntent(cordova.getActivity().getIntent(), false);
104
106
  handleLinkIntent(cordova.getActivity().getIntent(), false);
105
107
  registerSystemReceiver();
@@ -131,6 +133,9 @@ public class Html2ApkBridge extends CordovaPlugin {
131
133
  stopMicRecorderSilently();
132
134
  unregisterSystemReceiver();
133
135
  dispatchEvent("app:fechado", baseEvent("app:fechado"));
136
+ if (activeBridge == this) {
137
+ activeBridge = null;
138
+ }
134
139
  super.onDestroy();
135
140
  }
136
141
 
@@ -420,6 +425,22 @@ public class Html2ApkBridge extends CordovaPlugin {
420
425
  return false;
421
426
  }
422
427
 
428
+ private void rejectBusyCallback(CallbackContext callbackContext, String operation) {
429
+ callbackContext.error(operation + " is already waiting for Android. Wait for the previous call to finish.");
430
+ }
431
+
432
+ private boolean hasPendingNotificationPermissionRequest() {
433
+ return pendingNotificationCallback != null || notificationPermissionCallback != null;
434
+ }
435
+
436
+ private boolean hasPendingCameraPermissionRequest() {
437
+ return pendingFlashlightCallback != null || cameraPermissionCallback != null;
438
+ }
439
+
440
+ private boolean hasPendingMicrophonePermissionRequest() {
441
+ return pendingMicStartCallback != null || microphonePermissionCallback != null;
442
+ }
443
+
423
444
  @Override
424
445
  public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
425
446
  if (requestCode == REQUEST_CAMERA) {
@@ -756,9 +777,8 @@ public class Html2ApkBridge extends CordovaPlugin {
756
777
  callbackContext.success(notificationPermissionStatus());
757
778
  return;
758
779
  }
759
-
760
- if (shouldOpenSettingsForRuntimePermission(Manifest.permission.POST_NOTIFICATIONS)) {
761
- callbackContext.success(openSettingsForRuntimePermission(Manifest.permission.POST_NOTIFICATIONS, true, false));
780
+ if (hasPendingNotificationPermissionRequest()) {
781
+ rejectBusyCallback(callbackContext, "POST_NOTIFICATIONS permission");
762
782
  return;
763
783
  }
764
784
 
@@ -776,9 +796,8 @@ public class Html2ApkBridge extends CordovaPlugin {
776
796
  if (hasNotificationPermission()) {
777
797
  return false;
778
798
  }
779
-
780
- if (shouldOpenSettingsForRuntimePermission(Manifest.permission.POST_NOTIFICATIONS)) {
781
- callbackContext.success(openSettingsForRuntimePermission(Manifest.permission.POST_NOTIFICATIONS, true, false));
799
+ if (hasPendingNotificationPermissionRequest()) {
800
+ rejectBusyCallback(callbackContext, "POST_NOTIFICATIONS permission");
782
801
  return true;
783
802
  }
784
803
 
@@ -806,7 +825,7 @@ public class Html2ApkBridge extends CordovaPlugin {
806
825
  .setContentText(text)
807
826
  .setStyle(new NotificationCompat.BigTextStyle().bigText(text))
808
827
  .setAutoCancel(true)
809
- .setContentIntent(createContentIntent(context(), id, detailPayload(options)))
828
+ .setContentIntent(createNotificationClickIntent(context(), id, detailPayload(options)))
810
829
  .setPriority(NotificationCompat.PRIORITY_DEFAULT);
811
830
 
812
831
  addNotificationActions(builder, context(), id, options);
@@ -1068,9 +1087,8 @@ public class Html2ApkBridge extends CordovaPlugin {
1068
1087
  callbackContext.success(runtimePermissionResult(Manifest.permission.CAMERA, true, false, true));
1069
1088
  return;
1070
1089
  }
1071
-
1072
- if (shouldOpenSettingsForRuntimePermission(Manifest.permission.CAMERA)) {
1073
- callbackContext.success(openSettingsForRuntimePermission(Manifest.permission.CAMERA, true, false));
1090
+ if (hasPendingCameraPermissionRequest()) {
1091
+ rejectBusyCallback(callbackContext, "CAMERA permission");
1074
1092
  return;
1075
1093
  }
1076
1094
 
@@ -1091,9 +1109,8 @@ public class Html2ApkBridge extends CordovaPlugin {
1091
1109
  callbackContext.success(result);
1092
1110
  return;
1093
1111
  }
1094
-
1095
- if (shouldOpenSettingsForRuntimePermission(Manifest.permission.RECORD_AUDIO)) {
1096
- callbackContext.success(openSettingsForRuntimePermission(Manifest.permission.RECORD_AUDIO, true, false));
1112
+ if (hasPendingMicrophonePermissionRequest()) {
1113
+ rejectBusyCallback(callbackContext, "RECORD_AUDIO permission");
1097
1114
  return;
1098
1115
  }
1099
1116
 
@@ -1131,11 +1148,10 @@ public class Html2ApkBridge extends CordovaPlugin {
1131
1148
  }
1132
1149
 
1133
1150
  if (!hasMicrophonePermission()) {
1134
- if (shouldOpenSettingsForRuntimePermission(Manifest.permission.RECORD_AUDIO)) {
1135
- callbackContext.success(openSettingsForRuntimePermission(Manifest.permission.RECORD_AUDIO, true, false));
1151
+ if (hasPendingMicrophonePermissionRequest()) {
1152
+ rejectBusyCallback(callbackContext, "RECORD_AUDIO permission");
1136
1153
  return;
1137
1154
  }
1138
-
1139
1155
  pendingMicStartCallback = callbackContext;
1140
1156
  rememberRuntimePermissionRequest(Manifest.permission.RECORD_AUDIO);
1141
1157
  cordova.requestPermission(this, REQUEST_RECORD_AUDIO, Manifest.permission.RECORD_AUDIO);
@@ -1319,11 +1335,10 @@ public class Html2ApkBridge extends CordovaPlugin {
1319
1335
 
1320
1336
  private void setFlashlightWithPermission(boolean enabled, boolean toggle, CallbackContext callbackContext) throws Exception {
1321
1337
  if (!hasCameraPermission()) {
1322
- if (shouldOpenSettingsForRuntimePermission(Manifest.permission.CAMERA)) {
1323
- callbackContext.success(openSettingsForRuntimePermission(Manifest.permission.CAMERA, true, false));
1338
+ if (hasPendingCameraPermissionRequest()) {
1339
+ rejectBusyCallback(callbackContext, "CAMERA permission");
1324
1340
  return;
1325
1341
  }
1326
-
1327
1342
  pendingFlashlightCallback = callbackContext;
1328
1343
  pendingFlashlightEnabled = enabled;
1329
1344
  pendingFlashlightToggle = toggle;
@@ -1422,6 +1437,11 @@ public class Html2ApkBridge extends CordovaPlugin {
1422
1437
  }
1423
1438
 
1424
1439
  private void pickFile(JSONObject options, CallbackContext callbackContext) {
1440
+ if (filePickerCallback != null) {
1441
+ rejectBusyCallback(callbackContext, "File picker");
1442
+ return;
1443
+ }
1444
+
1425
1445
  JSONObject safeOptions = options == null ? new JSONObject() : options;
1426
1446
  String kind = safeOptions.optString("tipo", safeOptions.optString("kind", "file"));
1427
1447
  boolean multiple = safeOptions.optBoolean("multiplo", safeOptions.optBoolean("multiple", false));
@@ -1463,12 +1483,22 @@ public class Html2ApkBridge extends CordovaPlugin {
1463
1483
  }
1464
1484
 
1465
1485
  private void pickFolder(CallbackContext callbackContext) {
1486
+ if (folderPickerCallback != null) {
1487
+ rejectBusyCallback(callbackContext, "Folder picker");
1488
+ return;
1489
+ }
1490
+
1466
1491
  Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
1467
1492
  folderPickerCallback = callbackContext;
1468
1493
  cordova.startActivityForResult(this, intent, REQUEST_PICK_FOLDER);
1469
1494
  }
1470
1495
 
1471
1496
  private void saveFile(JSONObject options, CallbackContext callbackContext) throws Exception {
1497
+ if (saveFileCallback != null) {
1498
+ rejectBusyCallback(callbackContext, "File save dialog");
1499
+ return;
1500
+ }
1501
+
1472
1502
  JSONObject safeOptions = options == null ? new JSONObject() : options;
1473
1503
  String name = safeOptions.optString("nome", safeOptions.optString("name", "arquivo.txt"));
1474
1504
  String mimeType = safeOptions.optString("mimeType", "text/plain");
@@ -2016,6 +2046,167 @@ public class Html2ApkBridge extends CordovaPlugin {
2016
2046
  );
2017
2047
  }
2018
2048
 
2049
+ static PendingIntent createNotificationClickIntent(Context context, int id, JSONObject detail) {
2050
+ if (shouldOpenAppForNotificationClick(detail)) {
2051
+ return createContentIntent(context, id, detail);
2052
+ }
2053
+
2054
+ Intent intent = new Intent(context, NotificationClickReceiver.class);
2055
+ intent.putExtra(EXTRA_NOTIFICATION_CLICKED, true);
2056
+ intent.putExtra(EXTRA_NOTIFICATION_DETAIL, detail == null ? "{}" : detail.toString());
2057
+
2058
+ return PendingIntent.getBroadcast(
2059
+ context,
2060
+ id,
2061
+ intent,
2062
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
2063
+ );
2064
+ }
2065
+
2066
+ static void handleNotificationClickBroadcast(Context context, JSONObject detail) {
2067
+ if (detail == null) {
2068
+ return;
2069
+ }
2070
+
2071
+ if (activeBridge != null && activeBridge.webView != null) {
2072
+ activeBridge.dispatchNotificationClick(detail);
2073
+ return;
2074
+ }
2075
+
2076
+ handleNativeNotificationAction(context, detail);
2077
+ }
2078
+
2079
+ private static void handleNativeNotificationAction(Context context, JSONObject detail) {
2080
+ JSONObject action = notificationClickAction(detail);
2081
+ if (action == null) {
2082
+ return;
2083
+ }
2084
+
2085
+ String functionName = action.optString("funcao",
2086
+ action.optString("functionName",
2087
+ action.optString("function",
2088
+ action.optString("fn", action.optString("nomeFuncao", "")))));
2089
+
2090
+ if (!isExternalUrlFunction(functionName)) {
2091
+ return;
2092
+ }
2093
+
2094
+ String url = firstActionArgument(action);
2095
+ if (url.length() == 0) {
2096
+ url = action.optString("url", action.optString("href", ""));
2097
+ }
2098
+ if (url.length() == 0) {
2099
+ return;
2100
+ }
2101
+
2102
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
2103
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2104
+ try {
2105
+ context.startActivity(intent);
2106
+ } catch (Exception ignored) {
2107
+ }
2108
+ }
2109
+
2110
+ private static boolean isExternalUrlFunction(String functionName) {
2111
+ return "abrirForaDoApp".equals(functionName)
2112
+ || "abrirUrlExterno".equals(functionName)
2113
+ || "abrirUrl".equals(functionName)
2114
+ || "openOutsideApp".equals(functionName)
2115
+ || "openExternalUrl".equals(functionName)
2116
+ || "openUrl".equals(functionName);
2117
+ }
2118
+
2119
+ private static String firstActionArgument(JSONObject action) {
2120
+ JSONArray args = action.optJSONArray("argumentos");
2121
+ if (args == null) {
2122
+ args = action.optJSONArray("args");
2123
+ }
2124
+ if (args == null) {
2125
+ args = action.optJSONArray("parametros");
2126
+ }
2127
+ if (args == null) {
2128
+ args = action.optJSONArray("params");
2129
+ }
2130
+ if (args == null || args.length() == 0) {
2131
+ return "";
2132
+ }
2133
+ return args.optString(0, "");
2134
+ }
2135
+
2136
+ private static JSONObject notificationClickAction(JSONObject detail) {
2137
+ if (detail == null) {
2138
+ return null;
2139
+ }
2140
+
2141
+ JSONObject action = detail.optJSONObject("action");
2142
+ if (action != null) {
2143
+ JSONObject nested = action.optJSONObject("aoClicar");
2144
+ if (nested == null) {
2145
+ nested = action.optJSONObject("onClick");
2146
+ }
2147
+ return nested == null ? action : nested;
2148
+ }
2149
+
2150
+ action = detail.optJSONObject("acao");
2151
+ if (action != null) {
2152
+ JSONObject nested = action.optJSONObject("aoClicar");
2153
+ if (nested == null) {
2154
+ nested = action.optJSONObject("onClick");
2155
+ }
2156
+ return nested == null ? action : nested;
2157
+ }
2158
+
2159
+ action = detail.optJSONObject("aoClicar");
2160
+ if (action == null) {
2161
+ action = detail.optJSONObject("onClick");
2162
+ }
2163
+ return action;
2164
+ }
2165
+
2166
+ private static boolean shouldOpenAppForNotificationClick(JSONObject detail) {
2167
+ Boolean open = openFlag(detail);
2168
+ JSONObject action;
2169
+
2170
+ if (open != null) {
2171
+ return open.booleanValue();
2172
+ }
2173
+
2174
+ action = detail == null ? null : detail.optJSONObject("action");
2175
+ open = openFlag(action);
2176
+ if (open != null) {
2177
+ return open.booleanValue();
2178
+ }
2179
+
2180
+ action = detail == null ? null : detail.optJSONObject("acao");
2181
+ open = openFlag(action);
2182
+ if (open != null) {
2183
+ return open.booleanValue();
2184
+ }
2185
+
2186
+ action = notificationClickAction(detail);
2187
+ open = openFlag(action);
2188
+ return open == null || open.booleanValue();
2189
+ }
2190
+
2191
+ private static Boolean openFlag(JSONObject object) {
2192
+ if (object == null) {
2193
+ return null;
2194
+ }
2195
+ if (object.has("open")) {
2196
+ return Boolean.valueOf(object.optBoolean("open", true));
2197
+ }
2198
+ if (object.has("abrir")) {
2199
+ return Boolean.valueOf(object.optBoolean("abrir", true));
2200
+ }
2201
+ if (object.has("openApp")) {
2202
+ return Boolean.valueOf(object.optBoolean("openApp", true));
2203
+ }
2204
+ if (object.has("abrirApp")) {
2205
+ return Boolean.valueOf(object.optBoolean("abrirApp", true));
2206
+ }
2207
+ return null;
2208
+ }
2209
+
2019
2210
  static boolean canScheduleExactAlarms(Context context) {
2020
2211
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
2021
2212
  return true;
@@ -2219,9 +2410,13 @@ public class Html2ApkBridge extends CordovaPlugin {
2219
2410
  static JSONObject detailPayload(JSONObject options) throws Exception {
2220
2411
  JSONObject detail = new JSONObject();
2221
2412
  JSONObject click = options.optJSONObject("aoClicar");
2413
+ Boolean open = openFlag(options);
2222
2414
  if (click == null) {
2223
2415
  click = options.optJSONObject("onClick");
2224
2416
  }
2417
+ if (open == null) {
2418
+ open = openFlag(click);
2419
+ }
2225
2420
 
2226
2421
  detail.put("id", notificationId(options));
2227
2422
  detail.put("title", title(options));
@@ -2232,6 +2427,10 @@ public class Html2ApkBridge extends CordovaPlugin {
2232
2427
  detail.put("clickedAt", System.currentTimeMillis());
2233
2428
  detail.put("onClick", click == null ? new JSONObject().put("action", "open-app") : click);
2234
2429
  detail.put("aoClicar", click == null ? new JSONObject().put("acao", "abrir-app") : click);
2430
+ if (open != null) {
2431
+ detail.put("open", open.booleanValue());
2432
+ detail.put("abrir", open.booleanValue());
2433
+ }
2235
2434
  return detail;
2236
2435
  }
2237
2436
 
@@ -2259,7 +2458,7 @@ public class Html2ApkBridge extends CordovaPlugin {
2259
2458
  builder.addAction(
2260
2459
  context.getApplicationInfo().icon,
2261
2460
  title,
2262
- createContentIntent(context, notificationId * 100 + index + 1, detail)
2461
+ createNotificationClickIntent(context, notificationId * 100 + index + 1, detail)
2263
2462
  );
2264
2463
  } catch (Exception ignored) {
2265
2464
  }
@@ -0,0 +1,28 @@
1
+ package dev.html2apk.bridge;
2
+
3
+ import android.content.BroadcastReceiver;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+
7
+ import androidx.core.app.NotificationManagerCompat;
8
+
9
+ import org.json.JSONObject;
10
+
11
+ public class NotificationClickReceiver extends BroadcastReceiver {
12
+ @Override
13
+ public void onReceive(Context context, Intent intent) {
14
+ if (intent == null || !intent.getBooleanExtra(Html2ApkBridge.EXTRA_NOTIFICATION_CLICKED, false)) {
15
+ return;
16
+ }
17
+
18
+ JSONObject detail;
19
+ try {
20
+ detail = new JSONObject(intent.getStringExtra(Html2ApkBridge.EXTRA_NOTIFICATION_DETAIL));
21
+ } catch (Exception ignored) {
22
+ detail = new JSONObject();
23
+ }
24
+
25
+ Html2ApkBridge.handleNotificationClickBroadcast(context, detail);
26
+ NotificationManagerCompat.from(context).cancel(detail.optInt("id", 0));
27
+ }
28
+ }
@@ -58,7 +58,7 @@ public class NotificationReceiver extends BroadcastReceiver {
58
58
  .setContentText(text)
59
59
  .setStyle(new NotificationCompat.BigTextStyle().bigText(text))
60
60
  .setAutoCancel(true)
61
- .setContentIntent(Html2ApkBridge.createContentIntent(context, id, detail))
61
+ .setContentIntent(Html2ApkBridge.createNotificationClickIntent(context, id, detail))
62
62
  .setPriority(NotificationCompat.PRIORITY_DEFAULT);
63
63
 
64
64
  Html2ApkBridge.addNotificationActions(builder, context, id, displayOptions);