@capgo/capacitor-native-navigation 8.5.0 → 8.6.1
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 +1 -1
- package/android/src/main/java/app/capgo/nativenavigation/NativeNavigationPlugin.java +173 -39
- package/docs/android-floating-tabbar-before-300.png +0 -0
- package/docs/pr54-android-floating-reported-280.png +0 -0
- package/docs/pr54-android-floating-reported.png +0 -0
- package/ios/Sources/NativeNavigationPlugin/NativeNavigationPlugin.swift +11 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<a href="https://capgo.app/?ref=plugin_native_navigation"><img src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-native-navigation" alt="Capgo - Instant updates for Capacitor" /></a>
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
6
|
-
<p><b>Capgo</b>:
|
|
6
|
+
<p><b>Capgo</b>: push fixes to your Capacitor users in minutes, build signed iOS and Android apps without a Mac, and roll back in one click.</p>
|
|
7
7
|
<h2><a href="https://capgo.app/register/?ref=plugin_native_navigation">➡️ Get started for free</a></h2>
|
|
8
8
|
<p>14-day unlimited free trial. No credit card required</p>
|
|
9
9
|
<p><a href="https://capgo.app/consulting/?ref=plugin_native_navigation">Missing a feature? We'll build the plugin for you 💪</a></p>
|
|
@@ -36,6 +36,7 @@ import androidx.annotation.RequiresApi;
|
|
|
36
36
|
import androidx.appcompat.content.res.AppCompatResources;
|
|
37
37
|
import androidx.appcompat.widget.Toolbar;
|
|
38
38
|
import androidx.core.graphics.PathParser;
|
|
39
|
+
import androidx.core.widget.TextViewCompat;
|
|
39
40
|
import com.getcapacitor.JSArray;
|
|
40
41
|
import com.getcapacitor.JSObject;
|
|
41
42
|
import com.getcapacitor.Plugin;
|
|
@@ -61,6 +62,11 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
61
62
|
|
|
62
63
|
private static final int DEFAULT_NAVBAR_DP = 56;
|
|
63
64
|
private static final int DEFAULT_TABBAR_DP = 64;
|
|
65
|
+
private static final int TAB_LABEL_TEXT_SP = 12;
|
|
66
|
+
private static final int TAB_CONTENT_PADDING_DP = 4;
|
|
67
|
+
private static final int INDICATOR_HORIZONTAL_PADDING_DP = 12;
|
|
68
|
+
private static final int INDICATOR_VERTICAL_PADDING_DP = 6;
|
|
69
|
+
private static final int INDICATOR_SLOT_INSET_DP = 2;
|
|
64
70
|
private static final int DEFAULT_TRANSITION_MS = 350;
|
|
65
71
|
private static final int MENU_ITEM_BASE = 10_000;
|
|
66
72
|
private static final int DEFAULT_TABBAR_BACKGROUND_COLOR = Color.WHITE;
|
|
@@ -130,7 +136,7 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
130
136
|
configureSpecifiedGlassEffect = configureGlass != null && configureGlass.has("effect");
|
|
131
137
|
defaultGlassOptions = GlassOptions.from(configureGlass, defaultGlassOptions);
|
|
132
138
|
navbarGlassOptions = GlassOptions.from(navbarGlassConfig, defaultGlassOptions);
|
|
133
|
-
tabbarGlassOptions =
|
|
139
|
+
tabbarGlassOptions = resolveTabbarGlassOptions(call);
|
|
134
140
|
Double duration = call.getDouble("animationDuration");
|
|
135
141
|
if (duration != null) {
|
|
136
142
|
defaultTransitionMs = Math.max(0, duration.intValue());
|
|
@@ -838,7 +844,7 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
838
844
|
}
|
|
839
845
|
|
|
840
846
|
private FrameLayout makeTabButton(NativeTabItem item, boolean selected, boolean showLabel, boolean icons, boolean center) {
|
|
841
|
-
|
|
847
|
+
TabButton button = new TabButton(getContext());
|
|
842
848
|
button.setClipChildren(false);
|
|
843
849
|
button.setClipToPadding(false);
|
|
844
850
|
button.setForeground(selectableItemBackground());
|
|
@@ -852,25 +858,33 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
852
858
|
button.addView(centerFill, new FrameLayout.LayoutParams(centerFillDiameter, centerFillDiameter, Gravity.CENTER));
|
|
853
859
|
}
|
|
854
860
|
|
|
861
|
+
Drawable currentIcon = selected && item.selectedIcon != null ? item.selectedIcon : item.icon;
|
|
862
|
+
boolean labelVisible = center ? showLabel && (currentIcon == null || !icons) : showLabel;
|
|
863
|
+
boolean iconVisible = icons && currentIcon != null;
|
|
864
|
+
// Measured with the bold selected style for every tab so the slots don't shift when the selection changes.
|
|
865
|
+
int contentWidth = indicatorContentWidth(item.title, labelVisible, iconVisible);
|
|
866
|
+
button.preferredWidth = contentWidth + dp(INDICATOR_HORIZONTAL_PADDING_DP + INDICATOR_SLOT_INSET_DP) * 2;
|
|
867
|
+
|
|
855
868
|
if (!center && selected && !tabbarDisableIndicator) {
|
|
856
869
|
GradientDrawable selectedBackground = new GradientDrawable();
|
|
857
|
-
selectedBackground.setShape(GradientDrawable.
|
|
870
|
+
selectedBackground.setShape(GradientDrawable.RECTANGLE);
|
|
858
871
|
selectedBackground.setColor(TabbarChromeSupport.resolveSelectedIndicatorColor(tabbarIndicatorColor, tintColor));
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
button.addView(
|
|
872
|
+
TabIndicatorView indicator = new TabIndicatorView(getContext(), contentWidth, indicatorContentHeight(labelVisible, iconVisible));
|
|
873
|
+
indicator.setBackground(selectedBackground);
|
|
874
|
+
button.addView(
|
|
875
|
+
indicator,
|
|
876
|
+
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER)
|
|
877
|
+
);
|
|
862
878
|
}
|
|
863
879
|
|
|
864
880
|
LinearLayout content = new LinearLayout(getContext());
|
|
865
881
|
content.setOrientation(LinearLayout.VERTICAL);
|
|
866
882
|
content.setGravity(Gravity.CENTER);
|
|
867
|
-
content.setPadding(dp(
|
|
883
|
+
content.setPadding(dp(TAB_CONTENT_PADDING_DP), dp(TAB_CONTENT_PADDING_DP), dp(TAB_CONTENT_PADDING_DP), dp(TAB_CONTENT_PADDING_DP));
|
|
868
884
|
button.addView(content, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
869
885
|
|
|
870
|
-
Drawable currentIcon = selected && item.selectedIcon != null ? item.selectedIcon : item.icon;
|
|
871
|
-
boolean labelVisible = center ? showLabel && (currentIcon == null || !icons) : showLabel;
|
|
872
886
|
int itemColor = center ? tabbarStyle.centerButtonIconColor : (selected ? tintColor : inactiveTintColor);
|
|
873
|
-
if (
|
|
887
|
+
if (iconVisible) {
|
|
874
888
|
Drawable icon = currentIcon.mutate();
|
|
875
889
|
icon.setTint(itemColor);
|
|
876
890
|
ImageView image = new ImageView(getContext());
|
|
@@ -886,10 +900,13 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
886
900
|
TextView label = new TextView(getContext());
|
|
887
901
|
label.setText(item.title);
|
|
888
902
|
label.setTextColor(itemColor);
|
|
889
|
-
label.setTextSize(
|
|
903
|
+
label.setTextSize(TAB_LABEL_TEXT_SP);
|
|
890
904
|
label.setTypeface(Typeface.DEFAULT, selected ? Typeface.BOLD : Typeface.NORMAL);
|
|
891
905
|
label.setGravity(Gravity.CENTER);
|
|
892
|
-
|
|
906
|
+
// maxLines rather than singleLine: autosize is ignored on a single-line (horizontally scrolling) TextView.
|
|
907
|
+
label.setMaxLines(1);
|
|
908
|
+
// Shrink long titles to fit the tab instead of cutting them off.
|
|
909
|
+
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(label, 9, TAB_LABEL_TEXT_SP, 1, TypedValue.COMPLEX_UNIT_SP);
|
|
893
910
|
content.addView(label, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(18)));
|
|
894
911
|
}
|
|
895
912
|
|
|
@@ -919,6 +936,75 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
919
936
|
return button;
|
|
920
937
|
}
|
|
921
938
|
|
|
939
|
+
/** Width of the selected item's icon or label (whichever is wider), before the indicator padding. */
|
|
940
|
+
private int indicatorContentWidth(String title, boolean labelVisible, boolean iconVisible) {
|
|
941
|
+
int width = iconVisible ? dp(24) : 0;
|
|
942
|
+
if (labelVisible && title != null) {
|
|
943
|
+
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
944
|
+
paint.setTypeface(Typeface.DEFAULT_BOLD);
|
|
945
|
+
paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, TAB_LABEL_TEXT_SP, getContext().getResources().getDisplayMetrics()));
|
|
946
|
+
width = Math.max(width, (int) Math.ceil(paint.measureText(title)));
|
|
947
|
+
}
|
|
948
|
+
return width;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
private int indicatorContentHeight(boolean labelVisible, boolean iconVisible) {
|
|
952
|
+
int height = 0;
|
|
953
|
+
if (iconVisible) {
|
|
954
|
+
height += dp(24);
|
|
955
|
+
}
|
|
956
|
+
if (labelVisible) {
|
|
957
|
+
height += dp(18) + (iconVisible ? dp(2) : 0);
|
|
958
|
+
}
|
|
959
|
+
return height;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/** Tab item that reports how wide it wants to be, so the tabbar can size slots to their content. */
|
|
963
|
+
private static final class TabButton extends FrameLayout {
|
|
964
|
+
|
|
965
|
+
int preferredWidth = 0;
|
|
966
|
+
|
|
967
|
+
TabButton(Context context) {
|
|
968
|
+
super(context);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/** Selected-tab capsule that wraps the item's icon and label with padding, kept inside its tab slot. */
|
|
973
|
+
private static final class TabIndicatorView extends View {
|
|
974
|
+
|
|
975
|
+
private final int contentWidth;
|
|
976
|
+
private final int contentHeight;
|
|
977
|
+
|
|
978
|
+
TabIndicatorView(Context context, int contentWidth, int contentHeight) {
|
|
979
|
+
super(context);
|
|
980
|
+
this.contentWidth = contentWidth;
|
|
981
|
+
this.contentHeight = contentHeight;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
@Override
|
|
985
|
+
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
986
|
+
int slotWidth = MeasureSpec.getSize(widthMeasureSpec);
|
|
987
|
+
int slotHeight = MeasureSpec.getSize(heightMeasureSpec);
|
|
988
|
+
int height = contentHeight + dp(INDICATOR_VERTICAL_PADDING_DP) * 2;
|
|
989
|
+
if (slotHeight > 0) {
|
|
990
|
+
height = Math.min(height, slotHeight);
|
|
991
|
+
}
|
|
992
|
+
int width = Math.max(height, contentWidth + dp(INDICATOR_HORIZONTAL_PADDING_DP) * 2);
|
|
993
|
+
if (slotWidth > 0) {
|
|
994
|
+
width = Math.min(width, slotWidth - dp(INDICATOR_SLOT_INSET_DP) * 2);
|
|
995
|
+
}
|
|
996
|
+
setMeasuredDimension(width, height);
|
|
997
|
+
Drawable background = getBackground();
|
|
998
|
+
if (background instanceof GradientDrawable) {
|
|
999
|
+
((GradientDrawable) background).setCornerRadius(height / 2f);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
private int dp(int value) {
|
|
1004
|
+
return Math.round(value * getResources().getDisplayMetrics().density);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
922
1008
|
private Drawable iconFrom(JSONObject descriptor) {
|
|
923
1009
|
if (descriptor == null) {
|
|
924
1010
|
return null;
|
|
@@ -1213,11 +1299,7 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1213
1299
|
return;
|
|
1214
1300
|
}
|
|
1215
1301
|
|
|
1216
|
-
|
|
1217
|
-
int childWidth = width / count;
|
|
1218
|
-
for (int index = 0; index < getChildCount(); index++) {
|
|
1219
|
-
measureChildExact(getChildAt(index), childWidth, height);
|
|
1220
|
-
}
|
|
1302
|
+
measureRange(0, getChildCount(), width, height);
|
|
1221
1303
|
setMeasuredDimension(width, height);
|
|
1222
1304
|
}
|
|
1223
1305
|
|
|
@@ -1280,28 +1362,56 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1280
1362
|
}
|
|
1281
1363
|
|
|
1282
1364
|
private void measureRange(int start, int end, int width, int height) {
|
|
1283
|
-
int
|
|
1284
|
-
if (count == 0) {
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
int childWidth = Math.max(0, width / count);
|
|
1365
|
+
int[] widths = slotWidths(start, end, width);
|
|
1288
1366
|
for (int index = start; index < end; index++) {
|
|
1289
|
-
measureChildExact(getChildAt(index),
|
|
1367
|
+
measureChildExact(getChildAt(index), widths[index - start], height);
|
|
1290
1368
|
}
|
|
1291
1369
|
}
|
|
1292
1370
|
|
|
1293
1371
|
private void layoutRange(int start, int end, int left, int top, int width, int height) {
|
|
1294
|
-
int
|
|
1295
|
-
|
|
1296
|
-
return;
|
|
1297
|
-
}
|
|
1298
|
-
int childWidth = Math.max(0, width / count);
|
|
1372
|
+
int[] widths = slotWidths(start, end, width);
|
|
1373
|
+
int childLeft = left;
|
|
1299
1374
|
for (int index = start; index < end; index++) {
|
|
1300
|
-
int
|
|
1375
|
+
int childWidth = widths[index - start];
|
|
1301
1376
|
getChildAt(index).layout(childLeft, top, childLeft + childWidth, top + height);
|
|
1377
|
+
childLeft += childWidth;
|
|
1302
1378
|
}
|
|
1303
1379
|
}
|
|
1304
1380
|
|
|
1381
|
+
/**
|
|
1382
|
+
* Each tab gets the width its content needs; leftover space is shared equally so the gaps stay even. When the
|
|
1383
|
+
* bar is too narrow, slots shrink in proportion and long labels autosize down.
|
|
1384
|
+
*/
|
|
1385
|
+
private int[] slotWidths(int start, int end, int width) {
|
|
1386
|
+
int count = Math.max(0, end - start);
|
|
1387
|
+
int[] widths = new int[count];
|
|
1388
|
+
if (count == 0) {
|
|
1389
|
+
return widths;
|
|
1390
|
+
}
|
|
1391
|
+
int total = 0;
|
|
1392
|
+
for (int index = 0; index < count; index++) {
|
|
1393
|
+
View child = getChildAt(start + index);
|
|
1394
|
+
int preferred = child instanceof TabButton ? ((TabButton) child).preferredWidth : 0;
|
|
1395
|
+
widths[index] = Math.max(preferred, 0);
|
|
1396
|
+
total += widths[index];
|
|
1397
|
+
}
|
|
1398
|
+
if (total <= 0) {
|
|
1399
|
+
for (int index = 0; index < count; index++) {
|
|
1400
|
+
widths[index] = width / count;
|
|
1401
|
+
}
|
|
1402
|
+
} else if (total <= width) {
|
|
1403
|
+
int extra = (width - total) / count;
|
|
1404
|
+
for (int index = 0; index < count; index++) {
|
|
1405
|
+
widths[index] += extra;
|
|
1406
|
+
}
|
|
1407
|
+
} else {
|
|
1408
|
+
for (int index = 0; index < count; index++) {
|
|
1409
|
+
widths[index] = (int) ((long) widths[index] * width / total);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
return widths;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1305
1415
|
private void measureChildExact(View child, int width, int height) {
|
|
1306
1416
|
child.measure(
|
|
1307
1417
|
MeasureSpec.makeMeasureSpec(Math.max(0, width), MeasureSpec.EXACTLY),
|
|
@@ -1645,11 +1755,14 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1645
1755
|
if (tabbarContainer != null) {
|
|
1646
1756
|
tabbarContainer.setBackgroundColor(Color.TRANSPARENT);
|
|
1647
1757
|
}
|
|
1648
|
-
|
|
1758
|
+
if (tabbarGlassSurface != null) {
|
|
1759
|
+
tabbarGlassSurface.setBackground(chromeBackgroundDrawable(drawColor, 0f));
|
|
1760
|
+
tabbarGlassSurface.setVisibility(View.VISIBLE);
|
|
1761
|
+
}
|
|
1649
1762
|
if (tabbarGlassBackdrop != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
1650
1763
|
View webView = getBridge() == null ? null : getBridge().getWebView();
|
|
1651
1764
|
tabbarGlassBackdrop.setClipPathProvider((width, height) -> tabbar.backgroundPath(width, height));
|
|
1652
|
-
tabbarGlassBackdrop.configure(webView, dp(resolvedGlassOptions.blurRadiusDp),
|
|
1765
|
+
tabbarGlassBackdrop.configure(webView, dp(resolvedGlassOptions.blurRadiusDp), Color.TRANSPARENT);
|
|
1653
1766
|
tabbarGlassBackdrop.setVisibility(View.VISIBLE);
|
|
1654
1767
|
} else if (tabbarGlassBackdrop != null) {
|
|
1655
1768
|
tabbarGlassBackdrop.setClipPathProvider((width, height) -> tabbar.backgroundPath(width, height));
|
|
@@ -2187,26 +2300,37 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
2187
2300
|
return Math.max(0, rawNavigationBarInset() - contentRootBottomOffset());
|
|
2188
2301
|
}
|
|
2189
2302
|
|
|
2303
|
+
// API 30+ reads the currently visible bars so a hidden navigation bar (immersive mode) gives the space back.
|
|
2190
2304
|
private int rawStatusBarInset() {
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
if (
|
|
2194
|
-
return insets.
|
|
2305
|
+
WindowInsets insets = rootWindowInsets();
|
|
2306
|
+
if (insets != null) {
|
|
2307
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
2308
|
+
return insets.getInsets(WindowInsets.Type.statusBars() | WindowInsets.Type.displayCutout()).top;
|
|
2195
2309
|
}
|
|
2310
|
+
return insets.getStableInsetTop();
|
|
2196
2311
|
}
|
|
2197
2312
|
return systemDimension("status_bar_height");
|
|
2198
2313
|
}
|
|
2199
2314
|
|
|
2200
2315
|
private int rawNavigationBarInset() {
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
if (
|
|
2204
|
-
return insets.
|
|
2316
|
+
WindowInsets insets = rootWindowInsets();
|
|
2317
|
+
if (insets != null) {
|
|
2318
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
2319
|
+
return insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
|
|
2205
2320
|
}
|
|
2321
|
+
return insets.getStableInsetBottom();
|
|
2206
2322
|
}
|
|
2207
2323
|
return systemDimension("navigation_bar_height");
|
|
2208
2324
|
}
|
|
2209
2325
|
|
|
2326
|
+
private WindowInsets rootWindowInsets() {
|
|
2327
|
+
Activity activity = getActivity();
|
|
2328
|
+
if (activity == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
2329
|
+
return null;
|
|
2330
|
+
}
|
|
2331
|
+
return activity.getWindow().getDecorView().getRootWindowInsets();
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2210
2334
|
private int contentRootTopOffset() {
|
|
2211
2335
|
FrameLayout root = contentRoot();
|
|
2212
2336
|
if (root == null || !root.isLaidOut()) {
|
|
@@ -2244,6 +2368,16 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
2244
2368
|
view.post(this::updateInsetsAndNotify);
|
|
2245
2369
|
}
|
|
2246
2370
|
});
|
|
2371
|
+
// Showing or hiding a system bar changes the insets without necessarily moving the content root
|
|
2372
|
+
// (edge-to-edge apps). A zero-size probe hears every inset dispatch without replacing anyone's listener.
|
|
2373
|
+
View insetsProbe = new View(getContext());
|
|
2374
|
+
insetsProbe.setOnApplyWindowInsetsListener((view, insets) -> {
|
|
2375
|
+
if (navbarVisible || tabbarVisible) {
|
|
2376
|
+
view.post(this::updateInsetsAndNotify);
|
|
2377
|
+
}
|
|
2378
|
+
return insets;
|
|
2379
|
+
});
|
|
2380
|
+
root.addView(insetsProbe, new FrameLayout.LayoutParams(0, 0));
|
|
2247
2381
|
}
|
|
2248
2382
|
|
|
2249
2383
|
private int systemDimension(String name) {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import Foundation
|
|
4
4
|
import Capacitor
|
|
5
|
-
import ObjectiveC
|
|
6
5
|
import UIKit
|
|
7
6
|
|
|
8
7
|
private struct NativeNavigationTransitionContext {
|
|
@@ -2052,44 +2051,25 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
2052
2051
|
}
|
|
2053
2052
|
|
|
2054
2053
|
private func liquidGlassEffect() -> UIVisualEffect? {
|
|
2055
|
-
guard usesSystemLiquidGlass
|
|
2056
|
-
let effectClass = NSClassFromString("UIGlassEffect") else {
|
|
2054
|
+
guard usesSystemLiquidGlass else {
|
|
2057
2055
|
return nil
|
|
2058
2056
|
}
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
typealias EffectWithStyle = @convention(c) (AnyClass, Selector, Int) -> AnyObject?
|
|
2063
|
-
let factory = unsafeBitCast(method_getImplementation(method), to: EffectWithStyle.self)
|
|
2064
|
-
if let effect = factory(effectClass, styleSelector, 0) as? UIVisualEffect {
|
|
2065
|
-
return effect
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
|
-
if let objectType = effectClass as? NSObject.Type {
|
|
2070
|
-
return objectType.init() as? UIVisualEffect
|
|
2057
|
+
#if compiler(>=6.2)
|
|
2058
|
+
if #available(iOS 26.0, *) {
|
|
2059
|
+
return UIGlassEffect(style: .regular)
|
|
2071
2060
|
}
|
|
2072
|
-
|
|
2061
|
+
#endif
|
|
2073
2062
|
return nil
|
|
2074
2063
|
}
|
|
2075
2064
|
|
|
2076
2065
|
private func configureGlassBarButtonItem(_ item: UIBarButtonItem, id: String) {
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
// button Liquid Glass grouping APIs when the runtime exposes them.
|
|
2083
|
-
let object = item as NSObject
|
|
2084
|
-
if object.responds(to: NSSelectorFromString("setIdentifier:")) {
|
|
2085
|
-
object.setValue(id, forKey: "identifier")
|
|
2086
|
-
}
|
|
2087
|
-
if object.responds(to: NSSelectorFromString("setSharesBackground:")) {
|
|
2088
|
-
object.setValue(true, forKey: "sharesBackground")
|
|
2089
|
-
}
|
|
2090
|
-
if object.responds(to: NSSelectorFromString("setHidesSharedBackground:")) {
|
|
2091
|
-
object.setValue(false, forKey: "hidesSharedBackground")
|
|
2066
|
+
#if compiler(>=6.2)
|
|
2067
|
+
if #available(iOS 26.0, *) {
|
|
2068
|
+
item.identifier = id
|
|
2069
|
+
item.sharesBackground = true
|
|
2070
|
+
item.hidesSharedBackground = false
|
|
2092
2071
|
}
|
|
2072
|
+
#endif
|
|
2093
2073
|
}
|
|
2094
2074
|
|
|
2095
2075
|
private func currentInsets() -> [String: Any] {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-native-navigation",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.1",
|
|
4
4
|
"description": "Capacitor plugin for native navbar, tabbar, safe-area handling, and WebView snapshot transitions.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|