Merge remote-tracking branch 'upstream/main' into Improve-notification-localization

This commit is contained in:
Minseo Lee
2024-09-12 14:21:11 +09:00
24 changed files with 495 additions and 210 deletions
+1 -1
View File
@@ -372,7 +372,7 @@ function VideoEmbed({content}: {content: AppBskyEmbedVideo.View}) {
return (
<div
className="w-full overflow-hidden rounded-lg aspect-square"
className="w-full overflow-hidden rounded-lg aspect-square relative"
style={{aspectRatio: `${aspectRatio} / 1`}}>
<img
src={content.thumbnail}
-1
View File
@@ -259,7 +259,6 @@
pointer-events: none !important;
}
</style>
</style>
{% include "scripts.html" %}
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
+1 -1
View File
@@ -52,7 +52,7 @@
"open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web"
},
"dependencies": {
"@atproto/api": "0.13.5",
"@atproto/api": "^0.13.7",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
+17
View File
@@ -0,0 +1,17 @@
import React from 'react'
const MessageContext = React.createContext(false)
export function MessageContextProvider({
children,
}: {
children: React.ReactNode
}) {
return (
<MessageContext.Provider value={true}>{children}</MessageContext.Provider>
)
}
export function useIsWithinMessage() {
return React.useContext(MessageContext)
}
+3
View File
@@ -4,6 +4,7 @@ import {AppBskyEmbedRecord} from '@atproto/api'
import {PostEmbeds, PostEmbedViewContext} from '#/view/com/util/post-embeds'
import {atoms as a, native, useTheme} from '#/alf'
import {MessageContextProvider} from './MessageContext'
let MessageItemEmbed = ({
embed,
@@ -13,6 +14,7 @@ let MessageItemEmbed = ({
const t = useTheme()
return (
<MessageContextProvider>
<View style={[a.my_xs, t.atoms.bg, native({flexBasis: 0})]}>
<PostEmbeds
embed={embed}
@@ -20,6 +22,7 @@ let MessageItemEmbed = ({
viewContext={PostEmbedViewContext.Feed}
/>
</View>
</MessageContextProvider>
)
}
MessageItemEmbed = React.memo(MessageItemEmbed)
+2 -1
View File
@@ -5,7 +5,7 @@ import {SUPPORTED_MIME_TYPES, SupportedMimeTypes} from '#/lib/constants'
import {extToMime} from '#/state/queries/video/util'
import {CompressedVideo} from './types'
const MIN_SIZE_FOR_COMPRESSION = 1024 * 1024 * 25 // 25mb
const MIN_SIZE_FOR_COMPRESSION = 25 // 25mb
export async function compressVideo(
file: ImagePickerAsset,
@@ -30,6 +30,7 @@ export async function compressVideo(
compressionMethod: 'manual',
bitrate: 3_000_000, // 3mbps
maxSize: 1920,
// WARNING: this ONE SPECIFIC ARG is in MB -sfn
minimumFileSizeForCompress,
getCancellationId: id => {
if (signal) {
+1 -4
View File
@@ -1,6 +1,3 @@
export type Gate =
// Keep this alphabetic please.
| 'debug_show_feedcontext'
| 'suggested_feeds_interstitial'
| 'video_upload' // upload videos
| 'video_view_on_posts' // see posted videos
'debug_show_feedcontext' | 'suggested_feeds_interstitial' | 'video_upload' // upload videos
+73 -68
View File
@@ -127,7 +127,7 @@ msgstr ""
msgid "{0} joined this week"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:593
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:637
msgid "{0} of {1}"
msgstr ""
@@ -461,7 +461,7 @@ msgstr ""
#~ msgid "Add ALT text"
#~ msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:107
#: src/view/com/composer/videos/SubtitleDialog.tsx:109
msgid "Add alt text (optional)"
msgstr ""
@@ -607,9 +607,9 @@ msgid "ALT"
msgstr ""
#: src/view/com/composer/GifAltText.tsx:144
#: src/view/com/composer/videos/SubtitleDialog.tsx:54
#: src/view/com/composer/videos/SubtitleDialog.tsx:102
#: src/view/com/composer/videos/SubtitleDialog.tsx:106
#: src/view/com/composer/videos/SubtitleDialog.tsx:56
#: src/view/com/composer/videos/SubtitleDialog.tsx:104
#: src/view/com/composer/videos/SubtitleDialog.tsx:108
#: src/view/com/modals/EditImage.tsx:316
#: src/view/screens/AccessibilitySettings.tsx:87
msgid "Alt text"
@@ -640,7 +640,7 @@ msgstr ""
#~ msgid "An error occured"
#~ msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:369
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:413
msgid "An error occurred"
msgstr ""
@@ -652,11 +652,11 @@ msgstr ""
msgid "An error occurred while generating your starter pack. Want to try again?"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbed.tsx:213
#: src/view/com/util/post-embeds/VideoEmbed.tsx:215
msgid "An error occurred while loading the video. Please try again later."
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:170
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:171
msgid "An error occurred while loading the video. Please try again."
msgstr ""
@@ -669,7 +669,7 @@ msgstr ""
msgid "An error occurred while saving the QR code!"
msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:61
#: src/view/com/composer/videos/SelectVideoBtn.tsx:68
msgid "An error occurred while selecting the video"
msgstr ""
@@ -844,7 +844,7 @@ msgstr ""
msgid "Are you sure you want to remove this from your feeds?"
msgstr ""
#: src/view/com/composer/Composer.tsx:837
#: src/view/com/composer/Composer.tsx:841
msgid "Are you sure you'd like to discard this draft?"
msgstr ""
@@ -1096,8 +1096,8 @@ msgstr ""
#: src/components/Prompt.tsx:124
#: src/components/TagMenu/index.tsx:282
#: src/screens/Deactivated.tsx:161
#: src/view/com/composer/Composer.tsx:591
#: src/view/com/composer/Composer.tsx:606
#: src/view/com/composer/Composer.tsx:595
#: src/view/com/composer/Composer.tsx:610
#: src/view/com/modals/ChangeEmail.tsx:213
#: src/view/com/modals/ChangeEmail.tsx:215
#: src/view/com/modals/ChangeHandle.tsx:148
@@ -1165,11 +1165,11 @@ msgstr ""
msgid "Cannot interact with a blocked user"
msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:133
#: src/view/com/composer/videos/SubtitleDialog.tsx:135
msgid "Captions (.vtt)"
msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:54
#: src/view/com/composer/videos/SubtitleDialog.tsx:56
msgid "Captions & alt text"
msgstr ""
@@ -1457,7 +1457,7 @@ msgstr ""
msgid "Closes password update alert"
msgstr ""
#: src/view/com/composer/Composer.tsx:603
#: src/view/com/composer/Composer.tsx:607
msgid "Closes post composer and discards post draft"
msgstr ""
@@ -1496,7 +1496,7 @@ msgstr ""
msgid "Complete the challenge"
msgstr ""
#: src/view/com/composer/Composer.tsx:711
#: src/view/com/composer/Composer.tsx:715
msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length"
msgstr ""
@@ -1742,7 +1742,7 @@ msgstr ""
msgid "Could not mute chat"
msgstr ""
#: src/view/com/composer/videos/VideoPreview.web.tsx:45
#: src/view/com/composer/videos/VideoPreview.web.tsx:56
msgid "Could not process your video"
msgstr ""
@@ -2005,7 +2005,7 @@ msgstr ""
msgid "Dialog: adjust who can interact with this post"
msgstr ""
#: src/view/com/composer/Composer.tsx:352
#: src/view/com/composer/Composer.tsx:356
msgid "Did you want to say anything?"
msgstr ""
@@ -2038,7 +2038,7 @@ msgstr ""
#~ msgid "Disable haptics"
#~ msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:335
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:379
msgid "Disable subtitles"
msgstr ""
@@ -2055,11 +2055,11 @@ msgstr ""
msgid "Disabled"
msgstr ""
#: src/view/com/composer/Composer.tsx:839
#: src/view/com/composer/Composer.tsx:843
msgid "Discard"
msgstr ""
#: src/view/com/composer/Composer.tsx:836
#: src/view/com/composer/Composer.tsx:840
msgid "Discard draft?"
msgstr ""
@@ -2089,7 +2089,7 @@ msgstr ""
#~ msgid "Dismiss"
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:1106
#: src/view/com/composer/Composer.tsx:1110
msgid "Dismiss error"
msgstr ""
@@ -2141,8 +2141,8 @@ msgstr ""
#: src/screens/Onboarding/StepProfile/index.tsx:325
#: src/view/com/auth/server-input/index.tsx:169
#: src/view/com/auth/server-input/index.tsx:170
#: src/view/com/composer/videos/SubtitleDialog.tsx:167
#: src/view/com/composer/videos/SubtitleDialog.tsx:177
#: src/view/com/composer/videos/SubtitleDialog.tsx:171
#: src/view/com/composer/videos/SubtitleDialog.tsx:181
#: src/view/com/modals/AddAppPasswords.tsx:243
#: src/view/com/modals/AltImage.tsx:141
#: src/view/com/modals/crop-image/CropImage.web.tsx:177
@@ -2417,7 +2417,7 @@ msgstr ""
msgid "Enable priority notifications"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:336
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:380
msgid "Enable subtitles"
msgstr ""
@@ -2447,7 +2447,7 @@ msgstr ""
#~ msgid "End of onboarding tour window. Do not move forward. Instead, go backward for more options, or press to skip."
#~ msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:157
#: src/view/com/composer/videos/SubtitleDialog.tsx:161
msgid "Ensure you have selected a language for each subtitle file."
msgstr ""
@@ -2549,7 +2549,7 @@ msgstr ""
msgid "Excludes users you follow"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:353
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:397
msgid "Exit fullscreen"
msgstr ""
@@ -3057,7 +3057,7 @@ msgctxt "from-feed"
msgid "From <0/>"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:354
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:398
msgid "Fullscreen"
msgstr ""
@@ -3526,7 +3526,7 @@ msgstr ""
msgid "It's just you right now! Add more people to your starter pack by searching above."
msgstr ""
#: src/view/com/composer/Composer.tsx:1125
#: src/view/com/composer/Composer.tsx:1129
msgid "Job ID: {0}"
msgstr ""
@@ -4046,12 +4046,12 @@ msgstr ""
msgid "Music"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:345
msgctxt "video"
#: src/components/TagMenu/index.tsx:263
msgid "Mute"
msgstr ""
#: src/components/TagMenu/index.tsx:263
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:389
msgctxt "video"
msgid "Mute"
msgstr ""
@@ -4583,7 +4583,7 @@ msgstr ""
#~ msgid "Onboarding tour step {0}: {1}"
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:668
#: src/view/com/composer/Composer.tsx:672
msgid "One or more images is missing alt text."
msgstr ""
@@ -4638,8 +4638,8 @@ msgid "Open conversation options"
msgstr ""
#: src/screens/Messages/Conversation/MessageInput.web.tsx:165
#: src/view/com/composer/Composer.tsx:819
#: src/view/com/composer/Composer.tsx:820
#: src/view/com/composer/Composer.tsx:823
#: src/view/com/composer/Composer.tsx:824
msgid "Open emoji picker"
msgstr ""
@@ -4825,7 +4825,7 @@ msgstr ""
msgid "Opens this profile"
msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:81
#: src/view/com/composer/videos/SelectVideoBtn.tsx:88
msgid "Opens video picker"
msgstr ""
@@ -4903,11 +4903,11 @@ msgid "Password updated!"
msgstr ""
#: src/view/com/util/post-embeds/GifEmbed.tsx:44
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:322
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:366
msgid "Pause"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:275
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:319
msgid "Pause video"
msgstr ""
@@ -4967,7 +4967,7 @@ msgid "Pinned to your feeds"
msgstr ""
#: src/view/com/util/post-embeds/GifEmbed.tsx:44
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:323
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:367
msgid "Play"
msgstr ""
@@ -4984,8 +4984,8 @@ msgstr ""
msgid "Play or pause the GIF"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbed.tsx:187
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:276
#: src/view/com/util/post-embeds/VideoEmbed.tsx:189
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:320
msgid "Play video"
msgstr ""
@@ -5057,7 +5057,7 @@ msgstr ""
msgid "Please Verify Your Email"
msgstr ""
#: src/view/com/composer/Composer.tsx:356
#: src/view/com/composer/Composer.tsx:360
msgid "Please wait for your link card to finish loading"
msgstr ""
@@ -5070,8 +5070,8 @@ msgstr ""
msgid "Porn"
msgstr ""
#: src/view/com/composer/Composer.tsx:643
#: src/view/com/composer/Composer.tsx:650
#: src/view/com/composer/Composer.tsx:647
#: src/view/com/composer/Composer.tsx:654
msgctxt "action"
msgid "Post"
msgstr ""
@@ -5250,11 +5250,11 @@ msgstr ""
msgid "Public, shareable lists which can drive feeds."
msgstr ""
#: src/view/com/composer/Composer.tsx:628
#: src/view/com/composer/Composer.tsx:632
msgid "Publish post"
msgstr ""
#: src/view/com/composer/Composer.tsx:628
#: src/view/com/composer/Composer.tsx:632
msgid "Publish reply"
msgstr ""
@@ -5482,7 +5482,7 @@ msgstr ""
msgid "Remove repost"
msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:260
#: src/view/com/composer/videos/SubtitleDialog.tsx:264
msgid "Remove subtitle file"
msgstr ""
@@ -5559,7 +5559,7 @@ msgstr ""
#~ msgid "Replies to this thread are disabled"
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:641
#: src/view/com/composer/Composer.tsx:645
msgctxt "action"
msgid "Reply"
msgstr ""
@@ -6053,7 +6053,7 @@ msgstr ""
#~ msgid "See what's next"
#~ msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:587
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:631
msgid "Seek slider"
msgstr ""
@@ -6093,7 +6093,7 @@ msgstr ""
msgid "Select how long to mute this word for."
msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:245
#: src/view/com/composer/videos/SubtitleDialog.tsx:249
msgid "Select language..."
msgstr ""
@@ -6133,7 +6133,7 @@ msgstr ""
#~ msgid "Select topical feeds to follow from the list below"
#~ msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:80
#: src/view/com/composer/videos/SelectVideoBtn.tsx:87
msgid "Select video"
msgstr ""
@@ -7429,7 +7429,7 @@ msgstr ""
msgid "To report a conversation, please report one of its messages via the conversation screen. This lets our moderators understand the context of your issue."
msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:106
#: src/view/com/composer/videos/SelectVideoBtn.tsx:113
msgid "To upload videos to Bluesky, you must first verify your email."
msgstr ""
@@ -7572,13 +7572,13 @@ msgstr ""
msgid "Unlike this feed"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:344
msgctxt "video"
#: src/components/TagMenu/index.tsx:263
#: src/view/screens/ProfileList.tsx:689
msgid "Unmute"
msgstr ""
#: src/components/TagMenu/index.tsx:263
#: src/view/screens/ProfileList.tsx:689
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:388
msgctxt "video"
msgid "Unmute"
msgstr ""
@@ -7608,7 +7608,7 @@ msgstr ""
msgid "Unmute thread"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:273
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:317
msgid "Unmute video"
msgstr ""
@@ -7837,7 +7837,7 @@ msgstr ""
msgid "Value:"
msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:104
#: src/view/com/composer/videos/SelectVideoBtn.tsx:111
msgid "Verified email required"
msgstr ""
@@ -7870,7 +7870,7 @@ msgstr ""
msgid "Verify New Email"
msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:108
#: src/view/com/composer/videos/SelectVideoBtn.tsx:115
msgid "Verify now"
msgstr ""
@@ -7904,11 +7904,11 @@ msgstr ""
msgid "Video Games"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:163
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:164
msgid "Video not found."
msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:99
#: src/view/com/composer/videos/SubtitleDialog.tsx:101
msgid "Video settings"
msgstr ""
@@ -7920,6 +7920,11 @@ msgstr ""
#~ msgid "Videos cannot be larger than 50MB"
#~ msgstr ""
#: src/view/com/composer/videos/SelectVideoBtn.tsx:58
#: src/view/com/composer/videos/VideoPreview.web.tsx:44
msgid "Videos must be less than 60 seconds long"
msgstr ""
#: src/screens/Profile/Header/Shell.tsx:113
msgid "View {0}'s avatar"
msgstr ""
@@ -8093,7 +8098,7 @@ msgstr ""
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
msgstr ""
#: src/view/com/composer/Composer.tsx:418
#: src/view/com/composer/Composer.tsx:422
msgid "We're sorry! The post you are replying to has been deleted."
msgstr ""
@@ -8132,7 +8137,7 @@ msgstr ""
#: src/view/com/auth/SplashScreen.tsx:40
#: src/view/com/auth/SplashScreen.web.tsx:86
#: src/view/com/composer/Composer.tsx:513
#: src/view/com/composer/Composer.tsx:517
msgid "What's up?"
msgstr ""
@@ -8207,11 +8212,11 @@ msgstr ""
msgid "Write a message"
msgstr ""
#: src/view/com/composer/Composer.tsx:709
#: src/view/com/composer/Composer.tsx:713
msgid "Write post"
msgstr ""
#: src/view/com/composer/Composer.tsx:512
#: src/view/com/composer/Composer.tsx:516
#: src/view/com/post-thread/PostThreadComposePrompt.tsx:42
msgid "Write your reply"
msgstr ""
@@ -8571,7 +8576,7 @@ msgstr ""
msgid "Your birth date"
msgstr ""
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:167
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:168
msgid "Your browser does not support the video format. Please try a different browser."
msgstr ""
@@ -8626,7 +8631,7 @@ msgstr ""
msgid "Your password has been changed successfully!"
msgstr ""
#: src/view/com/composer/Composer.tsx:464
#: src/view/com/composer/Composer.tsx:468
msgid "Your post has been published"
msgstr ""
@@ -8642,7 +8647,7 @@ msgstr ""
msgid "Your profile, posts, feeds, and lists will no longer be visible to other Bluesky users. You can reactivate your account at any time by logging in."
msgstr ""
#: src/view/com/composer/Composer.tsx:463
#: src/view/com/composer/Composer.tsx:467
msgid "Your reply has been published"
msgstr ""
+76 -71
View File
@@ -127,7 +127,7 @@ msgstr ""
msgid "{0} joined this week"
msgstr "{0} entrou esta semana"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:593
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:637
msgid "{0} of {1}"
msgstr ""
@@ -461,7 +461,7 @@ msgstr "Adicionar texto alternativo"
#~ msgid "Add ALT text"
#~ msgstr "Adicionar texto alternativo"
#: src/view/com/composer/videos/SubtitleDialog.tsx:107
#: src/view/com/composer/videos/SubtitleDialog.tsx:109
msgid "Add alt text (optional)"
msgstr "Adicionar texto alternativo (opcional)"
@@ -607,9 +607,9 @@ msgid "ALT"
msgstr "ALT"
#: src/view/com/composer/GifAltText.tsx:144
#: src/view/com/composer/videos/SubtitleDialog.tsx:54
#: src/view/com/composer/videos/SubtitleDialog.tsx:102
#: src/view/com/composer/videos/SubtitleDialog.tsx:106
#: src/view/com/composer/videos/SubtitleDialog.tsx:56
#: src/view/com/composer/videos/SubtitleDialog.tsx:104
#: src/view/com/composer/videos/SubtitleDialog.tsx:108
#: src/view/com/modals/EditImage.tsx:316
#: src/view/screens/AccessibilitySettings.tsx:87
msgid "Alt text"
@@ -640,7 +640,7 @@ msgstr "Ocorreu um erro"
#~ msgid "An error occured"
#~ msgstr "Tivemos um problema"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:369
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:413
msgid "An error occurred"
msgstr "Ocorreu um erro"
@@ -652,11 +652,11 @@ msgstr "Ocorreu um erro ao compactar o vídeo."
msgid "An error occurred while generating your starter pack. Want to try again?"
msgstr "Ocorreu um erro ao gerar seu pacote inicial. Quer tentar novamente?"
#: src/view/com/util/post-embeds/VideoEmbed.tsx:213
#: src/view/com/util/post-embeds/VideoEmbed.tsx:215
msgid "An error occurred while loading the video. Please try again later."
msgstr "Ocorreu um erro ao carregar o vídeo. Tente novamente mais tarde."
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:170
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:171
msgid "An error occurred while loading the video. Please try again."
msgstr "Ocorreu um erro ao carregar o vídeo. Tente novamente."
@@ -669,7 +669,7 @@ msgstr "Ocorreu um erro ao carregar o vídeo. Tente novamente."
msgid "An error occurred while saving the QR code!"
msgstr "Ocorreu um erro ao salvar o QR code!"
#: src/view/com/composer/videos/SelectVideoBtn.tsx:61
#: src/view/com/composer/videos/SelectVideoBtn.tsx:68
msgid "An error occurred while selecting the video"
msgstr "Ocorreu um erro ao selecionar o vídeo"
@@ -844,7 +844,7 @@ msgstr "Tem certeza que deseja remover {0} dos seus feeds?"
msgid "Are you sure you want to remove this from your feeds?"
msgstr "Tem certeza que deseja remover isto de seus feeds?"
#: src/view/com/composer/Composer.tsx:837
#: src/view/com/composer/Composer.tsx:841
msgid "Are you sure you'd like to discard this draft?"
msgstr "Tem certeza que deseja descartar este rascunho?"
@@ -1096,8 +1096,8 @@ msgstr "Só pode conter letras, números, espaços, riscas e subtraços. Deve te
#: src/components/Prompt.tsx:124
#: src/components/TagMenu/index.tsx:282
#: src/screens/Deactivated.tsx:161
#: src/view/com/composer/Composer.tsx:591
#: src/view/com/composer/Composer.tsx:606
#: src/view/com/composer/Composer.tsx:595
#: src/view/com/composer/Composer.tsx:610
#: src/view/com/modals/ChangeEmail.tsx:213
#: src/view/com/modals/ChangeEmail.tsx:215
#: src/view/com/modals/ChangeHandle.tsx:148
@@ -1165,11 +1165,11 @@ msgstr "Cancela a abertura do link"
msgid "Cannot interact with a blocked user"
msgstr ""
#: src/view/com/composer/videos/SubtitleDialog.tsx:133
#: src/view/com/composer/videos/SubtitleDialog.tsx:135
msgid "Captions (.vtt)"
msgstr "Legendas (.vtt)"
#: src/view/com/composer/videos/SubtitleDialog.tsx:54
#: src/view/com/composer/videos/SubtitleDialog.tsx:56
msgid "Captions & alt text"
msgstr "Legendas e texto alt"
@@ -1457,7 +1457,7 @@ msgstr "Fecha barra de navegação inferior"
msgid "Closes password update alert"
msgstr "Fecha alerta de troca de senha"
#: src/view/com/composer/Composer.tsx:603
#: src/view/com/composer/Composer.tsx:607
msgid "Closes post composer and discards post draft"
msgstr "Fecha o editor de post e descarta o rascunho"
@@ -1496,7 +1496,7 @@ msgstr "Completar e começar a usar sua conta"
msgid "Complete the challenge"
msgstr "Complete o captcha"
#: src/view/com/composer/Composer.tsx:711
#: src/view/com/composer/Composer.tsx:715
msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length"
msgstr "Escreva posts de até {MAX_GRAPHEME_LENGTH} caracteres"
@@ -1742,7 +1742,7 @@ msgstr "Não foi possível carregar a lista"
msgid "Could not mute chat"
msgstr "Não foi possível silenciar este chat"
#: src/view/com/composer/videos/VideoPreview.web.tsx:45
#: src/view/com/composer/videos/VideoPreview.web.tsx:56
msgid "Could not process your video"
msgstr "Não foi possível processar seu vídeo"
@@ -2005,7 +2005,7 @@ msgstr "Desanexar postagem de citação?"
msgid "Dialog: adjust who can interact with this post"
msgstr "Diálogo: ajuste quem pode interagir com esta postagem"
#: src/view/com/composer/Composer.tsx:352
#: src/view/com/composer/Composer.tsx:356
msgid "Did you want to say anything?"
msgstr "Você gostaria de dizer alguma coisa?"
@@ -2038,7 +2038,7 @@ msgstr "Desabilitar feedback tátil"
#~ msgid "Disable haptics"
#~ msgstr "Desabilitar feedback tátil"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:335
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:379
msgid "Disable subtitles"
msgstr "Desativar legendas"
@@ -2055,11 +2055,11 @@ msgstr "Desativar legendas"
msgid "Disabled"
msgstr "Desabilitado"
#: src/view/com/composer/Composer.tsx:839
#: src/view/com/composer/Composer.tsx:843
msgid "Discard"
msgstr "Descartar"
#: src/view/com/composer/Composer.tsx:836
#: src/view/com/composer/Composer.tsx:840
msgid "Discard draft?"
msgstr "Descartar rascunho?"
@@ -2089,7 +2089,7 @@ msgstr "Descubra Novos Feeds"
#~ msgid "Dismiss"
#~ msgstr "Ocultar"
#: src/view/com/composer/Composer.tsx:1106
#: src/view/com/composer/Composer.tsx:1110
msgid "Dismiss error"
msgstr "Ocultar erro"
@@ -2141,8 +2141,8 @@ msgstr "Domínio verificado!"
#: src/screens/Onboarding/StepProfile/index.tsx:325
#: src/view/com/auth/server-input/index.tsx:169
#: src/view/com/auth/server-input/index.tsx:170
#: src/view/com/composer/videos/SubtitleDialog.tsx:167
#: src/view/com/composer/videos/SubtitleDialog.tsx:177
#: src/view/com/composer/videos/SubtitleDialog.tsx:171
#: src/view/com/composer/videos/SubtitleDialog.tsx:181
#: src/view/com/modals/AddAppPasswords.tsx:243
#: src/view/com/modals/AltImage.tsx:141
#: src/view/com/modals/crop-image/CropImage.web.tsx:177
@@ -2417,7 +2417,7 @@ msgstr "Habilitar mídia para"
msgid "Enable priority notifications"
msgstr "Habilitar notificações prioritárias"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:336
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:380
msgid "Enable subtitles"
msgstr "Habilitar legendas"
@@ -2447,7 +2447,7 @@ msgstr "Fim do feed"
#~ msgid "End of onboarding tour window. Do not move forward. Instead, go backward for more options, or press to skip."
#~ msgstr "Fim da integração da sua janela. Não avance. Em vez disso, volte para mais opções ou pressione para pular."
#: src/view/com/composer/videos/SubtitleDialog.tsx:157
#: src/view/com/composer/videos/SubtitleDialog.tsx:161
msgid "Ensure you have selected a language for each subtitle file."
msgstr "Certifique-se de ter selecionado um idioma para cada arquivo de legenda."
@@ -2549,7 +2549,7 @@ msgstr "Excluir usuário que você segue"
msgid "Excludes users you follow"
msgstr "Excluir usuário que você segue"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:353
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:397
msgid "Exit fullscreen"
msgstr "Sair da tela cheia"
@@ -3057,7 +3057,7 @@ msgctxt "from-feed"
msgid "From <0/>"
msgstr "Por <0/>"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:354
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:398
msgid "Fullscreen"
msgstr "Tela cheia"
@@ -3526,7 +3526,7 @@ msgstr "Convites, mas pessoais"
msgid "It's just you right now! Add more people to your starter pack by searching above."
msgstr "É só você por enquanto! Adicione mais pessoas ao seu pacote inicial pesquisando acima."
#: src/view/com/composer/Composer.tsx:1125
#: src/view/com/composer/Composer.tsx:1129
msgid "Job ID: {0}"
msgstr ""
@@ -4046,15 +4046,15 @@ msgstr "Filmes"
msgid "Music"
msgstr "Música"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:345
msgctxt "video"
msgid "Mute"
msgstr ""
#: src/components/TagMenu/index.tsx:263
msgid "Mute"
msgstr "Silenciar"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:389
msgctxt "video"
msgid "Mute"
msgstr ""
#: src/components/TagMenu/index.web.tsx:116
msgid "Mute {truncatedTag}"
msgstr "Silenciar {truncatedTag}"
@@ -4583,7 +4583,7 @@ msgstr "Resetar tutoriais"
#~ msgid "Onboarding tour step {0}: {1}"
#~ msgstr "Etapa do tour de integração {0}: {1}"
#: src/view/com/composer/Composer.tsx:668
#: src/view/com/composer/Composer.tsx:672
msgid "One or more images is missing alt text."
msgstr "Uma ou mais imagens estão sem texto alternativo."
@@ -4638,8 +4638,8 @@ msgid "Open conversation options"
msgstr "Abrir opções de conversa"
#: src/screens/Messages/Conversation/MessageInput.web.tsx:165
#: src/view/com/composer/Composer.tsx:819
#: src/view/com/composer/Composer.tsx:820
#: src/view/com/composer/Composer.tsx:823
#: src/view/com/composer/Composer.tsx:824
msgid "Open emoji picker"
msgstr "Abrir seletor de emojis"
@@ -4825,7 +4825,7 @@ msgstr "Abre as preferências de threads"
msgid "Opens this profile"
msgstr "Abre este perfil"
#: src/view/com/composer/videos/SelectVideoBtn.tsx:81
#: src/view/com/composer/videos/SelectVideoBtn.tsx:88
msgid "Opens video picker"
msgstr "Abre seletor de vídeos"
@@ -4903,11 +4903,11 @@ msgid "Password updated!"
msgstr "Senha atualizada!"
#: src/view/com/util/post-embeds/GifEmbed.tsx:44
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:322
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:366
msgid "Pause"
msgstr "Pausar"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:275
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:319
msgid "Pause video"
msgstr "Pausar vídeo"
@@ -4967,7 +4967,7 @@ msgid "Pinned to your feeds"
msgstr "Fixado em seus feeds"
#: src/view/com/util/post-embeds/GifEmbed.tsx:44
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:323
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:367
msgid "Play"
msgstr "Tocar"
@@ -4984,8 +4984,8 @@ msgstr "Reproduzir {0}"
msgid "Play or pause the GIF"
msgstr "Tocar ou pausar o GIF"
#: src/view/com/util/post-embeds/VideoEmbed.tsx:187
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:276
#: src/view/com/util/post-embeds/VideoEmbed.tsx:189
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:320
msgid "Play video"
msgstr "Reproduzir vídeo"
@@ -5057,7 +5057,7 @@ msgstr "Por favor entre como @{0}"
msgid "Please Verify Your Email"
msgstr "Por favor, verifique seu e-mail"
#: src/view/com/composer/Composer.tsx:356
#: src/view/com/composer/Composer.tsx:360
msgid "Please wait for your link card to finish loading"
msgstr "Aguarde até que a prévia de link termine de carregar"
@@ -5070,8 +5070,8 @@ msgstr "Política"
msgid "Porn"
msgstr "Pornografia"
#: src/view/com/composer/Composer.tsx:643
#: src/view/com/composer/Composer.tsx:650
#: src/view/com/composer/Composer.tsx:647
#: src/view/com/composer/Composer.tsx:654
msgctxt "action"
msgid "Post"
msgstr "Postar"
@@ -5250,11 +5250,11 @@ msgstr "Listas públicas e compartilháveis para silenciar ou bloquear usuários
msgid "Public, shareable lists which can drive feeds."
msgstr "Listas públicas e compartilháveis que geram feeds."
#: src/view/com/composer/Composer.tsx:628
#: src/view/com/composer/Composer.tsx:632
msgid "Publish post"
msgstr "Publicar post"
#: src/view/com/composer/Composer.tsx:628
#: src/view/com/composer/Composer.tsx:632
msgid "Publish reply"
msgstr "Publicar resposta"
@@ -5482,7 +5482,7 @@ msgstr "Remover citação"
msgid "Remove repost"
msgstr "Desfazer repost"
#: src/view/com/composer/videos/SubtitleDialog.tsx:260
#: src/view/com/composer/videos/SubtitleDialog.tsx:264
msgid "Remove subtitle file"
msgstr "Remover arquivo de legenda"
@@ -5559,7 +5559,7 @@ msgstr "Respostas para esta postagem estão desativadas."
#~ msgid "Replies to this thread are disabled"
#~ msgstr "Respostas para esta thread estão desativadas"
#: src/view/com/composer/Composer.tsx:641
#: src/view/com/composer/Composer.tsx:645
msgctxt "action"
msgid "Reply"
msgstr "Responder"
@@ -6053,7 +6053,7 @@ msgstr "Veja o guia"
#~ msgid "See what's next"
#~ msgstr "Veja o que vem por aí"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:587
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:631
msgid "Seek slider"
msgstr "Controle deslizante de busca"
@@ -6093,7 +6093,7 @@ msgstr "Selecionar GIF \"{0}\""
msgid "Select how long to mute this word for."
msgstr "Selecione por quanto tempo essa palavra deve ser silenciada."
#: src/view/com/composer/videos/SubtitleDialog.tsx:245
#: src/view/com/composer/videos/SubtitleDialog.tsx:249
msgid "Select language..."
msgstr "Selecione o idioma..."
@@ -6133,7 +6133,7 @@ msgstr "Selecione o serviço que hospeda seus dados."
#~ msgid "Select topical feeds to follow from the list below"
#~ msgstr "Selecione feeds de assuntos para seguir"
#: src/view/com/composer/videos/SelectVideoBtn.tsx:80
#: src/view/com/composer/videos/SelectVideoBtn.tsx:87
msgid "Select video"
msgstr "Selecione o vídeo"
@@ -7429,7 +7429,7 @@ msgstr "Para desabilitar o 2FA via e-mail, por favor verifique seu acesso a este
msgid "To report a conversation, please report one of its messages via the conversation screen. This lets our moderators understand the context of your issue."
msgstr "Para denunciar uma conversa, por favor, denuncie uma das mensagens individualmente. Isso vai permitir a análise da situação pelos nossos moderadores."
#: src/view/com/composer/videos/SelectVideoBtn.tsx:106
#: src/view/com/composer/videos/SelectVideoBtn.tsx:113
msgid "To upload videos to Bluesky, you must first verify your email."
msgstr "Para enviar vídeos para o Bluesky, você deve primeiro verificar seu e-mail."
@@ -7572,16 +7572,16 @@ msgstr "Deixar de seguir"
msgid "Unlike this feed"
msgstr "Descurtir este feed"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:344
msgctxt "video"
msgid "Unmute"
msgstr ""
#: src/components/TagMenu/index.tsx:263
#: src/view/screens/ProfileList.tsx:689
msgid "Unmute"
msgstr "Dessilenciar"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:388
msgctxt "video"
msgid "Unmute"
msgstr ""
#: src/components/TagMenu/index.web.tsx:115
msgid "Unmute {truncatedTag}"
msgstr "Dessilenciar {truncatedTag}"
@@ -7608,7 +7608,7 @@ msgstr "Desmutar conversa"
msgid "Unmute thread"
msgstr "Dessilenciar thread"
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:273
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:317
msgid "Unmute video"
msgstr "Desmutar vídeo"
@@ -7837,7 +7837,7 @@ msgstr "Usuários que curtiram este conteúdo ou perfil"
msgid "Value:"
msgstr "Conteúdo:"
#: src/view/com/composer/videos/SelectVideoBtn.tsx:104
#: src/view/com/composer/videos/SelectVideoBtn.tsx:111
msgid "Verified email required"
msgstr "E-mail verificado necessário"
@@ -7870,7 +7870,7 @@ msgstr "Verificar Meu Email"
msgid "Verify New Email"
msgstr "Verificar Novo E-mail"
#: src/view/com/composer/videos/SelectVideoBtn.tsx:108
#: src/view/com/composer/videos/SelectVideoBtn.tsx:115
msgid "Verify now"
msgstr "Verifique agora"
@@ -7904,11 +7904,11 @@ msgstr "Falha no processamento do vídeo"
msgid "Video Games"
msgstr "Games"
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:163
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:164
msgid "Video not found."
msgstr "Vídeo não encontrado."
#: src/view/com/composer/videos/SubtitleDialog.tsx:99
#: src/view/com/composer/videos/SubtitleDialog.tsx:101
msgid "Video settings"
msgstr "Configurações de vídeo"
@@ -7920,6 +7920,11 @@ msgstr ""
#~ msgid "Videos cannot be larger than 50MB"
#~ msgstr "Vídeos não podem ter mais de 100 MB"
#: src/view/com/composer/videos/SelectVideoBtn.tsx:58
#: src/view/com/composer/videos/VideoPreview.web.tsx:44
msgid "Videos must be less than 60 seconds long"
msgstr "Os vídeos devem ter menos de 60 segundos de duração."
#: src/screens/Profile/Header/Shell.tsx:113
msgid "View {0}'s avatar"
msgstr "Ver o avatar de {0}"
@@ -8093,7 +8098,7 @@ msgstr "Não foi possível carregar sua lista de palavras silenciadas. Por favor
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
msgstr "Lamentamos, mas sua busca não pôde ser concluída. Por favor, tente novamente em alguns minutos."
#: src/view/com/composer/Composer.tsx:418
#: src/view/com/composer/Composer.tsx:422
msgid "We're sorry! The post you are replying to has been deleted."
msgstr "Sentimos muito! A postagem que você está respondendo foi excluída."
@@ -8132,7 +8137,7 @@ msgstr "Como você quer chamar seu pacote inicial?"
#: src/view/com/auth/SplashScreen.tsx:40
#: src/view/com/auth/SplashScreen.web.tsx:86
#: src/view/com/composer/Composer.tsx:513
#: src/view/com/composer/Composer.tsx:517
msgid "What's up?"
msgstr "E aí?"
@@ -8207,11 +8212,11 @@ msgstr "Largo"
msgid "Write a message"
msgstr "Escreva uma mensagem"
#: src/view/com/composer/Composer.tsx:709
#: src/view/com/composer/Composer.tsx:713
msgid "Write post"
msgstr "Escrever post"
#: src/view/com/composer/Composer.tsx:512
#: src/view/com/composer/Composer.tsx:516
#: src/view/com/post-thread/PostThreadComposePrompt.tsx:42
msgid "Write your reply"
msgstr "Escreva sua resposta"
@@ -8571,7 +8576,7 @@ msgstr "O repositório da sua conta, contendo todos os seus dados públicos, pod
msgid "Your birth date"
msgstr "Sua data de nascimento"
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:167
#: src/view/com/util/post-embeds/VideoEmbed.web.tsx:168
msgid "Your browser does not support the video format. Please try a different browser."
msgstr "Seu navegador não suporta o formato de vídeo. Por favor, tente um navegador diferente."
@@ -8626,7 +8631,7 @@ msgstr "Suas palavras silenciadas"
msgid "Your password has been changed successfully!"
msgstr "Sua senha foi alterada com sucesso!"
#: src/view/com/composer/Composer.tsx:464
#: src/view/com/composer/Composer.tsx:468
msgid "Your post has been published"
msgstr "Seu post foi publicado"
@@ -8642,7 +8647,7 @@ msgstr "Seu perfil"
msgid "Your profile, posts, feeds, and lists will no longer be visible to other Bluesky users. You can reactivate your account at any time by logging in."
msgstr "Seu perfil, postagens, feeds e listas não serão mais visíveis para outros usuários do Bluesky. Você pode reativar sua conta a qualquer momento fazendo login."
#: src/view/com/composer/Composer.tsx:463
#: src/view/com/composer/Composer.tsx:467
msgid "Your reply has been published"
msgstr "Sua resposta foi publicada"
+1
View File
@@ -172,6 +172,7 @@ export function StepInfo({
defaultValue={state.password}
secureTextEntry
autoComplete="new-password"
autoCapitalize="none"
/>
</TextField.Root>
</View>
+29
View File
@@ -0,0 +1,29 @@
import zod from 'zod'
import {BaseNux} from '#/state/queries/nuxs/types'
export enum Nux {
One = 'one',
Two = 'two',
}
export const nuxNames = new Set(Object.values(Nux))
export type AppNux =
| BaseNux<{
id: Nux.One
data: {
likes: number
}
}>
| BaseNux<{
id: Nux.Two
data: undefined
}>
export const NuxSchemas = {
[Nux.One]: zod.object({
likes: zod.number(),
}),
[Nux.Two]: undefined,
}
+83
View File
@@ -0,0 +1,83 @@
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {AppNux, Nux} from '#/state/queries/nuxs/definitions'
import {parseAppNux, serializeAppNux} from '#/state/queries/nuxs/util'
import {
preferencesQueryKey,
usePreferencesQuery,
} from '#/state/queries/preferences'
import {useAgent} from '#/state/session'
export {Nux} from '#/state/queries/nuxs/definitions'
export function useNuxs() {
const {data, ...rest} = usePreferencesQuery()
if (data && rest.isSuccess) {
const nuxs = data.bskyAppState.nuxs
?.map(parseAppNux)
?.filter(Boolean) as AppNux[]
if (nuxs) {
return {
nuxs,
...rest,
}
}
}
return {
nuxs: undefined,
...rest,
}
}
export function useNux<T extends Nux>(id: T) {
const {nuxs, ...rest} = useNuxs()
if (nuxs && rest.isSuccess) {
const nux = nuxs.find(nux => nux.id === id)
if (nux) {
return {
nux: nux as Extract<AppNux, {id: T}>,
...rest,
}
}
}
return {
nux: undefined,
...rest,
}
}
export function useUpsertNuxMutation() {
const queryClient = useQueryClient()
const agent = useAgent()
return useMutation({
mutationFn: async (nux: AppNux) => {
await agent.bskyAppUpsertNux(serializeAppNux(nux))
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: preferencesQueryKey,
})
},
})
}
export function useRemoveNuxsMutation() {
const queryClient = useQueryClient()
const agent = useAgent()
return useMutation({
mutationFn: async (ids: string[]) => {
await agent.bskyAppRemoveNuxs(ids)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: preferencesQueryKey,
})
},
})
}
+9
View File
@@ -0,0 +1,9 @@
import {AppBskyActorDefs} from '@atproto/api'
export type Data = Record<string, unknown> | undefined
export type BaseNux<
T extends Pick<AppBskyActorDefs.Nux, 'id' | 'expiresAt'> & {data: Data},
> = T & {
completed: boolean
}
+52
View File
@@ -0,0 +1,52 @@
import {AppBskyActorDefs, nuxSchema} from '@atproto/api'
import {
AppNux,
Nux,
nuxNames,
NuxSchemas,
} from '#/state/queries/nuxs/definitions'
export function parseAppNux(nux: AppBskyActorDefs.Nux): AppNux | undefined {
if (!nuxNames.has(nux.id as Nux)) return
if (!nuxSchema.safeParse(nux).success) return
const {data, ...rest} = nux
const schema = NuxSchemas[nux.id as Nux]
if (schema && data) {
const parsedData = JSON.parse(data)
if (!schema.safeParse(parsedData).success) return
return {
...rest,
data: parsedData,
} as AppNux
}
return {
...rest,
data: undefined,
} as AppNux
}
export function serializeAppNux(nux: AppNux): AppBskyActorDefs.Nux {
const {data, ...rest} = nux
const schema = NuxSchemas[nux.id as Nux]
const result: AppBskyActorDefs.Nux = {
...rest,
data: undefined,
}
if (schema) {
schema.parse(data)
result.data = JSON.stringify(data)
}
nuxSchema.parse(result)
return result
}
+1
View File
@@ -37,5 +37,6 @@ export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = {
bskyAppState: {
queuedNudges: [],
activeProgressGuide: undefined,
nuxs: [],
},
}
+5 -1
View File
@@ -303,9 +303,13 @@ export const ComposePost = observer(function ComposePost({
const onPhotoPasted = useCallback(
async (uri: string) => {
track('Composer:PastedPhotos')
if (uri.startsWith('data:video/')) {
selectVideo({uri, type: 'video', height: 0, width: 0})
} else {
await gallery.paste(uri)
}
},
[gallery, track],
[gallery, track, selectVideo],
)
const isAltTextRequiredAndMissing = useMemo(() => {
@@ -93,9 +93,9 @@ export const TextInput = React.forwardRef(function TextInputImpl(
}
}, [onPressPublish])
React.useEffect(() => {
textInputWebEmitter.addListener('photo-pasted', onPhotoPasted)
textInputWebEmitter.addListener('media-pasted', onPhotoPasted)
return () => {
textInputWebEmitter.removeListener('photo-pasted', onPhotoPasted)
textInputWebEmitter.removeListener('media-pasted', onPhotoPasted)
}
}, [onPhotoPasted])
@@ -105,8 +105,8 @@ export const TextInput = React.forwardRef(function TextInputImpl(
if (transfer) {
const items = transfer.items
getImageFromUri(items, (uri: string) => {
textInputWebEmitter.emit('photo-pasted', uri)
getImageOrVideoFromUri(items, (uri: string) => {
textInputWebEmitter.emit('media-pasted', uri)
})
}
@@ -160,8 +160,8 @@ export const TextInput = React.forwardRef(function TextInputImpl(
view.pasteText(text)
preventDefault = true
}
getImageFromUri(clipboardData.items, (uri: string) => {
textInputWebEmitter.emit('photo-pasted', uri)
getImageOrVideoFromUri(clipboardData.items, (uri: string) => {
textInputWebEmitter.emit('media-pasted', uri)
})
if (preventDefault) {
// Return `true` to prevent ProseMirror's default paste behavior.
@@ -346,7 +346,7 @@ const styles = StyleSheet.create({
},
})
function getImageFromUri(
function getImageOrVideoFromUri(
items: DataTransferItemList,
callback: (uri: string) => void,
) {
@@ -363,11 +363,21 @@ function getImageFromUri(
if (blob.type.startsWith('image/')) {
blobToDataUri(blob).then(callback, err => console.error(err))
}
if (blob.type.startsWith('video/')) {
blobToDataUri(blob).then(callback, err => console.error(err))
}
}
})
} else if (type.startsWith('image/')) {
const file = item.getAsFile()
if (file) {
blobToDataUri(file).then(callback, err => console.error(err))
}
} else if (type.startsWith('video/')) {
const file = item.getAsFile()
if (file) {
blobToDataUri(file).then(callback, err => console.error(err))
}
@@ -18,7 +18,7 @@ import {Button} from '#/components/Button'
import {VideoClip_Stroke2_Corner0_Rounded as VideoClipIcon} from '#/components/icons/VideoClip'
import * as Prompt from '#/components/Prompt'
const VIDEO_MAX_DURATION = 60
const VIDEO_MAX_DURATION = 60 * 1000 // 60s in milliseconds
type Props = {
onSelectVideo: (video: ImagePickerAsset) => void
@@ -45,13 +45,20 @@ export function SelectVideoBtn({onSelectVideo, disabled, setError}: Props) {
const response = await launchImageLibraryAsync({
exif: false,
mediaTypes: MediaTypeOptions.Videos,
videoMaxDuration: VIDEO_MAX_DURATION,
quality: 1,
legacy: true,
preferredAssetRepresentationMode:
UIImagePickerPreferredAssetRepresentationMode.Current,
})
if (response.assets && response.assets.length > 0) {
if (isNative) {
if (typeof response.assets[0].duration !== 'number')
throw Error('Asset is not a video')
if (response.assets[0].duration > VIDEO_MAX_DURATION) {
setError(_(msg`Videos must be less than 60 seconds long`))
return
}
}
try {
onSelectVideo(response.assets[0])
} catch (err) {
@@ -12,6 +12,8 @@ import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
import {atoms as a} from '#/alf'
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
const MAX_DURATION = 60
export function VideoPreview({
asset,
video,
@@ -36,6 +38,15 @@ export function VideoPreview({
'loadedmetadata',
function () {
setDimensions(this.videoWidth, this.videoHeight)
if (!isNaN(this.duration)) {
if (this.duration > MAX_DURATION) {
Toast.show(
_(msg`Videos must be less than 60 seconds long`),
'xmark',
)
clear()
}
}
},
{signal},
)
+3 -1
View File
@@ -11,6 +11,7 @@ import {useAutoplayDisabled} from 'state/preferences'
import {VideoEmbedInnerNative} from '#/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative'
import {atoms as a} from '#/alf'
import {Button} from '#/components/Button'
import {useIsWithinMessage} from '#/components/dms/MessageContext'
import {Loader} from '#/components/Loader'
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
import {VisibilityView} from '../../../../../modules/expo-bluesky-swiss-army'
@@ -68,7 +69,8 @@ function InnerWrapper({embed}: Props) {
const [isMuted, setIsMuted] = useState(player.muted)
const [isFullscreen, setIsFullscreen] = React.useState(false)
const [timeRemaining, setTimeRemaining] = React.useState(0)
const disableAutoplay = useAutoplayDisabled()
const isWithinMessage = useIsWithinMessage()
const disableAutoplay = useAutoplayDisabled() || isWithinMessage
const isActive = embed.playlist === activeSource && activeViewId === viewId
// There are some different loading states that we should pay attention to and show a spinner for
const isLoading =
@@ -4,14 +4,15 @@ import {AppBskyEmbedVideo} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {isFirefox} from '#/lib/browser'
import {clamp} from '#/lib/numbers'
import {useGate} from '#/lib/statsig/statsig'
import {
HLSUnsupportedError,
VideoEmbedInnerWeb,
VideoNotFoundError,
} from '#/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb'
import {atoms as a} from '#/alf'
import {useIsWithinMessage} from '#/components/dms/MessageContext'
import {useFullscreen} from '#/components/hooks/useFullscreen'
import {ErrorBoundary} from '../ErrorBoundary'
import {useActiveVideoWeb} from './ActiveVideoWebContext'
@@ -19,13 +20,14 @@ import * as VideoFallback from './VideoEmbedInner/VideoFallback'
export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
const ref = useRef<HTMLDivElement>(null)
const gate = useGate()
const {active, setActive, sendPosition, currentActiveView} =
useActiveVideoWeb()
const [onScreen, setOnScreen] = useState(false)
const [isFullscreen] = useFullscreen()
useEffect(() => {
if (!ref.current) return
if (isFullscreen && !isFirefox) return
const observer = new IntersectionObserver(
entries => {
const entry = entries[0]
@@ -39,7 +41,7 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
)
observer.observe(ref.current)
return () => observer.disconnect()
}, [sendPosition])
}, [sendPosition, isFullscreen])
const [key, setKey] = useState(0)
const renderError = useCallback(
@@ -49,10 +51,6 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
[key],
)
if (!gate('video_view_on_posts')) {
return null
}
let aspectRatio = 16 / 9
if (embed.aspectRatio) {
@@ -103,17 +101,18 @@ function ViewportObserver({
}: {
children: React.ReactNode
sendPosition: (position: number) => void
isAnyViewActive?: boolean
isAnyViewActive: boolean
}) {
const ref = useRef<HTMLDivElement>(null)
const [nearScreen, setNearScreen] = useState(false)
const [isFullscreen] = useFullscreen()
const [nearScreenOrFullscreen, setNearScreenOrFullscreen] = useState(false)
const isWithinMessage = useIsWithinMessage()
// Send position when scrolling. This is done with an IntersectionObserver
// observing a div of 100vh height
useEffect(() => {
if (!ref.current) return
if (isFullscreen && !isFirefox) return
const observer = new IntersectionObserver(
entries => {
const entry = entries[0]
@@ -127,7 +126,7 @@ function ViewportObserver({
)
observer.observe(ref.current)
return () => observer.disconnect()
}, [sendPosition])
}, [sendPosition, isFullscreen])
// In case scrolling hasn't started yet, send up the position
useEffect(() => {
@@ -138,24 +137,18 @@ function ViewportObserver({
}
}, [isAnyViewActive, sendPosition])
// disguesting effect - it should be `nearScreen` except when fullscreen
// when it should be whatever it was before fullscreen changed
useEffect(() => {
if (!isFullscreen) {
setNearScreenOrFullscreen(nearScreen)
}
}, [isFullscreen, nearScreen])
return (
<View style={[a.flex_1, a.flex_row]}>
{nearScreenOrFullscreen && children}
{nearScreen && children}
<div
ref={ref}
style={{
// Don't escape bounds when in a message
...(isWithinMessage
? {top: 0, height: '100%'}
: {top: 'calc(50% - 50vh)', height: '100vh'}),
position: 'absolute',
top: 'calc(50% - 50vh)',
left: '50%',
height: '100vh',
width: 1,
pointerEvents: 'none',
}}
@@ -35,7 +35,13 @@ export function VideoEmbedInnerWeb({
if (!ref.current) return
if (!Hls.isSupported()) throw new HLSUnsupportedError()
const hls = new Hls({capLevelToPlayerSize: true})
const hls = new Hls({
capLevelToPlayerSize: true,
maxMaxBufferLength: 10, // only load 10s ahead
// note: the amount buffered is affected by both maxBufferLength and maxBufferSize
// it will buffer until it it's greater than *both* of those values
// so we use maxMaxBufferLength to set the actual maximum amount of buffering instead
})
hlsRef.current = hls
hls.attachMedia(ref.current)
@@ -15,6 +15,7 @@ import {
} from '#/state/preferences'
import {atoms as a, useTheme, web} from '#/alf'
import {Button} from '#/components/Button'
import {useIsWithinMessage} from '#/components/dms/MessageContext'
import {useFullscreen} from '#/components/hooks/useFullscreen'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {
@@ -95,6 +96,15 @@ export function Controls({
}
}, [interactingViaKeypress])
useEffect(() => {
if (isFullscreen) {
document.documentElement.style.scrollbarGutter = 'unset'
return () => {
document.documentElement.style.removeProperty('scrollbar-gutter')
}
}
}, [isFullscreen])
// pause + unfocus when another video is active
useEffect(() => {
if (!active) {
@@ -104,7 +114,8 @@ export function Controls({
}, [active, pause, setFocused])
// autoplay/pause based on visibility
const autoplayDisabled = useAutoplayDisabled()
const isWithinMessage = useIsWithinMessage()
const autoplayDisabled = useAutoplayDisabled() || isWithinMessage
useEffect(() => {
if (active) {
if (onScreen) {
@@ -121,8 +132,12 @@ export function Controls({
if (focused) {
// auto decide quality based on network conditions
hlsRef.current.autoLevelCapping = -1
// allow 30s of buffering
hlsRef.current.config.maxMaxBufferLength = 30
} else {
// back to what we initially set
hlsRef.current.autoLevelCapping = 0
hlsRef.current.config.maxMaxBufferLength = 10
}
}, [hlsRef, focused])
@@ -235,6 +250,39 @@ export function Controls({
}
}, [])
// these are used to trigger the hover state. on mobile, the hover state
// should stick around for a bit after they tap, and if the controls aren't
// present this initial tab should *only* show the controls and not activate anything
const onPointerDown = useCallback(
(evt: React.PointerEvent<HTMLDivElement>) => {
if (evt.pointerType !== 'mouse' && !hovered) {
evt.preventDefault()
}
},
[hovered],
)
const timeoutRef = useRef<ReturnType<typeof setTimeout>>()
const onHoverWithTimeout = useCallback(() => {
onHover()
clearTimeout(timeoutRef.current)
}, [onHover])
const onEndHoverWithTimeout = useCallback(
(evt: React.PointerEvent<HTMLDivElement>) => {
// if touch, end after 3s
// if mouse, end immediately
if (evt.pointerType !== 'mouse') {
setTimeout(onEndHover, 3000)
} else {
onEndHover()
}
},
[onEndHover],
)
const showControls =
((focused || autoplayDisabled) && !playing) ||
(interactingViaKeypress ? hasFocus : hovered)
@@ -252,9 +300,10 @@ export function Controls({
evt.stopPropagation()
setInteractingViaKeypress(false)
}}
onPointerEnter={onHover}
onPointerMove={onHover}
onPointerLeave={onEndHover}
onPointerEnter={onHoverWithTimeout}
onPointerMove={onHoverWithTimeout}
onPointerLeave={onEndHoverWithTimeout}
onPointerDown={onPointerDown}
onFocus={onFocus}
onBlur={onBlur}
onKeyDown={onKeyDown}>
@@ -543,7 +592,7 @@ function Scrubber({
return (
<View
testID="scrubber"
style={[{height: 10, width: '100%'}, a.flex_shrink_0, a.px_xs]}
style={[{height: 18, width: '100%'}, a.flex_shrink_0, a.px_xs, a.py_xs]}
onPointerEnter={onStartHover}
onPointerLeave={onEndHover}>
<div
+18 -17
View File
@@ -72,19 +72,6 @@
resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store/-/simple-store-0.1.1.tgz#e743a2722b5d8732166f0a72aca8bd10e9bff106"
integrity sha512-WKILW2b3QbAYKh+w5U2x6p5FqqLl0nAeLwGeDY+KjX01K4Dq3vQTR9b/qNp0jZm48CabPQVrqCv0PPU9LgRRRg==
"@atproto/api@0.13.5":
version "0.13.5"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.5.tgz#04305cdb0a467ba366305c5e95cebb7ce0d39735"
integrity sha512-yT/YimcKYkrI0d282Zxo7O30OSYR+KDW89f81C6oYZfDRBcShC1aniVV8kluP5LrEAg8O27yrOSnBgx2v7XPew==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc" "^0.6.1"
await-lock "^2.2.2"
multiformats "^9.9.0"
tlds "^1.234.0"
"@atproto/api@^0.13.0":
version "0.13.0"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.0.tgz#d1c65a407f1c3c6aba5be9425f4f739a01419bd8"
@@ -98,6 +85,20 @@
multiformats "^9.9.0"
tlds "^1.234.0"
"@atproto/api@^0.13.7":
version "0.13.7"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.7.tgz#072eba2025d5251505f17b0b5d2de33749ea5ee4"
integrity sha512-41kSLmFWDbuPOenb52WRq1lnBkSZrL+X29tWcvEt6SZXK4xBoKAalw1MjF+oabhzff12iMtNaNvmmt2fu1L+cw==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc" "^0.6.2"
await-lock "^2.2.2"
multiformats "^9.9.0"
tlds "^1.234.0"
zod "^3.23.8"
"@atproto/aws@^0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.2.tgz#703e5e06f288bcf61c6d99a990738f1e7299e653"
@@ -443,10 +444,10 @@
"@atproto/lexicon" "^0.4.1"
zod "^3.23.8"
"@atproto/xrpc@^0.6.1":
version "0.6.1"
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.1.tgz#dcd1315c8c60eef5af2db7fa4e35a38ebc6d79d5"
integrity sha512-Zy5ydXEdk6sY7FDUZcEVfCL1jvbL4tXu5CcdPqbEaW6LQtk9GLds/DK1bCX9kswTGaBC88EMuqQMfkxOhp2t4A==
"@atproto/xrpc@^0.6.2":
version "0.6.2"
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.2.tgz#634228a7e533de01bda2214837d11574fdadad55"
integrity sha512-as/gb08xJb02HAGNrSQSumCe10WnOAcnM6bR6KMatQyQJuEu7OY6ZDSTM/4HfjjoxsNqdvPmbYuoUab1bKTNlA==
dependencies:
"@atproto/lexicon" "^0.4.1"
zod "^3.23.8"