about summary refs log tree commit diff
path: root/src/lib/hooks
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-02-27 15:22:03 -0800
committerGitHub <noreply@github.com>2024-02-27 15:22:03 -0800
commitd451f82f54974b7b3da1477a7e1f221628860f62 (patch)
tree631d60b9d9ef47129529068753b10029fb99c34f /src/lib/hooks
parentac726497a475f7492ee0269851979817b17d98c2 (diff)
downloadvoidsky-d451f82f54974b7b3da1477a7e1f221628860f62.tar.zst
Share Extension/Intents (#2587)
* add native ios code outside of ios project

* helper script

* going to be a lot of these commits to squash...backing up

* save

* start of an expo plugin

* create info.plist

* copy the view controller

* maybe working

* working

* wait working now

* working plugin

* use current scheme

* update intent path

* use better params

* support text in uri

* build

* use better encoding

* handle images

* cleanup ios plugin

* android

* move bash script to /scripts

* handle cases where loaded data is uiimage rather than uri

* remove unnecessary logic, allow more than 4 images and just take first 4

* android build plugin

* limit images to four on android

* use js for plugins, no need to build

* revert changes to app config

* use correct scheme on android

* android readme

* move ios extension to /modules

* remove unnecessary event

* revert typo

* plugin readme

* scripts readme

* add configurable scheme to .env, default to `bluesky`

* remove debug

* revert .gitignore change

* add comment about updating .env to app.config.js for those modifying scheme

* modify .env

* update android module to use the proper url

* update ios extension

* remove comment

* parse and validate incoming image uris

* fix types

* rm oops

* fix a few typos
Diffstat (limited to 'src/lib/hooks')
-rw-r--r--src/lib/hooks/useIntentHandler.ts35
1 files changed, 29 insertions, 6 deletions
diff --git a/src/lib/hooks/useIntentHandler.ts b/src/lib/hooks/useIntentHandler.ts
index 249e6898e..de9a96da9 100644
--- a/src/lib/hooks/useIntentHandler.ts
+++ b/src/lib/hooks/useIntentHandler.ts
@@ -6,6 +6,8 @@ import {useSession} from 'state/session'
 
 type IntentType = 'compose'
 
+const VALID_IMAGE_REGEX = /^[\w.:\-_/]+\|\d+(\.\d+)?\|\d+(\.\d+)?$/
+
 export function useIntentHandler() {
   const incomingUrl = Linking.useURL()
   const composeIntent = useComposeIntent()
@@ -29,7 +31,7 @@ export function useIntentHandler() {
         case 'compose': {
           composeIntent({
             text: params.get('text'),
-            imageUris: params.get('imageUris'),
+            imageUrisStr: params.get('imageUris'),
           })
         }
       }
@@ -45,18 +47,39 @@ function useComposeIntent() {
 
   return React.useCallback(
     ({
-      // eslint-disable-next-line @typescript-eslint/no-unused-vars
       text,
-      // eslint-disable-next-line @typescript-eslint/no-unused-vars
-      imageUris,
+      imageUrisStr,
     }: {
       text: string | null
-      imageUris: string | null // unused for right now, will be used later with intents
+      imageUrisStr: string | null // unused for right now, will be used later with intents
     }) => {
       if (!hasSession) return
 
+      const imageUris = imageUrisStr
+        ?.split(',')
+        .filter(part => {
+          // For some security, we're going to filter out any image uri that is external. We don't want someone to
+          // be able to provide some link like "bluesky://intent/compose?imageUris=https://IHaveYourIpNow.com/image.jpeg
+          // and we load that image
+          if (part.includes('https://') || part.includes('http://')) {
+            return false
+          }
+          // We also should just filter out cases that don't have all the info we need
+          if (!VALID_IMAGE_REGEX.test(part)) {
+            return false
+          }
+          return true
+        })
+        .map(part => {
+          const [uri, width, height] = part.split('|')
+          return {uri, width: Number(width), height: Number(height)}
+        })
+
       setTimeout(() => {
-        openComposer({}) // will pass in values to the composer here in the share extension
+        openComposer({
+          text: text ?? undefined,
+          imageUris: isNative ? imageUris : undefined,
+        })
       }, 500)
     },
     [openComposer, hasSession],