Increase image upload resolution
This commit is contained in:
@@ -9,6 +9,7 @@ export enum Features {
|
|||||||
ImportContactsOnboardingDisable = 'import_contacts:onboarding:disable',
|
ImportContactsOnboardingDisable = 'import_contacts:onboarding:disable',
|
||||||
ImportContactsSettingsDisable = 'import_contacts:settings:disable',
|
ImportContactsSettingsDisable = 'import_contacts:settings:disable',
|
||||||
LiveNowBetaDisable = 'live_now_beta:disable',
|
LiveNowBetaDisable = 'live_now_beta:disable',
|
||||||
|
ImageUploadsHighResolution = 'image_uploads:high_resolution',
|
||||||
|
|
||||||
AATest = 'aa-test',
|
AATest = 'aa-test',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,6 +230,9 @@ export type Events = {
|
|||||||
|
|
||||||
'composer:gif:open': {}
|
'composer:gif:open': {}
|
||||||
'composer:gif:select': {}
|
'composer:gif:select': {}
|
||||||
|
'composer:image:edit': {
|
||||||
|
platform: Platform['OS']
|
||||||
|
}
|
||||||
'composerPrompt:press': {}
|
'composerPrompt:press': {}
|
||||||
'composerPrompt:camera:press': {}
|
'composerPrompt:camera:press': {}
|
||||||
'composerPrompt:gallery:press': {}
|
'composerPrompt:gallery:press': {}
|
||||||
|
|||||||
+19
-2
@@ -51,10 +51,15 @@ interface PostOpts {
|
|||||||
langs?: string[]
|
langs?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FeatureFlags = {
|
||||||
|
highResolutionImages?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export async function post(
|
export async function post(
|
||||||
agent: BskyAgent,
|
agent: BskyAgent,
|
||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
opts: PostOpts,
|
opts: PostOpts,
|
||||||
|
featureFlags?: FeatureFlags,
|
||||||
) {
|
) {
|
||||||
const thread = opts.thread
|
const thread = opts.thread
|
||||||
opts.onStateChange?.(t`Processing...`)
|
opts.onStateChange?.(t`Processing...`)
|
||||||
@@ -91,6 +96,7 @@ export async function post(
|
|||||||
queryClient,
|
queryClient,
|
||||||
draft,
|
draft,
|
||||||
opts.onStateChange,
|
opts.onStateChange,
|
||||||
|
featureFlags,
|
||||||
)
|
)
|
||||||
let labels: $Typed<ComAtprotoLabelDefs.SelfLabels> | undefined
|
let labels: $Typed<ComAtprotoLabelDefs.SelfLabels> | undefined
|
||||||
if (draft.labels.length) {
|
if (draft.labels.length) {
|
||||||
@@ -230,6 +236,7 @@ async function resolveEmbed(
|
|||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
draft: PostDraft,
|
draft: PostDraft,
|
||||||
onStateChange: ((state: string) => void) | undefined,
|
onStateChange: ((state: string) => void) | undefined,
|
||||||
|
featureFlags?: FeatureFlags,
|
||||||
): Promise<
|
): Promise<
|
||||||
| $Typed<AppBskyEmbedImages.Main>
|
| $Typed<AppBskyEmbedImages.Main>
|
||||||
| $Typed<AppBskyEmbedVideo.Main>
|
| $Typed<AppBskyEmbedVideo.Main>
|
||||||
@@ -240,7 +247,13 @@ async function resolveEmbed(
|
|||||||
> {
|
> {
|
||||||
if (draft.embed.quote) {
|
if (draft.embed.quote) {
|
||||||
const [resolvedMedia, resolvedQuote] = await Promise.all([
|
const [resolvedMedia, resolvedQuote] = await Promise.all([
|
||||||
resolveMedia(agent, queryClient, draft.embed, onStateChange),
|
resolveMedia(
|
||||||
|
agent,
|
||||||
|
queryClient,
|
||||||
|
draft.embed,
|
||||||
|
onStateChange,
|
||||||
|
featureFlags,
|
||||||
|
),
|
||||||
resolveRecord(agent, queryClient, draft.embed.quote.uri),
|
resolveRecord(agent, queryClient, draft.embed.quote.uri),
|
||||||
])
|
])
|
||||||
if (resolvedMedia) {
|
if (resolvedMedia) {
|
||||||
@@ -263,6 +276,7 @@ async function resolveEmbed(
|
|||||||
queryClient,
|
queryClient,
|
||||||
draft.embed,
|
draft.embed,
|
||||||
onStateChange,
|
onStateChange,
|
||||||
|
featureFlags,
|
||||||
)
|
)
|
||||||
if (resolvedMedia) {
|
if (resolvedMedia) {
|
||||||
return resolvedMedia
|
return resolvedMedia
|
||||||
@@ -288,6 +302,7 @@ async function resolveMedia(
|
|||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
embedDraft: EmbedDraft,
|
embedDraft: EmbedDraft,
|
||||||
onStateChange: ((state: string) => void) | undefined,
|
onStateChange: ((state: string) => void) | undefined,
|
||||||
|
featureFlags?: FeatureFlags,
|
||||||
): Promise<
|
): Promise<
|
||||||
| $Typed<AppBskyEmbedExternal.Main>
|
| $Typed<AppBskyEmbedExternal.Main>
|
||||||
| $Typed<AppBskyEmbedImages.Main>
|
| $Typed<AppBskyEmbedImages.Main>
|
||||||
@@ -303,7 +318,9 @@ async function resolveMedia(
|
|||||||
const images: AppBskyEmbedImages.Image[] = await Promise.all(
|
const images: AppBskyEmbedImages.Image[] = await Promise.all(
|
||||||
imagesDraft.map(async (image, i) => {
|
imagesDraft.map(async (image, i) => {
|
||||||
logger.debug(`Compressing image #${i}`)
|
logger.debug(`Compressing image #${i}`)
|
||||||
const {path, width, height, mime} = await compressImage(image)
|
const {path, width, height, mime} = await compressImage(image, {
|
||||||
|
highResolution: featureFlags?.highResolutionImages,
|
||||||
|
})
|
||||||
logger.debug(`Uploading image #${i}`)
|
logger.debug(`Uploading image #${i}`)
|
||||||
const res = await uploadBlob(agent, path, mime)
|
const res = await uploadBlob(agent, path, mime)
|
||||||
return {
|
return {
|
||||||
|
|||||||
+16
-2
@@ -200,10 +200,24 @@ export function resetImageManipulation(
|
|||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function compressImage(img: ComposerImage): Promise<PickerImage> {
|
export async function compressImage(
|
||||||
|
img: ComposerImage,
|
||||||
|
options?: {
|
||||||
|
highResolution?: boolean
|
||||||
|
},
|
||||||
|
): Promise<PickerImage> {
|
||||||
const source = img.transformed || img.source
|
const source = img.transformed || img.source
|
||||||
|
|
||||||
const [w, h] = containImageRes(source.width, source.height, POST_IMG_MAX)
|
const [w, h] = containImageRes(
|
||||||
|
source.width,
|
||||||
|
source.height,
|
||||||
|
options?.highResolution
|
||||||
|
? {
|
||||||
|
width: 4000,
|
||||||
|
height: 4000,
|
||||||
|
}
|
||||||
|
: POST_IMG_MAX,
|
||||||
|
)
|
||||||
|
|
||||||
let minQualityPercentage = 0
|
let minQualityPercentage = 0
|
||||||
let maxQualityPercentage = 101 // exclusive
|
let maxQualityPercentage = 101 // exclusive
|
||||||
|
|||||||
@@ -825,12 +825,21 @@ export const ComposePost = ({
|
|||||||
try {
|
try {
|
||||||
logger.info(`composer: posting...`)
|
logger.info(`composer: posting...`)
|
||||||
postUri = (
|
postUri = (
|
||||||
await apilib.post(agent, queryClient, {
|
await apilib.post(
|
||||||
thread,
|
agent,
|
||||||
replyTo: replyTo?.uri,
|
queryClient,
|
||||||
onStateChange: setPublishingStage,
|
{
|
||||||
langs: currentLanguages,
|
thread,
|
||||||
})
|
replyTo: replyTo?.uri,
|
||||||
|
onStateChange: setPublishingStage,
|
||||||
|
langs: currentLanguages,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
highResolutionImages: ax.features.enabled(
|
||||||
|
ax.features.ImageUploadsHighResolution,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
).uris[0]
|
).uris[0]
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
type ImageStyle,
|
type ImageStyle,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
type LayoutChangeEvent,
|
type LayoutChangeEvent,
|
||||||
|
Platform,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
@@ -24,6 +25,7 @@ import {Admonition} from '#/components/Admonition'
|
|||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_IOS, IS_NATIVE} from '#/env'
|
import {IS_IOS, IS_NATIVE} from '#/env'
|
||||||
import {type PostAction} from '../state/composer'
|
import {type PostAction} from '../state/composer'
|
||||||
import {EditImageDialog} from './EditImageDialog'
|
import {EditImageDialog} from './EditImageDialog'
|
||||||
@@ -147,6 +149,7 @@ const GalleryItem = ({
|
|||||||
}: GalleryItemProps): React.ReactNode => {
|
}: GalleryItemProps): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
const ax = useAnalytics()
|
||||||
|
|
||||||
const altTextControl = Dialog.useDialogControl()
|
const altTextControl = Dialog.useDialogControl()
|
||||||
const editControl = Dialog.useDialogControl()
|
const editControl = Dialog.useDialogControl()
|
||||||
@@ -161,6 +164,10 @@ const GalleryItem = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onImageEdit = () => {
|
const onImageEdit = () => {
|
||||||
|
ax.metric('composer:image:edit', {
|
||||||
|
platform: Platform.OS,
|
||||||
|
})
|
||||||
|
|
||||||
if (IS_NATIVE) {
|
if (IS_NATIVE) {
|
||||||
cropImage(image).then(next => {
|
cropImage(image).then(next => {
|
||||||
onChange(next)
|
onChange(next)
|
||||||
|
|||||||
Reference in New Issue
Block a user