about summary refs log tree commit diff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/expo-bluesky-translate/expo-module.config.json6
-rw-r--r--modules/expo-bluesky-translate/index.ts6
-rw-r--r--modules/expo-bluesky-translate/ios/Common/UIHostingControllerCompat.swift20
-rw-r--r--modules/expo-bluesky-translate/ios/ExpoBlueskyTranslate.podspec21
-rw-r--r--modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateModule.swift18
-rw-r--r--modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateView.swift22
-rw-r--r--modules/expo-bluesky-translate/ios/TranslateView.swift31
-rw-r--r--modules/expo-bluesky-translate/src/ExpoBlueskyTranslate.types.ts3
-rw-r--r--modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.ios.tsx48
-rw-r--r--modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.tsx13
-rw-r--r--modules/expo-scroll-forwarder/src/ExpoScrollForwarderView.tsx2
11 files changed, 190 insertions, 0 deletions
diff --git a/modules/expo-bluesky-translate/expo-module.config.json b/modules/expo-bluesky-translate/expo-module.config.json
new file mode 100644
index 000000000..28c5dd878
--- /dev/null
+++ b/modules/expo-bluesky-translate/expo-module.config.json
@@ -0,0 +1,6 @@
+{
+  "platforms": ["ios"],
+  "ios": {
+    "modules": ["ExpoBlueskyTranslateModule"]
+  }
+}
diff --git a/modules/expo-bluesky-translate/index.ts b/modules/expo-bluesky-translate/index.ts
new file mode 100644
index 000000000..f3e1d3b11
--- /dev/null
+++ b/modules/expo-bluesky-translate/index.ts
@@ -0,0 +1,6 @@
+export {
+  isAvailable,
+  isLanguageSupported,
+  NativeTranslationModule,
+  NativeTranslationView,
+} from './src/ExpoBlueskyTranslateView'
diff --git a/modules/expo-bluesky-translate/ios/Common/UIHostingControllerCompat.swift b/modules/expo-bluesky-translate/ios/Common/UIHostingControllerCompat.swift
new file mode 100644
index 000000000..c8ca3e027
--- /dev/null
+++ b/modules/expo-bluesky-translate/ios/Common/UIHostingControllerCompat.swift
@@ -0,0 +1,20 @@
+import ExpoModulesCore
+import SwiftUI
+
+// Thanks to Andrew Levy for this code snippet
+// https://github.com/andrew-levy/swiftui-react-native/blob/d3fbb2abf07601ff0d4b83055e7717bb980910d6/ios/Common/ExpoView%2BUIHostingController.swift
+
+extension ExpoView {
+  func setupHostingController(_ hostingController: UIHostingController<some View>) {
+    hostingController.view.translatesAutoresizingMaskIntoConstraints = false
+    hostingController.view.backgroundColor = .clear
+
+    addSubview(hostingController.view)
+    NSLayoutConstraint.activate([
+      hostingController.view.topAnchor.constraint(equalTo: self.topAnchor),
+      hostingController.view.bottomAnchor.constraint(equalTo: self.bottomAnchor),
+      hostingController.view.leftAnchor.constraint(equalTo: self.leftAnchor),
+      hostingController.view.rightAnchor.constraint(equalTo: self.rightAnchor),
+    ])
+  }
+}
diff --git a/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslate.podspec b/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslate.podspec
new file mode 100644
index 000000000..45f86a605
--- /dev/null
+++ b/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslate.podspec
@@ -0,0 +1,21 @@
+Pod::Spec.new do |s|
+  s.name           = 'ExpoBlueskyTranslate'
+  s.version        = '1.0.0'
+  s.summary        = 'Uses SwiftUI translation to translate text.'
+  s.description    = 'Uses SwiftUI translation to translate text.'
+  s.author         = ''
+  s.homepage       = 'https://docs.expo.dev/modules/'
+  s.platforms      = { :ios => '13.4' }
+  s.source         = { git: '' }
+  s.static_framework = true
+
+  s.dependency 'ExpoModulesCore'
+
+  # Swift/Objective-C compatibility
+  s.pod_target_xcconfig = {
+    'DEFINES_MODULE' => 'YES',
+    'SWIFT_COMPILATION_MODE' => 'wholemodule'
+  }
+
+  s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
+end
diff --git a/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateModule.swift b/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateModule.swift
new file mode 100644
index 000000000..afa813722
--- /dev/null
+++ b/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateModule.swift
@@ -0,0 +1,18 @@
+import ExpoModulesCore
+import Foundation
+import SwiftUI
+
+public class ExpoBlueskyTranslateModule: Module {
+  public func definition() -> ModuleDefinition {
+    Name("ExpoBlueskyTranslate")
+    
+    AsyncFunction("presentAsync") { (text: String) in
+      DispatchQueue.main.async { [weak state = TranslateViewState.shared] in
+        state?.isPresented = true
+        state?.text = text
+      }
+    }
+    
+    View(ExpoBlueskyTranslateView.self) {}
+  }
+}
diff --git a/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateView.swift b/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateView.swift
new file mode 100644
index 000000000..ca6e3be69
--- /dev/null
+++ b/modules/expo-bluesky-translate/ios/ExpoBlueskyTranslateView.swift
@@ -0,0 +1,22 @@
+import ExpoModulesCore
+import Foundation
+import SwiftUI
+
+class TranslateViewState: ObservableObject {
+  static var shared = TranslateViewState()
+  
+  @Published var isPresented = false
+  @Published var text = ""
+}
+
+class ExpoBlueskyTranslateView: ExpoView {
+  required init(appContext: AppContext? = nil) {
+    if #available(iOS 14.0, *) {
+      let hostingController = UIHostingController(rootView: TranslateView())
+      super.init(appContext: appContext)
+      setupHostingController(hostingController)
+    } else {
+      super.init(appContext: appContext)
+    }
+  }
+}
diff --git a/modules/expo-bluesky-translate/ios/TranslateView.swift b/modules/expo-bluesky-translate/ios/TranslateView.swift
new file mode 100644
index 000000000..e2886dc84
--- /dev/null
+++ b/modules/expo-bluesky-translate/ios/TranslateView.swift
@@ -0,0 +1,31 @@
+import SwiftUI
+// conditionally import the Translation module
+#if canImport(Translation)
+import Translation
+#endif
+
+struct TranslateView: View {
+  @ObservedObject var state = TranslateViewState.shared
+
+  var body: some View {
+    if #available(iOS 17.4, *) {
+      VStack {
+        UIViewRepresentableWrapper(view: UIView(frame: .zero))
+      }
+      .translationPresentation(
+        isPresented: $state.isPresented,
+        text: state.text
+      )
+    }
+  }
+}
+
+struct UIViewRepresentableWrapper: UIViewRepresentable {
+  let view: UIView
+
+  func makeUIView(context: Context) -> UIView {
+    return view
+  }
+
+  func updateUIView(_ uiView: UIView, context: Context) {}
+}
diff --git a/modules/expo-bluesky-translate/src/ExpoBlueskyTranslate.types.ts b/modules/expo-bluesky-translate/src/ExpoBlueskyTranslate.types.ts
new file mode 100644
index 000000000..a01d4d479
--- /dev/null
+++ b/modules/expo-bluesky-translate/src/ExpoBlueskyTranslate.types.ts
@@ -0,0 +1,3 @@
+export type ExpoBlueskyTranslateModule = {
+  presentAsync: (text: string) => Promise<void>
+}
diff --git a/modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.ios.tsx b/modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.ios.tsx
new file mode 100644
index 000000000..daddfa028
--- /dev/null
+++ b/modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.ios.tsx
@@ -0,0 +1,48 @@
+import React from 'react'
+import {Platform} from 'react-native'
+import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core'
+
+import {ExpoBlueskyTranslateModule} from './ExpoBlueskyTranslate.types'
+
+export const NativeTranslationModule =
+  requireNativeModule<ExpoBlueskyTranslateModule>('ExpoBlueskyTranslate')
+
+const NativeView: React.ComponentType = requireNativeViewManager(
+  'ExpoBlueskyTranslate',
+)
+
+export function NativeTranslationView() {
+  return <NativeView />
+}
+
+export const isAvailable = Number(Platform.Version) >= 17.4
+
+// https://en.wikipedia.org/wiki/Translate_(Apple)#Languages
+const SUPPORTED_LANGUAGES = [
+  'ar',
+  'zh',
+  'zh',
+  'nl',
+  'en',
+  'en',
+  'fr',
+  'de',
+  'id',
+  'it',
+  'ja',
+  'ko',
+  'pl',
+  'pt',
+  'ru',
+  'es',
+  'th',
+  'tr',
+  'uk',
+  'vi',
+]
+
+export function isLanguageSupported(lang?: string) {
+  // If the language is not provided, we assume it is supported
+  if (!lang) return true
+  return SUPPORTED_LANGUAGES.includes(lang)
+}
diff --git a/modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.tsx b/modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.tsx
new file mode 100644
index 000000000..16ff9d600
--- /dev/null
+++ b/modules/expo-bluesky-translate/src/ExpoBlueskyTranslateView.tsx
@@ -0,0 +1,13 @@
+export const NativeTranslationModule = {
+  presentAsync: async (_: string) => {},
+}
+
+export function NativeTranslationView() {
+  return null
+}
+
+export const isAvailable = false
+
+export function isLanguageSupported(_lang?: string) {
+  return false
+}
diff --git a/modules/expo-scroll-forwarder/src/ExpoScrollForwarderView.tsx b/modules/expo-scroll-forwarder/src/ExpoScrollForwarderView.tsx
index 93e69333f..0f5d01c13 100644
--- a/modules/expo-scroll-forwarder/src/ExpoScrollForwarderView.tsx
+++ b/modules/expo-scroll-forwarder/src/ExpoScrollForwarderView.tsx
@@ -1,5 +1,7 @@
 import React from 'react'
+
 import {ExpoScrollForwarderViewProps} from './ExpoScrollForwarder.types'
+
 export function ExpoScrollForwarderView({
   children,
 }: React.PropsWithChildren<ExpoScrollForwarderViewProps>) {