Files
ForumMobile/native-input/ios/Plugin/NativeInputPlugin.swift
2026-06-18 05:07:41 -05:00

118 lines
3.9 KiB
Swift

import Foundation
import Capacitor
@objc(NativeInputPlugin)
public class NativeInputPlugin: CAPPlugin {
private var bar: ChatInputBar?
private var currentChatId: String?
// MARK: Helpers
private func hostView() -> UIView? {
// Pin the bar as a sibling of the web view inside the same parent so it
// can float above the web content and track the keyboard.
return webView?.superview ?? webView
}
private func ensureBar() -> ChatInputBar? {
if let bar = bar { return bar }
guard let host = hostView() else { return nil }
let bar = ChatInputBar(hostView: host)
bar.onTextChange = { [weak self] text in
self?.notifyListeners("inputChange", data: ["text": text])
}
bar.onSend = { [weak self] text in
self?.notifyListeners("send", data: ["text": text])
}
bar.onAttach = { [weak self] in
self?.notifyListeners("attach", data: [:])
}
bar.onFocusChange = { [weak self] focused in
self?.notifyListeners("focusChange", data: ["focused": focused])
}
bar.onInsetChange = { [weak self] inset in
self?.notifyListeners("heightChange", data: ["bottomInset": Double(inset)])
}
bar.attach()
self.bar = bar
return bar
}
// MARK: Plugin methods
@objc func present(_ call: CAPPluginCall) {
let chatId = call.getString("chatId") ?? ""
let placeholder = call.getString("placeholder") ?? ""
let text = call.getString("text") ?? ""
let canSend = call.getBool("canSend") ?? true
let theme = call.getObject("theme")
DispatchQueue.main.async {
guard let bar = self.ensureBar() else { call.reject("No host view"); return }
bar.setVisible(true)
if let theme = theme { bar.applyTheme(theme) }
bar.setPlaceholder(placeholder)
bar.setEnabled(canSend)
// Only reset text when switching to a different chat; otherwise keep
// whatever the user already had typed in this bar.
if self.currentChatId != chatId {
bar.text = text
self.currentChatId = chatId
}
call.resolve()
}
}
@objc func dismiss(_ call: CAPPluginCall) {
DispatchQueue.main.async {
self.bar?.removeFromHost()
self.bar = nil
self.currentChatId = nil
call.resolve()
}
}
@objc func setText(_ call: CAPPluginCall) {
let text = call.getString("text") ?? ""
DispatchQueue.main.async {
self.bar?.text = text
call.resolve()
}
}
@objc func getText(_ call: CAPPluginCall) {
DispatchQueue.main.async {
call.resolve(["text": self.bar?.text ?? ""])
}
}
@objc func focus(_ call: CAPPluginCall) {
DispatchQueue.main.async { self.bar?.focus(); call.resolve() }
}
@objc func blur(_ call: CAPPluginCall) {
DispatchQueue.main.async { self.bar?.blur(); call.resolve() }
}
@objc func setPlaceholder(_ call: CAPPluginCall) {
let placeholder = call.getString("placeholder") ?? ""
DispatchQueue.main.async { self.bar?.setPlaceholder(placeholder); call.resolve() }
}
@objc func setEnabled(_ call: CAPPluginCall) {
let enabled = call.getBool("enabled") ?? true
DispatchQueue.main.async { self.bar?.setEnabled(enabled); call.resolve() }
}
@objc func setTheme(_ call: CAPPluginCall) {
let theme = call.getObject("theme") ?? [:]
DispatchQueue.main.async { self.bar?.applyTheme(theme); call.resolve() }
}
@objc func setVisible(_ call: CAPPluginCall) {
let visible = call.getBool("visible") ?? true
DispatchQueue.main.async { self.bar?.setVisible(visible); call.resolve() }
}
}