mirror of
https://github.com/VibedByKaKi/t3-code-android-nightly.git
synced 2026-10-11 21:01:16 +02:00
Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Bilal Bakr <62337003+Bil0000@users.noreply.github.com> Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Vitalii Yehorov <vitalyiegorov@gmail.com> Co-authored-by: Jake Leventhal <jakeleventhal@me.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Alex Southwell <saphid@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Nicholas Wasmiller <derped@mineperial.com> Co-authored-by: PB <poilmb@gmail.com> Co-authored-by: Exotic <118054752+extoci@users.noreply.github.com> Co-authored-by: Yash Singh <saiansh2525@gmail.com> Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: Gabriel De Andrade <30420087+gabrielelpidio@users.noreply.github.com> Co-authored-by: Dara Adedeji <76637177+SunkenInTime@users.noreply.github.com> Co-authored-by: scratchyone <scratchywon@gmail.com> Co-authored-by: Dominic Roy <dominic@sdko.org> Co-authored-by: chukfinley <chuk@chuk.dev> Co-authored-by: Primož Ajdišek <bigpod@bigpod.si> Co-authored-by: benthecarman <benthecarman@live.com> Co-authored-by: NaveDanan <nave0712@gmail.com> Co-authored-by: aaditagrawal <103925638+aaditagrawal@users.noreply.github.com> Co-authored-by: Aditya Garud <153842990+yashranaway@users.noreply.github.com> Co-authored-by: Nick Anisimov <n.anisimov.23@gmail.com> Co-authored-by: MacKinley Smith <smithmackinley@gmail.com> Co-authored-by: Yordis Prieto <yordis.prieto@gmail.com> Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: AKolenda <akole779@mtroyal.ca> Co-authored-by: Guillermo Casanova <75276669+Gigioxx@users.noreply.github.com> Co-authored-by: Otavio Salvador <otavio@ossystems.com.br> Co-authored-by: Shirish Pothi <183252392+shirishpothi@users.noreply.github.com> Co-authored-by: Ishaan Kothari <ishaanko.mail@gmail.com> Co-authored-by: Bob Fowler <bob@rjf.ca> Co-authored-by: Anton Bezdenezhnykh <gamer392@yandex.ru> Co-authored-by: ValeraZSD <48602572+ValeraZSD@users.noreply.github.com> Co-authored-by: Ephraim <ephraim39hr14m@gmail.com> Co-authored-by: Ryan Ilano <ryanilano@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: maco <gosarmarcel7@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Tristan Knight <admin@snappeh.com> Co-authored-by: PR Batch Tester <agent@local.test> Co-authored-by: oliver <97427849+flamboh@users.noreply.github.com> Co-authored-by: kamkm <99585688+Kamkmgamer@users.noreply.github.com> Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
134 lines
5.5 KiB
Swift
134 lines
5.5 KiB
Swift
import ExpoModulesCore
|
|
import UIKit
|
|
|
|
enum T3ComposerClipboard {
|
|
static let fragmentType = "app.t3.context-fragment"
|
|
|
|
static func write(text: String, fragment: String) {
|
|
var items: [String: Any] = ["public.utf8-plain-text": text]
|
|
if let data = fragment.data(using: .utf8),
|
|
var payload = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
let records = payload["records"] as? [[String: Any]] {
|
|
var selected = records.filter { record in
|
|
guard let id = record["contextId"] as? String else { return false }
|
|
return text.contains("/\(id))")
|
|
}
|
|
let screenshots = Set(selected.compactMap { $0["screenshotContextId"] as? String })
|
|
selected.append(contentsOf: records.filter { screenshots.contains($0["contextId"] as? String ?? "") && !text.contains("/\($0["contextId"] as? String ?? ""))") })
|
|
payload["records"] = selected
|
|
if !selected.isEmpty, let encoded = try? JSONSerialization.data(withJSONObject: payload), let raw = String(data: encoded, encoding: .utf8) {
|
|
let attribute = raw.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? ""
|
|
let escaped = text.replacingOccurrences(of: "&", with: "&").replacingOccurrences(of: "<", with: "<").replacingOccurrences(of: ">", with: ">")
|
|
items[fragmentType] = encoded
|
|
items["public.html"] = Data("<pre data-t3-context-fragment=\"\(attribute)\">\(escaped)</pre>".utf8)
|
|
}
|
|
}
|
|
UIPasteboard.general.items = [items]
|
|
}
|
|
|
|
static func read() -> [String: String] {
|
|
let board = UIPasteboard.general
|
|
return [
|
|
"text": board.string ?? "",
|
|
"fragment": board.data(forPasteboardType: fragmentType).flatMap { String(data: $0, encoding: .utf8) } ?? "",
|
|
"html": board.data(forPasteboardType: "public.html").flatMap { String(data: $0, encoding: .utf8) } ?? "",
|
|
]
|
|
}
|
|
}
|
|
|
|
// Expo Modules 2.0: the clipboard function is a @JS member; the view stays in
|
|
// definition() until the 2.0 view API lands.
|
|
@ExpoModule("T3ComposerEditor")
|
|
public class T3ComposerEditorModule: Module {
|
|
// UIPasteboard is main-thread only, so the member is main-actor isolated.
|
|
@JS
|
|
@MainActor
|
|
func writeContextClipboard(text: String, fragment: String) async {
|
|
T3ComposerClipboard.write(text: text, fragment: fragment)
|
|
}
|
|
|
|
public func definition() -> ModuleDefinition {
|
|
View(T3ComposerEditorView.self) {
|
|
Prop("controlledDocumentJson") { (view: T3ComposerEditorView, documentJson: String) in
|
|
view.setControlledDocumentJson(documentJson)
|
|
}
|
|
Prop("themeJson") { (view: T3ComposerEditorView, themeJson: String) in
|
|
view.setThemeJson(themeJson)
|
|
}
|
|
Prop("clipboardFragment") { (view: T3ComposerEditorView, fragment: String) in
|
|
view.setClipboardFragment(fragment)
|
|
}
|
|
Prop("placeholder") { (view: T3ComposerEditorView, placeholder: String) in
|
|
view.setPlaceholder(placeholder)
|
|
}
|
|
Prop("fontFamily") { (view: T3ComposerEditorView, fontFamily: String) in
|
|
view.setFontFamily(fontFamily)
|
|
}
|
|
Prop("fontSize") { (view: T3ComposerEditorView, fontSize: Double) in
|
|
view.setFontSize(CGFloat(fontSize))
|
|
}
|
|
Prop("lineHeight") { (view: T3ComposerEditorView, lineHeight: Double) in
|
|
view.setLineHeight(CGFloat(lineHeight))
|
|
}
|
|
Prop("contentInsetVertical") { (view: T3ComposerEditorView, contentInsetVertical: Double) in
|
|
view.setContentInsetVertical(CGFloat(contentInsetVertical))
|
|
}
|
|
Prop("editable") { (view: T3ComposerEditorView, editable: Bool) in
|
|
view.setEditable(editable)
|
|
}
|
|
Prop("readOnly") { (view: T3ComposerEditorView, readOnly: Bool) in
|
|
view.setReadOnly(readOnly)
|
|
}
|
|
Prop("scrollEnabled") { (view: T3ComposerEditorView, scrollEnabled: Bool) in
|
|
view.setScrollEnabled(scrollEnabled)
|
|
}
|
|
Prop("autoFocus") { (view: T3ComposerEditorView, autoFocus: Bool) in
|
|
view.setAutoFocus(autoFocus)
|
|
}
|
|
Prop("autoCorrect") { (view: T3ComposerEditorView, autoCorrect: Bool) in
|
|
view.setAutoCorrect(autoCorrect)
|
|
}
|
|
Prop("spellCheck") { (view: T3ComposerEditorView, spellCheck: Bool) in
|
|
view.setSpellCheck(spellCheck)
|
|
}
|
|
Prop("submitTitle") { (view: T3ComposerEditorView, title: String) in
|
|
view.setSubmitTitle(title)
|
|
}
|
|
Prop("alternateSubmitTitle") { (view: T3ComposerEditorView, title: String) in
|
|
view.setAlternateSubmitTitle(title)
|
|
}
|
|
Prop("enterBehavior") { (view: T3ComposerEditorView, behavior: String) in
|
|
view.setEnterBehavior(behavior)
|
|
}
|
|
Prop("textPasteThresholdBytes") { (view: T3ComposerEditorView, threshold: Int) in
|
|
view.setTextPasteThresholdBytes(threshold)
|
|
}
|
|
Prop("maxInputChars") { (view: T3ComposerEditorView, maxInputChars: Int) in
|
|
view.setMaxInputChars(maxInputChars)
|
|
}
|
|
|
|
Events(
|
|
"onComposerChange",
|
|
"onComposerSelectionChange",
|
|
"onComposerFocus",
|
|
"onComposerBlur",
|
|
"onComposerSubmit",
|
|
"onComposerPasteImages",
|
|
"onComposerContextPress",
|
|
"onComposerPasteContext",
|
|
"onComposerPasteText",
|
|
"onComposerContentSizeChange"
|
|
)
|
|
|
|
AsyncFunction("focus") { (view: T3ComposerEditorView) in
|
|
view.focusEditor()
|
|
}
|
|
AsyncFunction("blur") { (view: T3ComposerEditorView) in
|
|
view.blurEditor()
|
|
}
|
|
AsyncFunction("setSelection") { (view: T3ComposerEditorView, start: Int, end: Int) in
|
|
view.setSelection(start: start, end: end)
|
|
}
|
|
}
|
|
}
|
|
}
|