Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions v3/IOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,24 @@ object: `IOS.Haptics.Impact(style)`, `IOS.Device.Info()`,
`IOS.Scroll.SetEnabled(...)`, etc. Native tab selections arrive as a
`nativeTabSelected` `CustomEvent` on `window`.

Native tabs can also be controlled after startup from Go:

```go
application.IOS.SetNativeTabsEnabled(true)
application.IOS.SelectNativeTab(1) // zero-based index
enabled := application.IOS.NativeTabsIsEnabled()
```

Or from the frontend through the runtime package:

```ts
import { IOS } from "@wailsio/runtime";

await IOS.NativeTabs.SetEnabled(true);
await IOS.NativeTabs.Select(1); // zero-based index
const enabled = await IOS.NativeTabs.IsEnabled();
```

## Native mobile features

Beyond the cross-platform runtime, iOS exposes a set of "genuinely mobile"
Expand Down
5 changes: 5 additions & 0 deletions v3/examples/ios/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ <h1>Wails + Javascript</h1>

<!-- Screen 2: Go Runtime -->
<div class="p-mobile-tabs--content" id="screen-go">
<div class="input-box">
<button class="p-btn p-prim-col" onclick="selectNativeTab(0)">Go to Tab 1</button>
<button class="p-btn" onclick="setNativeTabsEnabled(false)">Disable Native Tabs</button>
<button class="p-btn" onclick="setNativeTabsEnabled(true)">Enable Native Tabs</button>
</div>
<div class="input-box">
<label><input type="checkbox" id="goScrollEnabled" checked onchange="setGoToggle('ios:setScrollEnabled', this.checked)"> Scroll Enabled (Go)</label>
</div>
Expand Down
25 changes: 24 additions & 1 deletion v3/examples/ios/frontend/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ window.getDeviceInfo = async () => {
}
}

window.selectNativeTab = async (index) => {
if (!IOS?.NativeTabs?.Select) {
console.warn('IOS native tabs runtime is not available.');
return;
}
try {
await IOS.NativeTabs.Select(index);
} catch (e) {
console.error('Unable to select native tab:', e);
}
}

window.setNativeTabsEnabled = async (enabled) => {
if (!IOS?.NativeTabs?.SetEnabled) {
console.warn('IOS native tabs runtime is not available.');
return;
}
try {
await IOS.NativeTabs.SetEnabled(enabled);
} catch (e) {
console.error('Unable to update native tabs:', e);
}
}

// Generic caller for IOS.<Group>.<Method>(args)
window.iosJsSet = async (methodPath, args) => {
if (!IOS) {
Expand Down Expand Up @@ -112,4 +136,3 @@ window.addEventListener('DOMContentLoaded', () => {
showPaneByIndex(0);
});


23 changes: 21 additions & 2 deletions v3/internal/assetserver/bundledassets/runtime.debug.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion v3/internal/assetserver/bundledassets/runtime.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions v3/internal/runtime/desktop/@wailsio/runtime/src/ios.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { afterEach, describe, expect, it, vi } from "vitest";

import * as IOS from "./ios.js";
import { objectNames, setTransport } from "./runtime.js";

describe("IOS.NativeTabs", () => {
afterEach(() => setTransport(null));

it("sends native tab controls through the iOS runtime object", async () => {
const call = vi.fn().mockResolvedValueOnce(undefined).mockResolvedValueOnce(undefined).mockResolvedValueOnce(true);
setTransport({ call });

await IOS.NativeTabs.SetEnabled(false);
await IOS.NativeTabs.Select(2);
await expect(IOS.NativeTabs.IsEnabled()).resolves.toBe(true);

expect(call).toHaveBeenNthCalledWith(1, objectNames.IOS, 9, "", { enabled: false });
expect(call).toHaveBeenNthCalledWith(2, objectNames.IOS, 11, "", { index: 2 });
expect(call).toHaveBeenNthCalledWith(3, objectNames.IOS, 10, "", null);
});
});
21 changes: 21 additions & 0 deletions v3/internal/runtime/desktop/@wailsio/runtime/src/ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const call = newRuntimeCaller(objectNames.IOS);
// Method IDs
const HapticsImpact = 0;
const DeviceInfo = 1;
const NativeTabsSetEnabled = 9;
const NativeTabsIsEnabled = 10;
const NativeTabsSelect = 11;

export namespace Haptics {
export type ImpactStyle = "light"|"medium"|"heavy"|"soft"|"rigid";
Expand All @@ -34,3 +37,21 @@ export namespace Device {
return call(DeviceInfo);
}
}

/** Controls the native iOS tab bar configured in the application options. */
export namespace NativeTabs {
/** Shows or hides the native tab bar. */
export function SetEnabled(enabled: boolean): Promise<void> {
return call(NativeTabsSetEnabled, { enabled });
}

/** Reports whether the native tab bar is currently enabled. */
export function IsEnabled(): Promise<boolean> {
return call(NativeTabsIsEnabled);
}

/** Selects the tab at the zero-based index. */
export function Select(index: number): Promise<void> {
return call(NativeTabsSelect, { index });
}
}
9 changes: 9 additions & 0 deletions v3/pkg/application/ios_runtime_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ func (iosManager) SetBackForwardGesturesEnabled(enabled bool) {
func (iosManager) SetLinkPreviewEnabled(enabled bool) { iosSetLinkPreviewEnabled(enabled) }
func (iosManager) SetInspectableEnabled(enabled bool) { iosSetInspectableEnabled(enabled) }
func (iosManager) SetCustomUserAgent(ua string) { iosSetCustomUserAgent(ua) }

// SetNativeTabsEnabled shows or hides the configured native tab bar at runtime.
func (iosManager) SetNativeTabsEnabled(enabled bool) { iosSetNativeTabsEnabled(enabled) }

// NativeTabsIsEnabled reports whether the native tab bar is currently enabled.
func (iosManager) NativeTabsIsEnabled() bool { return iosNativeTabsIsEnabled() }

// SelectNativeTab selects the native tab at the zero-based index.
func (iosManager) SelectNativeTab(index int) { iosSelectNativeTab(index) }
17 changes: 10 additions & 7 deletions v3/pkg/application/ios_runtime_stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ func iosDeviceInfo() deviceInfo {
}

// Live mutation stubs
func iosSetScrollEnabled(enabled bool) {}
func iosSetBounceEnabled(enabled bool) {}
func iosSetScrollIndicatorsEnabled(enabled bool) {}
func iosSetBackForwardGesturesEnabled(enabled bool) {}
func iosSetLinkPreviewEnabled(enabled bool) {}
func iosSetInspectableEnabled(enabled bool) {}
func iosSetCustomUserAgent(ua string) {}
func iosSetScrollEnabled(enabled bool) {}
func iosSetBounceEnabled(enabled bool) {}
func iosSetScrollIndicatorsEnabled(enabled bool) {}
func iosSetBackForwardGesturesEnabled(enabled bool) {}
func iosSetLinkPreviewEnabled(enabled bool) {}
func iosSetInspectableEnabled(enabled bool) {}
func iosSetCustomUserAgent(ua string) {}
func iosSetNativeTabsEnabled(enabled bool) {}
func iosNativeTabsIsEnabled() bool { return false }
func iosSelectNativeTab(index int) {}
22 changes: 22 additions & 0 deletions v3/pkg/application/messageprocessor_ios.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const (
IOSLinksSetPreviewEnabled = 6
IOSDebugSetInspectableEnabled = 7
IOSUserAgentSet = 8
IOSNativeTabsSetEnabled = 9
IOSNativeTabsIsEnabled = 10
IOSNativeTabsSelect = 11
)

// androidMethodNames is referenced by the shared messageprocessor debug logging;
Expand All @@ -32,6 +35,9 @@ var iosMethodNames = map[int]string{
IOSLinksSetPreviewEnabled: "Links.SetPreviewEnabled",
IOSDebugSetInspectableEnabled: "Debug.SetInspectableEnabled",
IOSUserAgentSet: "UserAgent.Set",
IOSNativeTabsSetEnabled: "NativeTabs.SetEnabled",
IOSNativeTabsIsEnabled: "NativeTabs.IsEnabled",
IOSNativeTabsSelect: "NativeTabs.Select",
}

func (m *MessageProcessor) processIOSMethod(req *RuntimeRequest, window Window) (any, error) {
Expand Down Expand Up @@ -98,6 +104,22 @@ func (m *MessageProcessor) processIOSMethod(req *RuntimeRequest, window Window)
}
iosSetCustomUserAgent(ua)
return unit, nil
case IOSNativeTabsSetEnabled:
enabled := true
if b := args.Bool("enabled"); b != nil {
enabled = *b
}
iosSetNativeTabsEnabled(enabled)
return unit, nil
case IOSNativeTabsIsEnabled:
return iosNativeTabsIsEnabled(), nil
case IOSNativeTabsSelect:
index := 0
if i := args.Int("index"); i != nil {
index = *i
}
iosSelectNativeTab(index)
return unit, nil
default:
return nil, errs.NewInvalidIOSCallErrorf("unknown method: %d", req.Method)
}
Expand Down
Loading