Add deviceId and deviceName to drafts, skip loading media for other devies
This commit is contained in:
@@ -119,6 +119,7 @@ module.exports = function (_config) {
|
|||||||
'com.apple.developer.kernel.increased-memory-limit': true,
|
'com.apple.developer.kernel.increased-memory-limit': true,
|
||||||
'com.apple.developer.kernel.extended-virtual-addressing': true,
|
'com.apple.developer.kernel.extended-virtual-addressing': true,
|
||||||
'com.apple.security.application-groups': 'group.app.bsky',
|
'com.apple.security.application-groups': 'group.app.bsky',
|
||||||
|
'com.apple.developer.device-information.user-assigned-device-name': true,
|
||||||
},
|
},
|
||||||
privacyManifests: {
|
privacyManifests: {
|
||||||
NSPrivacyCollectedDataTypes: [
|
NSPrivacyCollectedDataTypes: [
|
||||||
|
|||||||
+1
-1
@@ -73,7 +73,7 @@
|
|||||||
"icons:optimize": "svgo -f ./assets/icons"
|
"icons:optimize": "svgo -f ./assets/icons"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atproto/api": "^0.18.18",
|
"@atproto/api": "^0.18.20",
|
||||||
"@bitdrift/react-native": "^0.6.8",
|
"@bitdrift/react-native": "^0.6.8",
|
||||||
"@braintree/sanitize-url": "^6.0.2",
|
"@braintree/sanitize-url": "^6.0.2",
|
||||||
"@bsky.app/alf": "^0.1.6",
|
"@bsky.app/alf": "^0.1.6",
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import * as Device from 'expo-device'
|
||||||
|
|
||||||
|
import * as env from '#/env'
|
||||||
|
|
||||||
|
export function getDeviceName(): string {
|
||||||
|
const deviceName = Device.deviceName
|
||||||
|
if (env.IS_ANDROID) {
|
||||||
|
return deviceName || 'Android'
|
||||||
|
} else if (env.IS_IOS) {
|
||||||
|
// we need an entitlement to get the real device name on iOS, so just
|
||||||
|
// return a generic name for now
|
||||||
|
return 'iOS'
|
||||||
|
} else {
|
||||||
|
return 'Web' // could append browser info here
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -138,7 +138,7 @@ import {
|
|||||||
type RestoredVideo,
|
type RestoredVideo,
|
||||||
} from './drafts/state/api'
|
} from './drafts/state/api'
|
||||||
import {
|
import {
|
||||||
loadDraft,
|
loadDraftMedia,
|
||||||
useCleanupPublishedDraftMutation,
|
useCleanupPublishedDraftMutation,
|
||||||
useSaveDraftMutation,
|
useSaveDraftMutation,
|
||||||
} from './drafts/state/queries'
|
} from './drafts/state/queries'
|
||||||
@@ -482,7 +482,7 @@ export const ComposePost = ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Load local media files for the draft
|
// Load local media files for the draft
|
||||||
const {loadedMedia} = await loadDraft(draftSummary.draft)
|
const {loadedMedia} = await loadDraftMedia(draftSummary.draft)
|
||||||
|
|
||||||
// Extract original localRefs for orphan detection on save
|
// Extract original localRefs for orphan detection on save
|
||||||
const originalLocalRefs = extractLocalRefs(draftSummary.draft)
|
const originalLocalRefs = extractLocalRefs(draftSummary.draft)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Type converters for Draft API - convert between ComposerState and server Draft types.
|
* Type converters for Draft API - convert between ComposerState and server Draft types.
|
||||||
*/
|
*/
|
||||||
import {Platform} from 'react-native'
|
|
||||||
import {type AppBskyDraftDefs, AtUri, RichText} from '@atproto/api'
|
import {type AppBskyDraftDefs, AtUri, RichText} from '@atproto/api'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {resolveLink} from '#/lib/api/resolve'
|
import {resolveLink} from '#/lib/api/resolve'
|
||||||
|
import {getDeviceName} from '#/lib/deviceName'
|
||||||
import {getImageDim} from '#/lib/media/manip'
|
import {getImageDim} from '#/lib/media/manip'
|
||||||
import {mimeToExt} from '#/lib/media/video/util'
|
import {mimeToExt} from '#/lib/media/video/util'
|
||||||
import {type ComposerImage} from '#/state/gallery'
|
import {type ComposerImage} from '#/state/gallery'
|
||||||
@@ -69,7 +69,7 @@ export async function composerStateToDraft(state: ComposerState): Promise<{
|
|||||||
const draft: AppBskyDraftDefs.Draft = {
|
const draft: AppBskyDraftDefs.Draft = {
|
||||||
$type: 'app.bsky.draft.defs#draft',
|
$type: 'app.bsky.draft.defs#draft',
|
||||||
deviceId: getDeviceId(),
|
deviceId: getDeviceId(),
|
||||||
platform: Platform.OS,
|
deviceName: getDeviceName().slice(0, 100), // max length of 100 in lex
|
||||||
posts,
|
posts,
|
||||||
threadgateAllow: threadgateAllowUISettingToAllowRecordValue(
|
threadgateAllow: threadgateAllowUISettingToAllowRecordValue(
|
||||||
state.thread.threadgate,
|
state.thread.threadgate,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
import {isNetworkError} from '#/lib/strings/errors'
|
import {isNetworkError} from '#/lib/strings/errors'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
import {type ComposerState} from '#/view/com/composer/state/composer'
|
import {type ComposerState} from '#/view/com/composer/state/composer'
|
||||||
|
import {getDeviceId} from '#/analytics/identifiers'
|
||||||
import {composerStateToDraft, draftViewToSummary} from './api'
|
import {composerStateToDraft, draftViewToSummary} from './api'
|
||||||
import {logger} from './logger'
|
import {logger} from './logger'
|
||||||
import * as storage from './storage'
|
import * as storage from './storage'
|
||||||
@@ -42,11 +43,17 @@ export function useDraftsQuery() {
|
|||||||
* Load a draft's local media for editing.
|
* Load a draft's local media for editing.
|
||||||
* Takes the full Draft object (from DraftSummary) to avoid re-fetching.
|
* Takes the full Draft object (from DraftSummary) to avoid re-fetching.
|
||||||
*/
|
*/
|
||||||
export async function loadDraft(draft: AppBskyDraftDefs.Draft): Promise<{
|
export async function loadDraftMedia(draft: AppBskyDraftDefs.Draft): Promise<{
|
||||||
loadedMedia: Map<string, string>
|
loadedMedia: Map<string, string>
|
||||||
}> {
|
}> {
|
||||||
// Load local media files
|
// Load local media files
|
||||||
const loadedMedia = new Map<string, string>()
|
const loadedMedia = new Map<string, string>()
|
||||||
|
|
||||||
|
// can't load media from another device
|
||||||
|
if (draft.deviceId && draft.deviceId !== getDeviceId()) {
|
||||||
|
return {loadedMedia}
|
||||||
|
}
|
||||||
|
|
||||||
for (const post of draft.posts) {
|
for (const post of draft.posts) {
|
||||||
// Load images
|
// Load images
|
||||||
if (post.embedImages) {
|
if (post.embedImages) {
|
||||||
@@ -54,10 +61,10 @@ export async function loadDraft(draft: AppBskyDraftDefs.Draft): Promise<{
|
|||||||
try {
|
try {
|
||||||
const url = await storage.loadMediaFromLocal(img.localRef.path)
|
const url = await storage.loadMediaFromLocal(img.localRef.path)
|
||||||
loadedMedia.set(img.localRef.path, url)
|
loadedMedia.set(img.localRef.path, url)
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
logger.debug('Failed to load draft image', {
|
logger.error('Failed to load draft image', {
|
||||||
path: img.localRef.path,
|
path: img.localRef.path,
|
||||||
error: e,
|
safeMessage: e.message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,10 +75,10 @@ export async function loadDraft(draft: AppBskyDraftDefs.Draft): Promise<{
|
|||||||
try {
|
try {
|
||||||
const url = await storage.loadMediaFromLocal(vid.localRef.path)
|
const url = await storage.loadMediaFromLocal(vid.localRef.path)
|
||||||
loadedMedia.set(vid.localRef.path, url)
|
loadedMedia.set(vid.localRef.path, url)
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
logger.debug('Failed to load draft video', {
|
logger.error('Failed to load draft video', {
|
||||||
path: vid.localRef.path,
|
path: vid.localRef.path,
|
||||||
error: e,
|
safeMessage: e.message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,20 @@
|
|||||||
tlds "^1.234.0"
|
tlds "^1.234.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
|
"@atproto/api@^0.18.20":
|
||||||
|
version "0.18.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.20.tgz#3fdbb7b7fae90bd59101970c2b56cc31e8cf417d"
|
||||||
|
integrity sha512-BZYZkh2VJIFCXEnc/vzKwAwWjAQQTgbNJ8FBxpBK+z+KYh99O0uPCsRYKoCQsRrnkgrhzdU9+g2G+7zanTIGbw==
|
||||||
|
dependencies:
|
||||||
|
"@atproto/common-web" "^0.4.15"
|
||||||
|
"@atproto/lexicon" "^0.6.1"
|
||||||
|
"@atproto/syntax" "^0.4.3"
|
||||||
|
"@atproto/xrpc" "^0.7.7"
|
||||||
|
await-lock "^2.2.2"
|
||||||
|
multiformats "^9.9.0"
|
||||||
|
tlds "^1.234.0"
|
||||||
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/aws@^0.2.31":
|
"@atproto/aws@^0.2.31":
|
||||||
version "0.2.31"
|
version "0.2.31"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.31.tgz#e46d7db34ee57c4f9817269f1e73a7eddba2b9b8"
|
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.31.tgz#e46d7db34ee57c4f9817269f1e73a7eddba2b9b8"
|
||||||
@@ -190,6 +204,16 @@
|
|||||||
"@atproto/syntax" "0.4.3"
|
"@atproto/syntax" "0.4.3"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
|
"@atproto/common-web@^0.4.15":
|
||||||
|
version "0.4.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.15.tgz#1fffedf62d69b8c96f7b360e11c4180446a2cc82"
|
||||||
|
integrity sha512-A4l9gyqUNez8CjZp/Trypz/D3WIQsNj8dN05WR6+RoBbvwc9JhWjKPrm+WoVYc/F16RPdXHLkE3BEJlGIyYIiA==
|
||||||
|
dependencies:
|
||||||
|
"@atproto/lex-data" "^0.0.10"
|
||||||
|
"@atproto/lex-json" "^0.0.10"
|
||||||
|
"@atproto/syntax" "^0.4.3"
|
||||||
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/common@0.1.0":
|
"@atproto/common@0.1.0":
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.1.0.tgz#4216a8fef5b985ab62ac21252a0f8ca0f4a0f210"
|
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.1.0.tgz#4216a8fef5b985ab62ac21252a0f8ca0f4a0f210"
|
||||||
@@ -327,6 +351,16 @@
|
|||||||
uint8arrays "3.0.0"
|
uint8arrays "3.0.0"
|
||||||
unicode-segmenter "^0.14.0"
|
unicode-segmenter "^0.14.0"
|
||||||
|
|
||||||
|
"@atproto/lex-data@^0.0.10":
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@atproto/lex-data/-/lex-data-0.0.10.tgz#091c012af817a869951ce0e61eb757bd6c29797a"
|
||||||
|
integrity sha512-FDbcy8VIUVzS9Mi1F8SMxbkL/jOUmRRpqbeM1xB4A0fMxeZJTxf6naAbFt4gYF3quu/+TPJGmio6/7cav05FqQ==
|
||||||
|
dependencies:
|
||||||
|
multiformats "^9.9.0"
|
||||||
|
tslib "^2.8.1"
|
||||||
|
uint8arrays "3.0.0"
|
||||||
|
unicode-segmenter "^0.14.0"
|
||||||
|
|
||||||
"@atproto/lex-document@0.0.11":
|
"@atproto/lex-document@0.0.11":
|
||||||
version "0.0.11"
|
version "0.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/lex-document/-/lex-document-0.0.11.tgz#8cfdd6ab5b5befac4d1409c76e2d5a310845c1dc"
|
resolved "https://registry.yarnpkg.com/@atproto/lex-document/-/lex-document-0.0.11.tgz#8cfdd6ab5b5befac4d1409c76e2d5a310845c1dc"
|
||||||
@@ -344,6 +378,14 @@
|
|||||||
"@atproto/lex-data" "0.0.9"
|
"@atproto/lex-data" "0.0.9"
|
||||||
tslib "^2.8.1"
|
tslib "^2.8.1"
|
||||||
|
|
||||||
|
"@atproto/lex-json@^0.0.10":
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@atproto/lex-json/-/lex-json-0.0.10.tgz#18de1c8cc3ba564e5412bce1f8e22c198c956e64"
|
||||||
|
integrity sha512-L6MyXU17C5ODMeob8myQ2F3xvgCTvJUtM0ew8qSApnN//iDasB/FDGgd7ty4UVNmx4NQ/rtvz8xV94YpG6kneQ==
|
||||||
|
dependencies:
|
||||||
|
"@atproto/lex-data" "^0.0.10"
|
||||||
|
tslib "^2.8.1"
|
||||||
|
|
||||||
"@atproto/lex-resolver@0.0.12":
|
"@atproto/lex-resolver@0.0.12":
|
||||||
version "0.0.12"
|
version "0.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/lex-resolver/-/lex-resolver-0.0.12.tgz#fb6cd78c78c0acfc9a92d9e42abe7ff18b4c3a41"
|
resolved "https://registry.yarnpkg.com/@atproto/lex-resolver/-/lex-resolver-0.0.12.tgz#fb6cd78c78c0acfc9a92d9e42abe7ff18b4c3a41"
|
||||||
|
|||||||
Reference in New Issue
Block a user