Compare commits
12 Commits
b90aca402a
...
219a10eca9
Author | SHA1 | Date |
---|---|---|
Ducky | 219a10eca9 | |
Hailey | b37b64fb49 | |
Samuel Newman | 08f5f37b34 | |
Samuel Newman | 6bc5a05f4b | |
Frudrax Cheng | db9cf92d87 | |
Samuel Newman | 66239ba11d | |
Samuel Newman | 0f6be244a6 | |
Samuel Newman | 436e30fded | |
Hailey | 723a5e488e | |
Jaz | 9e1eb1f9f1 | |
surfdude29 | f240893980 | |
Samuel Newman | 44f1cd9fb5 |
|
@ -80,6 +80,13 @@ func run(args []string) {
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVars: []string{"BASIC_AUTH_PASSWORD"},
|
EnvVars: []string{"BASIC_AUTH_PASSWORD"},
|
||||||
},
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "cors-allowed-origins",
|
||||||
|
Usage: "list of allowed origins for CORS requests",
|
||||||
|
Required: false,
|
||||||
|
Value: cli.NewStringSlice("https://bsky.app", "https://main.bsky.dev", "https://app.staging.bsky.dev"),
|
||||||
|
EnvVars: []string{"CORS_ALLOWED_ORIGINS"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ func serve(cctx *cli.Context) error {
|
||||||
linkHost := cctx.String("link-host")
|
linkHost := cctx.String("link-host")
|
||||||
ipccHost := cctx.String("ipcc-host")
|
ipccHost := cctx.String("ipcc-host")
|
||||||
basicAuthPassword := cctx.String("basic-auth-password")
|
basicAuthPassword := cctx.String("basic-auth-password")
|
||||||
|
corsOrigins := cctx.StringSlice("cors-allowed-origins")
|
||||||
|
|
||||||
// Echo
|
// Echo
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
@ -168,6 +169,12 @@ func serve(cctx *cli.Context) error {
|
||||||
RedirectCode: http.StatusFound,
|
RedirectCode: http.StatusFound,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// CORS middleware
|
||||||
|
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||||
|
AllowOrigins: corsOrigins,
|
||||||
|
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodOptions},
|
||||||
|
}))
|
||||||
|
|
||||||
//
|
//
|
||||||
// configure routes
|
// configure routes
|
||||||
//
|
//
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
import {Trans} from '@lingui/macro'
|
import {Trans} from '@lingui/macro'
|
||||||
|
|
||||||
import {parseTenorGif} from '#/lib/strings/embed-player'
|
import {parseTenorGif} from '#/lib/strings/embed-player'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ export function Embed({
|
||||||
))}
|
))}
|
||||||
</Outer>
|
</Outer>
|
||||||
)
|
)
|
||||||
} else if (AppBskyEmbedExternal.isView(embed) && embed.external.thumb) {
|
} else if (AppBskyEmbedExternal.isView(media) && media.external.thumb) {
|
||||||
let url: URL | undefined
|
let url: URL | undefined
|
||||||
try {
|
try {
|
||||||
url = new URL(embed.external.uri)
|
url = new URL(media.external.uri)
|
||||||
} catch {}
|
} catch {}
|
||||||
if (url) {
|
if (url) {
|
||||||
const {success} = parseTenorGif(url)
|
const {success} = parseTenorGif(url)
|
||||||
|
@ -54,17 +54,17 @@ export function Embed({
|
||||||
return (
|
return (
|
||||||
<Outer style={style}>
|
<Outer style={style}>
|
||||||
<GifItem
|
<GifItem
|
||||||
thumbnail={embed.external.thumb}
|
thumbnail={media.external.thumb}
|
||||||
alt={embed.external.title}
|
alt={media.external.title}
|
||||||
/>
|
/>
|
||||||
</Outer>
|
</Outer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (AppBskyEmbedVideo.isView(embed)) {
|
} else if (AppBskyEmbedVideo.isView(media)) {
|
||||||
return (
|
return (
|
||||||
<Outer style={style}>
|
<Outer style={style}>
|
||||||
<VideoItem thumbnail={embed.thumbnail} alt={embed.alt} />
|
<VideoItem thumbnail={media.thumbnail} alt={media.alt} />
|
||||||
</Outer>
|
</Outer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,13 @@ export function ImageItem({
|
||||||
alt?: string
|
alt?: string
|
||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
}) {
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<View style={[a.relative, a.flex_1, {aspectRatio: 1, maxWidth: 100}]}>
|
<View style={[a.relative, a.flex_1, {aspectRatio: 1, maxWidth: 100}]}>
|
||||||
<Image
|
<Image
|
||||||
key={thumbnail}
|
key={thumbnail}
|
||||||
source={{uri: thumbnail}}
|
source={{uri: thumbnail}}
|
||||||
style={[a.flex_1, a.rounded_xs]}
|
style={[a.flex_1, a.rounded_xs, t.atoms.bg_contrast_25]}
|
||||||
contentFit="cover"
|
contentFit="cover"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
accessibilityIgnoresInvertColors
|
accessibilityIgnoresInvertColors
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
useSyncExternalStore,
|
||||||
|
} from 'react'
|
||||||
|
|
||||||
|
import {isFirefox, isSafari} from '#/lib/browser'
|
||||||
|
import {isWeb} from '#/platform/detection'
|
||||||
|
|
||||||
|
function fullscreenSubscribe(onChange: () => void) {
|
||||||
|
document.addEventListener('fullscreenchange', onChange)
|
||||||
|
return () => document.removeEventListener('fullscreenchange', onChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useFullscreen(ref?: React.RefObject<HTMLElement>) {
|
||||||
|
if (!isWeb) throw new Error("'useFullscreen' is a web-only hook")
|
||||||
|
const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () =>
|
||||||
|
Boolean(document.fullscreenElement),
|
||||||
|
)
|
||||||
|
const scrollYRef = useRef<null | number>(null)
|
||||||
|
const [prevIsFullscreen, setPrevIsFullscreen] = useState(isFullscreen)
|
||||||
|
|
||||||
|
const toggleFullscreen = useCallback(() => {
|
||||||
|
if (isFullscreen) {
|
||||||
|
document.exitFullscreen()
|
||||||
|
} else {
|
||||||
|
if (!ref) throw new Error('No ref provided')
|
||||||
|
if (!ref.current) return
|
||||||
|
scrollYRef.current = window.scrollY
|
||||||
|
ref.current.requestFullscreen()
|
||||||
|
}
|
||||||
|
}, [isFullscreen, ref])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (prevIsFullscreen === isFullscreen) return
|
||||||
|
setPrevIsFullscreen(isFullscreen)
|
||||||
|
|
||||||
|
// Chrome has an issue where it doesn't scroll back to the top after exiting fullscreen
|
||||||
|
// Let's play it safe and do it if not FF or Safari, since anything else will probably be chromium
|
||||||
|
if (prevIsFullscreen && !isFirefox && !isSafari) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (scrollYRef.current !== null) {
|
||||||
|
window.scrollTo(0, scrollYRef.current)
|
||||||
|
scrollYRef.current = null
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
}, [isFullscreen, prevIsFullscreen])
|
||||||
|
|
||||||
|
return [isFullscreen, toggleFullscreen] as const
|
||||||
|
}
|
|
@ -3,9 +3,9 @@ import {ImagePickerAsset} from 'expo-image-picker'
|
||||||
import {VideoTooLargeError} from 'lib/media/video/errors'
|
import {VideoTooLargeError} from 'lib/media/video/errors'
|
||||||
import {CompressedVideo} from './types'
|
import {CompressedVideo} from './types'
|
||||||
|
|
||||||
const MAX_VIDEO_SIZE = 1024 * 1024 * 100 // 100MB
|
const MAX_VIDEO_SIZE = 1024 * 1024 * 50 // 50mb
|
||||||
|
|
||||||
// doesn't actually compress, but throws if >100MB
|
// doesn't actually compress, converts to ArrayBuffer
|
||||||
export async function compressVideo(
|
export async function compressVideo(
|
||||||
asset: ImagePickerAsset,
|
asset: ImagePickerAsset,
|
||||||
_opts?: {
|
_opts?: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export class VideoTooLargeError extends Error {
|
export class VideoTooLargeError extends Error {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('Videos cannot be larger than 100MB')
|
super('Videos cannot be larger than 50mb')
|
||||||
this.name = 'VideoTooLargeError'
|
this.name = 'VideoTooLargeError'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
export type Gate =
|
export type Gate =
|
||||||
// Keep this alphabetic please.
|
// Keep this alphabetic please.
|
||||||
| 'debug_show_feedcontext'
|
'debug_show_feedcontext' | 'suggested_feeds_interstitial' | 'video_upload' // upload videos
|
||||||
| 'suggested_feeds_interstitial'
|
|
||||||
| 'video_upload' // upload videos
|
|
||||||
| 'video_view_on_posts' // see posted videos
|
|
||||||
|
|
|
@ -7664,8 +7664,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "La política de privacitat ha estat traslladada a <0/>"
|
msgstr "La política de privacitat ha estat traslladada a <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "El vídeo triat és més gran de 100MB."
|
msgstr "El vídeo triat és més gran de 50MB."
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
@ -8605,8 +8605,8 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr "Els vídeos no poder ser de més de 100MB"
|
#~ msgstr "Els vídeos no poder ser de més de 50MB"
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
msgid "View {0}'s avatar"
|
msgid "View {0}'s avatar"
|
||||||
|
|
|
@ -6965,7 +6965,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Die Datenschutzerklärung wurde nach <0/> verschoben"
|
msgstr "Die Datenschutzerklärung wurde nach <0/> verschoben"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7871,7 +7871,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -644,7 +644,7 @@ msgstr ""
|
||||||
msgid "An error occurred"
|
msgid "An error occurred"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:227
|
#: src/state/queries/video/video.ts:232
|
||||||
msgid "An error occurred while compressing the video."
|
msgid "An error occurred while compressing the video."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ msgstr ""
|
||||||
msgid "An error occurred while trying to follow all"
|
msgid "An error occurred while trying to follow all"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:194
|
#: src/state/queries/video/video.ts:199
|
||||||
msgid "An error occurred while uploading the video."
|
msgid "An error occurred while uploading the video."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1096,8 +1096,8 @@ msgstr ""
|
||||||
#: src/components/Prompt.tsx:124
|
#: src/components/Prompt.tsx:124
|
||||||
#: src/components/TagMenu/index.tsx:282
|
#: src/components/TagMenu/index.tsx:282
|
||||||
#: src/screens/Deactivated.tsx:161
|
#: src/screens/Deactivated.tsx:161
|
||||||
#: src/view/com/composer/Composer.tsx:590
|
#: src/view/com/composer/Composer.tsx:591
|
||||||
#: src/view/com/composer/Composer.tsx:605
|
#: src/view/com/composer/Composer.tsx:606
|
||||||
#: src/view/com/modals/ChangeEmail.tsx:213
|
#: src/view/com/modals/ChangeEmail.tsx:213
|
||||||
#: src/view/com/modals/ChangeEmail.tsx:215
|
#: src/view/com/modals/ChangeEmail.tsx:215
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:148
|
#: src/view/com/modals/ChangeHandle.tsx:148
|
||||||
|
@ -1457,7 +1457,7 @@ msgstr ""
|
||||||
msgid "Closes password update alert"
|
msgid "Closes password update alert"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:602
|
#: src/view/com/composer/Composer.tsx:603
|
||||||
msgid "Closes post composer and discards post draft"
|
msgid "Closes post composer and discards post draft"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1496,7 +1496,7 @@ msgstr ""
|
||||||
msgid "Complete the challenge"
|
msgid "Complete the challenge"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:710
|
#: src/view/com/composer/Composer.tsx:711
|
||||||
msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length"
|
msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2005,7 +2005,7 @@ msgstr ""
|
||||||
msgid "Dialog: adjust who can interact with this post"
|
msgid "Dialog: adjust who can interact with this post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:351
|
#: src/view/com/composer/Composer.tsx:352
|
||||||
msgid "Did you want to say anything?"
|
msgid "Did you want to say anything?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3086,7 +3086,7 @@ msgstr ""
|
||||||
msgid "Getting started"
|
msgid "Getting started"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/MediaPreview.tsx:119
|
#: src/components/MediaPreview.tsx:120
|
||||||
msgid "GIF"
|
msgid "GIF"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4046,8 +4046,12 @@ msgstr ""
|
||||||
msgid "Music"
|
msgid "Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/TagMenu/index.tsx:263
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:345
|
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:345
|
||||||
|
msgctxt "video"
|
||||||
|
msgid "Mute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/TagMenu/index.tsx:263
|
||||||
msgid "Mute"
|
msgid "Mute"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4579,7 +4583,7 @@ msgstr ""
|
||||||
#~ msgid "Onboarding tour step {0}: {1}"
|
#~ msgid "Onboarding tour step {0}: {1}"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:667
|
#: src/view/com/composer/Composer.tsx:668
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -5053,7 +5057,7 @@ msgstr ""
|
||||||
msgid "Please Verify Your Email"
|
msgid "Please Verify Your Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:355
|
#: src/view/com/composer/Composer.tsx:356
|
||||||
msgid "Please wait for your link card to finish loading"
|
msgid "Please wait for your link card to finish loading"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -5066,8 +5070,8 @@ msgstr ""
|
||||||
msgid "Porn"
|
msgid "Porn"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:642
|
#: src/view/com/composer/Composer.tsx:643
|
||||||
#: src/view/com/composer/Composer.tsx:649
|
#: src/view/com/composer/Composer.tsx:650
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Post"
|
msgid "Post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -5246,11 +5250,11 @@ msgstr ""
|
||||||
msgid "Public, shareable lists which can drive feeds."
|
msgid "Public, shareable lists which can drive feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:627
|
#: src/view/com/composer/Composer.tsx:628
|
||||||
msgid "Publish post"
|
msgid "Publish post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:627
|
#: src/view/com/composer/Composer.tsx:628
|
||||||
msgid "Publish reply"
|
msgid "Publish reply"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -5555,7 +5559,7 @@ msgstr ""
|
||||||
#~ msgid "Replies to this thread are disabled"
|
#~ msgid "Replies to this thread are disabled"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:640
|
#: src/view/com/composer/Composer.tsx:641
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Reply"
|
msgid "Reply"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -7034,8 +7038,8 @@ msgstr ""
|
||||||
msgid "The Privacy Policy has been moved to <0/>"
|
msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:227
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7568,8 +7572,12 @@ msgstr ""
|
||||||
msgid "Unlike this feed"
|
msgid "Unlike this feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/TagMenu/index.tsx:263
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:344
|
#: 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
|
#: src/view/screens/ProfileList.tsx:689
|
||||||
msgid "Unmute"
|
msgid "Unmute"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -7642,7 +7650,7 @@ msgstr ""
|
||||||
msgid "Unsubscribed from list"
|
msgid "Unsubscribed from list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:240
|
#: src/state/queries/video/video.ts:245
|
||||||
msgid "Unsupported video type: {mimeType}"
|
msgid "Unsupported video type: {mimeType}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -7909,7 +7917,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
@ -8085,7 +8093,7 @@ msgstr ""
|
||||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:417
|
#: src/view/com/composer/Composer.tsx:418
|
||||||
msgid "We're sorry! The post you are replying to has been deleted."
|
msgid "We're sorry! The post you are replying to has been deleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -8124,7 +8132,7 @@ msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/SplashScreen.tsx:40
|
#: src/view/com/auth/SplashScreen.tsx:40
|
||||||
#: src/view/com/auth/SplashScreen.web.tsx:86
|
#: src/view/com/auth/SplashScreen.web.tsx:86
|
||||||
#: src/view/com/composer/Composer.tsx:512
|
#: src/view/com/composer/Composer.tsx:513
|
||||||
msgid "What's up?"
|
msgid "What's up?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -8199,11 +8207,11 @@ msgstr ""
|
||||||
msgid "Write a message"
|
msgid "Write a message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:708
|
#: src/view/com/composer/Composer.tsx:709
|
||||||
msgid "Write post"
|
msgid "Write post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:511
|
#: src/view/com/composer/Composer.tsx:512
|
||||||
#: src/view/com/post-thread/PostThreadComposePrompt.tsx:42
|
#: src/view/com/post-thread/PostThreadComposePrompt.tsx:42
|
||||||
msgid "Write your reply"
|
msgid "Write your reply"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8551,6 +8559,10 @@ msgstr ""
|
||||||
msgid "Your account has been deleted"
|
msgid "Your account has been deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/state/queries/video/video.ts:185
|
||||||
|
msgid "Your account is not yet old enough to upload videos. Please try again later."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings/ExportCarDialog.tsx:65
|
#: src/view/screens/Settings/ExportCarDialog.tsx:65
|
||||||
msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately."
|
msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8614,7 +8626,7 @@ msgstr ""
|
||||||
msgid "Your password has been changed successfully!"
|
msgid "Your password has been changed successfully!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:463
|
#: src/view/com/composer/Composer.tsx:464
|
||||||
msgid "Your post has been published"
|
msgid "Your post has been published"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -8630,7 +8642,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."
|
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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:462
|
#: src/view/com/composer/Composer.tsx:463
|
||||||
msgid "Your reply has been published"
|
msgid "Your reply has been published"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -6893,7 +6893,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "La Política de privacidad se ha trasladado a <0/>"
|
msgstr "La Política de privacidad se ha trasladado a <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7763,7 +7763,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -6989,7 +6989,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Tietosuojakäytäntö on siirretty kohtaan <0/>"
|
msgstr "Tietosuojakäytäntö on siirretty kohtaan <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7863,7 +7863,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -6486,7 +6486,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Notre politique de confidentialité a été déplacée vers <0/>"
|
msgstr "Notre politique de confidentialité a été déplacée vers <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7302,7 +7302,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr "Les vidéos ne peuvent pas dépasser 100 Mo"
|
#~ msgstr "Les vidéos ne peuvent pas dépasser 100 Mo"
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -7035,7 +7035,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Bogadh Polasaí na Príobháideachta go dtí <0/>"
|
msgstr "Bogadh Polasaí na Príobháideachta go dtí <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7912,7 +7912,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -7609,7 +7609,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "गोपनीयता नीति को <0/> पर स्थानांतरित किया गया है"
|
msgstr "गोपनीयता नीति को <0/> पर स्थानांतरित किया गया है"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -8535,7 +8535,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -7040,7 +7040,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Kebijakan Privasi telah dipindahkan ke <0/>"
|
msgstr "Kebijakan Privasi telah dipindahkan ke <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7914,8 +7914,8 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr "Video tidak boleh lebih besar dari 100MB"
|
#~ msgstr "Video tidak boleh lebih besar dari 50MB"
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
msgid "View {0}'s avatar"
|
msgid "View {0}'s avatar"
|
||||||
|
|
|
@ -7321,8 +7321,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "La politica sulla privacy è stata spostata a <0/><0/>"
|
msgstr "La politica sulla privacy è stata spostata a <0/><0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "Questo video è più grande di 100MB."
|
msgstr "Questo video è più grande di 50MB."
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
@ -8222,8 +8222,8 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr "I video non possono essere più grandi di 100MB"
|
#~ msgstr "I video non possono essere più grandi di 50MB"
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
msgid "View {0}'s avatar"
|
msgid "View {0}'s avatar"
|
||||||
|
|
|
@ -6272,8 +6272,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "プライバシーポリシーは<0/>に移動しました"
|
msgstr "プライバシーポリシーは<0/>に移動しました"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "選択したビデオのサイズが100MBを超えています。"
|
msgstr "選択したビデオのサイズが50MBを超えています。"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
|
|
@ -6272,8 +6272,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "개인정보 처리방침을 <0/>(으)로 이동했습니다"
|
msgstr "개인정보 처리방침을 <0/>(으)로 이동했습니다"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "선택한 동영상이 100MB를 초과합니다."
|
msgstr "선택한 동영상이 50MB를 초과합니다."
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
|
|
@ -644,7 +644,7 @@ msgstr "Ocorreu um erro"
|
||||||
msgid "An error occurred"
|
msgid "An error occurred"
|
||||||
msgstr "Ocorreu um erro"
|
msgstr "Ocorreu um erro"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:227
|
#: src/state/queries/video/video.ts:232
|
||||||
msgid "An error occurred while compressing the video."
|
msgid "An error occurred while compressing the video."
|
||||||
msgstr "Ocorreu um erro ao compactar o vídeo."
|
msgstr "Ocorreu um erro ao compactar o vídeo."
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ msgstr "Ocorreu um erro ao selecionar o vídeo"
|
||||||
msgid "An error occurred while trying to follow all"
|
msgid "An error occurred while trying to follow all"
|
||||||
msgstr "Ocorreu um erro ao tentar seguir todos"
|
msgstr "Ocorreu um erro ao tentar seguir todos"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:194
|
#: src/state/queries/video/video.ts:199
|
||||||
msgid "An error occurred while uploading the video."
|
msgid "An error occurred while uploading the video."
|
||||||
msgstr "Ocorreu um erro ao enviar o vídeo."
|
msgstr "Ocorreu um erro ao enviar o vídeo."
|
||||||
|
|
||||||
|
@ -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/Prompt.tsx:124
|
||||||
#: src/components/TagMenu/index.tsx:282
|
#: src/components/TagMenu/index.tsx:282
|
||||||
#: src/screens/Deactivated.tsx:161
|
#: src/screens/Deactivated.tsx:161
|
||||||
#: src/view/com/composer/Composer.tsx:590
|
#: src/view/com/composer/Composer.tsx:591
|
||||||
#: src/view/com/composer/Composer.tsx:605
|
#: src/view/com/composer/Composer.tsx:606
|
||||||
#: src/view/com/modals/ChangeEmail.tsx:213
|
#: src/view/com/modals/ChangeEmail.tsx:213
|
||||||
#: src/view/com/modals/ChangeEmail.tsx:215
|
#: src/view/com/modals/ChangeEmail.tsx:215
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:148
|
#: src/view/com/modals/ChangeHandle.tsx:148
|
||||||
|
@ -1457,7 +1457,7 @@ msgstr "Fecha barra de navegação inferior"
|
||||||
msgid "Closes password update alert"
|
msgid "Closes password update alert"
|
||||||
msgstr "Fecha alerta de troca de senha"
|
msgstr "Fecha alerta de troca de senha"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:602
|
#: src/view/com/composer/Composer.tsx:603
|
||||||
msgid "Closes post composer and discards post draft"
|
msgid "Closes post composer and discards post draft"
|
||||||
msgstr "Fecha o editor de post e descarta o rascunho"
|
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"
|
msgid "Complete the challenge"
|
||||||
msgstr "Complete o captcha"
|
msgstr "Complete o captcha"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:710
|
#: src/view/com/composer/Composer.tsx:711
|
||||||
msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length"
|
msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length"
|
||||||
msgstr "Escreva posts de até {MAX_GRAPHEME_LENGTH} caracteres"
|
msgstr "Escreva posts de até {MAX_GRAPHEME_LENGTH} caracteres"
|
||||||
|
|
||||||
|
@ -2005,7 +2005,7 @@ msgstr "Desanexar postagem de citação?"
|
||||||
msgid "Dialog: adjust who can interact with this post"
|
msgid "Dialog: adjust who can interact with this post"
|
||||||
msgstr "Diálogo: ajuste quem pode interagir com esta postagem"
|
msgstr "Diálogo: ajuste quem pode interagir com esta postagem"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:351
|
#: src/view/com/composer/Composer.tsx:352
|
||||||
msgid "Did you want to say anything?"
|
msgid "Did you want to say anything?"
|
||||||
msgstr "Você gostaria de dizer alguma coisa?"
|
msgstr "Você gostaria de dizer alguma coisa?"
|
||||||
|
|
||||||
|
@ -3086,7 +3086,7 @@ msgstr "Vamos começar"
|
||||||
msgid "Getting started"
|
msgid "Getting started"
|
||||||
msgstr "Começando"
|
msgstr "Começando"
|
||||||
|
|
||||||
#: src/components/MediaPreview.tsx:119
|
#: src/components/MediaPreview.tsx:120
|
||||||
msgid "GIF"
|
msgid "GIF"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4046,8 +4046,12 @@ msgstr "Filmes"
|
||||||
msgid "Music"
|
msgid "Music"
|
||||||
msgstr "Música"
|
msgstr "Música"
|
||||||
|
|
||||||
#: src/components/TagMenu/index.tsx:263
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:345
|
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:345
|
||||||
|
msgctxt "video"
|
||||||
|
msgid "Mute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/TagMenu/index.tsx:263
|
||||||
msgid "Mute"
|
msgid "Mute"
|
||||||
msgstr "Silenciar"
|
msgstr "Silenciar"
|
||||||
|
|
||||||
|
@ -4579,7 +4583,7 @@ msgstr "Resetar tutoriais"
|
||||||
#~ msgid "Onboarding tour step {0}: {1}"
|
#~ msgid "Onboarding tour step {0}: {1}"
|
||||||
#~ msgstr "Etapa do tour de integração {0}: {1}"
|
#~ msgstr "Etapa do tour de integração {0}: {1}"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:667
|
#: src/view/com/composer/Composer.tsx:668
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr "Uma ou mais imagens estão sem texto alternativo."
|
msgstr "Uma ou mais imagens estão sem texto alternativo."
|
||||||
|
|
||||||
|
@ -5053,7 +5057,7 @@ msgstr "Por favor entre como @{0}"
|
||||||
msgid "Please Verify Your Email"
|
msgid "Please Verify Your Email"
|
||||||
msgstr "Por favor, verifique seu e-mail"
|
msgstr "Por favor, verifique seu e-mail"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:355
|
#: src/view/com/composer/Composer.tsx:356
|
||||||
msgid "Please wait for your link card to finish loading"
|
msgid "Please wait for your link card to finish loading"
|
||||||
msgstr "Aguarde até que a prévia de link termine de carregar"
|
msgstr "Aguarde até que a prévia de link termine de carregar"
|
||||||
|
|
||||||
|
@ -5066,8 +5070,8 @@ msgstr "Política"
|
||||||
msgid "Porn"
|
msgid "Porn"
|
||||||
msgstr "Pornografia"
|
msgstr "Pornografia"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:642
|
#: src/view/com/composer/Composer.tsx:643
|
||||||
#: src/view/com/composer/Composer.tsx:649
|
#: src/view/com/composer/Composer.tsx:650
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Post"
|
msgid "Post"
|
||||||
msgstr "Postar"
|
msgstr "Postar"
|
||||||
|
@ -5246,11 +5250,11 @@ msgstr "Listas públicas e compartilháveis para silenciar ou bloquear usuários
|
||||||
msgid "Public, shareable lists which can drive feeds."
|
msgid "Public, shareable lists which can drive feeds."
|
||||||
msgstr "Listas públicas e compartilháveis que geram feeds."
|
msgstr "Listas públicas e compartilháveis que geram feeds."
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:627
|
#: src/view/com/composer/Composer.tsx:628
|
||||||
msgid "Publish post"
|
msgid "Publish post"
|
||||||
msgstr "Publicar post"
|
msgstr "Publicar post"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:627
|
#: src/view/com/composer/Composer.tsx:628
|
||||||
msgid "Publish reply"
|
msgid "Publish reply"
|
||||||
msgstr "Publicar resposta"
|
msgstr "Publicar resposta"
|
||||||
|
|
||||||
|
@ -5555,7 +5559,7 @@ msgstr "Respostas para esta postagem estão desativadas."
|
||||||
#~ msgid "Replies to this thread are disabled"
|
#~ msgid "Replies to this thread are disabled"
|
||||||
#~ msgstr "Respostas para esta thread estão desativadas"
|
#~ msgstr "Respostas para esta thread estão desativadas"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:640
|
#: src/view/com/composer/Composer.tsx:641
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Reply"
|
msgid "Reply"
|
||||||
msgstr "Responder"
|
msgstr "Responder"
|
||||||
|
@ -7034,9 +7038,9 @@ msgstr "O post pode ter sido excluído."
|
||||||
msgid "The Privacy Policy has been moved to <0/>"
|
msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "A Política de Privacidade foi movida para <0/>"
|
msgstr "A Política de Privacidade foi movida para <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:227
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "Vídeo selecionado é maior que 100 MB."
|
msgstr "Vídeo selecionado é maior que 50 MB."
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
@ -7568,8 +7572,12 @@ msgstr "Deixar de seguir"
|
||||||
msgid "Unlike this feed"
|
msgid "Unlike this feed"
|
||||||
msgstr "Descurtir este feed"
|
msgstr "Descurtir este feed"
|
||||||
|
|
||||||
#: src/components/TagMenu/index.tsx:263
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:344
|
#: 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
|
#: src/view/screens/ProfileList.tsx:689
|
||||||
msgid "Unmute"
|
msgid "Unmute"
|
||||||
msgstr "Dessilenciar"
|
msgstr "Dessilenciar"
|
||||||
|
@ -7642,7 +7650,7 @@ msgstr "Desinscrever-se deste rotulador"
|
||||||
msgid "Unsubscribed from list"
|
msgid "Unsubscribed from list"
|
||||||
msgstr "Cancelada inscrição na lista"
|
msgstr "Cancelada inscrição na lista"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:240
|
#: src/state/queries/video/video.ts:245
|
||||||
msgid "Unsupported video type: {mimeType}"
|
msgid "Unsupported video type: {mimeType}"
|
||||||
msgstr "Tipo de vídeo não suportado: {mimeType}"
|
msgstr "Tipo de vídeo não suportado: {mimeType}"
|
||||||
|
|
||||||
|
@ -7909,7 +7917,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr "Vídeos não podem ter mais de 100 MB"
|
#~ msgstr "Vídeos não podem ter mais de 100 MB"
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
@ -8085,7 +8093,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."
|
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."
|
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:417
|
#: src/view/com/composer/Composer.tsx:418
|
||||||
msgid "We're sorry! The post you are replying to has been deleted."
|
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."
|
msgstr "Sentimos muito! A postagem que você está respondendo foi excluída."
|
||||||
|
|
||||||
|
@ -8124,7 +8132,7 @@ msgstr "Como você quer chamar seu pacote inicial?"
|
||||||
|
|
||||||
#: src/view/com/auth/SplashScreen.tsx:40
|
#: src/view/com/auth/SplashScreen.tsx:40
|
||||||
#: src/view/com/auth/SplashScreen.web.tsx:86
|
#: src/view/com/auth/SplashScreen.web.tsx:86
|
||||||
#: src/view/com/composer/Composer.tsx:512
|
#: src/view/com/composer/Composer.tsx:513
|
||||||
msgid "What's up?"
|
msgid "What's up?"
|
||||||
msgstr "E aí?"
|
msgstr "E aí?"
|
||||||
|
|
||||||
|
@ -8199,11 +8207,11 @@ msgstr "Largo"
|
||||||
msgid "Write a message"
|
msgid "Write a message"
|
||||||
msgstr "Escreva uma mensagem"
|
msgstr "Escreva uma mensagem"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:708
|
#: src/view/com/composer/Composer.tsx:709
|
||||||
msgid "Write post"
|
msgid "Write post"
|
||||||
msgstr "Escrever post"
|
msgstr "Escrever post"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:511
|
#: src/view/com/composer/Composer.tsx:512
|
||||||
#: src/view/com/post-thread/PostThreadComposePrompt.tsx:42
|
#: src/view/com/post-thread/PostThreadComposePrompt.tsx:42
|
||||||
msgid "Write your reply"
|
msgid "Write your reply"
|
||||||
msgstr "Escreva sua resposta"
|
msgstr "Escreva sua resposta"
|
||||||
|
@ -8551,6 +8559,10 @@ msgstr "Sua conta"
|
||||||
msgid "Your account has been deleted"
|
msgid "Your account has been deleted"
|
||||||
msgstr "Sua conta foi excluída"
|
msgstr "Sua conta foi excluída"
|
||||||
|
|
||||||
|
#: src/state/queries/video/video.ts:185
|
||||||
|
msgid "Your account is not yet old enough to upload videos. Please try again later."
|
||||||
|
msgstr "Sua conta ainda não tem idade suficiente para enviar vídeos. Por favor, tente novamente mais tarde."
|
||||||
|
|
||||||
#: src/view/screens/Settings/ExportCarDialog.tsx:65
|
#: src/view/screens/Settings/ExportCarDialog.tsx:65
|
||||||
msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately."
|
msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately."
|
||||||
msgstr "O repositório da sua conta, contendo todos os seus dados públicos, pode ser baixado como um arquivo \"CAR\". Este arquivo não inclui imagens ou dados privados, estes devem ser exportados separadamente."
|
msgstr "O repositório da sua conta, contendo todos os seus dados públicos, pode ser baixado como um arquivo \"CAR\". Este arquivo não inclui imagens ou dados privados, estes devem ser exportados separadamente."
|
||||||
|
@ -8614,7 +8626,7 @@ msgstr "Suas palavras silenciadas"
|
||||||
msgid "Your password has been changed successfully!"
|
msgid "Your password has been changed successfully!"
|
||||||
msgstr "Sua senha foi alterada com sucesso!"
|
msgstr "Sua senha foi alterada com sucesso!"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:463
|
#: src/view/com/composer/Composer.tsx:464
|
||||||
msgid "Your post has been published"
|
msgid "Your post has been published"
|
||||||
msgstr "Seu post foi publicado"
|
msgstr "Seu post foi publicado"
|
||||||
|
|
||||||
|
@ -8630,7 +8642,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."
|
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."
|
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:462
|
#: src/view/com/composer/Composer.tsx:463
|
||||||
msgid "Your reply has been published"
|
msgid "Your reply has been published"
|
||||||
msgstr "Sua resposta foi publicada"
|
msgstr "Sua resposta foi publicada"
|
||||||
|
|
||||||
|
|
|
@ -6237,8 +6237,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Политика конфиденциальности была перемещена в <0/>"
|
msgstr "Политика конфиденциальности была перемещена в <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:188
|
#: src/state/queries/video/video.ts:188
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "Размер выбранного видео превышает 100МБ."
|
msgstr "Размер выбранного видео превышает 50МБ."
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
|
|
@ -7498,7 +7498,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Gizlilik Politikası <0/> konumuna taşındı"
|
msgstr "Gizlilik Politikası <0/> konumuna taşındı"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -8412,7 +8412,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -7040,7 +7040,7 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "Політика конфіденційності була переміщена до <0/>"
|
msgstr "Політика конфіденційності була переміщена до <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
|
@ -7914,7 +7914,7 @@ msgid "Video: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/composer/videos/state.ts:27
|
#: src/view/com/composer/videos/state.ts:27
|
||||||
#~ msgid "Videos cannot be larger than 100MB"
|
#~ msgid "Videos cannot be larger than 50MB"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/screens/Profile/Header/Shell.tsx:113
|
#: src/screens/Profile/Header/Shell.tsx:113
|
||||||
|
|
|
@ -6272,8 +6272,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "隐私政策已迁移至 <0/>"
|
msgstr "隐私政策已迁移至 <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "选择的视频大小超过 100MB。"
|
msgstr "选择的视频大小超过 50MB。"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
|
|
@ -6272,8 +6272,8 @@ msgid "The Privacy Policy has been moved to <0/>"
|
||||||
msgstr "隱私政策已移動到 <0/>"
|
msgstr "隱私政策已移動到 <0/>"
|
||||||
|
|
||||||
#: src/state/queries/video/video.ts:222
|
#: src/state/queries/video/video.ts:222
|
||||||
msgid "The selected video is larger than 100MB."
|
msgid "The selected video is larger than 50MB."
|
||||||
msgstr "選擇的影片檔案大小超過 100MB。"
|
msgstr "選擇的影片檔案大小超過 50MB。"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
#: src/screens/StarterPack/StarterPackScreen.tsx:713
|
||||||
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead."
|
||||||
|
|
|
@ -180,6 +180,11 @@ export function useUploadVideo({
|
||||||
msg`You've reached your daily limit for video uploads (too many videos)`,
|
msg`You've reached your daily limit for video uploads (too many videos)`,
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
case 'Account is not old enough to upload videos':
|
||||||
|
message = _(
|
||||||
|
msg`Your account is not yet old enough to upload videos. Please try again later.`,
|
||||||
|
)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
message = e.message
|
message = e.message
|
||||||
break
|
break
|
||||||
|
@ -219,7 +224,7 @@ export function useUploadVideo({
|
||||||
} else if (e instanceof VideoTooLargeError) {
|
} else if (e instanceof VideoTooLargeError) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SetError',
|
type: 'SetError',
|
||||||
error: _(msg`The selected video is larger than 100MB.`),
|
error: _(msg`The selected video is larger than 50MB.`),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -303,9 +303,13 @@ export const ComposePost = observer(function ComposePost({
|
||||||
const onPhotoPasted = useCallback(
|
const onPhotoPasted = useCallback(
|
||||||
async (uri: string) => {
|
async (uri: string) => {
|
||||||
track('Composer:PastedPhotos')
|
track('Composer:PastedPhotos')
|
||||||
|
if (uri.startsWith('data:video/')) {
|
||||||
|
selectVideo({uri, type: 'video', height: 0, width: 0})
|
||||||
|
} else {
|
||||||
await gallery.paste(uri)
|
await gallery.paste(uri)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[gallery, track],
|
[gallery, track, selectVideo],
|
||||||
)
|
)
|
||||||
|
|
||||||
const isAltTextRequiredAndMissing = useMemo(() => {
|
const isAltTextRequiredAndMissing = useMemo(() => {
|
||||||
|
|
|
@ -93,9 +93,9 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
||||||
}
|
}
|
||||||
}, [onPressPublish])
|
}, [onPressPublish])
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
textInputWebEmitter.addListener('photo-pasted', onPhotoPasted)
|
textInputWebEmitter.addListener('media-pasted', onPhotoPasted)
|
||||||
return () => {
|
return () => {
|
||||||
textInputWebEmitter.removeListener('photo-pasted', onPhotoPasted)
|
textInputWebEmitter.removeListener('media-pasted', onPhotoPasted)
|
||||||
}
|
}
|
||||||
}, [onPhotoPasted])
|
}, [onPhotoPasted])
|
||||||
|
|
||||||
|
@ -105,8 +105,8 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
||||||
if (transfer) {
|
if (transfer) {
|
||||||
const items = transfer.items
|
const items = transfer.items
|
||||||
|
|
||||||
getImageFromUri(items, (uri: string) => {
|
getImageOrVideoFromUri(items, (uri: string) => {
|
||||||
textInputWebEmitter.emit('photo-pasted', uri)
|
textInputWebEmitter.emit('media-pasted', uri)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +160,8 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
||||||
view.pasteText(text)
|
view.pasteText(text)
|
||||||
preventDefault = true
|
preventDefault = true
|
||||||
}
|
}
|
||||||
getImageFromUri(clipboardData.items, (uri: string) => {
|
getImageOrVideoFromUri(clipboardData.items, (uri: string) => {
|
||||||
textInputWebEmitter.emit('photo-pasted', uri)
|
textInputWebEmitter.emit('media-pasted', uri)
|
||||||
})
|
})
|
||||||
if (preventDefault) {
|
if (preventDefault) {
|
||||||
// Return `true` to prevent ProseMirror's default paste behavior.
|
// Return `true` to prevent ProseMirror's default paste behavior.
|
||||||
|
@ -346,7 +346,7 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function getImageFromUri(
|
function getImageOrVideoFromUri(
|
||||||
items: DataTransferItemList,
|
items: DataTransferItemList,
|
||||||
callback: (uri: string) => void,
|
callback: (uri: string) => void,
|
||||||
) {
|
) {
|
||||||
|
@ -363,11 +363,21 @@ function getImageFromUri(
|
||||||
if (blob.type.startsWith('image/')) {
|
if (blob.type.startsWith('image/')) {
|
||||||
blobToDataUri(blob).then(callback, err => console.error(err))
|
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/')) {
|
} else if (type.startsWith('image/')) {
|
||||||
const file = item.getAsFile()
|
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) {
|
if (file) {
|
||||||
blobToDataUri(file).then(callback, err => console.error(err))
|
blobToDataUri(file).then(callback, err => console.error(err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {SubtitleFilePicker} from './SubtitleFilePicker'
|
import {SubtitleFilePicker} from './SubtitleFilePicker'
|
||||||
|
|
||||||
|
const MAX_NUM_CAPTIONS = 1
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
defaultAltText: string
|
defaultAltText: string
|
||||||
captions: {lang: string; file: File}[]
|
captions: {lang: string; file: File}[]
|
||||||
|
@ -134,7 +136,9 @@ function SubtitleDialogInner({
|
||||||
</Text>
|
</Text>
|
||||||
<SubtitleFilePicker
|
<SubtitleFilePicker
|
||||||
onSelectFile={handleSelectFile}
|
onSelectFile={handleSelectFile}
|
||||||
disabled={subtitleMissingLanguage || captions.length >= 4}
|
disabled={
|
||||||
|
subtitleMissingLanguage || captions.length >= MAX_NUM_CAPTIONS
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<View>
|
<View>
|
||||||
{captions.map((subtitle, i) => (
|
{captions.map((subtitle, i) => (
|
||||||
|
|
|
@ -4,27 +4,29 @@ import {AppBskyEmbedVideo} from '@atproto/api'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {isFirefox} from '#/lib/browser'
|
||||||
import {clamp} from '#/lib/numbers'
|
import {clamp} from '#/lib/numbers'
|
||||||
import {useGate} from '#/lib/statsig/statsig'
|
|
||||||
import {
|
import {
|
||||||
HLSUnsupportedError,
|
HLSUnsupportedError,
|
||||||
VideoEmbedInnerWeb,
|
VideoEmbedInnerWeb,
|
||||||
VideoNotFoundError,
|
VideoNotFoundError,
|
||||||
} from '#/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb'
|
} from '#/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
|
import {useFullscreen} from '#/components/hooks/useFullscreen'
|
||||||
import {ErrorBoundary} from '../ErrorBoundary'
|
import {ErrorBoundary} from '../ErrorBoundary'
|
||||||
import {useActiveVideoWeb} from './ActiveVideoWebContext'
|
import {useActiveVideoWeb} from './ActiveVideoWebContext'
|
||||||
import * as VideoFallback from './VideoEmbedInner/VideoFallback'
|
import * as VideoFallback from './VideoEmbedInner/VideoFallback'
|
||||||
|
|
||||||
export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
|
export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
const gate = useGate()
|
|
||||||
const {active, setActive, sendPosition, currentActiveView} =
|
const {active, setActive, sendPosition, currentActiveView} =
|
||||||
useActiveVideoWeb()
|
useActiveVideoWeb()
|
||||||
const [onScreen, setOnScreen] = useState(false)
|
const [onScreen, setOnScreen] = useState(false)
|
||||||
|
const [isFullscreen] = useFullscreen()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current) return
|
if (!ref.current) return
|
||||||
|
if (isFullscreen && !isFirefox) return
|
||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
entries => {
|
entries => {
|
||||||
const entry = entries[0]
|
const entry = entries[0]
|
||||||
|
@ -38,7 +40,7 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
|
||||||
)
|
)
|
||||||
observer.observe(ref.current)
|
observer.observe(ref.current)
|
||||||
return () => observer.disconnect()
|
return () => observer.disconnect()
|
||||||
}, [sendPosition])
|
}, [sendPosition, isFullscreen])
|
||||||
|
|
||||||
const [key, setKey] = useState(0)
|
const [key, setKey] = useState(0)
|
||||||
const renderError = useCallback(
|
const renderError = useCallback(
|
||||||
|
@ -48,10 +50,6 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
|
||||||
[key],
|
[key],
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!gate('video_view_on_posts')) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
let aspectRatio = 16 / 9
|
let aspectRatio = 16 / 9
|
||||||
|
|
||||||
if (embed.aspectRatio) {
|
if (embed.aspectRatio) {
|
||||||
|
@ -106,11 +104,13 @@ function ViewportObserver({
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
const [nearScreen, setNearScreen] = useState(false)
|
const [nearScreen, setNearScreen] = useState(false)
|
||||||
|
const [isFullscreen] = useFullscreen()
|
||||||
|
|
||||||
// Send position when scrolling. This is done with an IntersectionObserver
|
// Send position when scrolling. This is done with an IntersectionObserver
|
||||||
// observing a div of 100vh height
|
// observing a div of 100vh height
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current) return
|
if (!ref.current) return
|
||||||
|
if (isFullscreen && !isFirefox) return
|
||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
entries => {
|
entries => {
|
||||||
const entry = entries[0]
|
const entry = entries[0]
|
||||||
|
@ -124,7 +124,7 @@ function ViewportObserver({
|
||||||
)
|
)
|
||||||
observer.observe(ref.current)
|
observer.observe(ref.current)
|
||||||
return () => observer.disconnect()
|
return () => observer.disconnect()
|
||||||
}, [sendPosition])
|
}, [sendPosition, isFullscreen])
|
||||||
|
|
||||||
// In case scrolling hasn't started yet, send up the position
|
// In case scrolling hasn't started yet, send up the position
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import React, {
|
import React, {useCallback, useEffect, useRef, useState} from 'react'
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
useSyncExternalStore,
|
|
||||||
} from 'react'
|
|
||||||
import {Pressable, View} from 'react-native'
|
import {Pressable, View} from 'react-native'
|
||||||
import {SvgProps} from 'react-native-svg'
|
import {SvgProps} from 'react-native-svg'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
@ -21,6 +15,7 @@ import {
|
||||||
} from '#/state/preferences'
|
} from '#/state/preferences'
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
|
import {useFullscreen} from '#/components/hooks/useFullscreen'
|
||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {
|
import {
|
||||||
ArrowsDiagonalIn_Stroke2_Corner0_Rounded as ArrowsInIcon,
|
ArrowsDiagonalIn_Stroke2_Corner0_Rounded as ArrowsInIcon,
|
||||||
|
@ -341,8 +336,8 @@ export function Controls({
|
||||||
)}
|
)}
|
||||||
<ControlButton
|
<ControlButton
|
||||||
active={muted}
|
active={muted}
|
||||||
activeLabel={_(msg`Unmute`)}
|
activeLabel={_(msg({message: `Unmute`, context: 'video'}))}
|
||||||
inactiveLabel={_(msg`Mute`)}
|
inactiveLabel={_(msg({message: `Mute`, context: 'video'}))}
|
||||||
activeIcon={MuteIcon}
|
activeIcon={MuteIcon}
|
||||||
inactiveIcon={UnmuteIcon}
|
inactiveIcon={UnmuteIcon}
|
||||||
onPress={onPressMute}
|
onPress={onPressMute}
|
||||||
|
@ -850,25 +845,3 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
||||||
canPlay,
|
canPlay,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fullscreenSubscribe(onChange: () => void) {
|
|
||||||
document.addEventListener('fullscreenchange', onChange)
|
|
||||||
return () => document.removeEventListener('fullscreenchange', onChange)
|
|
||||||
}
|
|
||||||
|
|
||||||
function useFullscreen(ref: React.RefObject<HTMLElement>) {
|
|
||||||
const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () =>
|
|
||||||
Boolean(document.fullscreenElement),
|
|
||||||
)
|
|
||||||
|
|
||||||
const toggleFullscreen = useCallback(() => {
|
|
||||||
if (isFullscreen) {
|
|
||||||
document.exitFullscreen()
|
|
||||||
} else {
|
|
||||||
if (!ref.current) return
|
|
||||||
ref.current.requestFullscreen()
|
|
||||||
}
|
|
||||||
}, [isFullscreen, ref])
|
|
||||||
|
|
||||||
return [isFullscreen, toggleFullscreen] as const
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue