An ATproto social media client -- with an independent Appview.

[Video] Add dimension info to share intent (#5639)

authored by hailey.at and committed by

GitHub ee25b898 94e7bfbe

+47 -14
+20 -10
modules/Share-with-Bluesky/ShareViewController.swift
··· 1 1 import UIKit 2 + import AVKit 2 3 3 4 let IMAGE_EXTENSIONS: [String] = ["png", "jpg", "jpeg", "gif", "heic"] 4 5 let MOVIE_EXTENSIONS: [String] = ["mov", "mp4", "m4v"] ··· 119 120 private func handleVideos(items: [NSItemProvider]) async { 120 121 let firstItem = items.first 121 122 122 - if let dataUri = try? await firstItem?.loadItem(forTypeIdentifier: "public.movie") as? URL { 123 - let ext = String(dataUri.lastPathComponent.split(separator: ".").last ?? "mp4") 124 - if let tempUrl = getTempUrl(ext: ext) { 125 - let data = try? Data(contentsOf: dataUri) 126 - try? data?.write(to: tempUrl) 127 - 128 - if let encoded = tempUrl.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), 129 - let url = URL(string: "\(self.appScheme)://intent/compose?videoUri=\(encoded)") { 130 - _ = self.openURL(url) 131 - } 123 + if let dataUrl = try? await firstItem?.loadItem(forTypeIdentifier: "public.movie") as? URL { 124 + let ext = String(dataUrl.lastPathComponent.split(separator: ".").last ?? "mp4") 125 + if let videoUriInfo = saveVideoWithInfo(dataUrl), 126 + let url = URL(string: "\(self.appScheme)://intent/compose?videoUri=\(videoUriInfo)") { 127 + _ = self.openURL(url) 132 128 } 133 129 } 134 130 ··· 151 147 } 152 148 } catch {} 153 149 return nil 150 + } 151 + 152 + private func saveVideoWithInfo(_ dataUrl: URL) -> String? { 153 + let ext = String(dataUrl.lastPathComponent.split(separator: ".").last ?? "mp4") 154 + guard let tempUrl = getTempUrl(ext: ext), 155 + let track = AVURLAsset(url: dataUrl).tracks(withMediaType: AVMediaType.video).first else { 156 + return nil 157 + } 158 + let size = track.naturalSize.applying(track.preferredTransform) 159 + 160 + let data = try? Data(contentsOf: dataUrl) 161 + try? data?.write(to: tempUrl) 162 + 163 + return "\(tempUrl.absoluteString)|\(size.width)||\(size.height)" 154 164 } 155 165 156 166 private func completeRequest() {
+23 -1
modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt
··· 2 2 3 3 import android.content.Intent 4 4 import android.graphics.Bitmap 5 + import android.media.MediaMetadataRetriever 5 6 import android.net.Uri 6 7 import android.os.Build 7 8 import android.provider.MediaStore ··· 143 144 appContext.currentActivity?.contentResolver?.openInputStream(uri)?.use { 144 145 it.copyTo(out) 145 146 } 146 - "bluesky://intent/compose?videoUri=${URLEncoder.encode(file.path, "UTF-8")}".toUri().let { 147 + 148 + val info = getVideoInfo(uri) ?: return 149 + 150 + "bluesky://intent/compose?videoUri=${URLEncoder.encode(file.path, "UTF-8")}|${info["width"]}|${info["height"]}".toUri().let { 147 151 val newIntent = Intent(Intent.ACTION_VIEW, it) 148 152 appContext.currentActivity?.startActivity(newIntent) 149 153 } ··· 163 167 "width" to bitmap.width, 164 168 "height" to bitmap.height, 165 169 "path" to file.path.toString(), 170 + ) 171 + } 172 + 173 + private fun getVideoInfo(uri: Uri): Map<String, Any>? { 174 + val retriever = MediaMetadataRetriever() 175 + retriever.setDataSource(appContext.currentActivity, uri) 176 + 177 + val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() 178 + val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() 179 + 180 + if (width == null || height == null) { 181 + return null 182 + } 183 + 184 + return mapOf( 185 + "width" to width, 186 + "height" to height, 187 + "path" to uri.path.toString(), 166 188 ) 167 189 } 168 190
+2 -1
src/lib/hooks/useIntentHandler.ts
··· 93 93 94 94 // Whenever a video URI is present, we don't support adding images right now. 95 95 if (videoUri) { 96 + const [uri, width, height] = videoUri.split('|') 96 97 openComposer({ 97 98 text: text ?? undefined, 98 - videoUri, 99 + videoUri: {uri, width: Number(width), height: Number(height)}, 99 100 }) 100 101 return 101 102 }
+1 -1
src/state/shell/composer/index.tsx
··· 38 38 openEmojiPicker?: (pos: DOMRect | undefined) => void 39 39 text?: string 40 40 imageUris?: {uri: string; width: number; height: number; altText?: string}[] 41 - videoUri?: string 41 + videoUri?: {uri: string; width: number; height: number} 42 42 } 43 43 44 44 type StateContext = ComposerOpts | undefined
+1 -1
src/view/com/composer/Composer.tsx
··· 218 218 // Whenever we receive an initial video uri, we should immediately run compression if necessary 219 219 useEffect(() => { 220 220 if (initVideoUri) { 221 - selectVideo({uri: initVideoUri} as ImagePickerAsset) 221 + selectVideo(initVideoUri) 222 222 } 223 223 }, [initVideoUri, selectVideo]) 224 224