From ce53b3a2648732ee67abd3cf4333f154031bd7e5 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Thu, 3 Oct 2024 20:22:54 -0500 Subject: [PATCH 1/7] Font tweaks (#5597) * Increase fontWeight on android * Use atoms for a couple stray fontWeights * Rm unused file --- src/alf/atoms.ts | 6 +- src/alf/tokens.ts | 13 +- src/lib/themes.ts | 79 ++++---- src/screens/Profile/Header/DisplayName.tsx | 2 +- src/view/com/util/Html.tsx | 207 --------------------- src/view/shell/Drawer.tsx | 5 +- 6 files changed, 52 insertions(+), 260 deletions(-) delete mode 100644 src/view/com/util/Html.tsx diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index 2625beda27..ca4c14dc6d 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -276,13 +276,13 @@ export const atoms = { letterSpacing: tokens.TRACKING, }, font_normal: { - fontWeight: tokens.fontWeight.regular, + fontWeight: tokens.fontWeight.normal, }, font_bold: { - fontWeight: tokens.fontWeight.semibold, + fontWeight: tokens.fontWeight.bold, }, font_heavy: { - fontWeight: tokens.fontWeight.extrabold, + fontWeight: tokens.fontWeight.heavy, }, italic: { fontStyle: 'italic', diff --git a/src/alf/tokens.ts b/src/alf/tokens.ts index f3ac17e6af..9ea585ee7c 100644 --- a/src/alf/tokens.ts +++ b/src/alf/tokens.ts @@ -1,6 +1,6 @@ -import {Platform} from 'react-native' +import {isAndroid} from '#/platform/detection' -export const TRACKING = Platform.OS === 'android' ? 0.1 : 0 +export const TRACKING = isAndroid ? 0.1 : 0 export const color = { temp_purple: 'rgb(105 0 255)', @@ -51,12 +51,9 @@ export const borderRadius = { * These correspond to Inter font files we actually load. */ export const fontWeight = { - regular: '400', - // medium: '500', - semibold: '600', - // bold: '700', - extrabold: '800', - // black: '900', + normal: '400', + bold: isAndroid ? '700' : '600', + heavy: isAndroid ? '900' : '800', } as const export const gradients = { diff --git a/src/lib/themes.ts b/src/lib/themes.ts index eb11872fa3..2aeec31398 100644 --- a/src/lib/themes.ts +++ b/src/lib/themes.ts @@ -2,6 +2,7 @@ import {Platform} from 'react-native' import {tokens} from '#/alf' import {darkPalette, dimPalette, lightPalette} from '#/alf/themes' +import {fontWeight} from '#/alf/tokens' import {colors} from './styles' import type {Theme} from './ThemeContext' @@ -90,195 +91,195 @@ export const defaultTheme: Theme = { '2xl-thin': { fontSize: 18, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, '2xl': { fontSize: 18, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, '2xl-medium': { fontSize: 18, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, '2xl-bold': { fontSize: 18, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, '2xl-heavy': { fontSize: 18, letterSpacing: tokens.TRACKING, - fontWeight: '800', + fontWeight: fontWeight.heavy, }, 'xl-thin': { fontSize: 17, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, xl: { fontSize: 17, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'xl-medium': { fontSize: 17, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'xl-bold': { fontSize: 17, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'xl-heavy': { fontSize: 17, letterSpacing: tokens.TRACKING, - fontWeight: '800', + fontWeight: fontWeight.heavy, }, 'lg-thin': { fontSize: 16, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, lg: { fontSize: 16, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'lg-medium': { fontSize: 16, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'lg-bold': { fontSize: 16, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'lg-heavy': { fontSize: 16, letterSpacing: tokens.TRACKING, - fontWeight: '800', + fontWeight: fontWeight.heavy, }, 'md-thin': { fontSize: 15, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, md: { fontSize: 15, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'md-medium': { fontSize: 15, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'md-bold': { fontSize: 15, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'md-heavy': { fontSize: 15, letterSpacing: tokens.TRACKING, - fontWeight: '800', + fontWeight: fontWeight.heavy, }, 'sm-thin': { fontSize: 14, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, sm: { fontSize: 14, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'sm-medium': { fontSize: 14, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'sm-bold': { fontSize: 14, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'sm-heavy': { fontSize: 14, letterSpacing: tokens.TRACKING, - fontWeight: '800', + fontWeight: fontWeight.heavy, }, 'xs-thin': { fontSize: 13, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, xs: { fontSize: 13, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'xs-medium': { fontSize: 13, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'xs-bold': { fontSize: 13, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'xs-heavy': { fontSize: 13, letterSpacing: tokens.TRACKING, - fontWeight: '800', + fontWeight: fontWeight.heavy, }, 'title-2xl': { fontSize: 34, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'title-xl': { fontSize: 28, letterSpacing: tokens.TRACKING, - fontWeight: '600', + fontWeight: fontWeight.bold, }, 'title-lg': { fontSize: 22, - fontWeight: '600', + fontWeight: fontWeight.bold, }, title: { - fontWeight: '600', + fontWeight: fontWeight.bold, fontSize: 20, letterSpacing: tokens.TRACKING, }, 'title-sm': { - fontWeight: '600', + fontWeight: fontWeight.bold, fontSize: 17, letterSpacing: tokens.TRACKING, }, 'post-text': { fontSize: 16, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'post-text-lg': { fontSize: 20, letterSpacing: tokens.TRACKING, - fontWeight: '400', + fontWeight: fontWeight.normal, }, 'button-lg': { - fontWeight: '600', + fontWeight: fontWeight.bold, fontSize: 18, letterSpacing: tokens.TRACKING, }, button: { - fontWeight: '600', + fontWeight: fontWeight.bold, fontSize: 14, letterSpacing: tokens.TRACKING, }, diff --git a/src/screens/Profile/Header/DisplayName.tsx b/src/screens/Profile/Header/DisplayName.tsx index bcc56d7f66..6d4eea2ebc 100644 --- a/src/screens/Profile/Header/DisplayName.tsx +++ b/src/screens/Profile/Header/DisplayName.tsx @@ -27,7 +27,7 @@ export function ProfileHeaderDisplayName({ t.atoms.text, gtMobile ? a.text_4xl : a.text_3xl, a.self_start, - {fontWeight: '600'}, + a.font_heavy, ]}> {sanitizeDisplayName( profile.displayName || sanitizeHandle(profile.handle), diff --git a/src/view/com/util/Html.tsx b/src/view/com/util/Html.tsx deleted file mode 100644 index f77fb16034..0000000000 --- a/src/view/com/util/Html.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import * as React from 'react' -import {StyleSheet, View} from 'react-native' -import { - H1 as ExpoH1, - H2 as ExpoH2, - H3 as ExpoH3, - H4 as ExpoH4, -} from '@expo/html-elements' - -import {usePalette} from '#/lib/hooks/usePalette' -import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' -import {useTheme} from '#/lib/ThemeContext' -import {TextLink} from './Link' -import {Text} from './text/Text' - -/** - * These utilities are used to define long documents in an html-like - * DSL. See for instance /locale/en/privacy-policy.tsx - */ - -interface IsChildProps { - isChild?: boolean -} - -// type ReactNodeWithIsChildProp = -// | React.ReactElement -// | React.ReactElement[] -// | React.ReactNode - -export function H1({children}: React.PropsWithChildren<{}>) { - const styles = useStyles() - const pal = usePalette('default') - const typography = useTheme().typography['title-xl'] - // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf - return {children} -} - -export function H2({children}: React.PropsWithChildren<{}>) { - const styles = useStyles() - const pal = usePalette('default') - const typography = useTheme().typography['title-lg'] - // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf - return {children} -} - -export function H3({children}: React.PropsWithChildren<{}>) { - const styles = useStyles() - const pal = usePalette('default') - const typography = useTheme().typography.title - // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf - return {children} -} - -export function H4({children}: React.PropsWithChildren<{}>) { - const styles = useStyles() - const pal = usePalette('default') - const typography = useTheme().typography['title-sm'] - // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf - return {children} -} - -export function P({children}: React.PropsWithChildren<{}>) { - const styles = useStyles() - const pal = usePalette('default') - return ( - - {children} - - ) -} - -export function UL({children, isChild}: React.PropsWithChildren) { - const styles = useStyles() - return ( - - {markChildProps(children)} - - ) -} - -export function OL({children, isChild}: React.PropsWithChildren) { - const styles = useStyles() - return ( - - {markChildProps(children)} - - ) -} - -export function LI({ - children, - value, -}: React.PropsWithChildren<{value?: string}>) { - const styles = useStyles() - const pal = usePalette('default') - return ( - - {value || <>•} - - {markChildProps(children)} - - - ) -} - -export function A({children, href}: React.PropsWithChildren<{href: string}>) { - const styles = useStyles() - const pal = usePalette('default') - return ( - - ) -} - -export function STRONG({children}: React.PropsWithChildren<{}>) { - const pal = usePalette('default') - return ( - - {children} - - ) -} - -export function EM({children}: React.PropsWithChildren<{}>) { - const styles = useStyles() - const pal = usePalette('default') - return ( - - {children} - - ) -} - -function markChildProps(children: React.ReactNode) { - return React.Children.map(children, child => { - if (React.isValidElement(child)) { - return React.cloneElement( - child as React.ReactElement, - {isChild: true}, - ) - } - return child - }) -} - -const useStyles = () => { - const {isDesktop} = useWebMediaQueries() - return StyleSheet.create({ - h1: { - marginTop: 20, - marginBottom: 10, - letterSpacing: 0.8, - }, - h2: { - marginTop: 20, - marginBottom: 10, - letterSpacing: 0.8, - }, - h3: { - marginTop: 0, - marginBottom: 10, - }, - h4: { - marginTop: 0, - marginBottom: 10, - fontWeight: '600', - }, - p: { - marginBottom: 10, - }, - ul: { - marginBottom: 10, - paddingLeft: isDesktop ? 18 : 4, - }, - ulChild: { - paddingTop: 10, - marginBottom: 0, - }, - ol: { - marginBottom: 10, - paddingLeft: isDesktop ? 18 : 4, - }, - olChild: { - paddingTop: 10, - marginBottom: 0, - }, - li: { - flexDirection: 'row', - paddingRight: 20, - marginBottom: 10, - }, - liBullet: { - paddingRight: 10, - }, - liText: {}, - a: { - marginBottom: 10, - }, - em: { - fontStyle: 'italic', - }, - }) -} diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx index ca2cbb3e08..4212b28af9 100644 --- a/src/view/shell/Drawer.tsx +++ b/src/view/shell/Drawer.tsx @@ -590,7 +590,9 @@ function MenuItem({ ? styles.menuItemCountTens : undefined, ]}> - + {count} @@ -666,7 +668,6 @@ const styles = StyleSheet.create({ }, menuItemCountLabel: { fontSize: 12, - fontWeight: '600', fontVariant: ['tabular-nums'], color: colors.white, }, From 3f66531e83d5bc1409a444c3cf479b0f53063dc4 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Thu, 3 Oct 2024 20:23:07 -0500 Subject: [PATCH 2/7] Add option to search in any language (#5598) --- src/screens/Search/utils.ts | 1 + src/view/screens/Search/Search.tsx | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/screens/Search/utils.ts b/src/screens/Search/utils.ts index dcf92c0926..012ae4e9f3 100644 --- a/src/screens/Search/utils.ts +++ b/src/screens/Search/utils.ts @@ -35,6 +35,7 @@ export function makeSearchQuery(query: string, params: Params) { return [ query, Object.entries(params) + .filter(([_, value]) => value) .map(([name, value]) => `${name}:${value}`) .join(' '), ] diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx index 4a6c87f104..6fce998141 100644 --- a/src/view/screens/Search/Search.tsx +++ b/src/view/screens/Search/Search.tsx @@ -338,18 +338,28 @@ function SearchLanguageDropdown({ onChange(value: string): void }) { const t = useThemeNew() + const {_} = useLingui() const {contentLanguages} = useLanguagePrefs() const items = React.useMemo(() => { - return LANGUAGES.filter(l => Boolean(l.code2)) - .map(l => ({ - label: l.name, - inputLabel: l.name, - value: l.code2, - key: l.code2 + l.code3, - })) - .sort(a => (contentLanguages.includes(a.value) ? -1 : 1)) - }, [contentLanguages]) + return [ + { + label: _(msg`Any language`), + inputLabel: _(msg`Any language`), + value: '', + key: '*', + }, + ].concat( + LANGUAGES.filter(l => Boolean(l.code2)) + .map(l => ({ + label: l.name, + inputLabel: l.name, + value: l.code2, + key: l.code2 + l.code3, + })) + .sort(a => (contentLanguages.includes(a.value) ? -1 : 1)), + ) + }, [_, contentLanguages]) const style = { backgroundColor: t.atoms.bg_contrast_25.backgroundColor, From 48241cb2b6cec2b513daa86303f9e6ee4fcacd10 Mon Sep 17 00:00:00 2001 From: Hailey Date: Fri, 4 Oct 2024 01:28:26 -0700 Subject: [PATCH 3/7] Downgrade sentry to recommended 5.24.3 (#5604) --- package.json | 2 +- yarn.lock | 314 +++++++++++++++++++++++++-------------------------- 2 files changed, 155 insertions(+), 161 deletions(-) diff --git a/package.json b/package.json index 4ab196b6aa..99651582c8 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@react-navigation/drawer": "^6.6.15", "@react-navigation/native": "^6.1.17", "@react-navigation/native-stack": "^6.9.26", - "@sentry/react-native": "5.32.0", + "@sentry/react-native": "5.24.3", "@tamagui/focus-scope": "^1.84.1", "@tanstack/query-async-storage-persister": "^5.25.0", "@tanstack/react-query": "^5.8.1", diff --git a/yarn.lock b/yarn.lock index 8f68ea4f3f..c1e711242d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5901,92 +5901,87 @@ component-type "^1.2.1" join-component "^1.1.0" -"@sentry-internal/feedback@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.119.0.tgz#429b3ea0fd34e928d2e7de5dcbe9377272a3f221" - integrity sha512-om8TkAU5CQGO8nkmr7qsSBVkP+/vfeS4JgtW3sjoTK0fhj26+DljR6RlfCGWtYQdPSP6XV7atcPTjbSnsmG9FQ== - dependencies: - "@sentry/core" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry-internal/replay-canvas@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.119.0.tgz#85669d184ba79150e64d05de02f5e2b616e68371" - integrity sha512-NL02VQx6ekPxtVRcsdp1bp5Tb5w6vnfBKSIfMKuDRBy5A10Uc3GSoy/c3mPyHjOxB84452A+xZSx6bliEzAnuA== - dependencies: - "@sentry/core" "7.119.0" - "@sentry/replay" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry-internal/tracing@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.119.0.tgz#201561af2a4ad1837333287c26050a5e688537ca" - integrity sha512-oKdFJnn+56f0DHUADlL8o9l8jTib3VDLbWQBVkjD9EprxfaCwt2m8L5ACRBdQ8hmpxCEo4I8/6traZ7qAdBUqA== - dependencies: - "@sentry/core" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry/babel-plugin-component-annotate@2.20.1": - version "2.20.1" - resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.20.1.tgz#204c63ed006a048f48f633876e1b8bacf87a9722" - integrity sha512-4mhEwYTK00bIb5Y9UWIELVUfru587Vaeg0DQGswv4aIRHIiMKLyNqCEejaaybQ/fNChIZOKmvyqXk430YVd7Qg== - -"@sentry/browser@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.119.0.tgz#65004015c107be5d2f49a852ebcffc5d19d90e0d" - integrity sha512-WwmW1Y4D764kVGeKmdsNvQESZiAn9t8LmCWO0ucBksrjL2zw9gBPtOpRcO6l064sCLeSxxzCN+kIxhRm1gDFEA== - dependencies: - "@sentry-internal/feedback" "7.119.0" - "@sentry-internal/replay-canvas" "7.119.0" - "@sentry-internal/tracing" "7.119.0" - "@sentry/core" "7.119.0" - "@sentry/integrations" "7.119.0" - "@sentry/replay" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry/cli-darwin@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.36.1.tgz#786adf6984dbe3c6fb7dac51b625c314117b807d" - integrity sha512-JOHQjVD8Kqxm1jUKioAP5ohLOITf+Dh6+DBz4gQjCNdotsvNW5m63TKROwq2oB811p+Jzv5304ujmN4cAqW1Ww== - -"@sentry/cli-linux-arm64@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.36.1.tgz#ff449d7e7e715166257998c02cf635ca02acbadd" - integrity sha512-R//3ZEkbzvoStr3IA7nxBZNiBYyxOljOqAhgiTnejXHmnuwDzM3TBA2n5vKPE/kBFxboEBEw0UTzTIRb1T0bgw== - -"@sentry/cli-linux-arm@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.36.1.tgz#1ae5d335a1b4cd217a34c2bd6c6f5e0670136eb3" - integrity sha512-gvEOKN0fWL2AVqUBKHNXPRZfJNvKTs8kQhS8cQqahZGgZHiPCI4BqW45cKMq+ZTt1UUbLmt6khx5Dz7wi+0i5A== - -"@sentry/cli-linux-i686@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.36.1.tgz#112b9e26357e918cbbba918114ec8cdab07cdf60" - integrity sha512-R7sW5Vk/HacVy2YgQoQB+PwccvFYf2CZVPSFSFm2z7MEfNe77UYHWUq+sjJ4vxWG6HDWGVmaX0fjxyDkE01JRA== - -"@sentry/cli-linux-x64@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.36.1.tgz#c3e5bdb0c9a4bb44c83927c62a3cd7e006709bf7" - integrity sha512-UMr3ik8ksA7zQfbzsfwCb+ztenLnaeAbX94Gp+bzANZwPfi/vVHf2bLyqsBs4OyVt9SPlN1bbM/RTGfMjZ3JOw== - -"@sentry/cli-win32-i686@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.36.1.tgz#819573320e885e1dbf59b0a01d3bd370c84c1708" - integrity sha512-CflvhnvxPEs5GWQuuDtYSLqPrBaPbcSJFlBuUIb+8WNzRxvVfjgw1qzfZmkQqABqiy/YEsEekllOoMFZAvCcVA== - -"@sentry/cli-win32-x64@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.36.1.tgz#80779b4bffb4e2e32944eae72c60e6f40151b4dc" - integrity sha512-wWqht2xghcK3TGnooHZSzA3WSjdtno/xFjZLvWmw38rblGwgKMxLZnlxV6uDyS+OJ6CbfDTlCRay/0TIqA0N8g== - -"@sentry/cli@2.36.1": - version "2.36.1" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.36.1.tgz#a9146b798cb6d2f782a7a48d74633ddcd88dc8d3" - integrity sha512-gzK5uQKDWKhyH5udoB5+oaUNrS//urWyaXgKvHKz4gFfl744HuKY9dpLPP2nMnf0zLGmGM6xJnMXLqILq0mtxw== +"@sentry-internal/feedback@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.117.0.tgz#4ca62cc469611720e76877a756cf24b792cb178e" + integrity sha512-4X+NnnY17W74TymgLFH7/KPTVYpEtoMMJh8HzVdCmHTOE6j32XKBeBMRaXBhmNYmEgovgyRKKf2KvtSfgw+V1Q== + dependencies: + "@sentry/core" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry-internal/replay-canvas@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.117.0.tgz#d6b3b711453c88e040f31ebab1d4bc627b4a6505" + integrity sha512-7hjIhwEcoosr+BIa0AyEssB5xwvvlzUpvD5fXu4scd3I3qfX8gdnofO96a8r+LrQm3bSj+eN+4TfKEtWb7bU5A== + dependencies: + "@sentry/core" "7.117.0" + "@sentry/replay" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry-internal/tracing@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.117.0.tgz#c7d2357dae8d7ea2bc130e4513ac4ffc8dc7553c" + integrity sha512-fAIyijNvKBZNA12IcKo+dOYDRTNrzNsdzbm3DP37vJRKVQu19ucqP4Y6InvKokffDP2HZPzFPDoGXYuXkDhUZg== + dependencies: + "@sentry/core" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry/browser@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.117.0.tgz#3030073f360974dadcf5a5f2e1542497b3be2482" + integrity sha512-29X9HlvDEKIaWp6XKlNPPSNND0U6P/ede5WA2nVHfs1zJLWdZ7/ijuMc0sH/CueEkqHe/7gt94hBcI7HOU/wSw== + dependencies: + "@sentry-internal/feedback" "7.117.0" + "@sentry-internal/replay-canvas" "7.117.0" + "@sentry-internal/tracing" "7.117.0" + "@sentry/core" "7.117.0" + "@sentry/integrations" "7.117.0" + "@sentry/replay" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry/cli-darwin@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.31.2.tgz#faeb87d09d8b21b8b8dd2e2aa848b538f01ddd26" + integrity sha512-BHA/JJXj1dlnoZQdK4efRCtHRnbBfzbIZUKAze7oRR1RfNqERI84BVUQeKateD3jWSJXQfEuclIShc61KOpbKw== + +"@sentry/cli-linux-arm64@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.31.2.tgz#669c9c3f7f9130d26f5db732f793378863d58869" + integrity sha512-FLVKkJ/rWvPy/ka7OrUdRW63a/z8HYI1Gt8Pr6rWs50hb7YJja8lM8IO10tYmcFE/tODICsnHO9HTeUg2g2d1w== + +"@sentry/cli-linux-arm@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.31.2.tgz#3e36ed7db09e922f00221281252e58dfd8755ea5" + integrity sha512-W8k5mGYYZz/I/OxZH65YAK7dCkQAl+wbuoASGOQjUy5VDgqH0QJ8kGJufXvFPM+f3ZQGcKAnVsZ6tFqZXETBAw== + +"@sentry/cli-linux-i686@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.31.2.tgz#02b7da274369b78a5676c20bb26cc37caed5244b" + integrity sha512-A64QtzaPi3MYFpZ+Fwmi0mrSyXgeLJ0cWr4jdeTGrzNpeowSteKgd6tRKU+LVq0k5shKE7wdnHk+jXnoajulMA== + +"@sentry/cli-linux-x64@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.31.2.tgz#54f74a9e5925db9ddafebc0efd4056c5377be5fd" + integrity sha512-YL/r+15R4mOEiU3mzn7iFQOeFEUB6KxeKGTTrtpeOGynVUGIdq4nV5rHow5JDbIzOuBS3SpOmcIMluvo1NCh0g== + +"@sentry/cli-win32-i686@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.31.2.tgz#5dab845a824be0927566171aa05f015e887fe82d" + integrity sha512-Az/2bmW+TFI059RE0mSBIxTBcoShIclz7BDebmIoCkZ+retrwAzpmBnBCDAHow+Yi43utOow+3/4idGa2OxcLw== + +"@sentry/cli-win32-x64@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.31.2.tgz#e12fec0a54f6d9cced5235fbc68ba8f94165634b" + integrity sha512-XIzyRnJu539NhpFa+JYkotzVwv3NrZ/4GfHB/JWA2zReRvsk39jJG8D5HOmm0B9JA63QQT7Dt39RW8g3lkmb6w== + +"@sentry/cli@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.31.2.tgz#39df8e52966aa8db4f9c51f4bc77abd62b6a630e" + integrity sha512-2aKyUx6La2P+pplL8+2vO67qJ+c1C79KYWAyQBE0JIT5kvKK9JpwtdNoK1F0/2mRpwhhYPADCz3sVIRqmL8cQQ== dependencies: https-proxy-agent "^5.0.0" node-fetch "^2.6.7" @@ -5994,88 +5989,87 @@ proxy-from-env "^1.1.0" which "^2.0.2" optionalDependencies: - "@sentry/cli-darwin" "2.36.1" - "@sentry/cli-linux-arm" "2.36.1" - "@sentry/cli-linux-arm64" "2.36.1" - "@sentry/cli-linux-i686" "2.36.1" - "@sentry/cli-linux-x64" "2.36.1" - "@sentry/cli-win32-i686" "2.36.1" - "@sentry/cli-win32-x64" "2.36.1" - -"@sentry/core@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.119.0.tgz#a6e41119bb03ec27689f9ad04e79d1fba5b7fc37" - integrity sha512-CS2kUv9rAJJEjiRat6wle3JATHypB0SyD7pt4cpX5y0dN5dZ1JrF57oLHRMnga9fxRivydHz7tMTuBhSSwhzjw== - dependencies: - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry/hub@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.119.0.tgz#a94d657b9d3cfd4cc061c5c238f86faefb55d5d8" - integrity sha512-183h5B/rZosLxpB+ZYOvFdHk0rwZbKskxqKFtcyPbDAfpCUgCass41UTqyxF6aH1qLgCRxX8GcLRF7frIa/SOg== - dependencies: - "@sentry/core" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry/integrations@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.119.0.tgz#5b25c603026dbacfe1ae7bb8d768506a129149fb" - integrity sha512-OHShvtsRW0A+ZL/ZbMnMqDEtJddPasndjq+1aQXw40mN+zeP7At/V1yPZyFaURy86iX7Ucxw5BtmzuNy7hLyTA== - dependencies: - "@sentry/core" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" + "@sentry/cli-darwin" "2.31.2" + "@sentry/cli-linux-arm" "2.31.2" + "@sentry/cli-linux-arm64" "2.31.2" + "@sentry/cli-linux-i686" "2.31.2" + "@sentry/cli-linux-x64" "2.31.2" + "@sentry/cli-win32-i686" "2.31.2" + "@sentry/cli-win32-x64" "2.31.2" + +"@sentry/core@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.117.0.tgz#eebdb6e700d5fbdf3102c4abfb4ff92ef79ae9a5" + integrity sha512-1XZ4/d/DEwnfM2zBMloXDwX+W7s76lGKQMgd8bwgPJZjjEztMJ7X0uopKAGwlQcjn242q+hsCBR6C+fSuI5kvg== + dependencies: + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry/hub@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.117.0.tgz#924462cd083b57b45559eb5a25850e5b3004a7f8" + integrity sha512-pQrXnbzsRHCUsVIqz/sZ0vggnxuuHqsmyjoy2Ha1qn1Ya4QbyAWEEGoZTnZx6I/Vt3dzVvRnR3YCywatdkaFxg== + dependencies: + "@sentry/core" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry/integrations@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.117.0.tgz#4613dae3bc1d257c3c870461327fd4f70dbda229" + integrity sha512-U3suSZysmU9EiQqg0ga5CxveAyNbi9IVdsapMDq5EQGNcVDvheXtULs+BOc11WYP3Kw2yWB38VDqLepfc/Fg2g== + dependencies: + "@sentry/core" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" localforage "^1.8.1" -"@sentry/react-native@5.32.0": - version "5.32.0" - resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-5.32.0.tgz#14c46a65f7359f5e74a9cef7edb9d7bf9a0a449d" - integrity sha512-Rh5EEYuWUyPaTaL8b/tl3okGiWb3LSvfYiS/WkvTYH+pFYr2RNtrZSCxhP5TpWSqkoy8VVXeYhSmlBvjfD/uDg== - dependencies: - "@sentry/babel-plugin-component-annotate" "2.20.1" - "@sentry/browser" "7.119.0" - "@sentry/cli" "2.36.1" - "@sentry/core" "7.119.0" - "@sentry/hub" "7.119.0" - "@sentry/integrations" "7.119.0" - "@sentry/react" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" - -"@sentry/react@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.119.0.tgz#79f2c9d94322a3afbfa8af9f5b872f7c2e9b0820" - integrity sha512-cf8Cei+qdSA26gx+IMAuc/k44PeBImNzIpXi3930SLhUe44ypT5OZ/44L6xTODHZzTIyMSJPduf59vT2+eW9yg== - dependencies: - "@sentry/browser" "7.119.0" - "@sentry/core" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" +"@sentry/react-native@5.24.3": + version "5.24.3" + resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-5.24.3.tgz#debd2218f65b4112b8513468ac3ffef42713c4f1" + integrity sha512-KBtXSYzk4Ge9GX4e7520oHhmo6UqGl3rH627Xpl3Gxmh9psQsLDmYXVKiMOFBZrSBAv7FAV0jf6zERK8lNY/Gg== + dependencies: + "@sentry/browser" "7.117.0" + "@sentry/cli" "2.31.2" + "@sentry/core" "7.117.0" + "@sentry/hub" "7.117.0" + "@sentry/integrations" "7.117.0" + "@sentry/react" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" + +"@sentry/react@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.117.0.tgz#0a6e729f5d17782a02a48728821536ede569bc8d" + integrity sha512-aK+yaEP2esBhaczGU96Y7wkqB4umSIlRAzobv7ER88EGHzZulRaocTpQO8HJJGDHm4D8rD+E893BHnghkoqp4Q== + dependencies: + "@sentry/browser" "7.117.0" + "@sentry/core" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" hoist-non-react-statics "^3.3.2" -"@sentry/replay@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.119.0.tgz#50881079d013c77f87a994331d8bcad1d49e0960" - integrity sha512-BnNsYL+X5I4WCH6wOpY6HQtp4MgVt0NVlhLUsEyrvMUiTs0bPkDBrulsgZQBUKJsbOr3l9nHrFoNVB/0i6WNLA== +"@sentry/replay@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.117.0.tgz#c41844b60ad5d711d663a562e2df77fe14c51bbb" + integrity sha512-V4DfU+x4UsA4BsufbQ8jHYa5H0q5PYUgso2X1PR31g1fpx7yiYguSmCfz1UryM6KkH92dfTnqXapDB44kXOqzQ== dependencies: - "@sentry-internal/tracing" "7.119.0" - "@sentry/core" "7.119.0" - "@sentry/types" "7.119.0" - "@sentry/utils" "7.119.0" + "@sentry-internal/tracing" "7.117.0" + "@sentry/core" "7.117.0" + "@sentry/types" "7.117.0" + "@sentry/utils" "7.117.0" -"@sentry/types@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.119.0.tgz#8b3d7a1405c362e75cd900d46089df4e70919d2a" - integrity sha512-27qQbutDBPKGbuJHROxhIWc1i0HJaGLA90tjMu11wt0E4UNxXRX+UQl4Twu68v4EV3CPvQcEpQfgsViYcXmq+w== +"@sentry/types@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.117.0.tgz#c4d89aba487c05f4e5cbfa2f1c65180b536393b4" + integrity sha512-5dtdulcUttc3F0Te7ekZmpSp/ebt/CA71ELx0uyqVGjWsSAINwskFD77sdcjqvZWek//WjiYX1+GRKlpJ1QqsA== -"@sentry/utils@7.119.0": - version "7.119.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.119.0.tgz#debe29020f6ef3786a5bd855cf1b97116b7be826" - integrity sha512-ZwyXexWn2ZIe2bBoYnXJVPc2esCSbKpdc6+0WJa8eutXfHq3FRKg4ohkfCBpfxljQGEfP1+kfin945lA21Ka+A== +"@sentry/utils@7.117.0": + version "7.117.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.117.0.tgz#ac367a6f623bd09440b39d947437009c0ffe52b2" + integrity sha512-KkcLY8643SGBiDyPvMQOubBkwVX5IPknMHInc7jYC8pDVncGp7C65Wi506bCNPpKCWspUd/0VDNWOOen51/qKA== dependencies: - "@sentry/types" "7.119.0" + "@sentry/types" "7.117.0" "@sideway/address@^4.1.3": version "4.1.4" From 54ca8165360b886d8e7272a0e70ccf3bc7a11e2a Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Fri, 4 Oct 2024 09:33:32 -0500 Subject: [PATCH 4/7] Update built asset caching (#5601) --- bskyweb/cmd/bskyweb/server.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index 54c5f075ac..ea102802e7 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -204,14 +204,8 @@ func serve(cctx *cli.Context) error { path := c.Request().URL.Path maxAge := 1 * (60 * 60) // default is 1 hour - // Cache javascript and images files for 1 week, which works because - // they're always versioned (e.g. /static/js/main.64c14927.js) - if strings.HasPrefix(path, "/static/js/") || strings.HasPrefix(path, "/static/images/") || strings.HasPrefix(path, "/static/media/") { - maxAge = 7 * (60 * 60 * 24) // 1 week - } - - // fonts can be cached for a year - if strings.HasSuffix(path, ".otf") { + // all assets in /static/js, /static/css, /static/media are content-hashed and can be cached for a long time + if strings.HasPrefix(path, "/static/js/") || strings.HasPrefix(path, "/static/css/") || strings.HasPrefix(path, "/static/media/") { maxAge = 365 * (60 * 60 * 24) // 1 year } From 6382fe45356a1fd8696f7fa62a2d140fc833ac8a Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Fri, 4 Oct 2024 09:34:03 -0500 Subject: [PATCH 5/7] Bump SDK (#5602) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 99651582c8..9f66545db8 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "icons:optimize": "svgo -f ./assets/icons" }, "dependencies": { - "@atproto/api": "^0.13.8", + "@atproto/api": "^0.13.11", "@braintree/sanitize-url": "^6.0.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", "@emoji-mart/react": "^1.1.1", diff --git a/yarn.lock b/yarn.lock index c1e711242d..a7ef1e0d60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -85,10 +85,10 @@ multiformats "^9.9.0" tlds "^1.234.0" -"@atproto/api@^0.13.8": - version "0.13.8" - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.8.tgz#44aa4992442812604bccf9eebe4d1db9ed64c179" - integrity sha512-1RlvMg8iAT5k3F0U3549ct9+jXthlXtfFXIfTXLyXXFe9Exfvmr7ZJ1ra41vU1nXGsoouCoTxj7kdzC4MY8JZg== +"@atproto/api@^0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.11.tgz#936664d9b57686840231fbab222e19abbe3f93c9" + integrity sha512-YW+4WzZEGGj/SDYo9w+S2PkSaeSS+8Dosk21GFm4EFYq1eq7G0cxuMgvdcq6fov7f9zqsaTFQL2fA6cAgMA0ow== dependencies: "@atproto/common-web" "^0.3.1" "@atproto/lexicon" "^0.4.2" From 282db85c069841ef57bb3a0a7c57a93d7d31939a Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 5 Oct 2024 03:39:33 +0900 Subject: [PATCH 6/7] Track links and embeds in the composer reducer (#5593) * Scaffold embed draft types These don't map 1:1 to the record structure. Rather, we select data from the draft on posting. * Prefill initial quote * Implement the reducer --- src/view/com/composer/Composer.tsx | 17 ++- src/view/com/composer/state/composer.ts | 151 +++++++++++++++++++++--- 2 files changed, 151 insertions(+), 17 deletions(-) diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index f4e290ca8d..b5f2d84d4f 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -190,7 +190,7 @@ export const ComposePost = ({ // TODO: Move more state here. const [composerState, dispatch] = useReducer( composerReducer, - {initImageUris}, + {initImageUris, initQuoteUri: initQuote?.uri}, createComposerState, ) @@ -337,6 +337,7 @@ export const ComposePost = ({ const onNewLink = useCallback( (uri: string) => { + dispatch({type: 'embed_add_uri', uri}) if (extLink != null) return setExtLink({uri, isLoading: true}) }, @@ -582,6 +583,7 @@ export const ComposePost = ({ const onSelectGif = useCallback( (gif: Gif) => { + dispatch({type: 'embed_add_gif', gif}) setExtLink({ uri: `${gif.media_formats.gif.url}?hh=${gif.media_formats.gif.dims[1]}&ww=${gif.media_formats.gif.dims[0]}`, isLoading: true, @@ -600,6 +602,7 @@ export const ComposePost = ({ const handleChangeGifAltText = useCallback( (altText: string) => { + dispatch({type: 'embed_update_gif', alt: altText}) setExtLink(ext => ext && ext.meta ? { @@ -770,6 +773,11 @@ export const ComposePost = ({ link={extLink} gif={extGif} onRemove={() => { + if (extGif) { + dispatch({type: 'embed_remove_gif'}) + } else { + dispatch({type: 'embed_remove_link'}) + } setExtLink(undefined) setExtGif(undefined) }} @@ -818,7 +826,12 @@ export const ComposePost = ({ {quote.uri !== initQuote?.uri && ( - setQuote(undefined)} /> + { + dispatch({type: 'embed_remove_quote'}) + setQuote(undefined) + }} + /> )} ) : null} diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts index a23a5d8c86..769a0521d4 100644 --- a/src/view/com/composer/state/composer.ts +++ b/src/view/com/composer/state/composer.ts @@ -1,17 +1,14 @@ import {ImagePickerAsset} from 'expo-image-picker' +import {isBskyPostUrl} from '#/lib/strings/url-helpers' import {ComposerImage, createInitialImages} from '#/state/gallery' +import {Gif} from '#/state/queries/tenor' import {ComposerOpts} from '#/state/shell/composer' import {createVideoState, VideoAction, videoReducer, VideoState} from './video' -type PostRecord = { - uri: string -} - type ImagesMedia = { type: 'images' images: ComposerImage[] - labels: string[] } type VideoMedia = { @@ -19,16 +16,30 @@ type VideoMedia = { video: VideoState } -type ComposerEmbed = { - // TODO: Other record types. - record: PostRecord | undefined - // TODO: Other media types. - media: ImagesMedia | VideoMedia | undefined +type GifMedia = { + type: 'gif' + gif: Gif + alt: string +} + +type Link = { + type: 'link' + uri: string +} + +// This structure doesn't exactly correspond to the data model. +// Instead, it maps to how the UI is organized, and how we present a post. +type EmbedDraft = { + // We'll always submit quote and actual media (images, video, gifs) chosen by the user. + quote: Link | undefined + media: ImagesMedia | VideoMedia | GifMedia | undefined + // This field may end up ignored if we have more important things to display than a link card: + link: Link | undefined } export type ComposerState = { // TODO: Other draft data. - embed: ComposerEmbed + embed: EmbedDraft } export type ComposerAction = @@ -42,6 +53,12 @@ export type ComposerAction = } | {type: 'embed_remove_video'} | {type: 'embed_update_video'; videoAction: VideoAction} + | {type: 'embed_add_uri'; uri: string} + | {type: 'embed_remove_quote'} + | {type: 'embed_remove_link'} + | {type: 'embed_add_gif'; gif: Gif} + | {type: 'embed_update_gif'; alt: string} + | {type: 'embed_remove_gif'} const MAX_IMAGES = 4 @@ -60,7 +77,6 @@ export function composerReducer( nextMedia = { type: 'images', images: action.images.slice(0, MAX_IMAGES), - labels: [], } } else if (prevMedia.type === 'images') { nextMedia = { @@ -171,6 +187,102 @@ export function composerReducer( }, } } + case 'embed_add_uri': { + const prevQuote = state.embed.quote + const prevLink = state.embed.link + let nextQuote = prevQuote + let nextLink = prevLink + if (isBskyPostUrl(action.uri)) { + if (!prevQuote) { + nextQuote = { + type: 'link', + uri: action.uri, + } + } + } else { + if (!prevLink) { + nextLink = { + type: 'link', + uri: action.uri, + } + } + } + return { + ...state, + embed: { + ...state.embed, + quote: nextQuote, + link: nextLink, + }, + } + } + case 'embed_remove_link': { + return { + ...state, + embed: { + ...state.embed, + link: undefined, + }, + } + } + case 'embed_remove_quote': { + return { + ...state, + embed: { + ...state.embed, + quote: undefined, + }, + } + } + case 'embed_add_gif': { + const prevMedia = state.embed.media + let nextMedia = prevMedia + if (!prevMedia) { + nextMedia = { + type: 'gif', + gif: action.gif, + alt: '', + } + } + return { + ...state, + embed: { + ...state.embed, + media: nextMedia, + }, + } + } + case 'embed_update_gif': { + const prevMedia = state.embed.media + let nextMedia = prevMedia + if (prevMedia?.type === 'gif') { + nextMedia = { + ...prevMedia, + alt: action.alt, + } + } + return { + ...state, + embed: { + ...state.embed, + media: nextMedia, + }, + } + } + case 'embed_remove_gif': { + const prevMedia = state.embed.media + let nextMedia = prevMedia + if (prevMedia?.type === 'gif') { + nextMedia = undefined + } + return { + ...state, + embed: { + ...state.embed, + media: nextMedia, + }, + } + } default: return state } @@ -178,22 +290,31 @@ export function composerReducer( export function createComposerState({ initImageUris, + initQuoteUri, }: { initImageUris: ComposerOpts['imageUris'] + initQuoteUri: string | undefined }): ComposerState { let media: ImagesMedia | undefined if (initImageUris?.length) { media = { type: 'images', images: createInitialImages(initImageUris), - labels: [], } } - // TODO: initial video. + let quote: Link | undefined + if (initQuoteUri) { + quote = { + type: 'link', + uri: initQuoteUri, + } + } + // TODO: Other initial content. return { embed: { - record: undefined, + quote, media, + link: undefined, }, } } From 09caf327d9809311f78e7f0d5c2f7213924e53ae Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 5 Oct 2024 03:45:34 +0900 Subject: [PATCH 7/7] Make composer reducer source of truth for images/video when publishing (#5595) * Move caption and altText state into video reducer * Make composer state source of truth for images and video publish --- src/lib/api/index.ts | 32 ++++++------- src/view/com/composer/Composer.tsx | 47 +++++++++--------- src/view/com/composer/state/video.ts | 48 ++++++++++++++++++- .../com/composer/videos/SubtitleDialog.tsx | 12 ++--- 4 files changed, 89 insertions(+), 50 deletions(-) diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts index 8b79250042..c7608ae557 100644 --- a/src/lib/api/index.ts +++ b/src/lib/api/index.ts @@ -1,5 +1,4 @@ import { - AppBskyEmbedDefs, AppBskyEmbedExternal, AppBskyEmbedImages, AppBskyEmbedRecord, @@ -7,7 +6,6 @@ import { AppBskyEmbedVideo, AppBskyFeedPostgate, AtUri, - BlobRef, BskyAgent, ComAtprotoLabelDefs, RichText, @@ -46,14 +44,7 @@ interface PostOpts { uri: string cid: string } - video?: { - blobRef: BlobRef - altText: string - captions: {lang: string; file: File}[] - aspectRatio?: AppBskyEmbedDefs.AspectRatio - } extLink?: ExternalEmbedDraft - images?: ComposerImage[] labels?: string[] threadgate: ThreadgateAllowUISetting[] postgate: AppBskyFeedPostgate.Record @@ -230,13 +221,15 @@ async function resolveMedia( | AppBskyEmbedVideo.Main | undefined > { - if (opts.images?.length) { + const state = opts.composerState + const media = state.embed.media + if (media?.type === 'images') { logger.debug(`Uploading images`, { - count: opts.images.length, + count: media.images.length, }) opts.onStateChange?.(`Uploading images...`) const images: AppBskyEmbedImages.Image[] = await Promise.all( - opts.images.map(async (image, i) => { + media.images.map(async (image, i) => { logger.debug(`Compressing image #${i}`) const {path, width, height, mime} = await compressImage(image) logger.debug(`Uploading image #${i}`) @@ -253,9 +246,10 @@ async function resolveMedia( images, } } - if (opts.video) { + if (media?.type === 'video' && media.video.status === 'done') { + const video = media.video const captions = await Promise.all( - opts.video.captions + video.captions .filter(caption => caption.lang !== '') .map(async caption => { const {data} = await agent.uploadBlob(caption.file, { @@ -266,13 +260,17 @@ async function resolveMedia( ) return { $type: 'app.bsky.embed.video', - video: opts.video.blobRef, - alt: opts.video.altText || undefined, + video: video.pendingPublish.blobRef, + alt: video.altText || undefined, captions: captions.length === 0 ? undefined : captions, - aspectRatio: opts.video.aspectRatio, + aspectRatio: { + width: video.asset.width, + height: video.asset.height, + }, } } if (opts.extLink) { + // TODO: Read this from composer state as well. if (opts.extLink.embed) { return undefined } diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index b5f2d84d4f..2279649070 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -184,9 +184,6 @@ export const ComposePost = ({ initQuote, ) - const [videoAltText, setVideoAltText] = useState('') - const [captions, setCaptions] = useState<{lang: string; file: File}[]>([]) - // TODO: Move more state here. const [composerState, dispatch] = useReducer( composerReducer, @@ -422,10 +419,9 @@ export const ComposePost = ({ try { postUri = ( await apilib.post(agent, { - composerState, // TODO: not used yet. + composerState, // TODO: move more state here. rawText: richtext.text, replyTo: replyTo?.uri, - images, quote, extLink, labels, @@ -433,18 +429,6 @@ export const ComposePost = ({ postgate, onStateChange: setProcessingState, langs: toPostLanguages(langPrefs.postLanguage), - video: - videoState.status === 'done' - ? { - blobRef: videoState.pendingPublish.blobRef, - altText: videoAltText, - captions: captions, - aspectRatio: { - width: videoState.asset.width, - height: videoState.asset.height, - }, - } - : undefined, }) ).uri try { @@ -522,7 +506,6 @@ export const ComposePost = ({ [ _, agent, - captions, composerState, extLink, images, @@ -541,9 +524,7 @@ export const ComposePost = ({ setExtLink, setLangPrefs, threadgateAllowUISettings, - videoAltText, videoState.asset, - videoState.pendingPublish, videoState.status, ], ) @@ -811,10 +792,28 @@ export const ComposePost = ({ /> ) : null)} + dispatch({ + type: 'embed_update_video', + videoAction: { + type: 'update_alt_text', + altText, + signal: videoState.abortController.signal, + }, + }) + } + captions={videoState.captions} + setCaptions={updater => { + dispatch({ + type: 'embed_update_video', + videoAction: { + type: 'update_captions', + updater, + signal: videoState.abortController.signal, + }, + }) + }} /> )} diff --git a/src/view/com/composer/state/video.ts b/src/view/com/composer/state/video.ts index 2695056579..e29687200f 100644 --- a/src/view/com/composer/state/video.ts +++ b/src/view/com/composer/state/video.ts @@ -4,8 +4,6 @@ import {JobStatus} from '@atproto/api/dist/client/types/app/bsky/video/defs' import {I18n} from '@lingui/core' import {msg} from '@lingui/macro' -import {createVideoAgent} from '#/lib/media/video/util' -import {uploadVideo} from '#/lib/media/video/upload' import {AbortError} from '#/lib/async/cancelable' import {compressVideo} from '#/lib/media/video/compress' import { @@ -14,8 +12,12 @@ import { VideoTooLargeError, } from '#/lib/media/video/errors' import {CompressedVideo} from '#/lib/media/video/types' +import {uploadVideo} from '#/lib/media/video/upload' +import {createVideoAgent} from '#/lib/media/video/util' import {logger} from '#/logger' +type CaptionsTrack = {lang: string; file: File} + export type VideoAction = | { type: 'compressing_to_uploading' @@ -40,6 +42,16 @@ export type VideoAction = height: number signal: AbortSignal } + | { + type: 'update_alt_text' + altText: string + signal: AbortSignal + } + | { + type: 'update_captions' + updater: (prev: CaptionsTrack[]) => CaptionsTrack[] + signal: AbortSignal + } | { type: 'update_job_status' jobStatus: AppBskyVideoDefs.JobStatus @@ -57,6 +69,8 @@ export const NO_VIDEO = Object.freeze({ video: undefined, jobId: undefined, pendingPublish: undefined, + altText: '', + captions: [], }) export type NoVideoState = typeof NO_VIDEO @@ -70,6 +84,8 @@ type ErrorState = { jobId: string | null error: string pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type CompressingState = { @@ -80,6 +96,8 @@ type CompressingState = { video?: undefined jobId?: undefined pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type UploadingState = { @@ -90,6 +108,8 @@ type UploadingState = { video: CompressedVideo jobId?: undefined pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type ProcessingState = { @@ -101,6 +121,8 @@ type ProcessingState = { jobId: string jobStatus: AppBskyVideoDefs.JobStatus | null pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type DoneState = { @@ -111,6 +133,8 @@ type DoneState = { video: CompressedVideo jobId?: undefined pendingPublish: {blobRef: BlobRef; mutableProcessed: boolean} + altText: string + captions: CaptionsTrack[] } export type VideoState = @@ -129,6 +153,8 @@ export function createVideoState( progress: 0, abortController, asset, + altText: '', + captions: [], } } @@ -149,6 +175,8 @@ export function videoReducer( asset: state.asset ?? null, video: state.video ?? null, jobId: state.jobId ?? null, + altText: state.altText, + captions: state.captions, } } else if (action.type === 'update_progress') { if (state.status === 'compressing' || state.status === 'uploading') { @@ -164,6 +192,16 @@ export function videoReducer( asset: {...state.asset, width: action.width, height: action.height}, } } + } else if (action.type === 'update_alt_text') { + return { + ...state, + altText: action.altText, + } + } else if (action.type === 'update_captions') { + return { + ...state, + captions: action.updater(state.captions), + } } else if (action.type === 'compressing_to_uploading') { if (state.status === 'compressing') { return { @@ -172,6 +210,8 @@ export function videoReducer( abortController: state.abortController, asset: state.asset, video: action.video, + altText: state.altText, + captions: state.captions, } } return state @@ -185,6 +225,8 @@ export function videoReducer( video: state.video, jobId: action.jobId, jobStatus: null, + altText: state.altText, + captions: state.captions, } } } else if (action.type === 'update_job_status') { @@ -210,6 +252,8 @@ export function videoReducer( blobRef: action.blobRef, mutableProcessed: false, }, + altText: state.altText, + captions: state.captions, } } } diff --git a/src/view/com/composer/videos/SubtitleDialog.tsx b/src/view/com/composer/videos/SubtitleDialog.tsx index c07fdfc562..f66684d4ea 100644 --- a/src/view/com/composer/videos/SubtitleDialog.tsx +++ b/src/view/com/composer/videos/SubtitleDialog.tsx @@ -22,13 +22,13 @@ import {SubtitleFilePicker} from './SubtitleFilePicker' const MAX_NUM_CAPTIONS = 1 +type CaptionsTrack = {lang: string; file: File} + interface Props { defaultAltText: string - captions: {lang: string; file: File}[] + captions: CaptionsTrack[] saveAltText: (altText: string) => void - setCaptions: React.Dispatch< - React.SetStateAction<{lang: string; file: File}[]> - > + setCaptions: (updater: (prev: CaptionsTrack[]) => CaptionsTrack[]) => void } export function SubtitleDialogBtn(props: Props) { @@ -198,9 +198,7 @@ function SubtitleFileRow({ language: string file: File otherLanguages: {code2: string; code3: string; name: string}[] - setCaptions: React.Dispatch< - React.SetStateAction<{lang: string; file: File}[]> - > + setCaptions: (updater: (prev: CaptionsTrack[]) => CaptionsTrack[]) => void style: StyleProp }) { const {_} = useLingui()