Skip to content
Merged
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
63 changes: 57 additions & 6 deletions DemoApp/Demo/TypeSwift/TypeSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
/// An enumeration of TypeScript identifiers generated to be used in Swift code.
enum TypeSwift {

// State Variables
case total(_ value: Double)
case textFieldValue(_ value: String)
case switchValue(_ value: Bool)
case selectedDevice(_ device: Device)
case selectedOS(_ os: OperatingSystems)

// Functions
case updateTotal(_ value: Double)
case updateDeviceDropdown(_ device: Device)
Expand All @@ -20,6 +27,13 @@ enum TypeSwift {

var jsString: String {
switch self {
case .total(let value): return "total.value = \(value)"
case .textFieldValue(let value): return "textFieldValue.value = `\(value)`"
case .switchValue(let value): return "switchValue.value = \(value)"
case .selectedDevice(let device): return "selectedDevice.value = Device.\(device)"
case .selectedOS(let os): return "selectedOS.value = OperatingSystems.\(os)"

// Functions
case .updateTotal(let value): return "updateTotal(\(value))"
case .updateDeviceDropdown(let device): return "updateDeviceDropdown(Device.\(device))"
case .updateOSDropdown(let os): return "updateOSDropdown(OperatingSystems.\(os))"
Expand All @@ -43,6 +57,13 @@ import WebKit

extension TypeSwift {
enum MessageHandlers {
case total((Double) -> Void)
case textFieldValue((String) -> Void)
case switchValue((Bool) -> Void)
case selectedDevice((Device) -> Void)
case selectedOS((OperatingSystems) -> Void)

// Static Functions
case updateTotal((Double) -> Void)
case updateTextField((String) -> Void)
case updateDeviceDropdown((Device) -> Void)
Expand All @@ -51,6 +72,13 @@ extension TypeSwift {

var name: String {
switch self {
case .total: return "total"
case .textFieldValue: return "textFieldValue"
case .switchValue: return "switchValue"
case .selectedDevice: return "selectedDevice"
case .selectedOS: return "selectedOS"

// Static Functions
case .updateTotal: return "updateTotal"
case .updateTextField: return "updateTextField"
case .updateDeviceDropdown: return "updateDeviceDropdown"
Expand All @@ -61,18 +89,41 @@ extension TypeSwift {

func handle(message: WKScriptMessage) {
switch self {
case .total(let callback):
if let value = message.body as? Double {
callback(value)
}
case .textFieldValue(let callback):
if let value = message.body as? String {
callback(value)
}
case .selectedDevice(let callback):
if let deviceData = message.body as? String,
let device = Device(rawValue: deviceData) {
callback(device)
}
case .selectedOS(let callback):
if let osData = message.body as? String,
let os = OperatingSystems(rawValue: osData) {
callback(os)
}
case .switchValue(let callback):
if let value = message.body as? Bool {
callback(value)
}

// Static Functions
case .updateTotal(let callback):
if let value = message.body as? Double {
callback(value)
}
case .updateTextField(let callback):
if let text = message.body as? String {
callback(text)
if let value = message.body as? String {
callback(value)
}
case .updateDeviceDropdown(let callback):
if let deviceData = message.body as? String,
let data = deviceData.data(using: .utf8),
let device = try? JSONDecoder().decode(Device.self, from: data) {
let device = Device(rawValue: deviceData) {
callback(device)
}
case .updateOSDropdown(let callback):
Expand All @@ -81,8 +132,8 @@ extension TypeSwift {
callback(os)
}
case .updateSwitch(let callback):
if let switchValue = message.body as? Bool {
callback(switchValue)
if let value = message.body as? Bool {
callback(value)
}
}
}
Expand Down
24 changes: 12 additions & 12 deletions DemoApp/Demo/Views/Pages/ComponentsView/ComponentsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import SwiftUI
struct ComponentsView: View {
let manager: ObservableWebViewManager

@State private var textFieldValue: String = ""
@State private var total: Double = 0
@State private var textFieldValue: String = ""
@State private var selectedDevice: TypeSwift.Device = .Phone
@State private var selectedOS: TypeSwift.OperatingSystems = .iOS
@State private var switchValue: Bool = true
Expand All @@ -21,19 +21,19 @@ struct ComponentsView: View {
HStack(spacing: 0) {
ObservableWebView(manager: manager)
.frame(width: geometry.size.width / 2)
.tsMessageHandler(.updateTotal { newValue in
.tsMessageHandler(.total { newValue in
total = newValue
}, manager: manager)
.tsMessageHandler(.updateTextField { newValue in
.tsMessageHandler(.textFieldValue { newValue in
textFieldValue = newValue
}, manager: manager)
.tsMessageHandler(.updateDeviceDropdown { newValue in
.tsMessageHandler(.selectedDevice { newValue in
selectedDevice = newValue
}, manager: manager)
.tsMessageHandler(.updateOSDropdown { newValue in
.tsMessageHandler(.selectedOS { newValue in
selectedOS = newValue
}, manager: manager)
.tsMessageHandler(.updateSwitch { newValue in
.tsMessageHandler(.switchValue { newValue in
switchValue = newValue
}, manager: manager)

Expand All @@ -44,10 +44,10 @@ struct ComponentsView: View {
ComponentSection(header: "Buttons") {
HStack {
PrimaryButton("+1", foreground: .white, background: .blue) {
manager.ts(.updateTotal(total + 1))
manager.ts(.total(total + 1))
}
PrimaryButton("-1", foreground: .white, background: .red) {
manager.ts(.updateTotal(total - 1))
manager.ts(.total(total - 1))
}
Text("\(total, specifier: "%.0f")")
.font(.system(size: 14, weight: .medium))
Expand All @@ -57,7 +57,7 @@ struct ComponentsView: View {
ComponentSection(header: "TextField") {
PrimaryTextField(text: $textFieldValue)
.onChange(of: textFieldValue) {
manager.ts(.updateTextField(textFieldValue))
manager.ts(.textFieldValue(textFieldValue))
}
}

Expand All @@ -66,20 +66,20 @@ struct ComponentsView: View {
MonoSubheader("enum")
EnumDropdownMenu(selection: $selectedDevice)
.onChange(of: selectedDevice) {
manager.ts(.updateDeviceDropdown(selectedDevice))
manager.ts(.selectedDevice(selectedDevice))
}
MonoSubheader("const")
EnumDropdownMenu(selection: $selectedOS)
.onChange(of: selectedOS) {
manager.ts(.updateOSDropdown(selectedOS))
manager.ts(.selectedOS(selectedOS))
}
}
}

ComponentSection(header: "Switch") {
LargeSwitch(state: $switchValue)
.onChange(of: switchValue) {
manager.ts(.updateSwitch(switchValue))
manager.ts(.switchValue(switchValue))
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions ReactDemo/src/app/swift-components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { FC, ReactNode } from 'react';

const SwiftComponentsLayout: FC<{ children: ReactNode }> = ({ children }) => {
return (
<div>
<main>{children}</main>
<div className="min-h-screen flex justify-center">
<div className="py-6 px-3">
<h1 className="text-3xl font-bold mb-4">React</h1>
<p className="text-xs">This is a React web app</p>
<main>{children}</main>
</div>
</div>
);
};
Expand Down
84 changes: 15 additions & 69 deletions ReactDemo/src/app/swift-components/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Switch from '../../components/switches';
import ComponentSection from '../../components/sections';
import useExpose from '../../hooks/useExpose';
import useExposeType from '../../hooks/useExposeType';
import { handlers } from '@/utils/handlers';
import useExposeState from '@/hooks/useExposeState';

export enum Device {
Phone = 'Phone',
Expand All @@ -32,54 +32,19 @@ export const exposedTypes = {
};

const SplitComponentsView: FC = () => {
const [total, setTotal] = useState(0);
const [selectedDevice, setSelectedDevice] = useState<Device>();
const [selectedOS, setSelectedOS] = useState<OperatingSystemType>();
const [textFieldValue, setTextFieldValue] = useState<string>('');
const [switchValue, setSwitchValue] = useState<boolean>(false);

useEffect(() => {
postTotal(total);
}, [total]);

useEffect(() => {
if (selectedDevice) {
postDeviceDropdown(selectedDevice);
}
}, [selectedDevice]);

useEffect(() => {
if (selectedOS) {
postOSDropdown(selectedOS);
}
}, [selectedOS]);

useEffect(() => {
postSwitch(switchValue);
}, [switchValue]);

const postTotal = (value: number) => {
if (handlers.updateTotal) {
handlers.updateTotal.postMessage(value);
}
};

const postTextField = (value: string) => {
handlers.updateTextField.postMessage(value);
};

const postDeviceDropdown = (value: Device) => {
handlers.updateDeviceDropdown.postMessage(JSON.stringify(value));
};
const postOSDropdown = (value: OperatingSystemType) => {
handlers.updateOSDropdown.postMessage(value);
};

const postSwitch = (value: boolean) => {
if (handlers.updateSwitch) {
handlers.updateSwitch.postMessage(value);
}
};
const [total, setTotal] = useExposeState<number>(0, 'total');
const [selectedDevice, setSelectedDevice] =
useExposeState<Device>('selectedDevice');
const [selectedOS, setSelectedOS] =
useExposeState<OperatingSystemType>('selectedOS');
const [textFieldValue, setTextFieldValue] = useExposeState<string>(
'',
'textFieldValue'
);
const [switchValue, setSwitchValue] = useExposeState<boolean>(
true,
'switchValue'
);

const handleIncrement = () => {
updateTotal(total + 1);
Expand All @@ -91,18 +56,15 @@ const SplitComponentsView: FC = () => {

const handleDeviceSelect = (device: Device) => {
setSelectedDevice(device);
postDeviceDropdown(device);
};

const handleOSSelect = (os: OperatingSystemType) => {
setSelectedOS(os);
postOSDropdown(os);
};

const handleTextFieldChange = (event: ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value;
setTextFieldValue(newValue);
postTextField(newValue);
};

const handleSwitchChange = () => {
Expand All @@ -117,22 +79,18 @@ const SplitComponentsView: FC = () => {

const updateDeviceDropdown = (device: Device) => {
handleDeviceSelect(device);
postDeviceDropdown(device);
};

const updateOSDropdown = (os: OperatingSystemType) => {
handleOSSelect(os);
postOSDropdown(os);
};

const updateTextField = (text: string) => {
setTextFieldValue(text);
postTextField(text);
};

const updateSwitch = (state: boolean) => {
setSwitchValue(state);
postSwitch(state);
};

useExposeType(exposedTypes);
Expand Down Expand Up @@ -212,16 +170,4 @@ const OperatingSystemDropdown: FC<{
);
};

const SwiftComponents: FC = () => {
return (
<div className="min-h-screen flex justify-center">
<div className="py-6 px-3">
<h1 className="text-3xl font-bold mb-4">React</h1>
<p className="text-xs">This is a React web app</p>
<SplitComponentsView />
</div>
</div>
);
};

export default SwiftComponents;
export default SplitComponentsView;
Loading