Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Strip metadata using @uwx/exif-be-gone-web instead of reencoding

authored by

uwx and committed by tangled.org 5a796ad1 39eae538

+127 -7
+2
package.json
··· 136 136 "@types/invariant": "^2.2.37", 137 137 "@types/lodash.throttle": "^4.1.9", 138 138 "@types/node": "^20.14.3", 139 + "@uwx/exif-be-gone-web": "1.6.5", 139 140 "array.prototype.findlast": "^1.2.3", 140 141 "babel-plugin-transform-remove-console": "^6.9.4", 142 + "base64-js": "^1.5.1", 141 143 "bcp-47": "^2.1.0", 142 144 "bcp-47-match": "^2.0.3", 143 145 "chroma-js": "^3.2.0",
+54 -6
src/state/gallery.ts
··· 12 12 SaveFormat, 13 13 } from 'expo-image-manipulator' 14 14 import {type BlobRef} from '@atproto/api' 15 + import {transformExif} from '@uwx/exif-be-gone-web' 16 + import {toByteArray} from 'base64-js' 15 17 import {nanoid} from 'nanoid/non-secure' 16 18 17 19 import {POST_IMG_MAX} from '#/lib/constants' ··· 207 209 async function bypassCompression( 208 210 img: ComposerImage, 209 211 ): Promise<PickerImage | undefined> { 212 + // TODO: use expo-file-system instead of working directly in memory 213 + 214 + function dataUriToUint8Array(uri: string) { 215 + const base64 = uri.split(',')[1] 216 + return toByteArray(base64) 217 + } 218 + 219 + function toArrayBuffer(uint8: Uint8Array) { 220 + if (uint8.buffer instanceof ArrayBuffer) { 221 + if ( 222 + uint8.byteOffset === 0 && 223 + uint8.byteLength === uint8.buffer.byteLength 224 + ) { 225 + return uint8.buffer 226 + } 227 + 228 + return uint8.buffer.slice( 229 + uint8.byteOffset, 230 + uint8.byteOffset + uint8.byteLength, 231 + ) 232 + } 233 + 234 + // Fallback for environments where Uint8Array.buffer is not an ArrayBuffer 235 + const buffer = new ArrayBuffer(uint8.length) 236 + const view = new Uint8Array(buffer) 237 + view.set(uint8) 238 + return buffer 239 + } 240 + 210 241 const source = img.transformed || img.source 211 242 if ( 212 243 source.width > POST_IMG_MAX.width || ··· 227 258 return undefined 228 259 } 229 260 261 + let data: Uint8Array 262 + 230 263 const path = source.path 231 264 // convert path to data URI if it is not already 232 265 if (!path.startsWith('data:')) { 233 266 try { 234 267 await fetch(path) 235 268 const response = await fetch(path) 236 - const blob = await response.blob() 237 - if (blob.size > POST_IMG_MAX.size) { 269 + data = new Uint8Array(await response.arrayBuffer()) 270 + if (data.byteLength > POST_IMG_MAX.size) { 238 271 return undefined 239 272 } 240 - // path = await blobToDataUri(blob) 241 273 } catch (e) { 242 274 // Fetch failed, likely due to CORS. Return undefined to trigger normal compression flow and error handling. 243 275 return undefined 244 276 } 245 - } else if (getDataUriSize(path) > POST_IMG_MAX.size) { 277 + } else { 278 + if (getDataUriSize(path) > POST_IMG_MAX.size) { 279 + return undefined 280 + } 281 + data = new Uint8Array(dataUriToUint8Array(path).buffer) 282 + } 283 + 284 + try { 285 + data = await transformExif(data) 286 + } catch (err) { 287 + console.error( 288 + 'Failed to transform EXIF data, proceeding with original image', 289 + err, 290 + ) 246 291 return undefined 247 292 } 248 293 294 + const dataUri = await blobToDataUri( 295 + new Blob([toArrayBuffer(data)], {type: source.mime}), 296 + ) 249 297 return { 250 - path: await moveIfNecessary(path), 298 + path: dataUri, 251 299 width: source.width, 252 300 height: source.height, 253 301 mime: source.mime, 254 - size: getDataUriSize(path), 302 + size: getDataUriSize(dataUri), 255 303 } 256 304 } 257 305
+71 -1
yarn.lock
··· 5105 5105 resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" 5106 5106 integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== 5107 5107 5108 + "@sindresorhus/merge-streams@^4.0.0": 5109 + version "4.0.0" 5110 + resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#abb11d99aeb6d27f1b563c38147a72d50058e339" 5111 + integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== 5112 + 5108 5113 "@sinonjs/commons@^3.0.0": 5109 5114 version "3.0.0" 5110 5115 resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" ··· 5853 5858 dependencies: 5854 5859 "@urql/core" "^5.0.0" 5855 5860 wonka "^6.3.2" 5861 + 5862 + "@uwx/exif-be-gone-web@1.6.5": 5863 + version "1.6.5" 5864 + resolved "https://registry.yarnpkg.com/@uwx/exif-be-gone-web/-/exif-be-gone-web-1.6.5.tgz#4956529e3fa31b4f49b0627380de15e014606789" 5865 + integrity sha512-KLcTMfusQmYPzI9cvoacm8tX/z6259AN6dBIJf31pfhQCnE23IODY0nQte1Hxxo+3uVKHBFEmg+Y0EI+gnwtQA== 5866 + dependencies: 5867 + fflate "^0.8.2" 5868 + globby "^16.2.0" 5869 + hex-encoding "^2.0.3" 5856 5870 5857 5871 "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": 5858 5872 version "1.11.6" ··· 9309 9323 merge2 "^1.3.0" 9310 9324 micromatch "^4.0.4" 9311 9325 9326 + fast-glob@^3.3.3: 9327 + version "3.3.3" 9328 + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" 9329 + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== 9330 + dependencies: 9331 + "@nodelib/fs.stat" "^2.0.2" 9332 + "@nodelib/fs.walk" "^1.2.3" 9333 + glob-parent "^5.1.2" 9334 + merge2 "^1.3.0" 9335 + micromatch "^4.0.8" 9336 + 9312 9337 fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: 9313 9338 version "2.1.0" 9314 9339 resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" ··· 9384 9409 version "6.5.0" 9385 9410 resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" 9386 9411 integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== 9412 + 9413 + fflate@^0.8.2: 9414 + version "0.8.2" 9415 + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" 9416 + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== 9387 9417 9388 9418 file-entry-cache@^8.0.0: 9389 9419 version "8.0.0" ··· 9867 9897 merge2 "^1.4.1" 9868 9898 slash "^4.0.0" 9869 9899 9900 + globby@^16.2.0: 9901 + version "16.2.0" 9902 + resolved "https://registry.yarnpkg.com/globby/-/globby-16.2.0.tgz#6ab1351fbac1d9b9e47ed423814c2ad41af308ea" 9903 + integrity sha512-QrJia2qDf5BB/V6HYlDTs0I0lBahyjLzpGQg3KT7FnCdTonAyPy2RtY802m2k4ALx6Dp752f82WsOczEVr3l6Q== 9904 + dependencies: 9905 + "@sindresorhus/merge-streams" "^4.0.0" 9906 + fast-glob "^3.3.3" 9907 + ignore "^7.0.5" 9908 + is-path-inside "^4.0.0" 9909 + slash "^5.1.0" 9910 + unicorn-magic "^0.4.0" 9911 + 9870 9912 globby@^6.1.0: 9871 9913 version "6.1.0" 9872 9914 resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" ··· 10026 10068 integrity sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA== 10027 10069 dependencies: 10028 10070 hermes-estree "0.25.1" 10071 + 10072 + hex-encoding@^2.0.3: 10073 + version "2.0.3" 10074 + resolved "https://registry.yarnpkg.com/hex-encoding/-/hex-encoding-2.0.3.tgz#59ecfa5c07170f29405db7c2a7633b1ad380df47" 10075 + integrity sha512-sSmMo4ij2Vejht+5UkzuzNGiYgIWTSUw0GQqxHIQXsuuXB1ozYnjCZJZ/nwWNYRoU8+92Dp736wqxmiAN6/fcw== 10076 + dependencies: 10077 + node-buffer-encoding "^1.0.3" 10078 + uint8-encoding "^2.0.1" 10029 10079 10030 10080 hls.js@^1.6.2: 10031 10081 version "1.6.2" ··· 10624 10674 dependencies: 10625 10675 path-is-inside "^1.0.2" 10626 10676 10677 + is-path-inside@^4.0.0: 10678 + version "4.0.0" 10679 + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-4.0.0.tgz#805aeb62c47c1b12fc3fd13bfb3ed1e7430071db" 10680 + integrity sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA== 10681 + 10627 10682 is-plain-obj@^2.1.0: 10628 10683 version "2.1.0" 10629 10684 resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" ··· 12492 12547 lower-case "^2.0.2" 12493 12548 tslib "^2.0.3" 12494 12549 12550 + node-buffer-encoding@^1.0.3: 12551 + version "1.0.3" 12552 + resolved "https://registry.yarnpkg.com/node-buffer-encoding/-/node-buffer-encoding-1.0.3.tgz#94bab4c82e8ace9e69c17771f9fe8269f9469ddd" 12553 + integrity sha512-9hJZNChhQoCN1rCFScJiEwtzvWEJw2wSnu2nhDLD/YOYl1Ce8GbtnorsnjwwjpSk4sWE7zSp2etX6j7+bO7fVA== 12554 + 12495 12555 node-fetch@2.7.0: 12496 12556 version "2.7.0" 12497 12557 resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" ··· 15023 15083 resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" 15024 15084 integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== 15025 15085 15026 - slash@^5.0.0: 15086 + slash@^5.0.0, slash@^5.1.0: 15027 15087 version "5.1.0" 15028 15088 resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" 15029 15089 integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== ··· 15949 16009 resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" 15950 16010 integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== 15951 16011 16012 + uint8-encoding@^2.0.1: 16013 + version "2.0.1" 16014 + resolved "https://registry.yarnpkg.com/uint8-encoding/-/uint8-encoding-2.0.1.tgz#f8011194c8e576f9629dfd751b2c36d468dcaf59" 16015 + integrity sha512-xZAjZ+3OvrDtjFLLgojrLmG6T0YwZEo0OTyqCBxFjlFimIKnLtFqyYk6z/jDOUlJFJE52Srtrv4W4x7t4Cn/dA== 16016 + 15952 16017 uint8arrays@3.0.0: 15953 16018 version "3.0.0" 15954 16019 resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.0.0.tgz#260869efb8422418b6f04e3fac73a3908175c63b" ··· 16013 16078 version "0.14.5" 16014 16079 resolved "https://registry.yarnpkg.com/unicode-segmenter/-/unicode-segmenter-0.14.5.tgz#c658f6dd30de172cdcd94542adc205ba43fb63c6" 16015 16080 integrity sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g== 16081 + 16082 + unicorn-magic@^0.4.0: 16083 + version "0.4.0" 16084 + resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.4.0.tgz#78c6a090fd6d07abd2468b83b385603e00dfdb24" 16085 + integrity sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw== 16016 16086 16017 16087 universalify@^0.2.0: 16018 16088 version "0.2.0"