@capgo/inappbrowser 7.3.0 → 7.4.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/README.md +47 -41
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +149 -41
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +65 -22
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +2 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +660 -102
- package/android/src/main/res/drawable/ic_share.xml +10 -0
- package/android/src/main/res/layout/activity_browser.xml +8 -0
- package/android/src/main/res/layout/tool_bar.xml +19 -7
- package/android/src/main/res/values/strings.xml +2 -0
- package/dist/docs.json +169 -35
- package/dist/esm/definitions.d.ts +222 -29
- package/dist/esm/definitions.js +12 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/plugin.cjs.js +12 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +12 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/InAppBrowserPlugin.swift +339 -44
- package/ios/Plugin/WKWebViewController.swift +478 -45
- package/package.json +1 -1
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back@2x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back@3x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Contents.json +0 -26
- package/ios/Plugin/Assets.xcassets/Contents.json +0 -6
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Contents.json +0 -26
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward.png +0 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward@2x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward@3x.png +0 -0
|
@@ -9,15 +9,21 @@ import android.content.Context;
|
|
|
9
9
|
import android.content.DialogInterface;
|
|
10
10
|
import android.content.Intent;
|
|
11
11
|
import android.content.res.AssetManager;
|
|
12
|
+
import android.content.res.Resources;
|
|
12
13
|
import android.graphics.Bitmap;
|
|
14
|
+
import android.graphics.Canvas;
|
|
13
15
|
import android.graphics.Color;
|
|
16
|
+
import android.graphics.Paint;
|
|
14
17
|
import android.graphics.Picture;
|
|
18
|
+
import android.graphics.PorterDuff;
|
|
19
|
+
import android.graphics.PorterDuffColorFilter;
|
|
15
20
|
import android.graphics.drawable.PictureDrawable;
|
|
16
21
|
import android.net.Uri;
|
|
17
22
|
import android.net.http.SslError;
|
|
18
23
|
import android.text.TextUtils;
|
|
19
24
|
import android.util.Base64;
|
|
20
25
|
import android.util.Log;
|
|
26
|
+
import android.util.TypedValue;
|
|
21
27
|
import android.view.View;
|
|
22
28
|
import android.view.Window;
|
|
23
29
|
import android.view.WindowManager;
|
|
@@ -33,6 +39,7 @@ import android.webkit.WebResourceResponse;
|
|
|
33
39
|
import android.webkit.WebView;
|
|
34
40
|
import android.webkit.WebViewClient;
|
|
35
41
|
import android.widget.ImageButton;
|
|
42
|
+
import android.widget.ImageView;
|
|
36
43
|
import android.widget.TextView;
|
|
37
44
|
import android.widget.Toast;
|
|
38
45
|
import android.widget.Toolbar;
|
|
@@ -89,6 +96,7 @@ public class WebViewDialog extends Dialog {
|
|
|
89
96
|
new HashMap<>();
|
|
90
97
|
private final ExecutorService executorService =
|
|
91
98
|
Executors.newCachedThreadPool();
|
|
99
|
+
private int iconColor = Color.BLACK; // Default icon color
|
|
92
100
|
|
|
93
101
|
Semaphore preShowSemaphore = null;
|
|
94
102
|
String preShowError = null;
|
|
@@ -145,13 +153,10 @@ public class WebViewDialog extends Dialog {
|
|
|
145
153
|
if (activity != null) {
|
|
146
154
|
activity.runOnUiThread(() -> {
|
|
147
155
|
try {
|
|
156
|
+
String currentUrl = _webView != null ? _webView.getUrl() : "";
|
|
148
157
|
dismiss();
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
if (_options != null && _options.getCallbacks() != null) {
|
|
152
|
-
_options.getCallbacks().closeEvent(currentUrl);
|
|
153
|
-
}
|
|
154
|
-
_webView.destroy();
|
|
158
|
+
if (_options != null && _options.getCallbacks() != null) {
|
|
159
|
+
_options.getCallbacks().closeEvent(currentUrl);
|
|
155
160
|
}
|
|
156
161
|
} catch (Exception e) {
|
|
157
162
|
Log.e("InAppBrowser", "Error closing WebView: " + e.getMessage());
|
|
@@ -203,14 +208,78 @@ public class WebViewDialog extends Dialog {
|
|
|
203
208
|
setContentView(R.layout.activity_browser);
|
|
204
209
|
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
205
210
|
|
|
211
|
+
// Make status bar transparent
|
|
212
|
+
if (getWindow() != null) {
|
|
213
|
+
getWindow().setStatusBarColor(Color.TRANSPARENT);
|
|
214
|
+
|
|
215
|
+
// Add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
|
|
216
|
+
getWindow()
|
|
217
|
+
.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
|
218
|
+
|
|
219
|
+
// On Android 30+ clear FLAG_TRANSLUCENT_STATUS flag
|
|
220
|
+
getWindow()
|
|
221
|
+
.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
|
222
|
+
}
|
|
223
|
+
|
|
206
224
|
WindowInsetsControllerCompat insetsController =
|
|
207
|
-
new WindowInsetsControllerCompat(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
225
|
+
new WindowInsetsControllerCompat(
|
|
226
|
+
getWindow(),
|
|
227
|
+
getWindow() != null ? getWindow().getDecorView() : null
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
if (getWindow() != null) {
|
|
231
|
+
getWindow()
|
|
232
|
+
.getDecorView()
|
|
233
|
+
.post(() -> {
|
|
234
|
+
// Get status bar height
|
|
235
|
+
int statusBarHeight = 0;
|
|
236
|
+
int resourceId = getContext()
|
|
237
|
+
.getResources()
|
|
238
|
+
.getIdentifier("status_bar_height", "dimen", "android");
|
|
239
|
+
if (resourceId > 0) {
|
|
240
|
+
statusBarHeight = getContext()
|
|
241
|
+
.getResources()
|
|
242
|
+
.getDimensionPixelSize(resourceId);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Find the status bar color view
|
|
246
|
+
View statusBarColorView = findViewById(R.id.status_bar_color_view);
|
|
247
|
+
|
|
248
|
+
// Set the height of the status bar color view
|
|
249
|
+
if (statusBarColorView != null) {
|
|
250
|
+
statusBarColorView.getLayoutParams().height = statusBarHeight;
|
|
251
|
+
statusBarColorView.requestLayout();
|
|
252
|
+
|
|
253
|
+
// Set color based on toolbar color or dark mode
|
|
254
|
+
if (
|
|
255
|
+
_options.getToolbarColor() != null &&
|
|
256
|
+
!_options.getToolbarColor().isEmpty()
|
|
257
|
+
) {
|
|
258
|
+
try {
|
|
259
|
+
// Use explicitly provided toolbar color for status bar
|
|
260
|
+
int toolbarColor = Color.parseColor(_options.getToolbarColor());
|
|
261
|
+
statusBarColorView.setBackgroundColor(toolbarColor);
|
|
262
|
+
|
|
263
|
+
// Set status bar text to white or black based on background
|
|
264
|
+
boolean isDarkBackground = isDarkColor(toolbarColor);
|
|
265
|
+
insetsController.setAppearanceLightStatusBars(
|
|
266
|
+
!isDarkBackground
|
|
267
|
+
);
|
|
268
|
+
} catch (IllegalArgumentException e) {
|
|
269
|
+
// Fallback to default black if color parsing fails
|
|
270
|
+
statusBarColorView.setBackgroundColor(Color.BLACK);
|
|
271
|
+
insetsController.setAppearanceLightStatusBars(false);
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
// Follow system dark mode if no toolbar color provided
|
|
275
|
+
boolean isDarkTheme = isDarkThemeEnabled();
|
|
276
|
+
int statusBarColor = isDarkTheme ? Color.BLACK : Color.WHITE;
|
|
277
|
+
statusBarColorView.setBackgroundColor(statusBarColor);
|
|
278
|
+
insetsController.setAppearanceLightStatusBars(!isDarkTheme);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
214
283
|
|
|
215
284
|
getWindow()
|
|
216
285
|
.setLayout(
|
|
@@ -249,9 +318,25 @@ public class WebViewDialog extends Dialog {
|
|
|
249
318
|
ValueCallback<Uri[]> filePathCallback,
|
|
250
319
|
FileChooserParams fileChooserParams
|
|
251
320
|
) {
|
|
321
|
+
// Get the accept type safely
|
|
322
|
+
String acceptType = "*/*"; // Default to all file types
|
|
323
|
+
if (
|
|
324
|
+
fileChooserParams.getAcceptTypes() != null &&
|
|
325
|
+
fileChooserParams.getAcceptTypes().length > 0 &&
|
|
326
|
+
!TextUtils.isEmpty(fileChooserParams.getAcceptTypes()[0])
|
|
327
|
+
) {
|
|
328
|
+
acceptType = fileChooserParams.getAcceptTypes()[0];
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Check if the file chooser is already open
|
|
332
|
+
if (mFilePathCallback != null) {
|
|
333
|
+
mFilePathCallback.onReceiveValue(null);
|
|
334
|
+
mFilePathCallback = null;
|
|
335
|
+
}
|
|
336
|
+
|
|
252
337
|
openFileChooser(
|
|
253
338
|
filePathCallback,
|
|
254
|
-
|
|
339
|
+
acceptType,
|
|
255
340
|
fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE
|
|
256
341
|
);
|
|
257
342
|
return true;
|
|
@@ -436,16 +521,100 @@ public class WebViewDialog extends Dialog {
|
|
|
436
521
|
mFilePathCallback = filePathCallback;
|
|
437
522
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
|
438
523
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
439
|
-
|
|
524
|
+
|
|
525
|
+
// Fix MIME type handling
|
|
526
|
+
if (
|
|
527
|
+
acceptType == null ||
|
|
528
|
+
acceptType.isEmpty() ||
|
|
529
|
+
acceptType.equals("undefined")
|
|
530
|
+
) {
|
|
531
|
+
acceptType = "*/*";
|
|
532
|
+
} else {
|
|
533
|
+
// Handle common web input accept types
|
|
534
|
+
if (acceptType.equals("image/*")) {
|
|
535
|
+
// Keep as is - image/*
|
|
536
|
+
} else if (acceptType.contains("image/")) {
|
|
537
|
+
// Specific image type requested but keep it general for better compatibility
|
|
538
|
+
acceptType = "image/*";
|
|
539
|
+
} else if (
|
|
540
|
+
acceptType.equals("audio/*") || acceptType.contains("audio/")
|
|
541
|
+
) {
|
|
542
|
+
acceptType = "audio/*";
|
|
543
|
+
} else if (
|
|
544
|
+
acceptType.equals("video/*") || acceptType.contains("video/")
|
|
545
|
+
) {
|
|
546
|
+
acceptType = "video/*";
|
|
547
|
+
} else if (acceptType.startsWith(".") || acceptType.contains(",")) {
|
|
548
|
+
// Handle file extensions like ".pdf, .docx" by using a general mime type
|
|
549
|
+
if (acceptType.contains(".pdf")) {
|
|
550
|
+
acceptType = "application/pdf";
|
|
551
|
+
} else if (
|
|
552
|
+
acceptType.contains(".doc") || acceptType.contains(".docx")
|
|
553
|
+
) {
|
|
554
|
+
acceptType = "application/msword";
|
|
555
|
+
} else if (
|
|
556
|
+
acceptType.contains(".xls") || acceptType.contains(".xlsx")
|
|
557
|
+
) {
|
|
558
|
+
acceptType = "application/vnd.ms-excel";
|
|
559
|
+
} else if (
|
|
560
|
+
acceptType.contains(".txt") || acceptType.contains(".text")
|
|
561
|
+
) {
|
|
562
|
+
acceptType = "text/plain";
|
|
563
|
+
} else {
|
|
564
|
+
// Default for extension lists
|
|
565
|
+
acceptType = "*/*";
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
Log.d("InAppBrowser", "File picker using MIME type: " + acceptType);
|
|
571
|
+
intent.setType(acceptType);
|
|
440
572
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, isMultiple);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
573
|
+
|
|
574
|
+
try {
|
|
575
|
+
activity.startActivityForResult(
|
|
576
|
+
Intent.createChooser(intent, "Select File"),
|
|
577
|
+
FILE_CHOOSER_REQUEST_CODE
|
|
578
|
+
);
|
|
579
|
+
} catch (ActivityNotFoundException e) {
|
|
580
|
+
// If no app can handle the specific MIME type, try with a more generic one
|
|
581
|
+
Log.e(
|
|
582
|
+
"InAppBrowser",
|
|
583
|
+
"No app available for type: " + acceptType + ", trying with */*"
|
|
584
|
+
);
|
|
585
|
+
intent.setType("*/*");
|
|
586
|
+
try {
|
|
587
|
+
activity.startActivityForResult(
|
|
588
|
+
Intent.createChooser(intent, "Select File"),
|
|
589
|
+
FILE_CHOOSER_REQUEST_CODE
|
|
590
|
+
);
|
|
591
|
+
} catch (ActivityNotFoundException ex) {
|
|
592
|
+
// If still failing, report error
|
|
593
|
+
Log.e("InAppBrowser", "No app can handle file picker", ex);
|
|
594
|
+
if (mFilePathCallback != null) {
|
|
595
|
+
mFilePathCallback.onReceiveValue(null);
|
|
596
|
+
mFilePathCallback = null;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
445
600
|
}
|
|
446
601
|
|
|
447
602
|
public void reload() {
|
|
448
|
-
_webView
|
|
603
|
+
if (_webView != null) {
|
|
604
|
+
// First stop any ongoing loading
|
|
605
|
+
_webView.stopLoading();
|
|
606
|
+
|
|
607
|
+
// Check if there's a URL to reload
|
|
608
|
+
if (_webView.getUrl() != null) {
|
|
609
|
+
// Reload the current page
|
|
610
|
+
_webView.reload();
|
|
611
|
+
Log.d("InAppBrowser", "Reloading page: " + _webView.getUrl());
|
|
612
|
+
} else if (_options != null && _options.getUrl() != null) {
|
|
613
|
+
// If webView URL is null but we have an initial URL, load that
|
|
614
|
+
setUrl(_options.getUrl());
|
|
615
|
+
Log.d("InAppBrowser", "Loading initial URL: " + _options.getUrl());
|
|
616
|
+
}
|
|
617
|
+
}
|
|
449
618
|
}
|
|
450
619
|
|
|
451
620
|
public void destroy() {
|
|
@@ -488,56 +657,72 @@ public class WebViewDialog extends Dialog {
|
|
|
488
657
|
}
|
|
489
658
|
|
|
490
659
|
private void setupToolbar() {
|
|
491
|
-
_toolbar =
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
_toolbar.setBackgroundColor(color);
|
|
499
|
-
_toolbar.findViewById(R.id.backButton).setBackgroundColor(color);
|
|
500
|
-
_toolbar.findViewById(R.id.forwardButton).setBackgroundColor(color);
|
|
501
|
-
_toolbar.findViewById(R.id.closeButton).setBackgroundColor(color);
|
|
502
|
-
_toolbar.findViewById(R.id.reloadButton).setBackgroundColor(color);
|
|
503
|
-
|
|
504
|
-
if (!TextUtils.isEmpty(_options.getTitle())) {
|
|
505
|
-
this.setTitle(_options.getTitle());
|
|
506
|
-
} else {
|
|
660
|
+
_toolbar = findViewById(R.id.tool_bar);
|
|
661
|
+
|
|
662
|
+
// Apply toolbar color early, for ALL toolbar types, before any view configuration
|
|
663
|
+
if (
|
|
664
|
+
_options.getToolbarColor() != null &&
|
|
665
|
+
!_options.getToolbarColor().isEmpty()
|
|
666
|
+
) {
|
|
507
667
|
try {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
} catch (URISyntaxException e) {
|
|
511
|
-
this.setTitle(_options.getTitle());
|
|
512
|
-
}
|
|
513
|
-
}
|
|
668
|
+
int toolbarColor = Color.parseColor(_options.getToolbarColor());
|
|
669
|
+
_toolbar.setBackgroundColor(toolbarColor);
|
|
514
670
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
671
|
+
// Get toolbar title and ensure it gets the right color
|
|
672
|
+
TextView titleText = _toolbar.findViewById(R.id.titleText);
|
|
673
|
+
|
|
674
|
+
// Determine icon and text color
|
|
675
|
+
int iconColor;
|
|
676
|
+
if (
|
|
677
|
+
_options.getToolbarTextColor() != null &&
|
|
678
|
+
!_options.getToolbarTextColor().isEmpty()
|
|
679
|
+
) {
|
|
680
|
+
try {
|
|
681
|
+
iconColor = Color.parseColor(_options.getToolbarTextColor());
|
|
682
|
+
} catch (IllegalArgumentException e) {
|
|
683
|
+
// Fallback to automatic detection if parsing fails
|
|
684
|
+
boolean isDarkBackground = isDarkColor(toolbarColor);
|
|
685
|
+
iconColor = isDarkBackground ? Color.WHITE : Color.BLACK;
|
|
522
686
|
}
|
|
687
|
+
} else {
|
|
688
|
+
// No explicit toolbarTextColor, use automatic detection based on background
|
|
689
|
+
boolean isDarkBackground = isDarkColor(toolbarColor);
|
|
690
|
+
iconColor = isDarkBackground ? Color.WHITE : Color.BLACK;
|
|
523
691
|
}
|
|
524
|
-
}
|
|
525
|
-
);
|
|
526
692
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
693
|
+
// Store for later use with navigation buttons
|
|
694
|
+
this.iconColor = iconColor;
|
|
695
|
+
|
|
696
|
+
// Set title text color directly
|
|
697
|
+
titleText.setTextColor(iconColor);
|
|
698
|
+
|
|
699
|
+
// Apply colors to all buttons
|
|
700
|
+
applyColorToAllButtons(toolbarColor, iconColor);
|
|
701
|
+
|
|
702
|
+
// Also ensure status bar gets the color
|
|
703
|
+
if (getWindow() != null) {
|
|
704
|
+
// Set status bar color
|
|
705
|
+
getWindow().setStatusBarColor(toolbarColor);
|
|
706
|
+
|
|
707
|
+
// Determine proper status bar text color (light or dark icons)
|
|
708
|
+
boolean isDarkBackground = isDarkColor(toolbarColor);
|
|
709
|
+
WindowInsetsControllerCompat insetsController =
|
|
710
|
+
new WindowInsetsControllerCompat(
|
|
711
|
+
getWindow(),
|
|
712
|
+
getWindow().getDecorView()
|
|
713
|
+
);
|
|
714
|
+
insetsController.setAppearanceLightStatusBars(!isDarkBackground);
|
|
535
715
|
}
|
|
716
|
+
} catch (IllegalArgumentException e) {
|
|
717
|
+
Log.e(
|
|
718
|
+
"InAppBrowser",
|
|
719
|
+
"Invalid toolbar color: " + _options.getToolbarColor()
|
|
720
|
+
);
|
|
536
721
|
}
|
|
537
|
-
|
|
722
|
+
}
|
|
538
723
|
|
|
539
|
-
ImageButton
|
|
540
|
-
|
|
724
|
+
ImageButton closeButtonView = _toolbar.findViewById(R.id.closeButton);
|
|
725
|
+
closeButtonView.setOnClickListener(
|
|
541
726
|
new View.OnClickListener() {
|
|
542
727
|
@Override
|
|
543
728
|
public void onClick(View view) {
|
|
@@ -551,96 +736,316 @@ public class WebViewDialog extends Dialog {
|
|
|
551
736
|
new OnClickListener() {
|
|
552
737
|
public void onClick(DialogInterface dialog, int which) {
|
|
553
738
|
// Close button clicked, do something
|
|
739
|
+
String currentUrl = _webView != null
|
|
740
|
+
? _webView.getUrl()
|
|
741
|
+
: "";
|
|
554
742
|
dismiss();
|
|
555
|
-
_options.getCallbacks()
|
|
556
|
-
|
|
743
|
+
if (_options != null && _options.getCallbacks() != null) {
|
|
744
|
+
_options.getCallbacks().closeEvent(currentUrl);
|
|
745
|
+
}
|
|
557
746
|
}
|
|
558
747
|
}
|
|
559
748
|
)
|
|
560
749
|
.setNegativeButton(_options.getCloseModalCancel(), null)
|
|
561
750
|
.show();
|
|
562
751
|
} else {
|
|
752
|
+
String currentUrl = _webView != null ? _webView.getUrl() : "";
|
|
563
753
|
dismiss();
|
|
564
|
-
_options.getCallbacks()
|
|
565
|
-
|
|
754
|
+
if (_options != null && _options.getCallbacks() != null) {
|
|
755
|
+
_options.getCallbacks().closeEvent(currentUrl);
|
|
756
|
+
}
|
|
566
757
|
}
|
|
567
758
|
}
|
|
568
759
|
}
|
|
569
760
|
);
|
|
570
761
|
|
|
571
762
|
if (_options.showArrow()) {
|
|
572
|
-
|
|
763
|
+
closeButtonView.setImageResource(R.drawable.arrow_back_enabled);
|
|
573
764
|
}
|
|
574
765
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
766
|
+
// Handle reload button visibility
|
|
767
|
+
if (
|
|
768
|
+
_options.getShowReloadButton() &&
|
|
769
|
+
!TextUtils.equals(_options.getToolbarType(), "activity")
|
|
770
|
+
) {
|
|
771
|
+
View reloadButtonView = _toolbar.findViewById(R.id.reloadButton);
|
|
772
|
+
reloadButtonView.setVisibility(View.VISIBLE);
|
|
773
|
+
reloadButtonView.setOnClickListener(
|
|
579
774
|
new View.OnClickListener() {
|
|
580
775
|
@Override
|
|
581
776
|
public void onClick(View view) {
|
|
582
|
-
_webView
|
|
777
|
+
if (_webView != null) {
|
|
778
|
+
// First stop any ongoing loading
|
|
779
|
+
_webView.stopLoading();
|
|
780
|
+
|
|
781
|
+
// Check if there's a URL to reload
|
|
782
|
+
if (_webView.getUrl() != null) {
|
|
783
|
+
// Reload the current page
|
|
784
|
+
_webView.reload();
|
|
785
|
+
Log.d("InAppBrowser", "Reloading page: " + _webView.getUrl());
|
|
786
|
+
} else if (_options.getUrl() != null) {
|
|
787
|
+
// If webView URL is null but we have an initial URL, load that
|
|
788
|
+
setUrl(_options.getUrl());
|
|
789
|
+
Log.d(
|
|
790
|
+
"InAppBrowser",
|
|
791
|
+
"Loading initial URL: " + _options.getUrl()
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
583
795
|
}
|
|
584
796
|
}
|
|
585
797
|
);
|
|
798
|
+
} else {
|
|
799
|
+
View reloadButtonView = _toolbar.findViewById(R.id.reloadButton);
|
|
800
|
+
reloadButtonView.setVisibility(View.GONE);
|
|
586
801
|
}
|
|
587
802
|
|
|
588
803
|
if (TextUtils.equals(_options.getToolbarType(), "activity")) {
|
|
804
|
+
// Activity mode should ONLY have:
|
|
805
|
+
// 1. Close button
|
|
806
|
+
// 2. Share button (if shareSubject is provided)
|
|
807
|
+
|
|
808
|
+
// Hide all navigation buttons
|
|
589
809
|
_toolbar.findViewById(R.id.forwardButton).setVisibility(View.GONE);
|
|
590
810
|
_toolbar.findViewById(R.id.backButton).setVisibility(View.GONE);
|
|
811
|
+
|
|
812
|
+
// Hide buttonNearDone
|
|
591
813
|
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
592
814
|
R.id.buttonNearDone
|
|
593
815
|
);
|
|
594
816
|
buttonNearDoneView.setVisibility(View.GONE);
|
|
595
|
-
|
|
817
|
+
|
|
818
|
+
// In activity mode, always make the share button visible by setting a default shareSubject if not provided
|
|
819
|
+
if (
|
|
820
|
+
_options.getShareSubject() == null ||
|
|
821
|
+
_options.getShareSubject().isEmpty()
|
|
822
|
+
) {
|
|
823
|
+
_options.setShareSubject("Share");
|
|
824
|
+
Log.d("InAppBrowser", "Activity mode: Setting default shareSubject");
|
|
825
|
+
}
|
|
826
|
+
// Status bar color is already set at the top of this method, no need to set again
|
|
827
|
+
|
|
828
|
+
// Share button visibility is handled separately later
|
|
596
829
|
} else if (TextUtils.equals(_options.getToolbarType(), "navigation")) {
|
|
597
830
|
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
598
831
|
R.id.buttonNearDone
|
|
599
832
|
);
|
|
600
833
|
buttonNearDoneView.setVisibility(View.GONE);
|
|
601
|
-
//
|
|
834
|
+
// Status bar color is already set at the top of this method, no need to set again
|
|
602
835
|
} else if (TextUtils.equals(_options.getToolbarType(), "blank")) {
|
|
603
836
|
_toolbar.setVisibility(View.GONE);
|
|
837
|
+
|
|
838
|
+
// Also set window background color to match status bar for blank toolbar
|
|
839
|
+
View statusBarColorView = findViewById(R.id.status_bar_color_view);
|
|
840
|
+
if (
|
|
841
|
+
_options.getToolbarColor() != null &&
|
|
842
|
+
!_options.getToolbarColor().isEmpty()
|
|
843
|
+
) {
|
|
844
|
+
try {
|
|
845
|
+
int toolbarColor = Color.parseColor(_options.getToolbarColor());
|
|
846
|
+
if (getWindow() != null) {
|
|
847
|
+
getWindow().getDecorView().setBackgroundColor(toolbarColor);
|
|
848
|
+
}
|
|
849
|
+
// Also set status bar color view background if available
|
|
850
|
+
if (statusBarColorView != null) {
|
|
851
|
+
statusBarColorView.setBackgroundColor(toolbarColor);
|
|
852
|
+
}
|
|
853
|
+
} catch (IllegalArgumentException e) {
|
|
854
|
+
// Fallback to system default if color parsing fails
|
|
855
|
+
boolean isDarkTheme = isDarkThemeEnabled();
|
|
856
|
+
int windowBackgroundColor = isDarkTheme ? Color.BLACK : Color.WHITE;
|
|
857
|
+
if (getWindow() != null) {
|
|
858
|
+
getWindow()
|
|
859
|
+
.getDecorView()
|
|
860
|
+
.setBackgroundColor(windowBackgroundColor);
|
|
861
|
+
}
|
|
862
|
+
// Also set status bar color view background if available
|
|
863
|
+
if (statusBarColorView != null) {
|
|
864
|
+
statusBarColorView.setBackgroundColor(windowBackgroundColor);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
} else {
|
|
868
|
+
// Follow system dark mode
|
|
869
|
+
boolean isDarkTheme = isDarkThemeEnabled();
|
|
870
|
+
int windowBackgroundColor = isDarkTheme ? Color.BLACK : Color.WHITE;
|
|
871
|
+
if (getWindow() != null) {
|
|
872
|
+
getWindow().getDecorView().setBackgroundColor(windowBackgroundColor);
|
|
873
|
+
}
|
|
874
|
+
// Also set status bar color view background if available
|
|
875
|
+
if (statusBarColorView != null) {
|
|
876
|
+
statusBarColorView.setBackgroundColor(windowBackgroundColor);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
604
879
|
} else {
|
|
605
880
|
_toolbar.findViewById(R.id.forwardButton).setVisibility(View.GONE);
|
|
606
881
|
_toolbar.findViewById(R.id.backButton).setVisibility(View.GONE);
|
|
607
882
|
|
|
883
|
+
// Status bar color is already set at the top of this method, no need to set again
|
|
884
|
+
|
|
608
885
|
Options.ButtonNearDone buttonNearDone = _options.getButtonNearDone();
|
|
609
886
|
if (buttonNearDone != null) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
try {
|
|
615
|
-
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
616
|
-
R.id.buttonNearDone
|
|
617
|
-
);
|
|
618
|
-
buttonNearDoneView.setVisibility(View.VISIBLE);
|
|
619
|
-
|
|
620
|
-
inputStream = assetManager.open(buttonNearDone.getIcon());
|
|
887
|
+
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
888
|
+
R.id.buttonNearDone
|
|
889
|
+
);
|
|
890
|
+
buttonNearDoneView.setVisibility(View.VISIBLE);
|
|
621
891
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
892
|
+
// Handle different icon types
|
|
893
|
+
String iconType = buttonNearDone.getIconType();
|
|
894
|
+
if ("vector".equals(iconType)) {
|
|
895
|
+
// Use native Android vector drawable
|
|
896
|
+
try {
|
|
897
|
+
String iconName = buttonNearDone.getIcon();
|
|
898
|
+
// Convert name to Android resource ID (remove file extension if present)
|
|
899
|
+
if (iconName.endsWith(".xml")) {
|
|
900
|
+
iconName = iconName.substring(0, iconName.length() - 4);
|
|
901
|
+
}
|
|
628
902
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
903
|
+
// Get resource ID
|
|
904
|
+
int resourceId = _context
|
|
905
|
+
.getResources()
|
|
906
|
+
.getIdentifier(iconName, "drawable", _context.getPackageName());
|
|
907
|
+
|
|
908
|
+
if (resourceId != 0) {
|
|
909
|
+
// Set the vector drawable
|
|
910
|
+
buttonNearDoneView.setImageResource(resourceId);
|
|
911
|
+
// Apply color filter
|
|
912
|
+
buttonNearDoneView.setColorFilter(iconColor);
|
|
913
|
+
Log.d(
|
|
914
|
+
"InAppBrowser",
|
|
915
|
+
"Successfully loaded vector drawable: " + iconName
|
|
916
|
+
);
|
|
917
|
+
} else {
|
|
918
|
+
Log.e(
|
|
919
|
+
"InAppBrowser",
|
|
920
|
+
"Vector drawable not found: " + iconName + ", using fallback"
|
|
921
|
+
);
|
|
922
|
+
// Fallback to a common system icon
|
|
923
|
+
buttonNearDoneView.setImageResource(
|
|
924
|
+
android.R.drawable.ic_menu_info_details
|
|
925
|
+
);
|
|
926
|
+
buttonNearDoneView.setColorFilter(iconColor);
|
|
927
|
+
}
|
|
928
|
+
} catch (Exception e) {
|
|
929
|
+
Log.e(
|
|
930
|
+
"InAppBrowser",
|
|
931
|
+
"Error loading vector drawable: " + e.getMessage()
|
|
932
|
+
);
|
|
933
|
+
// Fallback to a common system icon
|
|
934
|
+
buttonNearDoneView.setImageResource(
|
|
935
|
+
android.R.drawable.ic_menu_info_details
|
|
936
|
+
);
|
|
937
|
+
buttonNearDoneView.setColorFilter(iconColor);
|
|
938
|
+
}
|
|
939
|
+
} else if ("asset".equals(iconType)) {
|
|
940
|
+
// Handle SVG from assets
|
|
941
|
+
AssetManager assetManager = _context.getAssets();
|
|
942
|
+
InputStream inputStream = null;
|
|
943
|
+
try {
|
|
944
|
+
// Try to load from public folder first
|
|
945
|
+
String iconPath = "public/" + buttonNearDone.getIcon();
|
|
637
946
|
try {
|
|
638
|
-
inputStream.
|
|
947
|
+
inputStream = assetManager.open(iconPath);
|
|
639
948
|
} catch (IOException e) {
|
|
640
|
-
|
|
949
|
+
// If not found in public, try root assets
|
|
950
|
+
try {
|
|
951
|
+
inputStream = assetManager.open(buttonNearDone.getIcon());
|
|
952
|
+
} catch (IOException e2) {
|
|
953
|
+
Log.e(
|
|
954
|
+
"InAppBrowser",
|
|
955
|
+
"SVG file not found in assets: " + buttonNearDone.getIcon()
|
|
956
|
+
);
|
|
957
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
if (inputStream == null) {
|
|
963
|
+
Log.e(
|
|
964
|
+
"InAppBrowser",
|
|
965
|
+
"Failed to load SVG icon: " + buttonNearDone.getIcon()
|
|
966
|
+
);
|
|
967
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// Parse and render SVG
|
|
972
|
+
SVG svg = SVG.getFromInputStream(inputStream);
|
|
973
|
+
if (svg == null) {
|
|
974
|
+
Log.e(
|
|
975
|
+
"InAppBrowser",
|
|
976
|
+
"Failed to parse SVG icon: " + buttonNearDone.getIcon()
|
|
977
|
+
);
|
|
978
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// Get the dimensions from options or use SVG's size
|
|
983
|
+
float width = buttonNearDone.getWidth() > 0
|
|
984
|
+
? buttonNearDone.getWidth()
|
|
985
|
+
: 24;
|
|
986
|
+
float height = buttonNearDone.getHeight() > 0
|
|
987
|
+
? buttonNearDone.getHeight()
|
|
988
|
+
: 24;
|
|
989
|
+
|
|
990
|
+
// Get density for proper scaling
|
|
991
|
+
float density = _context.getResources().getDisplayMetrics().density;
|
|
992
|
+
int targetWidth = Math.round(width * density);
|
|
993
|
+
int targetHeight = Math.round(height * density);
|
|
994
|
+
|
|
995
|
+
// Set document size
|
|
996
|
+
svg.setDocumentWidth(targetWidth);
|
|
997
|
+
svg.setDocumentHeight(targetHeight);
|
|
998
|
+
|
|
999
|
+
// Create a bitmap and render SVG to it for better quality
|
|
1000
|
+
Bitmap bitmap = Bitmap.createBitmap(
|
|
1001
|
+
targetWidth,
|
|
1002
|
+
targetHeight,
|
|
1003
|
+
Bitmap.Config.ARGB_8888
|
|
1004
|
+
);
|
|
1005
|
+
Canvas canvas = new Canvas(bitmap);
|
|
1006
|
+
svg.renderToCanvas(canvas);
|
|
1007
|
+
|
|
1008
|
+
// Apply color filter to the bitmap
|
|
1009
|
+
Paint paint = new Paint();
|
|
1010
|
+
paint.setColorFilter(
|
|
1011
|
+
new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
|
|
1012
|
+
);
|
|
1013
|
+
Canvas colorFilterCanvas = new Canvas(bitmap);
|
|
1014
|
+
colorFilterCanvas.drawBitmap(bitmap, 0, 0, paint);
|
|
1015
|
+
|
|
1016
|
+
// Set the colored bitmap as image
|
|
1017
|
+
buttonNearDoneView.setImageBitmap(bitmap);
|
|
1018
|
+
buttonNearDoneView.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
|
1019
|
+
buttonNearDoneView.setPadding(12, 12, 12, 12); // Standard button padding
|
|
1020
|
+
} catch (SVGParseException e) {
|
|
1021
|
+
Log.e(
|
|
1022
|
+
"InAppBrowser",
|
|
1023
|
+
"Error loading SVG icon: " + e.getMessage(),
|
|
1024
|
+
e
|
|
1025
|
+
);
|
|
1026
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
1027
|
+
} finally {
|
|
1028
|
+
if (inputStream != null) {
|
|
1029
|
+
try {
|
|
1030
|
+
inputStream.close();
|
|
1031
|
+
} catch (IOException e) {
|
|
1032
|
+
Log.e(
|
|
1033
|
+
"InAppBrowser",
|
|
1034
|
+
"Error closing input stream: " + e.getMessage()
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
641
1037
|
}
|
|
642
1038
|
}
|
|
1039
|
+
} else {
|
|
1040
|
+
// Default fallback or unsupported type
|
|
1041
|
+
Log.e("InAppBrowser", "Unsupported icon type: " + iconType);
|
|
1042
|
+
buttonNearDoneView.setVisibility(View.GONE);
|
|
643
1043
|
}
|
|
1044
|
+
|
|
1045
|
+
// Set the click listener
|
|
1046
|
+
buttonNearDoneView.setOnClickListener(view ->
|
|
1047
|
+
_options.getCallbacks().buttonNearDoneClicked()
|
|
1048
|
+
);
|
|
644
1049
|
} else {
|
|
645
1050
|
ImageButton buttonNearDoneView = _toolbar.findViewById(
|
|
646
1051
|
R.id.buttonNearDone
|
|
@@ -648,6 +1053,94 @@ public class WebViewDialog extends Dialog {
|
|
|
648
1053
|
buttonNearDoneView.setVisibility(View.GONE);
|
|
649
1054
|
}
|
|
650
1055
|
}
|
|
1056
|
+
|
|
1057
|
+
// Add share button functionality
|
|
1058
|
+
ImageButton shareButton = _toolbar.findViewById(R.id.shareButton);
|
|
1059
|
+
if (
|
|
1060
|
+
_options.getShareSubject() != null &&
|
|
1061
|
+
!_options.getShareSubject().isEmpty()
|
|
1062
|
+
) {
|
|
1063
|
+
shareButton.setVisibility(View.VISIBLE);
|
|
1064
|
+
Log.d(
|
|
1065
|
+
"InAppBrowser",
|
|
1066
|
+
"Share button should be visible, shareSubject: " +
|
|
1067
|
+
_options.getShareSubject()
|
|
1068
|
+
);
|
|
1069
|
+
|
|
1070
|
+
// Apply the same color filter as other buttons to ensure visibility
|
|
1071
|
+
shareButton.setColorFilter(iconColor);
|
|
1072
|
+
|
|
1073
|
+
// The color filter is now applied in applyColorToAllButtons
|
|
1074
|
+
shareButton.setOnClickListener(view -> {
|
|
1075
|
+
JSObject shareDisclaimer = _options.getShareDisclaimer();
|
|
1076
|
+
if (shareDisclaimer != null) {
|
|
1077
|
+
new AlertDialog.Builder(_context)
|
|
1078
|
+
.setTitle(shareDisclaimer.getString("title", "Title"))
|
|
1079
|
+
.setMessage(shareDisclaimer.getString("message", "Message"))
|
|
1080
|
+
.setPositiveButton(
|
|
1081
|
+
shareDisclaimer.getString("confirmBtn", "Confirm"),
|
|
1082
|
+
(dialog, which) -> {
|
|
1083
|
+
_options.getCallbacks().confirmBtnClicked();
|
|
1084
|
+
shareUrl();
|
|
1085
|
+
}
|
|
1086
|
+
)
|
|
1087
|
+
.setNegativeButton(
|
|
1088
|
+
shareDisclaimer.getString("cancelBtn", "Cancel"),
|
|
1089
|
+
null
|
|
1090
|
+
)
|
|
1091
|
+
.show();
|
|
1092
|
+
} else {
|
|
1093
|
+
shareUrl();
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1096
|
+
} else {
|
|
1097
|
+
shareButton.setVisibility(View.GONE);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// Also color the title text
|
|
1101
|
+
TextView titleText = _toolbar.findViewById(R.id.titleText);
|
|
1102
|
+
if (titleText != null) {
|
|
1103
|
+
titleText.setTextColor(iconColor);
|
|
1104
|
+
|
|
1105
|
+
// Set the title text
|
|
1106
|
+
if (!TextUtils.isEmpty(_options.getTitle())) {
|
|
1107
|
+
this.setTitle(_options.getTitle());
|
|
1108
|
+
} else {
|
|
1109
|
+
try {
|
|
1110
|
+
URI uri = new URI(_options.getUrl());
|
|
1111
|
+
this.setTitle(uri.getHost());
|
|
1112
|
+
} catch (URISyntaxException e) {
|
|
1113
|
+
this.setTitle(_options.getTitle());
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Applies background and tint colors to all buttons in the toolbar
|
|
1121
|
+
*/
|
|
1122
|
+
private void applyColorToAllButtons(int backgroundColor, int iconColor) {
|
|
1123
|
+
// Get all buttons
|
|
1124
|
+
ImageButton backButton = _toolbar.findViewById(R.id.backButton);
|
|
1125
|
+
ImageButton forwardButton = _toolbar.findViewById(R.id.forwardButton);
|
|
1126
|
+
ImageButton closeButton = _toolbar.findViewById(R.id.closeButton);
|
|
1127
|
+
ImageButton reloadButton = _toolbar.findViewById(R.id.reloadButton);
|
|
1128
|
+
ImageButton shareButton = _toolbar.findViewById(R.id.shareButton);
|
|
1129
|
+
ImageButton buttonNearDoneView = _toolbar.findViewById(R.id.buttonNearDone);
|
|
1130
|
+
|
|
1131
|
+
// Set button backgrounds
|
|
1132
|
+
backButton.setBackgroundColor(backgroundColor);
|
|
1133
|
+
forwardButton.setBackgroundColor(backgroundColor);
|
|
1134
|
+
closeButton.setBackgroundColor(backgroundColor);
|
|
1135
|
+
reloadButton.setBackgroundColor(backgroundColor);
|
|
1136
|
+
|
|
1137
|
+
// Apply tint colors to buttons
|
|
1138
|
+
backButton.setColorFilter(iconColor);
|
|
1139
|
+
forwardButton.setColorFilter(iconColor);
|
|
1140
|
+
closeButton.setColorFilter(iconColor);
|
|
1141
|
+
reloadButton.setColorFilter(iconColor);
|
|
1142
|
+
shareButton.setColorFilter(iconColor);
|
|
1143
|
+
buttonNearDoneView.setColorFilter(iconColor);
|
|
651
1144
|
}
|
|
652
1145
|
|
|
653
1146
|
public void handleProxyResultError(String result, String id) {
|
|
@@ -837,7 +1330,7 @@ public class WebViewDialog extends Dialog {
|
|
|
837
1330
|
);
|
|
838
1331
|
}
|
|
839
1332
|
String s = String.format(
|
|
840
|
-
"try {function getHeaders() {const h = {}; %s return h}; window.InAppBrowserProxyRequest(new Request(atob('%s'), {headers: getHeaders(), method: '%s'})).then(async (res) => Capacitor.Plugins.InAppBrowser.lsuakdchgbbaHandleProxiedRequest({ok: true, result: (!!res ? {headers: Object.fromEntries(res.headers.entries()), code: res.status, body: (await res.text())} : null), id: '%s'})).catch((e) => Capacitor.Plugins.InAppBrowser.lsuakdchgbbaHandleProxiedRequest({ok: false, result: e.toString(), id: '%s'})
|
|
1333
|
+
"try {function getHeaders() {const h = {}; %s return h}; window.InAppBrowserProxyRequest(new Request(atob('%s'), {headers: getHeaders(), method: '%s'})).then(async (res) => Capacitor.Plugins.InAppBrowser.lsuakdchgbbaHandleProxiedRequest({ok: true, result: (!!res ? {headers: Object.fromEntries(res.headers.entries()), code: res.status, body: (await res.text())} : null), id: '%s'})).catch((e) => Capacitor.Plugins.InAppBrowser.lsuakdchgbbaHandleProxiedRequest({ok: false, result: e.toString(), id: '%s'})} catch (e) {Capacitor.Plugins.InAppBrowser.lsuakdchgbbaHandleProxiedRequest({ok: false, result: e.toString(), id: '%s'})}",
|
|
841
1334
|
headers,
|
|
842
1335
|
toBase64(request.getUrl().toString()),
|
|
843
1336
|
request.getMethod(),
|
|
@@ -1020,18 +1513,36 @@ public class WebViewDialog extends Dialog {
|
|
|
1020
1513
|
if (_webView.canGoBack()) {
|
|
1021
1514
|
backButton.setImageResource(R.drawable.arrow_back_enabled);
|
|
1022
1515
|
backButton.setEnabled(true);
|
|
1516
|
+
backButton.setColorFilter(iconColor);
|
|
1023
1517
|
} else {
|
|
1024
1518
|
backButton.setImageResource(R.drawable.arrow_back_disabled);
|
|
1025
1519
|
backButton.setEnabled(false);
|
|
1520
|
+
backButton.setColorFilter(
|
|
1521
|
+
Color.argb(
|
|
1522
|
+
128,
|
|
1523
|
+
Color.red(iconColor),
|
|
1524
|
+
Color.green(iconColor),
|
|
1525
|
+
Color.blue(iconColor)
|
|
1526
|
+
)
|
|
1527
|
+
);
|
|
1026
1528
|
}
|
|
1027
1529
|
|
|
1028
1530
|
ImageButton forwardButton = _toolbar.findViewById(R.id.forwardButton);
|
|
1029
1531
|
if (_webView.canGoForward()) {
|
|
1030
1532
|
forwardButton.setImageResource(R.drawable.arrow_forward_enabled);
|
|
1031
1533
|
forwardButton.setEnabled(true);
|
|
1534
|
+
forwardButton.setColorFilter(iconColor);
|
|
1032
1535
|
} else {
|
|
1033
1536
|
forwardButton.setImageResource(R.drawable.arrow_forward_disabled);
|
|
1034
1537
|
forwardButton.setEnabled(false);
|
|
1538
|
+
forwardButton.setColorFilter(
|
|
1539
|
+
Color.argb(
|
|
1540
|
+
128,
|
|
1541
|
+
Color.red(iconColor),
|
|
1542
|
+
Color.green(iconColor),
|
|
1543
|
+
Color.blue(iconColor)
|
|
1544
|
+
)
|
|
1545
|
+
);
|
|
1035
1546
|
}
|
|
1036
1547
|
|
|
1037
1548
|
_options.getCallbacks().pageLoaded();
|
|
@@ -1177,4 +1688,51 @@ public class WebViewDialog extends Dialog {
|
|
|
1177
1688
|
proxiedRequestsHashmap.remove(key);
|
|
1178
1689
|
}
|
|
1179
1690
|
}
|
|
1691
|
+
|
|
1692
|
+
private void shareUrl() {
|
|
1693
|
+
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
|
1694
|
+
shareIntent.setType("text/plain");
|
|
1695
|
+
shareIntent.putExtra(Intent.EXTRA_SUBJECT, _options.getShareSubject());
|
|
1696
|
+
shareIntent.putExtra(Intent.EXTRA_TEXT, _options.getUrl());
|
|
1697
|
+
_context.startActivity(Intent.createChooser(shareIntent, "Share"));
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
private boolean isDarkColor(int color) {
|
|
1701
|
+
int red = Color.red(color);
|
|
1702
|
+
int green = Color.green(color);
|
|
1703
|
+
int blue = Color.blue(color);
|
|
1704
|
+
double luminance = (0.299 * red + 0.587 * green + 0.114 * blue) / 255.0;
|
|
1705
|
+
return luminance < 0.5;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
private boolean isDarkThemeEnabled() {
|
|
1709
|
+
// This method checks if dark theme is currently enabled without using Configuration class
|
|
1710
|
+
try {
|
|
1711
|
+
// On Android 10+, check via resources for night mode
|
|
1712
|
+
Resources.Theme theme = _context.getTheme();
|
|
1713
|
+
TypedValue typedValue = new TypedValue();
|
|
1714
|
+
|
|
1715
|
+
if (
|
|
1716
|
+
theme.resolveAttribute(android.R.attr.isLightTheme, typedValue, true)
|
|
1717
|
+
) {
|
|
1718
|
+
// isLightTheme exists - returns true if light, false if dark
|
|
1719
|
+
return typedValue.data != 1;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// Fallback method - check background color of window
|
|
1723
|
+
if (
|
|
1724
|
+
theme.resolveAttribute(
|
|
1725
|
+
android.R.attr.windowBackground,
|
|
1726
|
+
typedValue,
|
|
1727
|
+
true
|
|
1728
|
+
)
|
|
1729
|
+
) {
|
|
1730
|
+
int backgroundColor = typedValue.data;
|
|
1731
|
+
return isDarkColor(backgroundColor);
|
|
1732
|
+
}
|
|
1733
|
+
} catch (Exception e) {
|
|
1734
|
+
// Ignore and fallback to light theme
|
|
1735
|
+
}
|
|
1736
|
+
return false;
|
|
1737
|
+
}
|
|
1180
1738
|
}
|