about summary refs log tree commit diff
path: root/src/lib/hooks
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2025-08-11 18:37:39 +0300
committerGitHub <noreply@github.com>2025-08-11 08:37:39 -0700
commitbb949e4f44c4ed1e19c7bddc5779515b419a7022 (patch)
tree9cb70c6573ee6c4224de38b625f91483e52a5983 /src/lib/hooks
parent2a6172cbaf2db0eda2a7cd2afaeef4b60aadf3ba (diff)
downloadvoidsky-bb949e4f44c4ed1e19c7bddc5779515b419a7022.tar.zst
Fix translations on Android using PROCESS_TEXT intent (#8486)
* use intents to translate text on android

* clean up config plugins

* restore day night plugin

just to be safe

* leave a comment for why we can't open translate directly

* add todo

* fix lockfile lint
Diffstat (limited to 'src/lib/hooks')
-rw-r--r--src/lib/hooks/useTranslate.ts54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/lib/hooks/useTranslate.ts b/src/lib/hooks/useTranslate.ts
new file mode 100644
index 000000000..7824a682c
--- /dev/null
+++ b/src/lib/hooks/useTranslate.ts
@@ -0,0 +1,54 @@
+import {useCallback} from 'react'
+import * as IntentLauncher from 'expo-intent-launcher'
+
+import {getTranslatorLink} from '#/locale/helpers'
+import {isAndroid} from '#/platform/detection'
+import {useOpenLink} from './useOpenLink'
+
+export function useTranslate() {
+  const openLink = useOpenLink()
+
+  return useCallback(
+    async (text: string, language: string) => {
+      const translateUrl = getTranslatorLink(text, language)
+      if (isAndroid) {
+        try {
+          // use getApplicationIconAsync to determine if the translate app is installed
+          if (
+            !(await IntentLauncher.getApplicationIconAsync(
+              'com.google.android.apps.translate',
+            ))
+          ) {
+            throw new Error('Translate app not installed')
+          }
+
+          // TODO: this should only be called one at a time, use something like
+          // RQ's `scope` - otherwise can trigger the browser to open unexpectedly when the call throws -sfn
+          await IntentLauncher.startActivityAsync(
+            'android.intent.action.PROCESS_TEXT',
+            {
+              type: 'text/plain',
+              extra: {
+                'android.intent.extra.PROCESS_TEXT': text,
+                'android.intent.extra.PROCESS_TEXT_READONLY': true,
+              },
+              // note: to skip the intermediate app select, we need to specify a
+              // `className`. however, this isn't safe to hardcode, we'd need to query the
+              // package manager for the correct activity. this requires native code, so
+              // skip for now -sfn
+              // packageName: 'com.google.android.apps.translate',
+              // className: 'com.google.android.apps.translate.TranslateActivity',
+            },
+          )
+        } catch (err) {
+          if (__DEV__) console.error(err)
+          // most likely means they don't have the translate app
+          await openLink(translateUrl)
+        }
+      } else {
+        await openLink(translateUrl)
+      }
+    },
+    [openLink],
+  )
+}