Merge remote-tracking branch 'origin/main' into mod-auth
* origin/main: (21 commits) Add border to menu on web (#5439) Add eslint rule to fix imports without the `#/` path alias (#5175) [Neue] Parallel font loading on web (#5411) Adjust toggle components sizing (#5408) [Neue] Copy and spacing tweaks (#5428) [Neue] Ligatures & composer (#5427) Remove expo/vector-icons from EditImage modal (#5422) Revert provider stacking changes (#5423) Fix ext embeds in DMs (#5419) Fix font loading on web (#5412) [Neue] Base (#5395) Update sentry sourcemaps upload (#5409) Fix for undefined ref on hot reload on web (#5407) remove expo-sentry (#5405) Revert unneeded changes to `expo-modules-core` patch (#5393) Temporary Sentry hack patch for iOS 18 (#5400) Make it work with Xcode 16 (#5386) Fix border radius on avatars (#5392) Make like animation on web same speed as mobile (#5391) Pre-fill alt text with 10-million card post (#5389) ...
@@ -33,6 +33,7 @@ module.exports = {
|
||||
],
|
||||
'bsky-internal/use-exact-imports': 'error',
|
||||
'bsky-internal/use-typed-gates': 'error',
|
||||
'bsky-internal/use-prefixed-imports': 'warn',
|
||||
'simple-import-sort/imports': [
|
||||
'warn',
|
||||
{
|
||||
|
||||
@@ -55,6 +55,7 @@ module.exports = function (config) {
|
||||
: undefined
|
||||
const UPDATES_ENABLED = !!UPDATES_CHANNEL
|
||||
|
||||
const USE_SENTRY = Boolean(process.env.SENTRY_AUTH_TOKEN)
|
||||
const SENTRY_DIST = `${PLATFORM}.${VERSION}.${IS_TESTFLIGHT ? 'tf' : ''}${
|
||||
IS_DEV ? 'dev' : ''
|
||||
}`
|
||||
@@ -186,7 +187,15 @@ module.exports = function (config) {
|
||||
},
|
||||
plugins: [
|
||||
'expo-localization',
|
||||
Boolean(process.env.SENTRY_AUTH_TOKEN) && 'sentry-expo',
|
||||
USE_SENTRY && [
|
||||
'@sentry/react-native/expo',
|
||||
{
|
||||
organization: 'blueskyweb',
|
||||
project: 'react-native',
|
||||
release: VERSION,
|
||||
dist: SENTRY_DIST,
|
||||
},
|
||||
],
|
||||
[
|
||||
'expo-build-properties',
|
||||
{
|
||||
@@ -221,6 +230,31 @@ module.exports = function (config) {
|
||||
'./plugins/shareExtension/withShareExtensions.js',
|
||||
'./plugins/notificationsExtension/withNotificationsExtension.js',
|
||||
'./plugins/withAppDelegateReferrer.js',
|
||||
[
|
||||
'expo-font',
|
||||
{
|
||||
fonts: [
|
||||
// './assets/fonts/inter/Inter-Thin.otf',
|
||||
// './assets/fonts/inter/Inter-ThinItalic.otf',
|
||||
// './assets/fonts/inter/Inter-ExtraLight.otf',
|
||||
// './assets/fonts/inter/Inter-ExtraLightItalic.otf',
|
||||
// './assets/fonts/inter/Inter-Light.otf',
|
||||
// './assets/fonts/inter/Inter-LightItalic.otf',
|
||||
'./assets/fonts/inter/Inter-Regular.otf',
|
||||
'./assets/fonts/inter/Inter-Italic.otf',
|
||||
'./assets/fonts/inter/Inter-Medium.otf',
|
||||
'./assets/fonts/inter/Inter-MediumItalic.otf',
|
||||
'./assets/fonts/inter/Inter-SemiBold.otf',
|
||||
'./assets/fonts/inter/Inter-SemiBoldItalic.otf',
|
||||
'./assets/fonts/inter/Inter-Bold.otf',
|
||||
'./assets/fonts/inter/Inter-BoldItalic.otf',
|
||||
'./assets/fonts/inter/Inter-ExtraBold.otf',
|
||||
'./assets/fonts/inter/Inter-ExtraBoldItalic.otf',
|
||||
'./assets/fonts/inter/Inter-Black.otf',
|
||||
'./assets/fonts/inter/Inter-BlackItalic.otf',
|
||||
],
|
||||
},
|
||||
],
|
||||
].filter(Boolean),
|
||||
extra: {
|
||||
eas: {
|
||||
@@ -263,7 +297,7 @@ module.exports = function (config) {
|
||||
* @see https://docs.expo.dev/guides/using-sentry/#app-configuration
|
||||
*/
|
||||
{
|
||||
file: 'sentry-expo/upload-sourcemaps',
|
||||
file: './postHooks/uploadSentrySourcemapsPostHook',
|
||||
config: {
|
||||
organization: 'blueskyweb',
|
||||
project: 'react-native',
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M3 4a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4Zm2 1v14h14V5H5Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 229 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M4 2c0-.552.41-1 .917-1h14.666c.507 0 .917.448.917 1v20c0 .552-.41 1-.917 1H4.917C4.41 23 4 22.552 4 22V2Zm1.833 1v18h12.834V3H5.833Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 276 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M2 20.5c-.552 0-1-.41-1-.917V4.917C1 4.41 1.448 4 2 4h20c.552 0 1 .41 1 .917v14.666c0 .507-.448.917-1 .917H2Zm1-1.833h18V5.833H3v12.834Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 279 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M4 21a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5v2H5v14h4v2H4Zm9-20v22h-2V1h2Zm7.707 2.293A1 1 0 0 1 21 4v1h-2V3h1a1 1 0 0 1 .707.293ZM19 7h2v2h-2V7Zm0 4h2v2h-2v-2Zm0 4h2v2h-2v-2Zm0 4h2v1a1 1 0 0 1-1 1h-1v-2Zm-2 0v2h-2v-2h2ZM15 5h2V3h-2v2Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 371 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M3 4a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5h-2V5H5v4H3V4Zm20 9H1v-2h22v2Zm-2.293 7.707A1 1 0 0 1 20 21h-1v-2h2v1a1 1 0 0 1-.293.707ZM17 19v2h-2v-2h2Zm-4 0v2h-2v-2h2Zm-4 0v2H7v-2h2Zm-4 0v2H4a1 1 0 0 1-1-1v-1h2Zm0-2H3v-2h2v2Zm14-2v2h2v-2h-2Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 376 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M9 5a1 1 0 0 1 1-1h12a1 1 0 1 1 0 2h-5v14a1 1 0 1 1-2 0V6h-5a1 1 0 0 1-1-1Zm-3.073 7v8a1 1 0 1 0 2 0v-8H12a1 1 0 1 0 0-2H6.971a1.015 1.015 0 0 0-.089 0H2a1 1 0 1 0 0 2h3.927Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 317 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M3.65 17.247c-.242.832-.632 1.178-1.325 1.178-.814 0-1.325-.476-1.325-1.23 0-.216.06-.51.173-.831L4.586 7.07c.364-1.014.979-1.482 1.966-1.482 1.022 0 1.629.45 2.001 1.473l3.43 9.303c.121.337.165.571.165.831 0 .72-.546 1.23-1.308 1.23-.736 0-1.126-.338-1.36-1.152l-.658-1.975H4.309l-.658 1.95ZM6.5 8.152l-1.62 5.12h3.335l-1.654-5.12H6.5Zm13.005 8.688c-.52.988-1.68 1.568-2.84 1.568-1.768 0-3.11-1.144-3.11-2.815 0-1.69 1.299-2.668 3.62-2.807l2.34-.138v-.615c0-.867-.607-1.369-1.56-1.369-.771 0-1.239.251-1.802.979-.277.312-.597.468-1.004.468-.615 0-1.057-.399-1.057-.97 0-.2.043-.382.13-.572.433-1.109 1.923-1.793 3.845-1.793 2.383 0 3.933 1.23 3.933 3.1v5.293c0 .84-.511 1.273-1.23 1.273-.684 0-1.16-.38-1.213-1.126v-.476h-.052Zm-3.43-1.386c0 .693.572 1.126 1.42 1.126 1.11 0 2.02-.719 2.02-1.723v-.676l-1.959.121c-.944.07-1.48.494-1.48 1.152Z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 986 B |
@@ -210,6 +210,11 @@ func serve(cctx *cli.Context) error {
|
||||
maxAge = 7 * (60 * 60 * 24) // 1 week
|
||||
}
|
||||
|
||||
// fonts can be cached for a year
|
||||
if strings.HasSuffix(path, ".otf") {
|
||||
maxAge = 365 * (60 * 60 * 24) // 1 year
|
||||
}
|
||||
|
||||
c.Response().Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", maxAge))
|
||||
return next(c)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,105 @@
|
||||
|
||||
<!-- Hello Humans! API docs at https://atproto.com -->
|
||||
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Italic.95778eb0c75dc956257e.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Medium.296aa2d65964269836b3.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBold.2277990330981b8409bb.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Bold.8d330503e1d034ad68de.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Black.66e9a87f1c921e844ed4.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf">
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Inter-Regular";
|
||||
src: local("Inter-Regular"), url(/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf) format("font/otf");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Italic";
|
||||
src: local("Inter-Italic"), url(/static/media/Inter-Italic.95778eb0c75dc956257e.otf) format("font/otf");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Medium";
|
||||
src: local("Inter-Medium"), url(/static/media/Inter-Medium.296aa2d65964269836b3.otf) format("font/otf");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-MediumItalic";
|
||||
src: local("Inter-MediumItalic"), url(/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf) format("font/otf");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-SemiBold";
|
||||
src: local("Inter-SemiBold"), url(/static/media/Inter-SemiBold.2277990330981b8409bb.otf) format("font/otf");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-SemiBoldItalic";
|
||||
src: local("Inter-SemiBoldItalic"), url(/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf) format("font/otf");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Bold";
|
||||
src: local("Inter-Bold"), url(/static/media/Inter-Bold.8d330503e1d034ad68de.otf) format("font/otf");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-BoldItalic";
|
||||
src: local("Inter-BoldItalic"), url(/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf) format("font/otf");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-ExtraBold";
|
||||
src: local("Inter-ExtraBold"), url(/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf) format("font/otf");
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-ExtraBoldItalic";
|
||||
src: local("Inter-ExtraBoldItalic"), url(/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf) format("font/otf");
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Black";
|
||||
src: local("Inter-Black"), url(/static/media/Inter-Black.66e9a87f1c921e844ed4.otf) format("font/otf");
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-BlackItalic";
|
||||
src: local("Inter-BlackItalic"), url(/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf) format("font/otf");
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the react-native-web reset:
|
||||
* https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
|
||||
@@ -149,7 +247,6 @@
|
||||
|
||||
/* ProseMirror */
|
||||
.ProseMirror {
|
||||
font: 18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Liberation Sans", Helvetica, Arial, sans-serif;
|
||||
min-height: 140px;
|
||||
}
|
||||
.ProseMirror-dark {
|
||||
|
||||
@@ -5,5 +5,6 @@ module.exports = {
|
||||
'avoid-unwrapped-text': require('./avoid-unwrapped-text'),
|
||||
'use-exact-imports': require('./use-exact-imports'),
|
||||
'use-typed-gates': require('./use-typed-gates'),
|
||||
'use-prefixed-imports': require('./use-prefixed-imports'),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable bsky-internal/use-exact-imports */
|
||||
const BANNED_IMPORTS = [
|
||||
'@fortawesome/free-regular-svg-icons',
|
||||
'@fortawesome/free-solid-svg-icons',
|
||||
@@ -6,11 +5,12 @@ const BANNED_IMPORTS = [
|
||||
|
||||
exports.create = function create(context) {
|
||||
return {
|
||||
Literal(node) {
|
||||
if (typeof node.value !== 'string') {
|
||||
ImportDeclaration(node) {
|
||||
const source = node.source
|
||||
if (typeof source.value !== 'string') {
|
||||
return
|
||||
}
|
||||
if (BANNED_IMPORTS.includes(node.value)) {
|
||||
if (BANNED_IMPORTS.includes(source.value)) {
|
||||
context.report({
|
||||
node,
|
||||
message:
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
const BANNED_IMPORT_PREFIXES = [
|
||||
'alf/',
|
||||
'components/',
|
||||
'lib/',
|
||||
'locale/',
|
||||
'logger/',
|
||||
'platform/',
|
||||
'state/',
|
||||
'storage/',
|
||||
'view/',
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
fixable: 'code',
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
ImportDeclaration(node) {
|
||||
const source = node.source
|
||||
if (typeof source.value !== 'string') {
|
||||
return
|
||||
}
|
||||
if (
|
||||
BANNED_IMPORT_PREFIXES.some(banned => source.value.startsWith(banned))
|
||||
) {
|
||||
context.report({
|
||||
node: source,
|
||||
message: `Use '#/${source.value}'`,
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(source, `'#/${source.value}'`)
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
"web": "expo start --web",
|
||||
"use-build-number": "./scripts/useBuildNumberEnv.sh",
|
||||
"use-build-number-with-bump": "./scripts/useBuildNumberEnvWithBump.sh",
|
||||
"build-web": "expo export:web && node ./scripts/post-web-build.js && cp -v ./web-build/static/js/*.* ./bskyweb/static/js/ && cp -v ./web-build/static/media/*.png ./bskyweb/static/media/",
|
||||
"build-web": "expo export:web && node ./scripts/post-web-build.js && cp -v ./web-build/static/js/*.* ./bskyweb/static/js/ && cp -v ./web-build/static/media/* ./bskyweb/static/media/",
|
||||
"build-all": "yarn intl:build && yarn use-build-number-with-bump eas build --platform all",
|
||||
"build-ios": "yarn use-build-number-with-bump eas build -p ios",
|
||||
"build-android": "yarn use-build-number-with-bump eas build -p android",
|
||||
@@ -85,7 +85,7 @@
|
||||
"@segment/analytics-react": "^1.0.0-rc1",
|
||||
"@segment/analytics-react-native": "^2.10.1",
|
||||
"@segment/sovran-react-native": "^0.4.5",
|
||||
"@sentry/react-native": "5.5.0",
|
||||
"@sentry/react-native": "5.32.0",
|
||||
"@tamagui/focus-scope": "^1.84.1",
|
||||
"@tanstack/query-async-storage-persister": "^5.25.0",
|
||||
"@tanstack/react-query": "^5.8.1",
|
||||
@@ -124,6 +124,7 @@
|
||||
"expo-dev-client": "^4.0.14",
|
||||
"expo-device": "~6.0.2",
|
||||
"expo-file-system": "^17.0.1",
|
||||
"expo-font": "~12.0.10",
|
||||
"expo-haptics": "^13.0.1",
|
||||
"expo-image": "~1.12.9",
|
||||
"expo-image-manipulator": "^12.0.5",
|
||||
@@ -177,7 +178,7 @@
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "~2.16.2",
|
||||
"react-native-get-random-values": "~1.11.0",
|
||||
"react-native-image-crop-picker": "0.40.3",
|
||||
"react-native-image-crop-picker": "0.41.2",
|
||||
"react-native-ios-context-menu": "^1.15.3",
|
||||
"react-native-keyboard-controller": "^1.12.1",
|
||||
"react-native-mmkv": "^2.12.2",
|
||||
@@ -200,7 +201,6 @@
|
||||
"react-responsive": "^9.0.2",
|
||||
"react-textarea-autosize": "^8.5.3",
|
||||
"rn-fetch-blob": "^0.12.0",
|
||||
"sentry-expo": "~7.0.1",
|
||||
"statsig-react-native-expo": "^4.6.1",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tlds": "^1.234.0",
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
diff --git a/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js b/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
|
||||
index 7e0b4cd..177454c 100644
|
||||
--- a/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
|
||||
+++ b/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
|
||||
@@ -3,6 +3,8 @@ import { LogBox } from 'react-native';
|
||||
* This is a workaround for using fetch on RN, this is a known issue in react-native and only generates a warning.
|
||||
*/
|
||||
export function ignoreRequireCycleLogs() {
|
||||
- LogBox.ignoreLogs(['Require cycle:']);
|
||||
+ try {
|
||||
+ LogBox.ignoreLogs(['Require cycle:']);
|
||||
+ } catch (e) {}
|
||||
}
|
||||
//# sourceMappingURL=ignorerequirecyclelogs.js.map
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js b/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js
|
||||
index 0f244f2..ae7dfb3 100755
|
||||
--- a/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js
|
||||
+++ b/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js
|
||||
@@ -174,6 +174,7 @@ if (!outputDir) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
+const otherArgs = process.argv.slice(3);
|
||||
const files = getAssetPathsSync(outputDir);
|
||||
const groupedAssets = groupAssets(files);
|
||||
|
||||
@@ -195,7 +196,7 @@ for (const [assetGroupName, assets] of Object.entries(groupedAssets)) {
|
||||
|
||||
const isHermes = assets.find(asset => asset.endsWith('.hbc'));
|
||||
const windowsCallback = process.platform === "win32" ? 'node ' : '';
|
||||
- execSync(`${windowsCallback}${sentryCliBin} sourcemaps upload ${isHermes ? '--debug-id-reference' : ''} ${assets.join(' ')}`, {
|
||||
+ execSync(`${windowsCallback}${sentryCliBin} sourcemaps upload ${isHermes ? '--debug-id-reference' : ''} ${assets.join(' ')} ${otherArgs.join(' ')}`, {
|
||||
env: {
|
||||
...process.env,
|
||||
[SENTRY_PROJECT]: sentryProject,
|
||||
@@ -1,15 +0,0 @@
|
||||
diff --git a/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js b/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
|
||||
index 7e0b4cd..177454c 100644
|
||||
--- a/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
|
||||
+++ b/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
|
||||
@@ -3,6 +3,8 @@ import { LogBox } from 'react-native';
|
||||
* This is a workaround for using fetch on RN, this is a known issue in react-native and only generates a warning.
|
||||
*/
|
||||
export function ignoreRequireCycleLogs() {
|
||||
- LogBox.ignoreLogs(['Require cycle:']);
|
||||
+ try {
|
||||
+ LogBox.ignoreLogs(['Require cycle:']);
|
||||
+ } catch (e) {}
|
||||
}
|
||||
//# sourceMappingURL=ignorerequirecyclelogs.js.map
|
||||
\ No newline at end of file
|
||||
@@ -12,28 +12,3 @@ index bb74e80..0aa0202 100644
|
||||
|
||||
Map<String, Object> constants = new HashMap<>(3);
|
||||
constants.put(MODULES_CONSTANTS_KEY, new HashMap<>());
|
||||
diff --git a/node_modules/expo-modules-core/build/uuid/uuid.js b/node_modules/expo-modules-core/build/uuid/uuid.js
|
||||
index 109d3fe..c421931 100644
|
||||
--- a/node_modules/expo-modules-core/build/uuid/uuid.js
|
||||
+++ b/node_modules/expo-modules-core/build/uuid/uuid.js
|
||||
@@ -1,5 +1,7 @@
|
||||
import bytesToUuid from './lib/bytesToUuid';
|
||||
import { Uuidv5Namespace } from './uuid.types';
|
||||
+import { ensureNativeModulesAreInstalled } from '../ensureNativeModulesAreInstalled';
|
||||
+ensureNativeModulesAreInstalled();
|
||||
const nativeUuidv4 = globalThis?.expo?.uuidv4;
|
||||
const nativeUuidv5 = globalThis?.expo?.uuidv5;
|
||||
function uuidv4() {
|
||||
diff --git a/node_modules/expo-modules-core/ios/Core/SharedObjects/SharedObjectRegistry.swift b/node_modules/expo-modules-core/ios/Core/SharedObjects/SharedObjectRegistry.swift
|
||||
index ee2268a..4851b67 100644
|
||||
--- a/node_modules/expo-modules-core/ios/Core/SharedObjects/SharedObjectRegistry.swift
|
||||
+++ b/node_modules/expo-modules-core/ios/Core/SharedObjects/SharedObjectRegistry.swift
|
||||
@@ -173,7 +173,7 @@ public final class SharedObjectRegistry {
|
||||
}
|
||||
|
||||
internal func clear() {
|
||||
- Self.lockQueue.async {
|
||||
+ Self.lockQueue.sync {
|
||||
self.pairs.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
const exec = require('child_process').execSync
|
||||
|
||||
const SENTRY_AUTH_TOKEN = process.env.SENTRY_AUTH_TOKEN
|
||||
|
||||
module.exports = ({config}) => {
|
||||
if (!SENTRY_AUTH_TOKEN) {
|
||||
console.log(
|
||||
'SENTRY_AUTH_TOKEN environment variable must be set to upload sourcemaps. Skipping.',
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const org = config.organization
|
||||
const project = config.project
|
||||
const release = config.release
|
||||
const dist = config.dist
|
||||
|
||||
if (!org || !project || !release || !dist) {
|
||||
console.log(
|
||||
'"organization", "project", "release", and "dist" must be set in the hook config to upload sourcemaps. Skipping.',
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('Uploading sourcemaps to Sentry...')
|
||||
exec(
|
||||
`node node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps dist --url https://sentry.io/ -o ${org} -p ${project} -r ${release} -d ${dist}`,
|
||||
)
|
||||
console.log('Sourcemaps uploaded to Sentry.')
|
||||
} catch (e) {
|
||||
console.error('Error uploading sourcemaps to Sentry:', e)
|
||||
}
|
||||
}
|
||||
@@ -143,8 +143,8 @@ function InnerApp() {
|
||||
</MessagesProvider>
|
||||
</StatsigProvider>
|
||||
</QueryProvider>
|
||||
<ToastContainer />
|
||||
</React.Fragment>
|
||||
<ToastContainer />
|
||||
</ActiveVideoProvider>
|
||||
</VideoVolumeProvider>
|
||||
</RootSiblingParent>
|
||||
|
||||
@@ -225,43 +225,43 @@ export const atoms = {
|
||||
},
|
||||
text_2xs: {
|
||||
fontSize: tokens.fontSize._2xs,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_xs: {
|
||||
fontSize: tokens.fontSize.xs,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_sm: {
|
||||
fontSize: tokens.fontSize.sm,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_md: {
|
||||
fontSize: tokens.fontSize.md,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_lg: {
|
||||
fontSize: tokens.fontSize.lg,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_xl: {
|
||||
fontSize: tokens.fontSize.xl,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_2xl: {
|
||||
fontSize: tokens.fontSize._2xl,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_3xl: {
|
||||
fontSize: tokens.fontSize._3xl,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_4xl: {
|
||||
fontSize: tokens.fontSize._4xl,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
text_5xl: {
|
||||
fontSize: tokens.fontSize._5xl,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
leading_tight: {
|
||||
lineHeight: 1.15,
|
||||
@@ -273,10 +273,7 @@ export const atoms = {
|
||||
lineHeight: 1.5,
|
||||
},
|
||||
tracking_normal: {
|
||||
letterSpacing: 0,
|
||||
},
|
||||
tracking_wide: {
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
font_normal: {
|
||||
fontWeight: tokens.fontWeight.normal,
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
import {useFonts as defaultUseFonts} from 'expo-font'
|
||||
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {Device, device} from '#/storage'
|
||||
|
||||
const FAMILIES = `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Liberation Sans", Helvetica, Arial, sans-serif`
|
||||
|
||||
const factor = 0.0625 // 1 - (15/16)
|
||||
const fontScaleMultipliers: Record<Device['fontScale'], number> = {
|
||||
'-2': 1 - factor * 3,
|
||||
'-1': 1 - factor * 2,
|
||||
'0': 1 - factor * 1, // default
|
||||
'1': 1,
|
||||
'2': 1 + factor * 1,
|
||||
}
|
||||
|
||||
export function computeFontScaleMultiplier(scale: Device['fontScale']) {
|
||||
return fontScaleMultipliers[scale]
|
||||
}
|
||||
|
||||
export function getFontScale() {
|
||||
return device.get(['fontScale']) ?? '0'
|
||||
}
|
||||
|
||||
export function setFontScale(fontScale: Device['fontScale']) {
|
||||
device.set(['fontScale'], fontScale)
|
||||
}
|
||||
|
||||
export function getFontFamily() {
|
||||
return device.get(['fontFamily']) || 'theme'
|
||||
}
|
||||
|
||||
export function setFontFamily(fontFamily: Device['fontFamily']) {
|
||||
device.set(['fontFamily'], fontFamily)
|
||||
}
|
||||
|
||||
/*
|
||||
* IMPORTANT: This is unused. Expo statically extracts these fonts, but we load
|
||||
* them manually so that we can parallelize the loading along with the JS
|
||||
* bundle.
|
||||
*
|
||||
* See `#/alf/util/useFonts` for the actually used hooks.
|
||||
*
|
||||
* All used fonts MUST be configured here. Unused fonts are commented out, but
|
||||
* the files are there if we need them.
|
||||
*/
|
||||
export function DO_NOT_USE() {
|
||||
return defaultUseFonts({
|
||||
// 'Inter-Thin': require('../../assets/fonts/inter/Inter-Thin.otf'),
|
||||
// 'Inter-ThinItalic': require('../../assets/fonts/inter/Inter-ThinItalic.otf'),
|
||||
// 'Inter-ExtraLight': require('../../assets/fonts/inter/Inter-ExtraLight.otf'),
|
||||
// 'Inter-ExtraLightItalic': require('../../assets/fonts/inter/Inter-ExtraLightItalic.otf'),
|
||||
// 'Inter-Light': require('../../assets/fonts/inter/Inter-Light.otf'),
|
||||
// 'Inter-LightItalic': require('../../assets/fonts/inter/Inter-LightItalic.otf'),
|
||||
'Inter-Regular': require('../../assets/fonts/inter/Inter-Regular.otf'),
|
||||
'Inter-Italic': require('../../assets/fonts/inter/Inter-Italic.otf'),
|
||||
'Inter-Medium': require('../../assets/fonts/inter/Inter-Medium.otf'),
|
||||
'Inter-MediumItalic': require('../../assets/fonts/inter/Inter-MediumItalic.otf'),
|
||||
'Inter-SemiBold': require('../../assets/fonts/inter/Inter-SemiBold.otf'),
|
||||
'Inter-SemiBoldItalic': require('../../assets/fonts/inter/Inter-SemiBoldItalic.otf'),
|
||||
'Inter-Bold': require('../../assets/fonts/inter/Inter-Bold.otf'),
|
||||
'Inter-BoldItalic': require('../../assets/fonts/inter/Inter-BoldItalic.otf'),
|
||||
'Inter-ExtraBold': require('../../assets/fonts/inter/Inter-ExtraBold.otf'),
|
||||
'Inter-ExtraBoldItalic': require('../../assets/fonts/inter/Inter-ExtraBoldItalic.otf'),
|
||||
'Inter-Black': require('../../assets/fonts/inter/Inter-Black.otf'),
|
||||
'Inter-BlackItalic': require('../../assets/fonts/inter/Inter-BlackItalic.otf'),
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Unused fonts are commented out, but the files are there if we need them.
|
||||
*/
|
||||
export function applyFonts(
|
||||
style: Record<string, any>,
|
||||
fontFamily: 'system' | 'theme',
|
||||
) {
|
||||
if (fontFamily === 'theme') {
|
||||
style.fontFamily =
|
||||
{
|
||||
// '100': 'Inter-Thin',
|
||||
// '200': 'Inter-ExtraLight',
|
||||
// '300': 'Inter-Light',
|
||||
'100': 'Inter-Regular',
|
||||
'200': 'Inter-Regular',
|
||||
'300': 'Inter-Regular',
|
||||
'400': 'Inter-Regular',
|
||||
'500': 'Inter-Medium',
|
||||
'600': 'Inter-SemiBold',
|
||||
'700': 'Inter-Bold',
|
||||
'800': 'Inter-ExtraBold',
|
||||
'900': 'Inter-Black',
|
||||
}[style.fontWeight as string] || 'Inter-Regular'
|
||||
|
||||
if (style.fontStyle === 'italic') {
|
||||
if (style.fontFamily === 'Inter-Regular') {
|
||||
style.fontFamily = 'Inter-Italic'
|
||||
} else {
|
||||
style.fontFamily += 'Italic'
|
||||
}
|
||||
}
|
||||
|
||||
// fallback families only supported on web
|
||||
if (isWeb) {
|
||||
style.fontFamily += `, ${FAMILIES}`
|
||||
}
|
||||
} else {
|
||||
// fallback families only supported on web
|
||||
if (isWeb) {
|
||||
style.fontFamily = style.fontFamily || FAMILIES
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable contextual ligatures
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant}
|
||||
*/
|
||||
style.fontVariant = ['no-contextual']
|
||||
}
|
||||
@@ -1,25 +1,47 @@
|
||||
import React from 'react'
|
||||
import {useMediaQuery} from 'react-responsive'
|
||||
|
||||
import {
|
||||
computeFontScaleMultiplier,
|
||||
getFontFamily,
|
||||
getFontScale,
|
||||
setFontFamily as persistFontFamily,
|
||||
setFontScale as persistFontScale,
|
||||
} from '#/alf/fonts'
|
||||
import {createThemes, defaultTheme} from '#/alf/themes'
|
||||
import {Theme, ThemeName} from '#/alf/types'
|
||||
import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration'
|
||||
import {Device} from '#/storage'
|
||||
|
||||
export {atoms} from '#/alf/atoms'
|
||||
export * from '#/alf/fonts'
|
||||
export * as tokens from '#/alf/tokens'
|
||||
export * from '#/alf/types'
|
||||
export * from '#/alf/util/flatten'
|
||||
export * from '#/alf/util/platform'
|
||||
export * from '#/alf/util/themeSelector'
|
||||
|
||||
/*
|
||||
* Context
|
||||
*/
|
||||
export const Context = React.createContext<{
|
||||
export type Alf = {
|
||||
themeName: ThemeName
|
||||
theme: Theme
|
||||
themes: ReturnType<typeof createThemes>
|
||||
}>({
|
||||
fonts: {
|
||||
scale: Exclude<Device['fontScale'], undefined>
|
||||
scaleMultiplier: number
|
||||
family: Device['fontFamily']
|
||||
setFontScale: (fontScale: Exclude<Device['fontScale'], undefined>) => void
|
||||
setFontFamily: (fontFamily: Device['fontFamily']) => void
|
||||
}
|
||||
/**
|
||||
* Feature flags or other gated options
|
||||
*/
|
||||
flags: {}
|
||||
}
|
||||
|
||||
/*
|
||||
* Context
|
||||
*/
|
||||
export const Context = React.createContext<Alf>({
|
||||
themeName: 'light',
|
||||
theme: defaultTheme,
|
||||
themes: createThemes({
|
||||
@@ -29,12 +51,48 @@ export const Context = React.createContext<{
|
||||
positive: GREEN_HUE,
|
||||
},
|
||||
}),
|
||||
fonts: {
|
||||
scale: getFontScale(),
|
||||
scaleMultiplier: computeFontScaleMultiplier(getFontScale()),
|
||||
family: getFontFamily(),
|
||||
setFontScale: () => {},
|
||||
setFontFamily: () => {},
|
||||
},
|
||||
flags: {},
|
||||
})
|
||||
|
||||
export function ThemeProvider({
|
||||
children,
|
||||
theme: themeName,
|
||||
}: React.PropsWithChildren<{theme: ThemeName}>) {
|
||||
const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() =>
|
||||
getFontScale(),
|
||||
)
|
||||
const [fontScaleMultiplier, setFontScaleMultiplier] = React.useState(() =>
|
||||
computeFontScaleMultiplier(fontScale),
|
||||
)
|
||||
const setFontScaleAndPersist = React.useCallback<
|
||||
Alf['fonts']['setFontScale']
|
||||
>(
|
||||
fontScale => {
|
||||
setFontScale(fontScale)
|
||||
persistFontScale(fontScale)
|
||||
setFontScaleMultiplier(computeFontScaleMultiplier(fontScale))
|
||||
},
|
||||
[setFontScale],
|
||||
)
|
||||
const [fontFamily, setFontFamily] = React.useState<Alf['fonts']['family']>(
|
||||
() => getFontFamily(),
|
||||
)
|
||||
const setFontFamilyAndPersist = React.useCallback<
|
||||
Alf['fonts']['setFontFamily']
|
||||
>(
|
||||
fontFamily => {
|
||||
setFontFamily(fontFamily)
|
||||
persistFontFamily(fontFamily)
|
||||
},
|
||||
[setFontFamily],
|
||||
)
|
||||
const themes = React.useMemo(() => {
|
||||
return createThemes({
|
||||
hues: {
|
||||
@@ -44,28 +102,47 @@ export function ThemeProvider({
|
||||
},
|
||||
})
|
||||
}, [])
|
||||
const theme = themes[themeName]
|
||||
|
||||
return (
|
||||
<Context.Provider
|
||||
value={React.useMemo(
|
||||
value={React.useMemo<Alf>(
|
||||
() => ({
|
||||
themes,
|
||||
themeName: themeName,
|
||||
theme: theme,
|
||||
theme: themes[themeName],
|
||||
fonts: {
|
||||
scale: fontScale,
|
||||
scaleMultiplier: fontScaleMultiplier,
|
||||
family: fontFamily,
|
||||
setFontScale: setFontScaleAndPersist,
|
||||
setFontFamily: setFontFamilyAndPersist,
|
||||
},
|
||||
flags: {},
|
||||
}),
|
||||
[theme, themeName, themes],
|
||||
[
|
||||
themeName,
|
||||
themes,
|
||||
fontScale,
|
||||
setFontScaleAndPersist,
|
||||
fontFamily,
|
||||
setFontFamilyAndPersist,
|
||||
fontScaleMultiplier,
|
||||
],
|
||||
)}>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useAlf() {
|
||||
return React.useContext(Context)
|
||||
}
|
||||
|
||||
export function useTheme(theme?: ThemeName) {
|
||||
const ctx = React.useContext(Context)
|
||||
const alf = useAlf()
|
||||
return React.useMemo(() => {
|
||||
return theme ? ctx.themes[theme] : ctx.theme
|
||||
}, [theme, ctx])
|
||||
return theme ? alf.themes[theme] : alf.theme
|
||||
}, [theme, alf])
|
||||
}
|
||||
|
||||
export function useBreakpoints() {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import {Platform} from 'react-native'
|
||||
|
||||
export const TRACKING = Platform.OS === 'android' ? 0.1 : 0
|
||||
|
||||
export const color = {
|
||||
temp_purple: 'rgb(105 0 255)',
|
||||
temp_purple_dark: 'rgb(83 0 202)',
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
PressableProps,
|
||||
StyleProp,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextProps,
|
||||
TextStyle,
|
||||
View,
|
||||
@@ -17,7 +16,7 @@ import {LinearGradient} from 'expo-linear-gradient'
|
||||
|
||||
import {android, atoms as a, flatten, select, tokens, useTheme} from '#/alf'
|
||||
import {Props as SVGIconProps} from '#/components/icons/common'
|
||||
import {normalizeTextStyles} from '#/components/Typography'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'gradient'
|
||||
export type ButtonColor =
|
||||
@@ -635,14 +634,7 @@ export function ButtonText({children, style, ...rest}: ButtonTextProps) {
|
||||
const textStyles = useSharedButtonTextStyles()
|
||||
|
||||
return (
|
||||
<Text
|
||||
{...rest}
|
||||
style={normalizeTextStyles([
|
||||
a.font_bold,
|
||||
a.text_center,
|
||||
textStyles,
|
||||
style,
|
||||
])}>
|
||||
<Text {...rest} style={[a.font_bold, a.text_center, textStyles, style]}>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -37,6 +37,7 @@ import {Portal} from '#/components/Portal'
|
||||
|
||||
export {useDialogContext, useDialogControl} from '#/components/Dialog/context'
|
||||
export * from '#/components/Dialog/types'
|
||||
export * from '#/components/Dialog/utils'
|
||||
// @ts-ignore
|
||||
export const Input = createInput(BottomSheetTextInput)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import {Portal} from '#/components/Portal'
|
||||
|
||||
export {useDialogContext, useDialogControl} from '#/components/Dialog/context'
|
||||
export * from '#/components/Dialog/types'
|
||||
export * from '#/components/Dialog/utils'
|
||||
export {Input} from '#/components/forms/TextField'
|
||||
|
||||
const stopPropagation = (e: any) => e.stopPropagation()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
|
||||
import {DialogControlProps} from '#/components/Dialog/types'
|
||||
|
||||
export function useAutoOpen(control: DialogControlProps, showTimeout?: number) {
|
||||
React.useEffect(() => {
|
||||
if (showTimeout) {
|
||||
const timeout = setTimeout(() => {
|
||||
control.open()
|
||||
}, showTimeout)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
} else {
|
||||
control.open()
|
||||
}
|
||||
}, [control, showTimeout])
|
||||
}
|
||||
@@ -179,8 +179,10 @@ export function Outer({
|
||||
style={[
|
||||
a.rounded_sm,
|
||||
a.p_xs,
|
||||
a.border,
|
||||
t.name === 'light' ? t.atoms.bg : t.atoms.bg_contrast_25,
|
||||
t.atoms.shadow_md,
|
||||
t.atoms.border_contrast_low,
|
||||
style,
|
||||
]}>
|
||||
{children}
|
||||
|
||||
@@ -3,7 +3,7 @@ import {StyleProp, TextProps as RNTextProps, TextStyle} from 'react-native'
|
||||
import {UITextView} from 'react-native-uitextview'
|
||||
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {atoms, flatten, useTheme, web} from '#/alf'
|
||||
import {Alf, applyFonts, atoms, flatten, useAlf, useTheme, web} from '#/alf'
|
||||
|
||||
export type TextProps = RNTextProps & {
|
||||
/**
|
||||
@@ -34,19 +34,30 @@ export function leading<
|
||||
* If the `lineHeight` value is > 2, we assume it's an absolute value and
|
||||
* returns it as-is.
|
||||
*/
|
||||
export function normalizeTextStyles(styles: StyleProp<TextStyle>) {
|
||||
export function normalizeTextStyles(
|
||||
styles: StyleProp<TextStyle>,
|
||||
{
|
||||
fontScale,
|
||||
fontFamily,
|
||||
}: {
|
||||
fontScale: number
|
||||
fontFamily: Alf['fonts']['family']
|
||||
} & Pick<Alf, 'flags'>,
|
||||
) {
|
||||
const s = flatten(styles)
|
||||
// should always be defined on these components
|
||||
const fontSize = s.fontSize || atoms.text_md.fontSize
|
||||
s.fontSize = (s.fontSize || atoms.text_md.fontSize) * fontScale
|
||||
|
||||
if (s?.lineHeight) {
|
||||
if (s.lineHeight !== 0 && s.lineHeight <= 2) {
|
||||
s.lineHeight = Math.round(fontSize * s.lineHeight)
|
||||
s.lineHeight = Math.round(s.fontSize * s.lineHeight)
|
||||
}
|
||||
} else if (!isNative) {
|
||||
s.lineHeight = s.fontSize
|
||||
}
|
||||
|
||||
applyFonts(s, fontFamily)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -54,8 +65,13 @@ export function normalizeTextStyles(styles: StyleProp<TextStyle>) {
|
||||
* Our main text component. Use this most of the time.
|
||||
*/
|
||||
export function Text({style, selectable, ...rest}: TextProps) {
|
||||
const {fonts, flags} = useAlf()
|
||||
const t = useTheme()
|
||||
const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, flatten(style)])
|
||||
const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, flatten(style)], {
|
||||
fontScale: fonts.scaleMultiplier,
|
||||
fontFamily: fonts.family,
|
||||
flags,
|
||||
})
|
||||
|
||||
return <UITextView selectable={selectable} uiTextView style={s} {...rest} />
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {AppearanceToggleButtonGroup} from '#/screens/Settings/AppearanceSettings'
|
||||
import {atoms as a, useAlf, useTheme} from '#/alf'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
|
||||
import {Divider} from '#/components/Divider'
|
||||
import {TextSize_Stroke2_Corner0_Rounded as TextSize} from '#/components/icons/TextSize'
|
||||
import {TitleCase_Stroke2_Corner0_Rounded as Aa} from '#/components/icons/TitleCase'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function NeueTypography() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const nuxDialogs = useNuxDialogContext()
|
||||
const control = Dialog.useDialogControl()
|
||||
const {fonts} = useAlf()
|
||||
|
||||
Dialog.useAutoOpen(control, 3e3)
|
||||
|
||||
const onClose = React.useCallback(() => {
|
||||
nuxDialogs.dismissActiveNux()
|
||||
}, [nuxDialogs])
|
||||
|
||||
const onChangeFontFamily = React.useCallback(
|
||||
(values: string[]) => {
|
||||
const next = values[0] === 'system' ? 'system' : 'theme'
|
||||
fonts.setFontFamily(next)
|
||||
},
|
||||
[fonts],
|
||||
)
|
||||
|
||||
const onChangeFontScale = React.useCallback(
|
||||
(values: string[]) => {
|
||||
const next = values[0] || ('0' as any)
|
||||
fonts.setFontScale(next)
|
||||
},
|
||||
[fonts],
|
||||
)
|
||||
|
||||
return (
|
||||
<Dialog.Outer control={control} onClose={onClose}>
|
||||
<Dialog.Handle />
|
||||
|
||||
<Dialog.ScrollableInner label={_(msg`Introducing new font settings`)}>
|
||||
<View style={[a.gap_xl]}>
|
||||
<View style={[a.gap_md]}>
|
||||
<Text style={[a.text_3xl, {fontWeight: '900'}]}>
|
||||
<Trans>New font settings ✨</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_lg, a.leading_snug, {maxWidth: 400}]}>
|
||||
<Trans>
|
||||
We're introducing a new theme font, along with adjustable font
|
||||
sizing.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text
|
||||
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||
<Trans>
|
||||
You can adjust these in your Appearance Settings later.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Divider />
|
||||
|
||||
<View style={[a.gap_lg]}>
|
||||
<AppearanceToggleButtonGroup
|
||||
title={_(msg`Font`)}
|
||||
description={_(
|
||||
msg`For the best experience, we recommend using the theme font.`,
|
||||
)}
|
||||
icon={Aa}
|
||||
items={[
|
||||
{
|
||||
label: _(msg`System`),
|
||||
name: 'system',
|
||||
},
|
||||
{
|
||||
label: _(msg`Theme`),
|
||||
name: 'theme',
|
||||
},
|
||||
]}
|
||||
values={[fonts.family]}
|
||||
onChange={onChangeFontFamily}
|
||||
/>
|
||||
|
||||
<AppearanceToggleButtonGroup
|
||||
title={_(msg`Font size`)}
|
||||
icon={TextSize}
|
||||
items={[
|
||||
{
|
||||
label: _(msg`Smaller`),
|
||||
name: '-1',
|
||||
},
|
||||
{
|
||||
label: _(msg`Default`),
|
||||
name: '0',
|
||||
},
|
||||
{
|
||||
label: _(msg`Larger`),
|
||||
name: '1',
|
||||
},
|
||||
]}
|
||||
values={[fonts.scale]}
|
||||
onChange={onChangeFontScale}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
</Dialog.Outer>
|
||||
)
|
||||
}
|
||||
@@ -197,6 +197,27 @@ export function TenMillionInner({
|
||||
const isLoadingData = isProfileLoading || !moderation || !profile
|
||||
const isLoadingImage = !uri
|
||||
|
||||
const displayName = React.useMemo(() => {
|
||||
if (!profile || !moderation) return ''
|
||||
return sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
)
|
||||
}, [profile, moderation])
|
||||
const handle = React.useMemo(() => {
|
||||
if (!profile) return ''
|
||||
return sanitizeHandle(profile.handle, '@')
|
||||
}, [profile])
|
||||
const joinedDate = React.useMemo(() => {
|
||||
if (!profile || !profile.createdAt) return ''
|
||||
const date = i18n.date(profile.createdAt, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})
|
||||
return date
|
||||
}, [i18n, profile])
|
||||
|
||||
const error: string = React.useMemo(() => {
|
||||
if (profileError) {
|
||||
return _(
|
||||
@@ -235,19 +256,34 @@ export function TenMillionInner({
|
||||
msg`Bluesky now has over 10 million users, and I was #${i18n.number(
|
||||
userNumber,
|
||||
)}!`,
|
||||
), // TODO
|
||||
),
|
||||
imageUris: [
|
||||
{
|
||||
uri,
|
||||
width: WIDTH,
|
||||
height: HEIGHT,
|
||||
altText: _(
|
||||
msg`A virtual certificate with text "Celebrating 10M users on Bluesky, #${i18n.number(
|
||||
userNumber,
|
||||
)}, ${displayName} ${handle}, joined on ${joinedDate}"`,
|
||||
),
|
||||
},
|
||||
],
|
||||
})
|
||||
}, 1e3)
|
||||
})
|
||||
}
|
||||
}, [_, i18n, control, openComposer, uri, userNumber])
|
||||
}, [
|
||||
_,
|
||||
i18n,
|
||||
control,
|
||||
openComposer,
|
||||
uri,
|
||||
userNumber,
|
||||
displayName,
|
||||
handle,
|
||||
joinedDate,
|
||||
])
|
||||
const onNativeShare = React.useCallback(() => {
|
||||
if (uri) {
|
||||
control.close(() => {
|
||||
@@ -490,11 +526,7 @@ export function TenMillionInner({
|
||||
a.leading_tight,
|
||||
{maxWidth: '60%'},
|
||||
]}>
|
||||
{sanitizeDisplayName(
|
||||
profile.displayName ||
|
||||
sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
)}
|
||||
{displayName}
|
||||
</Text>
|
||||
<View
|
||||
style={[a.flex_row, a.justify_between, a.gap_4xl]}>
|
||||
@@ -508,7 +540,7 @@ export function TenMillionInner({
|
||||
a.leading_snug,
|
||||
lightTheme.atoms.text_contrast_medium,
|
||||
]}>
|
||||
{sanitizeHandle(profile.handle, '@')}
|
||||
{handle}
|
||||
</Text>
|
||||
|
||||
{profile.createdAt && (
|
||||
@@ -524,14 +556,7 @@ export function TenMillionInner({
|
||||
a.text_right,
|
||||
lightTheme.atoms.text_contrast_low,
|
||||
]}>
|
||||
<Trans>
|
||||
Joined{' '}
|
||||
{i18n.date(profile.createdAt, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</Trans>
|
||||
<Trans>Joined on {joinedDate}</Trans>
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react'
|
||||
import {AppBskyActorDefs} from '@atproto/api'
|
||||
|
||||
import {useGate} from '#/lib/statsig/statsig'
|
||||
import {logger} from '#/logger'
|
||||
@@ -8,9 +9,16 @@ import {
|
||||
useRemoveNuxsMutation,
|
||||
useUpsertNuxMutation,
|
||||
} from '#/state/queries/nuxs'
|
||||
import {useSession} from '#/state/session'
|
||||
import {
|
||||
usePreferencesQuery,
|
||||
UsePreferencesQueryResponse,
|
||||
} from '#/state/queries/preferences'
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {SessionAccount, useSession} from '#/state/session'
|
||||
import {useOnboardingState} from '#/state/shell'
|
||||
import {NeueTypography} from '#/components/dialogs/nuxs/NeueTypography'
|
||||
import {isSnoozed, snooze, unsnooze} from '#/components/dialogs/nuxs/snoozing'
|
||||
// NUXs
|
||||
import {TenMillion} from '#/components/dialogs/nuxs/TenMillion'
|
||||
import {IS_DEV} from '#/env'
|
||||
|
||||
@@ -21,11 +29,27 @@ type Context = {
|
||||
|
||||
const queuedNuxs: {
|
||||
id: Nux
|
||||
enabled?: (props: {gate: ReturnType<typeof useGate>}) => boolean
|
||||
enabled?: (props: {
|
||||
gate: ReturnType<typeof useGate>
|
||||
currentAccount: SessionAccount
|
||||
currentProfile: AppBskyActorDefs.ProfileViewDetailed
|
||||
preferences: UsePreferencesQueryResponse
|
||||
}) => boolean
|
||||
}[] = [
|
||||
{
|
||||
id: Nux.TenMillionDialog,
|
||||
},
|
||||
{
|
||||
id: Nux.NeueTypography,
|
||||
enabled(props) {
|
||||
if (props.currentProfile.createdAt) {
|
||||
if (new Date(props.currentProfile.createdAt) < new Date('2024-09-25')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const Context = React.createContext<Context>({
|
||||
@@ -38,12 +62,31 @@ export function useNuxDialogContext() {
|
||||
}
|
||||
|
||||
export function NuxDialogs() {
|
||||
const {hasSession} = useSession()
|
||||
const onboardingState = useOnboardingState()
|
||||
return hasSession && !onboardingState.isActive ? <Inner /> : null
|
||||
const {currentAccount} = useSession()
|
||||
const {data: preferences} = usePreferencesQuery()
|
||||
const {data: profile} = useProfileQuery({did: currentAccount?.did})
|
||||
const onboardingActive = useOnboardingState().isActive
|
||||
|
||||
const isLoading =
|
||||
!currentAccount || !preferences || !profile || onboardingActive
|
||||
return !isLoading ? (
|
||||
<Inner
|
||||
currentAccount={currentAccount}
|
||||
currentProfile={profile}
|
||||
preferences={preferences}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
|
||||
function Inner() {
|
||||
function Inner({
|
||||
currentAccount,
|
||||
currentProfile,
|
||||
preferences,
|
||||
}: {
|
||||
currentAccount: SessionAccount
|
||||
currentProfile: AppBskyActorDefs.ProfileViewDetailed
|
||||
preferences: UsePreferencesQueryResponse
|
||||
}) {
|
||||
const gate = useGate()
|
||||
const {nuxs} = useNuxs()
|
||||
const [snoozed, setSnoozed] = React.useState(() => {
|
||||
@@ -80,10 +123,19 @@ function Inner() {
|
||||
const nux = nuxs.find(nux => nux.id === id)
|
||||
|
||||
// check if completed first
|
||||
if (nux && nux.completed) continue
|
||||
if (nux && nux.completed) {
|
||||
continue
|
||||
}
|
||||
|
||||
// then check gate (track exposure)
|
||||
if (enabled && !enabled({gate})) continue
|
||||
if (
|
||||
enabled &&
|
||||
!enabled({gate, currentAccount, currentProfile, preferences})
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.debug(`NUX dialogs: activating '${id}' NUX`)
|
||||
|
||||
// we have a winner
|
||||
setActiveNux(id)
|
||||
@@ -104,7 +156,16 @@ function Inner() {
|
||||
|
||||
break
|
||||
}
|
||||
}, [nuxs, snoozed, snoozeNuxDialog, upsertNux, gate])
|
||||
}, [
|
||||
nuxs,
|
||||
snoozed,
|
||||
snoozeNuxDialog,
|
||||
upsertNux,
|
||||
gate,
|
||||
currentAccount,
|
||||
currentProfile,
|
||||
preferences,
|
||||
])
|
||||
|
||||
const ctx = React.useMemo(() => {
|
||||
return {
|
||||
@@ -116,6 +177,7 @@ function Inner() {
|
||||
return (
|
||||
<Context.Provider value={ctx}>
|
||||
{activeNux === Nux.TenMillionDialog && <TenMillion />}
|
||||
{activeNux === Nux.NeueTypography && <NeueTypography />}
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -351,8 +351,8 @@ export function Checkbox() {
|
||||
t.atoms.border_contrast_high,
|
||||
{
|
||||
borderWidth: 1,
|
||||
height: 20,
|
||||
width: 20,
|
||||
height: 24,
|
||||
width: 24,
|
||||
},
|
||||
baseStyles,
|
||||
hovered ? baseHoverStyles : {},
|
||||
@@ -383,9 +383,9 @@ export function Switch() {
|
||||
t.atoms.border_contrast_high,
|
||||
{
|
||||
borderWidth: 1,
|
||||
height: 20,
|
||||
width: 32,
|
||||
padding: 2,
|
||||
height: 24,
|
||||
width: 36,
|
||||
padding: 3,
|
||||
},
|
||||
baseStyles,
|
||||
hovered ? baseHoverStyles : {},
|
||||
@@ -395,8 +395,8 @@ export function Switch() {
|
||||
style={[
|
||||
a.rounded_full,
|
||||
{
|
||||
height: 14,
|
||||
width: 14,
|
||||
height: 16,
|
||||
width: 16,
|
||||
},
|
||||
selected
|
||||
? {
|
||||
@@ -436,8 +436,8 @@ export function Radio() {
|
||||
t.atoms.border_contrast_high,
|
||||
{
|
||||
borderWidth: 1,
|
||||
height: 20,
|
||||
width: 20,
|
||||
height: 24,
|
||||
width: 24,
|
||||
},
|
||||
baseStyles,
|
||||
hovered ? baseHoverStyles : {},
|
||||
@@ -447,7 +447,7 @@ export function Radio() {
|
||||
style={[
|
||||
a.absolute,
|
||||
a.rounded_full,
|
||||
{height: 12, width: 12},
|
||||
{height: 16, width: 16},
|
||||
selected
|
||||
? {
|
||||
backgroundColor: t.palette.primary_500,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import {createSinglePathSVG} from './TEMPLATE'
|
||||
|
||||
export const AspectRatio11_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M3 4a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4Zm2 1v14h14V5H5Z',
|
||||
})
|
||||
|
||||
export const AspectRatio43_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M2 20.5c-.552 0-1-.41-1-.917V4.917C1 4.41 1.448 4 2 4h20c.552 0 1 .41 1 .917v14.666c0 .507-.448.917-1 .917H2Zm1-1.833h18V5.833H3v12.834Z',
|
||||
})
|
||||
|
||||
export const AspectRatio34_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M4 2c0-.552.41-1 .917-1h14.666c.507 0 .917.448.917 1v20c0 .552-.41 1-.917 1H4.917C4.41 23 4 22.552 4 22V2Zm1.833 1v18h12.834V3H5.833Z',
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
import {createSinglePathSVG} from './TEMPLATE'
|
||||
|
||||
export const FlipVertical_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M3 4a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5h-2V5H5v4H3V4Zm20 9H1v-2h22v2Zm-2.293 7.707A1 1 0 0 1 20 21h-1v-2h2v1a1 1 0 0 1-.293.707ZM17 19v2h-2v-2h2Zm-4 0v2h-2v-2h2Zm-4 0v2H7v-2h2Zm-4 0v2H4a1 1 0 0 1-1-1v-1h2Zm0-2H3v-2h2v2Zm14-2v2h2v-2h-2Z',
|
||||
})
|
||||
|
||||
export const FlipHorizontal_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M4 21a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5v2H5v14h4v2H4Zm9-20v22h-2V1h2Zm7.707 2.293A1 1 0 0 1 21 4v1h-2V3h1a1 1 0 0 1 .707.293ZM19 7h2v2h-2V7Zm0 4h2v2h-2v-2Zm0 4h2v2h-2v-2Zm0 4h2v1a1 1 0 0 1-1 1h-1v-2Zm-2 0v2h-2v-2h2ZM15 5h2V3h-2v2Z',
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
import {createSinglePathSVG} from './TEMPLATE'
|
||||
|
||||
export const TextSize_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M9 5a1 1 0 0 1 1-1h12a1 1 0 1 1 0 2h-5v14a1 1 0 1 1-2 0V6h-5a1 1 0 0 1-1-1Zm-3.073 7v8a1 1 0 1 0 2 0v-8H12a1 1 0 1 0 0-2H6.971a1.015 1.015 0 0 0-.089 0H2a1 1 0 1 0 0 2h3.927Z',
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
import {createSinglePathSVG} from './TEMPLATE'
|
||||
|
||||
export const TitleCase_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||
path: 'M3.65 17.247c-.242.832-.632 1.178-1.325 1.178-.814 0-1.325-.476-1.325-1.23 0-.216.06-.51.173-.831L4.586 7.07c.364-1.014.979-1.482 1.966-1.482 1.022 0 1.629.45 2.001 1.473l3.43 9.303c.121.337.165.571.165.831 0 .72-.546 1.23-1.308 1.23-.736 0-1.126-.338-1.36-1.152l-.658-1.975H4.309l-.658 1.95ZM6.5 8.152l-1.62 5.12h3.335l-1.654-5.12H6.5Zm13.005 8.688c-.52.988-1.68 1.568-2.84 1.568-1.768 0-3.11-1.144-3.11-2.815 0-1.69 1.299-2.668 3.62-2.807l2.34-.138v-.615c0-.867-.607-1.369-1.56-1.369-.771 0-1.239.251-1.802.979-.277.312-.597.468-1.004.468-.615 0-1.057-.399-1.057-.97 0-.2.043-.382.13-.572.433-1.109 1.923-1.793 3.845-1.793 2.383 0 3.933 1.23 3.933 3.1v5.293c0 .84-.511 1.273-1.23 1.273-.684 0-1.16-.38-1.213-1.126v-.476h-.052Zm-3.43-1.386c0 .693.572 1.126 1.42 1.126 1.11 0 2.02-.719 2.02-1.723v-.676l-1.959.121c-.944.07-1.48.494-1.48 1.152Z',
|
||||
})
|
||||
@@ -2,12 +2,12 @@ import React from 'react'
|
||||
import {AppState, AppStateStatus} from 'react-native'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import {createClient, SegmentClient} from '@segment/analytics-react-native'
|
||||
import * as Sentry from '@sentry/react-native'
|
||||
import {sha256} from 'js-sha256'
|
||||
import {Native} from 'sentry-expo'
|
||||
|
||||
import {useSession, SessionAccount} from '#/state/session'
|
||||
import {ScreenPropertiesMap, TrackPropertiesMap} from './types'
|
||||
import {logger} from '#/logger'
|
||||
import {SessionAccount, useSession} from '#/state/session'
|
||||
import {ScreenPropertiesMap, TrackPropertiesMap} from './types'
|
||||
|
||||
type AppInfo = {
|
||||
build?: string | undefined
|
||||
@@ -72,7 +72,7 @@ export function init(account: SessionAccount | undefined) {
|
||||
if (account.did) {
|
||||
const did_hashed = sha256(account.did)
|
||||
client.identify(did_hashed, {did_hashed})
|
||||
Native.setUser({id: did_hashed})
|
||||
Sentry.setUser({id: did_hashed})
|
||||
logger.debug('Ping w/hash')
|
||||
} else {
|
||||
logger.debug('Ping w/o hash')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react'
|
||||
import {createClient} from '@segment/analytics-react'
|
||||
import * as Sentry from '@sentry/react-native'
|
||||
import {sha256} from 'js-sha256'
|
||||
import {Browser} from 'sentry-expo'
|
||||
|
||||
import {ScreenPropertiesMap, TrackPropertiesMap} from './types'
|
||||
import {useSession, SessionAccount} from '#/state/session'
|
||||
import {logger} from '#/logger'
|
||||
import {SessionAccount, useSession} from '#/state/session'
|
||||
import {ScreenPropertiesMap, TrackPropertiesMap} from './types'
|
||||
|
||||
type SegmentClient = ReturnType<typeof createClient>
|
||||
|
||||
@@ -70,7 +70,7 @@ export function init(account: SessionAccount | undefined) {
|
||||
if (account.did) {
|
||||
const did_hashed = sha256(account.did)
|
||||
client.identify(did_hashed, {did_hashed})
|
||||
Browser.setUser({id: did_hashed})
|
||||
Sentry.setUser({id: did_hashed})
|
||||
logger.debug('Ping w/hash')
|
||||
} else {
|
||||
logger.debug('Ping w/o hash')
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '#/components/icons/Heart2'
|
||||
|
||||
const animationConfig = {
|
||||
duration: 400,
|
||||
duration: 600,
|
||||
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
fill: 'forwards' as FillMode,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
AppBskyFeedDefs,
|
||||
AppBskyEmbedRecord,
|
||||
AppBskyEmbedRecordWithMedia,
|
||||
AppBskyFeedDefs,
|
||||
} from '@atproto/api'
|
||||
|
||||
export function isEmbedByEmbedder(
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import {Platform} from 'react-native'
|
||||
import {nativeApplicationVersion, nativeBuildVersion} from 'expo-application'
|
||||
import {init} from 'sentry-expo'
|
||||
import {init} from '@sentry/react-native'
|
||||
|
||||
import {BUILD_ENV, IS_DEV, IS_TESTFLIGHT} from 'lib/app-info'
|
||||
|
||||
@@ -30,10 +30,10 @@ const dist = `${Platform.OS}.${nativeBuildVersion}.${
|
||||
}${IS_DEV ? 'dev' : ''}`
|
||||
|
||||
init({
|
||||
enabled: !__DEV__,
|
||||
autoSessionTracking: false,
|
||||
dsn: 'https://05bc3789bf994b81bd7ce20c86ccd3ae@o4505071687041024.ingest.sentry.io/4505071690514432',
|
||||
debug: false, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production
|
||||
enableInExpoDevelopment: false, // enable this to test in dev
|
||||
environment: BUILD_ENV ?? 'development',
|
||||
dist,
|
||||
release,
|
||||
|
||||
@@ -79,13 +79,13 @@ export const s = StyleSheet.create({
|
||||
|
||||
// font weights
|
||||
fw600: {fontWeight: '600'},
|
||||
bold: {fontWeight: 'bold'},
|
||||
bold: {fontWeight: '700'},
|
||||
fw500: {fontWeight: '500'},
|
||||
semiBold: {fontWeight: '500'},
|
||||
fw400: {fontWeight: '400'},
|
||||
normal: {fontWeight: '400'},
|
||||
fw300: {fontWeight: '300'},
|
||||
light: {fontWeight: '300'},
|
||||
fw300: {fontWeight: '400'},
|
||||
light: {fontWeight: '400'},
|
||||
fw200: {fontWeight: '200'},
|
||||
|
||||
// text decoration
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {Platform} from 'react-native'
|
||||
|
||||
import {tokens} from '#/alf'
|
||||
import {darkPalette, dimPalette, lightPalette} from '#/alf/themes'
|
||||
import {colors} from './styles'
|
||||
import type {Theme} from './ThemeContext'
|
||||
@@ -88,163 +89,163 @@ export const defaultTheme: Theme = {
|
||||
typography: {
|
||||
'2xl-thin': {
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.25,
|
||||
fontWeight: '300',
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'2xl': {
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'2xl-medium': {
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'2xl-bold': {
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '700',
|
||||
},
|
||||
'2xl-heavy': {
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '800',
|
||||
},
|
||||
'xl-thin': {
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.25,
|
||||
fontWeight: '300',
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
xl: {
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'xl-medium': {
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'xl-bold': {
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '700',
|
||||
},
|
||||
'xl-heavy': {
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '800',
|
||||
},
|
||||
'lg-thin': {
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.25,
|
||||
fontWeight: '300',
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
lg: {
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'lg-medium': {
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'lg-bold': {
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '700',
|
||||
},
|
||||
'lg-heavy': {
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '800',
|
||||
},
|
||||
'md-thin': {
|
||||
fontSize: 15,
|
||||
letterSpacing: 0.25,
|
||||
fontWeight: '300',
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
md: {
|
||||
fontSize: 15,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'md-medium': {
|
||||
fontSize: 15,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'md-bold': {
|
||||
fontSize: 15,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '700',
|
||||
},
|
||||
'md-heavy': {
|
||||
fontSize: 15,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '800',
|
||||
},
|
||||
'sm-thin': {
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.25,
|
||||
fontWeight: '300',
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
sm: {
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'sm-medium': {
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'sm-bold': {
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '700',
|
||||
},
|
||||
'sm-heavy': {
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '800',
|
||||
},
|
||||
'xs-thin': {
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.25,
|
||||
fontWeight: '300',
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
xs: {
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'xs-medium': {
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'xs-bold': {
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '700',
|
||||
},
|
||||
'xs-heavy': {
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '800',
|
||||
},
|
||||
|
||||
'title-2xl': {
|
||||
fontSize: 34,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'title-xl': {
|
||||
fontSize: 28,
|
||||
letterSpacing: 0.25,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '500',
|
||||
},
|
||||
'title-lg': {
|
||||
@@ -254,32 +255,32 @@ export const defaultTheme: Theme = {
|
||||
title: {
|
||||
fontWeight: '500',
|
||||
fontSize: 20,
|
||||
letterSpacing: 0.15,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
'title-sm': {
|
||||
fontWeight: 'bold',
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.15,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
'post-text': {
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.2,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'post-text-lg': {
|
||||
fontSize: 20,
|
||||
letterSpacing: 0.2,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
fontWeight: '400',
|
||||
},
|
||||
'button-lg': {
|
||||
fontWeight: '500',
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.5,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
button: {
|
||||
fontWeight: '500',
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.5,
|
||||
letterSpacing: tokens.TRACKING,
|
||||
},
|
||||
mono: {
|
||||
fontSize: 14,
|
||||
|
||||
@@ -75,7 +75,7 @@ msgstr "{0, plural, one {# segon} other {# segons}}"
|
||||
|
||||
#: src/components/KnownFollowers.tsx:179
|
||||
#~ msgid "{0, plural, one {and # other} other {and # others}}"
|
||||
#~ msgstr "{0, plural, one {i # altre} other {i # altres}"
|
||||
#~ msgstr "{0, plural, one {i # altre} other {i # altres}}"
|
||||
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:398
|
||||
#: src/screens/Profile/Header/Metrics.tsx:23
|
||||
|
||||
@@ -127,7 +127,7 @@ msgstr "{0} <0>em <1>texto e tags</1></0>"
|
||||
msgid "{0} joined this week"
|
||||
msgstr "{0} entrou esta semana"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:637
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/Scrubber.tsx:195
|
||||
msgid "{0} of {1}"
|
||||
msgstr "{0} de {1}"
|
||||
|
||||
@@ -343,12 +343,16 @@ msgstr "7 dias"
|
||||
#~ msgid "A help tooltip"
|
||||
#~ msgstr "Uma sugestão de ajuda"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:266
|
||||
msgid "A virtual certificate with text \"Celebrating 10M users on Bluesky, #{0}, {displayName} {handle}, joined on {joinedDate}\""
|
||||
msgstr "Um certificado virtual com o texto \"Comemorando 10 milhões de usuários no Bluesky, #{0}, {displayName} {handle}, ingressou em {joinedDate}\""
|
||||
|
||||
#: src/view/com/util/ViewHeader.tsx:92
|
||||
#: src/view/screens/Search/Search.tsx:684
|
||||
msgid "Access navigation links and settings"
|
||||
msgstr "Acessar links de navegação e configurações"
|
||||
|
||||
#: src/view/com/home/HomeHeaderLayoutMobile.tsx:56
|
||||
#: src/view/com/home/HomeHeaderLayoutMobile.tsx:103
|
||||
msgid "Access profile and other navigation links"
|
||||
msgstr "Acessar perfil e outros links de navegação"
|
||||
|
||||
@@ -640,7 +644,7 @@ msgstr "Ocorreu um erro"
|
||||
#~ msgid "An error occured"
|
||||
#~ msgstr "Tivemos um problema"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:413
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:416
|
||||
msgid "An error occurred"
|
||||
msgstr "Ocorreu um erro"
|
||||
|
||||
@@ -660,7 +664,7 @@ msgstr "Ocorreu um erro ao carregar o vídeo. Tente novamente mais tarde."
|
||||
msgid "An error occurred while loading the video. Please try again."
|
||||
msgstr "Ocorreu um erro ao carregar o vídeo. Tente novamente."
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:250
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:315
|
||||
msgid "An error occurred while saving the image!"
|
||||
msgstr "Ocorreu um erro ao salvar a imagem!"
|
||||
|
||||
@@ -990,6 +994,11 @@ msgstr "Bluesky é uma rede aberta que permite a escolha do seu provedor de hosp
|
||||
msgid "Bluesky is better with friends!"
|
||||
msgstr "Bluesky é melhor com amigos!"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/Trigger.tsx:43
|
||||
#: src/components/dialogs/nuxs/TenMillion/Trigger.tsx:59
|
||||
msgid "Bluesky is celebrating 10 million users!"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/onboarding/WelcomeDesktop.tsx:80
|
||||
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:82
|
||||
#~ msgid "Bluesky is flexible."
|
||||
@@ -1005,9 +1014,9 @@ msgstr "Bluesky é melhor com amigos!"
|
||||
#~ msgid "Bluesky is public."
|
||||
#~ msgstr "Bluesky é público."
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:206
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:256
|
||||
msgid "Bluesky now has over 10 million users, and I was #{0}!"
|
||||
msgstr "O Bluesky agora tem mais de 10 milhões de usuários, e eu tinha #{0}!"
|
||||
msgstr "O Bluesky agora tem mais de 10 milhões de usuários, e eu fui o #{0}!"
|
||||
|
||||
#: src/components/StarterPack/ProfileStarterPacks.tsx:282
|
||||
msgid "Bluesky will choose a set of recommended accounts from people in your network."
|
||||
@@ -1030,7 +1039,7 @@ msgstr "Desfocar imagens e filtrar dos feeds"
|
||||
msgid "Books"
|
||||
msgstr "Livros"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:614
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:677
|
||||
msgid "Brag a little!"
|
||||
msgstr "Gabe-se um pouco!"
|
||||
|
||||
@@ -1100,8 +1109,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must
|
||||
msgstr "Só pode conter letras, números, espaços, riscas e subtraços. Deve ter pelo menos 4 caracteres, mas não mais de 32 caracteres."
|
||||
|
||||
#: src/components/Menu/index.tsx:235
|
||||
#: src/components/Prompt.tsx:122
|
||||
#: src/components/Prompt.tsx:124
|
||||
#: src/components/Prompt.tsx:126
|
||||
#: src/components/TagMenu/index.tsx:282
|
||||
#: src/screens/Deactivated.tsx:161
|
||||
#: src/view/com/composer/Composer.tsx:594
|
||||
@@ -1181,7 +1190,7 @@ msgstr "Legendas (.vtt)"
|
||||
msgid "Captions & alt text"
|
||||
msgstr "Legendas e texto alt"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:368
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:434
|
||||
msgid "Celebrating {0} users"
|
||||
msgstr "Comemorando {0} usuários"
|
||||
|
||||
@@ -1532,8 +1541,8 @@ msgstr "Configure o filtro de conteúdo por categoria: {name}"
|
||||
msgid "Configured in <0>moderation settings</0>."
|
||||
msgstr "Configure no <0>painel de moderação</0>."
|
||||
|
||||
#: src/components/Prompt.tsx:165
|
||||
#: src/components/Prompt.tsx:168
|
||||
#: src/components/Prompt.tsx:167
|
||||
#: src/components/Prompt.tsx:170
|
||||
#: src/view/com/modals/SelfLabel.tsx:155
|
||||
#: src/view/com/modals/VerifyEmail.tsx:239
|
||||
#: src/view/com/modals/VerifyEmail.tsx:241
|
||||
@@ -2050,7 +2059,7 @@ msgstr "Desabilitar feedback tátil"
|
||||
#~ msgid "Disable haptics"
|
||||
#~ msgstr "Desabilitar feedback tátil"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:379
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:382
|
||||
msgid "Disable subtitles"
|
||||
msgstr "Desativar legendas"
|
||||
|
||||
@@ -2186,7 +2195,7 @@ msgstr "Baixe o Bluesky"
|
||||
msgid "Download CAR file"
|
||||
msgstr "Baixar arquivo CAR"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:622
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:686
|
||||
msgid "Download image"
|
||||
msgstr "Baixar imagem"
|
||||
|
||||
@@ -2433,7 +2442,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:380
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:383
|
||||
msgid "Enable subtitles"
|
||||
msgstr "Habilitar legendas"
|
||||
|
||||
@@ -2565,7 +2574,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:397
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:400
|
||||
msgid "Exit fullscreen"
|
||||
msgstr "Sair da tela cheia"
|
||||
|
||||
@@ -2912,13 +2921,13 @@ msgstr "Seguir Conta"
|
||||
msgid "Follow all"
|
||||
msgstr "Siga todos"
|
||||
|
||||
#: src/view/com/profile/FollowButton.tsx:79
|
||||
msgctxt "action"
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:223
|
||||
#: src/view/com/post-thread/PostThreadFollowBtn.tsx:142
|
||||
msgid "Follow Back"
|
||||
msgstr "Seguir De Volta"
|
||||
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:223
|
||||
#: src/view/com/post-thread/PostThreadFollowBtn.tsx:142
|
||||
#: src/view/com/profile/FollowButton.tsx:79
|
||||
msgctxt "action"
|
||||
msgid "Follow Back"
|
||||
msgstr "Seguir De Volta"
|
||||
|
||||
@@ -3075,7 +3084,7 @@ msgctxt "from-feed"
|
||||
msgid "From <0/>"
|
||||
msgstr "Por <0/>"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:398
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:401
|
||||
msgid "Fullscreen"
|
||||
msgstr "Tela cheia"
|
||||
|
||||
@@ -3419,7 +3428,7 @@ msgstr "Imagem"
|
||||
msgid "Image alt text"
|
||||
msgstr "Texto alternativo da imagem"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:247
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:312
|
||||
#: src/components/StarterPack/ShareDialog.tsx:76
|
||||
msgid "Image saved to your camera roll!"
|
||||
msgstr "Imagem salva no rolo da câmera!"
|
||||
@@ -3566,8 +3575,12 @@ msgid "Join the conversation"
|
||||
msgstr "Participe da conversa"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:492
|
||||
msgid "Joined {0}"
|
||||
msgstr "Juntou-se {0}"
|
||||
#~ msgid "Joined {0}"
|
||||
#~ msgstr "Juntou-se {0}"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:559
|
||||
msgid "Joined on {joinedDate}"
|
||||
msgstr ""
|
||||
|
||||
#: src/screens/Onboarding/index.tsx:21
|
||||
#: src/screens/Onboarding/state.ts:89
|
||||
@@ -4074,8 +4087,8 @@ msgstr "Música"
|
||||
msgid "Mute"
|
||||
msgstr "Silenciar"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:166
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:389
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:157
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VolumeControl.tsx:94
|
||||
msgctxt "video"
|
||||
msgid "Mute"
|
||||
msgstr "Silenciar"
|
||||
@@ -4387,6 +4400,11 @@ msgstr "Nenhum GIF em destaque encontrado."
|
||||
msgid "No feeds found. Try searching for something else."
|
||||
msgstr "Nenhum feed encontrado. Tente pesquisar por outra coisa."
|
||||
|
||||
#: src/components/LikedByList.tsx:78
|
||||
#: src/view/com/post-thread/PostLikedBy.tsx:85
|
||||
msgid "No likes yet"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/ProfileCard.tsx:336
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:116
|
||||
msgid "No longer following {0}"
|
||||
@@ -4423,6 +4441,14 @@ msgstr "Ninguém além do autor pode citar esta postagem."
|
||||
msgid "No posts yet."
|
||||
msgstr "Nenhuma postagem ainda."
|
||||
|
||||
#: src/view/com/post-thread/PostQuotes.tsx:106
|
||||
msgid "No quotes yet"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostRepostedBy.tsx:78
|
||||
msgid "No reposts yet"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/text-input/mobile/Autocomplete.tsx:101
|
||||
#: src/view/com/composer/text-input/web/Autocomplete.tsx:195
|
||||
msgid "No result"
|
||||
@@ -4469,11 +4495,20 @@ msgstr "Ninguém"
|
||||
#~ msgid "Nobody can reply"
|
||||
#~ msgstr "Ninguém pode responder"
|
||||
|
||||
#: src/components/LikedByList.tsx:79
|
||||
#: src/components/LikedByList.tsx:80
|
||||
#: src/components/LikesDialog.tsx:99
|
||||
#: src/view/com/post-thread/PostLikedBy.tsx:87
|
||||
msgid "Nobody has liked this yet. Maybe you should be the first!"
|
||||
msgstr "Ninguém curtiu isso ainda. Você pode ser o primeiro!"
|
||||
|
||||
#: src/view/com/post-thread/PostQuotes.tsx:108
|
||||
msgid "Nobody has quoted this yet. Maybe you should be the first!"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostRepostedBy.tsx:80
|
||||
msgid "Nobody has reposted this yet. Maybe you should be the first!"
|
||||
msgstr ""
|
||||
|
||||
#: src/screens/StarterPack/Wizard/StepProfiles.tsx:103
|
||||
msgid "Nobody was found. Try searching for someone else."
|
||||
msgstr "Ninguém foi encontrado. Tente procurar por outra pessoa."
|
||||
@@ -4576,7 +4611,7 @@ msgstr "Opa!"
|
||||
msgid "Oh no! Something went wrong."
|
||||
msgstr "Opa! Algo deu errado."
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:175
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:224
|
||||
msgid "Oh no! We weren't able to generate an image for you to share. Rest assured, we're glad you're here 🦋"
|
||||
msgstr "Ah, não! Não conseguimos gerar uma imagem para você compartilhar. Fique tranquilo, estamos felizes que você esteja aqui 🦋"
|
||||
|
||||
@@ -4624,7 +4659,7 @@ msgstr "Apenas {0} pode responder."
|
||||
msgid "Only contains letters, numbers, and hyphens"
|
||||
msgstr "Contém apenas letras, números e hífens"
|
||||
|
||||
#: src/view/com/composer/videos/SubtitleFilePicker.tsx:39
|
||||
#: src/view/com/composer/videos/SubtitleFilePicker.tsx:40
|
||||
msgid "Only WebVTT (.vtt) files are supported"
|
||||
msgstr "Somente arquivos WebVTT (.vtt) são suportados"
|
||||
|
||||
@@ -4680,7 +4715,7 @@ msgstr "Abrir opções de mensagem"
|
||||
msgid "Open muted words and tags settings"
|
||||
msgstr "Abrir opções de palavras/tags silenciadas"
|
||||
|
||||
#: src/view/com/home/HomeHeaderLayoutMobile.tsx:54
|
||||
#: src/view/com/home/HomeHeaderLayoutMobile.tsx:101
|
||||
msgid "Open navigation"
|
||||
msgstr "Abrir navegação"
|
||||
|
||||
@@ -4924,12 +4959,12 @@ msgid "Password updated!"
|
||||
msgstr "Senha atualizada!"
|
||||
|
||||
#: src/view/com/util/post-embeds/GifEmbed.tsx:46
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:150
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:366
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:141
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:369
|
||||
msgid "Pause"
|
||||
msgstr "Pausar"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:319
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:320
|
||||
msgid "Pause video"
|
||||
msgstr "Pausar vídeo"
|
||||
|
||||
@@ -4989,8 +5024,8 @@ msgid "Pinned to your feeds"
|
||||
msgstr "Fixado em seus feeds"
|
||||
|
||||
#: src/view/com/util/post-embeds/GifEmbed.tsx:46
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:150
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:367
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:141
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:370
|
||||
msgid "Play"
|
||||
msgstr "Tocar"
|
||||
|
||||
@@ -5008,7 +5043,7 @@ msgid "Play or pause the GIF"
|
||||
msgstr "Tocar ou pausar o GIF"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbed.tsx:110
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:320
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:321
|
||||
msgid "Play video"
|
||||
msgstr "Reproduzir vídeo"
|
||||
|
||||
@@ -6076,7 +6111,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:631
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/Scrubber.tsx:189
|
||||
msgid "Seek slider"
|
||||
msgstr "Controle deslizante de busca"
|
||||
|
||||
@@ -6136,7 +6171,7 @@ msgstr "Seleciona opção {i} de {numItems}"
|
||||
#~ msgid "Select some accounts below to follow"
|
||||
#~ msgstr "Selecione algumas contas para seguir"
|
||||
|
||||
#: src/view/com/composer/videos/SubtitleFilePicker.tsx:65
|
||||
#: src/view/com/composer/videos/SubtitleFilePicker.tsx:66
|
||||
msgid "Select subtitle file (.vtt)"
|
||||
msgstr "Selecione o arquivo de legenda (.vtt)"
|
||||
|
||||
@@ -6344,7 +6379,7 @@ msgstr "Atividade sexual ou nudez erótica."
|
||||
msgid "Sexually Suggestive"
|
||||
msgstr "Sexualmente Sugestivo"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:644
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:708
|
||||
#: src/components/StarterPack/QrCodeDialog.tsx:177
|
||||
#: src/screens/StarterPack/StarterPackScreen.tsx:411
|
||||
#: src/screens/StarterPack/StarterPackScreen.tsx:582
|
||||
@@ -6381,11 +6416,11 @@ msgstr "Compartilhar assim"
|
||||
msgid "Share feed"
|
||||
msgstr "Compartilhar feed"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:621
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:685
|
||||
msgid "Share image externally"
|
||||
msgstr "Compartilhar imagem externamente"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:639
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:703
|
||||
msgid "Share image in post"
|
||||
msgstr "Compartilhe a imagem na postagem"
|
||||
|
||||
@@ -6894,15 +6929,15 @@ msgstr "Alto"
|
||||
msgid "Tap to dismiss"
|
||||
msgstr "Toque para dispensar"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:145
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:136
|
||||
msgid "Tap to enter full screen"
|
||||
msgstr "Toque para entrar em tela cheia"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:151
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:142
|
||||
msgid "Tap to play or pause"
|
||||
msgstr "Toque para reproduzir ou pausar"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:164
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:159
|
||||
msgid "Tap to toggle sound"
|
||||
msgstr "Toque para alternar o som"
|
||||
|
||||
@@ -6936,7 +6971,7 @@ msgstr "Conte uma piada!"
|
||||
msgid "Tell us a little more"
|
||||
msgstr "Conte-nos um pouco mais"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:518
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:578
|
||||
msgid "Ten Million"
|
||||
msgstr "Dez milhões"
|
||||
|
||||
@@ -6977,7 +7012,7 @@ msgstr "Campo de entrada de texto"
|
||||
msgid "Thank you. Your report has been sent."
|
||||
msgstr "Obrigado. Sua denúncia foi enviada."
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:593
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:654
|
||||
msgid "Thanks for being one of our first 10 million users."
|
||||
msgstr "Obrigado por ser um dos nossos primeiros 10 milhões de usuários."
|
||||
|
||||
@@ -7002,7 +7037,7 @@ msgstr "Este identificador de usuário já está sendo usado."
|
||||
msgid "That starter pack could not be found."
|
||||
msgstr "Esse pacote inicial não pôde ser encontrado."
|
||||
|
||||
#: src/view/com/post-thread/PostQuotes.tsx:127
|
||||
#: src/view/com/post-thread/PostQuotes.tsx:133
|
||||
msgid "That's all, folks!"
|
||||
msgstr "É isso, pessoal!"
|
||||
|
||||
@@ -7457,6 +7492,10 @@ msgstr "Preferências das Threads"
|
||||
msgid "To disable the email 2FA method, please verify your access to the email address."
|
||||
msgstr "Para desabilitar o 2FA via e-mail, por favor verifique seu acesso a este endereço de e-mail."
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/Trigger.tsx:69
|
||||
msgid "To learn more, <0>check out our post.</0>"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dms/ReportConversationPrompt.tsx:20
|
||||
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."
|
||||
@@ -7469,7 +7508,8 @@ msgstr "Para enviar vídeos para o Bluesky, você deve primeiro verificar seu e-
|
||||
msgid "To whom would you like to send this report?"
|
||||
msgstr "Para quem você gostaria de enviar esta denúncia?"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:597
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:658
|
||||
#: src/components/dialogs/nuxs/TenMillion/Trigger.tsx:63
|
||||
msgid "Together, we're rebuilding the social internet. We're glad you're here."
|
||||
msgstr "Juntos, estamos reconstruindo a internet social. Estamos felizes que você esteja aqui."
|
||||
|
||||
@@ -7613,8 +7653,8 @@ msgstr "Descurtir este feed"
|
||||
msgid "Unmute"
|
||||
msgstr "Dessilenciar"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:165
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:388
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:156
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VolumeControl.tsx:93
|
||||
msgctxt "video"
|
||||
msgid "Unmute"
|
||||
msgstr "Ativar o áudio"
|
||||
@@ -7645,13 +7685,13 @@ msgstr "Desmutar conversa"
|
||||
msgid "Unmute thread"
|
||||
msgstr "Dessilenciar thread"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx:317
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:318
|
||||
msgid "Unmute video"
|
||||
msgstr "Ativar o áudio do vídeo"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:168
|
||||
msgid "Unmuted"
|
||||
msgstr "Áudio ativado"
|
||||
#~ msgid "Unmuted"
|
||||
#~ msgstr "Áudio ativado"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:292
|
||||
#: src/view/screens/ProfileList.tsx:673
|
||||
@@ -7927,8 +7967,8 @@ msgstr "Verificar Seu E-mail"
|
||||
msgid "Version {appVersion} {bundleInfo}"
|
||||
msgstr "Versão {appVersion} {bundleInfo}"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:93
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:144
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:84
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:135
|
||||
msgid "Video"
|
||||
msgstr "Vídeo"
|
||||
|
||||
@@ -7949,7 +7989,7 @@ msgstr "Vídeo não encontrado."
|
||||
msgid "Video settings"
|
||||
msgstr "Configurações de vídeo"
|
||||
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:93
|
||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx:84
|
||||
msgid "Video: {0}"
|
||||
msgstr "Vídeo: {0}"
|
||||
|
||||
@@ -7999,6 +8039,10 @@ msgstr "Ver thread completa"
|
||||
msgid "View information about these labels"
|
||||
msgstr "Ver informações sobre estes rótulos"
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/Trigger.tsx:72
|
||||
msgid "View our post"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:418
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:436
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:463
|
||||
@@ -8023,8 +8067,8 @@ msgstr "Ver usuários que curtiram este feed"
|
||||
msgid "View your blocked accounts"
|
||||
msgstr "Veja suas contas bloqueadas"
|
||||
|
||||
#: src/view/com/home/HomeHeaderLayout.web.tsx:79
|
||||
#: src/view/com/home/HomeHeaderLayoutMobile.tsx:86
|
||||
#: src/view/com/home/HomeHeaderLayout.web.tsx:132
|
||||
#: src/view/com/home/HomeHeaderLayoutMobile.tsx:143
|
||||
msgid "View your feeds and explore more"
|
||||
msgstr "Veja seus feeds e explore mais"
|
||||
|
||||
@@ -8497,7 +8541,7 @@ msgstr "Você deve estar seguindo pelo menos sete outras pessoas para gerar um p
|
||||
msgid "You must grant access to your photo library to save a QR code"
|
||||
msgstr "Você deve conceder acesso à sua biblioteca de fotos para salvar o QR code."
|
||||
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:237
|
||||
#: src/components/dialogs/nuxs/TenMillion/index.tsx:302
|
||||
#: src/components/StarterPack/ShareDialog.tsx:68
|
||||
msgid "You must grant access to your photo library to save the image."
|
||||
msgstr "Você deve conceder acesso à sua biblioteca de fotos para salvar a imagem."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {beforeAll, describe, expect, jest, test} from '@jest/globals'
|
||||
import * as Sentry from '@sentry/react-native'
|
||||
import {nanoid} from 'nanoid/non-secure'
|
||||
import {jest, describe, expect, test, beforeAll} from '@jest/globals'
|
||||
import {Native as Sentry} from 'sentry-expo'
|
||||
|
||||
import {Logger, LogLevel, sentryTransport} from '#/logger'
|
||||
|
||||
@@ -16,12 +16,10 @@ jest.mock('#/env', () => ({
|
||||
LOG_DEBUG: '',
|
||||
}))
|
||||
|
||||
jest.mock('sentry-expo', () => ({
|
||||
Native: {
|
||||
addBreadcrumb: jest.fn(),
|
||||
captureException: jest.fn(),
|
||||
captureMessage: jest.fn(),
|
||||
},
|
||||
jest.mock('@sentry/react-native', () => ({
|
||||
addBreadcrumb: jest.fn(),
|
||||
captureException: jest.fn(),
|
||||
captureMessage: jest.fn(),
|
||||
}))
|
||||
|
||||
beforeAll(() => {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export {Native as Sentry} from 'sentry-expo'
|
||||
export * as Sentry from '@sentry/react-native'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export {Browser as Sentry} from 'sentry-expo'
|
||||
export * as Sentry from '@sentry/react-native'
|
||||
|
||||
@@ -14,17 +14,21 @@ import {s} from '#/lib/styles'
|
||||
import {useSetThemePrefs, useThemePrefs} from '#/state/shell'
|
||||
import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader'
|
||||
import {ScrollView} from '#/view/com/util/Views'
|
||||
import {atoms as a, native, useTheme} from '#/alf'
|
||||
import {atoms as a, native, useAlf, useTheme} from '#/alf'
|
||||
import * as ToggleButton from '#/components/forms/ToggleButton'
|
||||
import {Props as SVGIconProps} from '#/components/icons/common'
|
||||
import {Moon_Stroke2_Corner0_Rounded as MoonIcon} from '#/components/icons/Moon'
|
||||
import {Phone_Stroke2_Corner0_Rounded as PhoneIcon} from '#/components/icons/Phone'
|
||||
import {TextSize_Stroke2_Corner0_Rounded as TextSize} from '#/components/icons/TextSize'
|
||||
import {TitleCase_Stroke2_Corner0_Rounded as Aa} from '#/components/icons/TitleCase'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppearanceSettings'>
|
||||
export function AppearanceSettingsScreen({}: Props) {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {isTabletOrMobile} = useWebMediaQueries()
|
||||
const {fonts} = useAlf()
|
||||
|
||||
const {colorMode, darkTheme} = useThemePrefs()
|
||||
const {setColorMode, setDarkTheme} = useSetThemePrefs()
|
||||
@@ -54,6 +58,22 @@ export function AppearanceSettingsScreen({}: Props) {
|
||||
[setDarkTheme, darkTheme],
|
||||
)
|
||||
|
||||
const onChangeFontFamily = useCallback(
|
||||
(values: string[]) => {
|
||||
const next = values[0] === 'system' ? 'system' : 'theme'
|
||||
fonts.setFontFamily(next)
|
||||
},
|
||||
[fonts],
|
||||
)
|
||||
|
||||
const onChangeFontScale = useCallback(
|
||||
(values: string[]) => {
|
||||
const next = values[0] || ('0' as any)
|
||||
fonts.setFontScale(next)
|
||||
},
|
||||
[fonts],
|
||||
)
|
||||
|
||||
return (
|
||||
<LayoutAnimationConfig skipExiting skipEntering>
|
||||
<View testID="preferencesThreadsScreen" style={s.hContentRegion}>
|
||||
@@ -71,65 +91,143 @@ export function AppearanceSettingsScreen({}: Props) {
|
||||
</View>
|
||||
</SimpleViewHeader>
|
||||
|
||||
<View style={[a.p_xl, a.gap_lg]}>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_md]}>
|
||||
<PhoneIcon style={t.atoms.text} />
|
||||
<Text style={a.text_md}>
|
||||
<Trans>Mode</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
<ToggleButton.Group
|
||||
label={_(msg`Dark mode`)}
|
||||
values={[colorMode]}
|
||||
onChange={onChangeAppearance}>
|
||||
<ToggleButton.Button label={_(msg`System`)} name="system">
|
||||
<ToggleButton.ButtonText>
|
||||
<Trans>System</Trans>
|
||||
</ToggleButton.ButtonText>
|
||||
</ToggleButton.Button>
|
||||
<ToggleButton.Button label={_(msg`Light`)} name="light">
|
||||
<ToggleButton.ButtonText>
|
||||
<Trans>Light</Trans>
|
||||
</ToggleButton.ButtonText>
|
||||
</ToggleButton.Button>
|
||||
<ToggleButton.Button label={_(msg`Dark`)} name="dark">
|
||||
<ToggleButton.ButtonText>
|
||||
<Trans>Dark</Trans>
|
||||
</ToggleButton.ButtonText>
|
||||
</ToggleButton.Button>
|
||||
</ToggleButton.Group>
|
||||
{colorMode !== 'light' && (
|
||||
<Animated.View
|
||||
entering={native(FadeInDown)}
|
||||
exiting={native(FadeOutDown)}
|
||||
style={[a.mt_md, a.gap_lg]}>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_md]}>
|
||||
<MoonIcon style={t.atoms.text} />
|
||||
<Text style={a.text_md}>
|
||||
<Trans>Dark theme</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[a.gap_3xl, a.pt_xl, a.px_xl]}>
|
||||
<View style={[a.gap_lg]}>
|
||||
<AppearanceToggleButtonGroup
|
||||
title={_(msg`Color mode`)}
|
||||
icon={PhoneIcon}
|
||||
items={[
|
||||
{
|
||||
label: _(msg`System`),
|
||||
name: 'system',
|
||||
},
|
||||
{
|
||||
label: _(msg`Light`),
|
||||
name: 'light',
|
||||
},
|
||||
{
|
||||
label: _(msg`Dark`),
|
||||
name: 'dark',
|
||||
},
|
||||
]}
|
||||
values={[colorMode]}
|
||||
onChange={onChangeAppearance}
|
||||
/>
|
||||
|
||||
<ToggleButton.Group
|
||||
label={_(msg`Dark theme`)}
|
||||
values={[darkTheme ?? 'dim']}
|
||||
onChange={onChangeDarkTheme}>
|
||||
<ToggleButton.Button label={_(msg`Dim`)} name="dim">
|
||||
<ToggleButton.ButtonText>
|
||||
<Trans>Dim</Trans>
|
||||
</ToggleButton.ButtonText>
|
||||
</ToggleButton.Button>
|
||||
<ToggleButton.Button label={_(msg`Dark`)} name="dark">
|
||||
<ToggleButton.ButtonText>
|
||||
<Trans>Dark</Trans>
|
||||
</ToggleButton.ButtonText>
|
||||
</ToggleButton.Button>
|
||||
</ToggleButton.Group>
|
||||
</Animated.View>
|
||||
)}
|
||||
{colorMode !== 'light' && (
|
||||
<Animated.View
|
||||
entering={native(FadeInDown)}
|
||||
exiting={native(FadeOutDown)}>
|
||||
<AppearanceToggleButtonGroup
|
||||
title={_(msg`Dark theme`)}
|
||||
icon={MoonIcon}
|
||||
items={[
|
||||
{
|
||||
label: _(msg`Dim`),
|
||||
name: 'dim',
|
||||
},
|
||||
{
|
||||
label: _(msg`Dark`),
|
||||
name: 'dark',
|
||||
},
|
||||
]}
|
||||
values={[darkTheme ?? 'dim']}
|
||||
onChange={onChangeDarkTheme}
|
||||
/>
|
||||
</Animated.View>
|
||||
)}
|
||||
|
||||
<AppearanceToggleButtonGroup
|
||||
title={_(msg`Font`)}
|
||||
description={_(
|
||||
msg`For the best experience, we recommend using the theme font.`,
|
||||
)}
|
||||
icon={Aa}
|
||||
items={[
|
||||
{
|
||||
label: _(msg`System`),
|
||||
name: 'system',
|
||||
},
|
||||
{
|
||||
label: _(msg`Theme`),
|
||||
name: 'theme',
|
||||
},
|
||||
]}
|
||||
values={[fonts.family]}
|
||||
onChange={onChangeFontFamily}
|
||||
/>
|
||||
|
||||
<AppearanceToggleButtonGroup
|
||||
title={_(msg`Font size`)}
|
||||
icon={TextSize}
|
||||
items={[
|
||||
{
|
||||
label: _(msg`Smaller`),
|
||||
name: '-1',
|
||||
},
|
||||
{
|
||||
label: _(msg`Default`),
|
||||
name: '0',
|
||||
},
|
||||
{
|
||||
label: _(msg`Larger`),
|
||||
name: '1',
|
||||
},
|
||||
]}
|
||||
values={[fonts.scale]}
|
||||
onChange={onChangeFontScale}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</LayoutAnimationConfig>
|
||||
)
|
||||
}
|
||||
|
||||
export function AppearanceToggleButtonGroup({
|
||||
title,
|
||||
description,
|
||||
icon: Icon,
|
||||
items,
|
||||
values,
|
||||
onChange,
|
||||
}: {
|
||||
title: string
|
||||
description?: string
|
||||
icon: React.ComponentType<SVGIconProps>
|
||||
items: {
|
||||
label: string
|
||||
name: string
|
||||
}[]
|
||||
values: string[]
|
||||
onChange: (values: string[]) => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<View style={[a.gap_sm]}>
|
||||
<View style={[a.gap_xs]}>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_md]}>
|
||||
<Icon style={t.atoms.text} />
|
||||
<Text style={[a.text_md, a.font_bold]}>{title}</Text>
|
||||
</View>
|
||||
{description && (
|
||||
<Text
|
||||
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
<ToggleButton.Group label={title} values={values} onChange={onChange}>
|
||||
{items.map(item => (
|
||||
<ToggleButton.Button
|
||||
key={item.name}
|
||||
label={item.label}
|
||||
name={item.name}>
|
||||
<ToggleButton.ButtonText>{item.label}</ToggleButton.ButtonText>
|
||||
</ToggleButton.Button>
|
||||
))}
|
||||
</ToggleButton.Group>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {ImageModel} from './image'
|
||||
import {Image as RNImage} from 'react-native-image-crop-picker'
|
||||
import {openPicker} from 'lib/media/picker'
|
||||
|
||||
import {getImageDim} from 'lib/media/manip'
|
||||
import {openPicker} from 'lib/media/picker'
|
||||
import {ImageInitOptions, ImageModel} from './image'
|
||||
|
||||
interface InitialImageUri {
|
||||
uri: string
|
||||
width: number
|
||||
height: number
|
||||
altText?: string
|
||||
}
|
||||
|
||||
export class GalleryModel {
|
||||
images: ImageModel[] = []
|
||||
|
||||
constructor(uris?: {uri: string; width: number; height: number}[]) {
|
||||
constructor(uris?: InitialImageUri[]) {
|
||||
makeAutoObservable(this)
|
||||
|
||||
if (uris) {
|
||||
@@ -33,7 +34,7 @@ export class GalleryModel {
|
||||
return this.images.some(image => image.altText.trim() === '')
|
||||
}
|
||||
|
||||
*add(image_: Omit<RNImage, 'size'>) {
|
||||
*add(image_: ImageInitOptions) {
|
||||
if (this.size >= 4) {
|
||||
return
|
||||
}
|
||||
@@ -59,7 +60,6 @@ export class GalleryModel {
|
||||
path: uri,
|
||||
height,
|
||||
width,
|
||||
mime: 'image/jpeg',
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
@@ -100,10 +100,10 @@ export class GalleryModel {
|
||||
async addFromUris(uris: InitialImageUri[]) {
|
||||
for (const uriObj of uris) {
|
||||
this.add({
|
||||
mime: 'image/jpeg',
|
||||
height: uriObj.height,
|
||||
width: uriObj.width,
|
||||
path: uriObj.uri,
|
||||
altText: uriObj.altText,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import {Image as RNImage} from 'react-native-image-crop-picker'
|
||||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {POST_IMG_MAX} from 'lib/constants'
|
||||
import * as ImageManipulator from 'expo-image-manipulator'
|
||||
import {getDataUriSize} from 'lib/media/util'
|
||||
import {openCropper} from 'lib/media/picker'
|
||||
import {ActionCrop, FlipType, SaveFormat} from 'expo-image-manipulator'
|
||||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {Position} from 'react-avatar-editor'
|
||||
import {Dimensions} from 'lib/media/types'
|
||||
import {isIOS} from 'platform/detection'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import {POST_IMG_MAX} from 'lib/constants'
|
||||
import {openCropper} from 'lib/media/picker'
|
||||
import {Dimensions} from 'lib/media/types'
|
||||
import {getDataUriSize} from 'lib/media/util'
|
||||
import {isIOS} from 'platform/detection'
|
||||
|
||||
export interface ImageManipulationAttributes {
|
||||
aspectRatio?: '4:3' | '1:1' | '3:4' | 'None'
|
||||
@@ -19,6 +20,13 @@ export interface ImageManipulationAttributes {
|
||||
flipVertical?: boolean
|
||||
}
|
||||
|
||||
export interface ImageInitOptions {
|
||||
path: string
|
||||
width: number
|
||||
height: number
|
||||
altText?: string
|
||||
}
|
||||
|
||||
const MAX_IMAGE_SIZE_IN_BYTES = 976560
|
||||
|
||||
export class ImageModel implements Omit<RNImage, 'size'> {
|
||||
@@ -41,12 +49,15 @@ export class ImageModel implements Omit<RNImage, 'size'> {
|
||||
}
|
||||
prevAttributes: ImageManipulationAttributes = {}
|
||||
|
||||
constructor(image: Omit<RNImage, 'size'>) {
|
||||
constructor(image: ImageInitOptions) {
|
||||
makeAutoObservable(this)
|
||||
|
||||
this.path = image.path
|
||||
this.width = image.width
|
||||
this.height = image.height
|
||||
if (image.altText !== undefined) {
|
||||
this.setAltText(image.altText)
|
||||
}
|
||||
}
|
||||
|
||||
setRatio(aspectRatio: ImageManipulationAttributes['aspectRatio']) {
|
||||
|
||||
@@ -4,15 +4,22 @@ import {BaseNux} from '#/state/queries/nuxs/types'
|
||||
|
||||
export enum Nux {
|
||||
TenMillionDialog = 'TenMillionDialog',
|
||||
NeueTypography = 'NeueTypography',
|
||||
}
|
||||
|
||||
export const nuxNames = new Set(Object.values(Nux))
|
||||
|
||||
export type AppNux = BaseNux<{
|
||||
id: Nux.TenMillionDialog
|
||||
data: undefined
|
||||
}>
|
||||
export type AppNux =
|
||||
| BaseNux<{
|
||||
id: Nux.TenMillionDialog
|
||||
data: undefined
|
||||
}>
|
||||
| BaseNux<{
|
||||
id: Nux.NeueTypography
|
||||
data: undefined
|
||||
}>
|
||||
|
||||
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||
[Nux.TenMillionDialog]: undefined,
|
||||
[Nux.NeueTypography]: undefined,
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export interface ComposerOpts {
|
||||
mention?: string // handle of user to mention
|
||||
openEmojiPicker?: (pos: DOMRect | undefined) => void
|
||||
text?: string
|
||||
imageUris?: {uri: string; width: number; height: number}[]
|
||||
imageUris?: {uri: string; width: number; height: number; altText?: string}[]
|
||||
}
|
||||
|
||||
type StateContext = ComposerOpts | undefined
|
||||
|
||||
@@ -48,7 +48,7 @@ export function useComposerKeyboardShortcut() {
|
||||
function handler(event: KeyboardEvent) {
|
||||
if (shouldIgnore(event)) return
|
||||
if (
|
||||
openDialogs.current.size > 0 ||
|
||||
openDialogs?.current.size > 0 ||
|
||||
isModalActive ||
|
||||
activeLightbox ||
|
||||
isDrawerOpen
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* Device data that's specific to the device and does not vary based account
|
||||
*/
|
||||
export type Device = {
|
||||
fontScale: '-2' | '-1' | '0' | '1' | '2'
|
||||
fontFamily: 'system' | 'theme'
|
||||
lastNuxDialog: string | undefined
|
||||
geolocation?: {
|
||||
countryCode: string | undefined
|
||||
|
||||
@@ -19,6 +19,7 @@ import PasteInput, {
|
||||
PasteInputRef,
|
||||
} from '@mattermost/react-native-paste-input'
|
||||
|
||||
import {isAndroid} from '#/platform/detection'
|
||||
import {POST_IMG_MAX} from 'lib/constants'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {downloadAndResize} from 'lib/media/manip'
|
||||
@@ -26,12 +27,13 @@ import {isUriImage} from 'lib/media/util'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {getMentionAt, insertMentionAt} from 'lib/strings/mention-manip'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {isIOS} from 'platform/detection'
|
||||
import {
|
||||
LinkFacetMatch,
|
||||
suggestLinkCardUri,
|
||||
} from 'view/com/composer/text-input/text-input-util'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {atoms as a, useAlf} from '#/alf'
|
||||
import {normalizeTextStyles} from '#/components/Typography'
|
||||
import {Autocomplete} from './mobile/Autocomplete'
|
||||
|
||||
export interface TextInputRef {
|
||||
@@ -67,6 +69,7 @@ export const TextInput = forwardRef(function TextInputImpl(
|
||||
}: TextInputProps,
|
||||
ref,
|
||||
) {
|
||||
const {theme: t, fonts} = useAlf()
|
||||
const pal = usePalette('default')
|
||||
const textInput = useRef<PasteInputRef>(null)
|
||||
const textInputSelection = useRef<Selection>({start: 0, end: 0})
|
||||
@@ -180,6 +183,33 @@ export const TextInput = forwardRef(function TextInputImpl(
|
||||
[onChangeText, richtext, setAutocompletePrefix],
|
||||
)
|
||||
|
||||
const inputTextStyle = React.useMemo(() => {
|
||||
const style = normalizeTextStyles(
|
||||
[a.text_xl, a.leading_snug, t.atoms.text],
|
||||
{
|
||||
fontScale: fonts.scaleMultiplier,
|
||||
fontFamily: fonts.family,
|
||||
flags: {},
|
||||
},
|
||||
)
|
||||
|
||||
/*
|
||||
* `PasteInput` appears to prefer no `lineHeight`
|
||||
*/
|
||||
style.lineHeight = undefined
|
||||
|
||||
/*
|
||||
* Android impl of `PasteInput` doesn't support the array syntax for `fontVariant`
|
||||
*/
|
||||
if (isAndroid) {
|
||||
// @ts-ignore
|
||||
style.fontVariant = style.fontVariant
|
||||
? style.fontVariant.join(' ')
|
||||
: undefined
|
||||
}
|
||||
return style
|
||||
}, [t, fonts])
|
||||
|
||||
const textDecorated = useMemo(() => {
|
||||
let i = 0
|
||||
|
||||
@@ -187,15 +217,12 @@ export const TextInput = forwardRef(function TextInputImpl(
|
||||
return (
|
||||
<Text
|
||||
key={i++}
|
||||
style={[
|
||||
segment.facet ? pal.link : pal.text,
|
||||
styles.textInputFormatting,
|
||||
]}>
|
||||
style={[inputTextStyle, segment.facet ? pal.link : pal.text]}>
|
||||
{segment.text}
|
||||
</Text>
|
||||
)
|
||||
})
|
||||
}, [richtext, pal.link, pal.text])
|
||||
}, [richtext, pal.link, pal.text, inputTextStyle])
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
@@ -213,12 +240,7 @@ export const TextInput = forwardRef(function TextInputImpl(
|
||||
multiline
|
||||
scrollEnabled={false}
|
||||
numberOfLines={4}
|
||||
style={[
|
||||
pal.text,
|
||||
styles.textInput,
|
||||
styles.textInputFormatting,
|
||||
{textAlignVertical: 'top'},
|
||||
]}
|
||||
style={[inputTextStyle, styles.textInput, {textAlignVertical: 'top'}]}
|
||||
{...props}>
|
||||
{textDecorated}
|
||||
</PasteInput>
|
||||
@@ -242,11 +264,4 @@ const styles = StyleSheet.create({
|
||||
marginLeft: 8,
|
||||
alignSelf: 'flex-start',
|
||||
},
|
||||
textInputFormatting: {
|
||||
fontSize: 18,
|
||||
letterSpacing: 0.2,
|
||||
fontWeight: '400',
|
||||
// This is broken on ios right now, so don't set it there.
|
||||
lineHeight: isIOS ? undefined : 23.4, // 1.3*16
|
||||
},
|
||||
})
|
||||
|
||||
@@ -22,7 +22,9 @@ import {
|
||||
LinkFacetMatch,
|
||||
suggestLinkCardUri,
|
||||
} from 'view/com/composer/text-input/text-input-util'
|
||||
import {atoms as a, useAlf} from '#/alf'
|
||||
import {Portal} from '#/components/Portal'
|
||||
import {normalizeTextStyles} from '#/components/Typography'
|
||||
import {Text} from '../../util/text/Text'
|
||||
import {createSuggestion} from './web/Autocomplete'
|
||||
import {Emoji} from './web/EmojiPicker.web'
|
||||
@@ -58,6 +60,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
||||
TextInputProps,
|
||||
ref,
|
||||
) {
|
||||
const {theme: t, fonts} = useAlf()
|
||||
const autocomplete = useActorAutocompleteFn()
|
||||
const pal = usePalette('default')
|
||||
const modeClass = useColorSchemeStyle('ProseMirror-light', 'ProseMirror-dark')
|
||||
@@ -247,13 +250,32 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
||||
},
|
||||
}))
|
||||
|
||||
const inputStyle = React.useMemo(() => {
|
||||
const style = normalizeTextStyles(
|
||||
[a.text_lg, a.leading_snug, t.atoms.text],
|
||||
{
|
||||
fontScale: fonts.scaleMultiplier,
|
||||
fontFamily: fonts.family,
|
||||
flags: {},
|
||||
},
|
||||
)
|
||||
/*
|
||||
* TipTap component isn't a RN View and while it seems to convert
|
||||
* `fontSize` to `px`, it doesn't convert `lineHeight`.
|
||||
*
|
||||
* `lineHeight` should always be defined here, this is defensive.
|
||||
*/
|
||||
style.lineHeight = style.lineHeight
|
||||
? ((style.lineHeight + 'px') as unknown as number)
|
||||
: undefined
|
||||
return style
|
||||
}, [t, fonts])
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={styles.container}>
|
||||
<EditorContent
|
||||
editor={editor}
|
||||
style={{color: pal.text.color as string}}
|
||||
/>
|
||||
{/* @ts-ignore inputStyle is fine */}
|
||||
<EditorContent editor={editor} style={inputStyle} />
|
||||
</View>
|
||||
|
||||
{isDropping && (
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
||||
import {Pressable, StyleSheet, View} from 'react-native'
|
||||
import {useWindowDimensions} from 'react-native'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {MaterialIcons} from '@expo/vector-icons'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Slider} from '@miblanchard/react-native-slider'
|
||||
@@ -13,13 +12,24 @@ import {useModalControls} from '#/state/modals'
|
||||
import {MAX_ALT_TEXT} from 'lib/constants'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {RectTallIcon, RectWideIcon, SquareIcon} from 'lib/icons'
|
||||
import {enforceLen} from 'lib/strings/helpers'
|
||||
import {gradients, s} from 'lib/styles'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {getKeys} from 'lib/type-assertions'
|
||||
import {GalleryModel} from 'state/models/media/gallery'
|
||||
import {ImageModel} from 'state/models/media/image'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import {
|
||||
AspectRatio11_Stroke2_Corner0_Rounded as A11,
|
||||
AspectRatio34_Stroke2_Corner0_Rounded as A34,
|
||||
AspectRatio43_Stroke2_Corner0_Rounded as A43,
|
||||
} from '#/components/icons/AspectRatio'
|
||||
import {CircleBanSign_Stroke2_Corner0_Rounded as Ban} from '#/components/icons/CircleBanSign'
|
||||
import {
|
||||
FlipHorizontal_Stroke2_Corner0_Rounded as FlipHorizontal,
|
||||
FlipVertical_Stroke2_Corner0_Rounded as FlipVertical,
|
||||
} from '#/components/icons/FlipImage'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {TextInput} from './util'
|
||||
|
||||
@@ -27,18 +37,16 @@ export const snapPoints = ['80%']
|
||||
|
||||
const RATIOS = {
|
||||
'4:3': {
|
||||
Icon: RectWideIcon,
|
||||
icon: A43,
|
||||
},
|
||||
'1:1': {
|
||||
Icon: SquareIcon,
|
||||
icon: A11,
|
||||
},
|
||||
'3:4': {
|
||||
Icon: RectTallIcon,
|
||||
icon: A34,
|
||||
},
|
||||
None: {
|
||||
label: 'None',
|
||||
Icon: MaterialIcons,
|
||||
name: 'do-not-disturb-alt',
|
||||
icon: Ban,
|
||||
},
|
||||
} as const
|
||||
|
||||
@@ -112,12 +120,12 @@ export const Component = observer(function EditImageImpl({
|
||||
// },
|
||||
// },
|
||||
{
|
||||
name: 'flip' as const,
|
||||
icon: FlipHorizontal,
|
||||
label: _(msg`Flip horizontal`),
|
||||
onPress: onFlipHorizontal,
|
||||
},
|
||||
{
|
||||
name: 'flip' as const,
|
||||
icon: FlipVertical,
|
||||
label: _(msg`Flip vertically`),
|
||||
onPress: onFlipVertical,
|
||||
},
|
||||
@@ -165,17 +173,6 @@ export const Component = observer(function EditImageImpl({
|
||||
onCloseModal()
|
||||
}, [altText, image, position, scale, onCloseModal])
|
||||
|
||||
const getLabelIconSize = useCallback((as: AspectRatio) => {
|
||||
switch (as) {
|
||||
case 'None':
|
||||
return 22
|
||||
case '1:1':
|
||||
return 32
|
||||
default:
|
||||
return 26
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (image.cropped === undefined) {
|
||||
return null
|
||||
}
|
||||
@@ -231,7 +228,7 @@ export const Component = observer(function EditImageImpl({
|
||||
maximumValue={3}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
<View style={[a.gap_sm]}>
|
||||
{!isMobile ? (
|
||||
<Text type="sm-bold" style={pal.text}>
|
||||
<Trans>Ratios</Trans>
|
||||
@@ -239,31 +236,25 @@ export const Component = observer(function EditImageImpl({
|
||||
) : null}
|
||||
<View style={imgControlStyles}>
|
||||
{getKeys(RATIOS).map(ratio => {
|
||||
const {Icon, ...props} = RATIOS[ratio]
|
||||
const labelIconSize = getLabelIconSize(ratio)
|
||||
const {icon} = RATIOS[ratio]
|
||||
const isSelected = aspectRatio === ratio
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
<Button
|
||||
key={ratio}
|
||||
label={ratio}
|
||||
size="large"
|
||||
shape="square"
|
||||
variant="outline"
|
||||
color={isSelected ? 'primary' : 'secondary'}
|
||||
onPress={() => {
|
||||
onSetRatio(ratio)
|
||||
}}
|
||||
accessibilityLabel={ratio}
|
||||
accessibilityHint="">
|
||||
<Icon
|
||||
size={labelIconSize}
|
||||
style={[styles.imgControl, isSelected ? s.blue3 : pal.text]}
|
||||
color={(isSelected ? s.blue3 : pal.text).color}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
<Text
|
||||
type={isSelected ? 'xs-bold' : 'xs-medium'}
|
||||
style={[isSelected ? s.blue3 : pal.text, s.textCenter]}>
|
||||
{ratio}
|
||||
</Text>
|
||||
</Pressable>
|
||||
}}>
|
||||
<View style={[a.align_center, a.gap_2xs]}>
|
||||
<ButtonIcon icon={icon} />
|
||||
<ButtonText style={[a.text_xs]}>{ratio}</ButtonText>
|
||||
</View>
|
||||
</Button>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
@@ -273,24 +264,17 @@ export const Component = observer(function EditImageImpl({
|
||||
</Text>
|
||||
) : null}
|
||||
<View style={imgControlStyles}>
|
||||
{adjustments.map(({label, name, onPress}) => (
|
||||
<Pressable
|
||||
{adjustments.map(({label, icon, onPress}) => (
|
||||
<Button
|
||||
key={label}
|
||||
onPress={onPress}
|
||||
accessibilityLabel={label}
|
||||
accessibilityHint=""
|
||||
style={styles.flipBtn}>
|
||||
<MaterialIcons
|
||||
name={name}
|
||||
size={label?.startsWith('Flip') ? 22 : 24}
|
||||
style={[
|
||||
pal.text,
|
||||
label === _(msg`Flip vertically`)
|
||||
? styles.flipVertical
|
||||
: undefined,
|
||||
]}
|
||||
/>
|
||||
</Pressable>
|
||||
label={label}
|
||||
size="large"
|
||||
shape="square"
|
||||
variant="outline"
|
||||
color="secondary"
|
||||
onPress={onPress}>
|
||||
<ButtonIcon icon={icon} />
|
||||
</Button>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
@@ -362,12 +346,6 @@ const styles = StyleSheet.create({
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 24,
|
||||
},
|
||||
imgControl: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: 40,
|
||||
},
|
||||
imgEditor: {
|
||||
maxWidth: '100%',
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@ import {colors} from 'lib/styles'
|
||||
import {isAndroid, isNative, isWeb} from 'platform/detection'
|
||||
import {precacheProfile} from 'state/queries/profile'
|
||||
import {HighPriorityImage} from 'view/com/util/images/Image'
|
||||
import {atoms as a, tokens, useTheme} from '#/alf'
|
||||
import {tokens, useTheme} from '#/alf'
|
||||
import {
|
||||
Camera_Filled_Stroke2_Corner0_Rounded as CameraFilled,
|
||||
Camera_Stroke2_Corner0_Rounded as Camera,
|
||||
@@ -241,7 +241,13 @@ let UserAvatar = ({
|
||||
onLoad={onLoad}
|
||||
/>
|
||||
)}
|
||||
<MediaInsetBorder style={[a.rounded_full]} />
|
||||
<MediaInsetBorder
|
||||
style={[
|
||||
{
|
||||
borderRadius: aviStyle.borderRadius,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{alert}
|
||||
</View>
|
||||
) : (
|
||||
|
||||
@@ -59,7 +59,7 @@ export const ExternalLinkEmbed = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[a.flex_col, a.rounded_sm]}>
|
||||
<View style={[a.flex_col, a.w_full]}>
|
||||
<LinkWrapper link={link} onOpen={onOpen} style={style}>
|
||||
{imageUri && !embedPlayerParams ? (
|
||||
<View>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react'
|
||||
import {Text as RNText, TextProps} from 'react-native'
|
||||
import {StyleSheet, Text as RNText, TextProps} from 'react-native'
|
||||
import {UITextView} from 'react-native-uitextview'
|
||||
|
||||
import {lh, s} from 'lib/styles'
|
||||
import {TypographyVariant, useTheme} from 'lib/ThemeContext'
|
||||
import {isIOS, isWeb} from 'platform/detection'
|
||||
import {applyFonts, useAlf} from '#/alf'
|
||||
|
||||
export type CustomTextProps = TextProps & {
|
||||
type?: TypographyVariant
|
||||
@@ -32,11 +33,28 @@ export function Text({
|
||||
const theme = useTheme()
|
||||
const typography = theme.typography[type]
|
||||
const lineHeightStyle = lineHeight ? lh(theme, type, lineHeight) : undefined
|
||||
const {fonts} = useAlf()
|
||||
|
||||
if (selectable && isIOS) {
|
||||
const flattened = StyleSheet.flatten([
|
||||
s.black,
|
||||
typography,
|
||||
lineHeightStyle,
|
||||
style,
|
||||
])
|
||||
|
||||
applyFonts(flattened, fonts.family)
|
||||
|
||||
// should always be defined on `typography`
|
||||
// @ts-ignore
|
||||
if (flattened.fontSize) {
|
||||
// @ts-ignore
|
||||
flattened.fontSize = flattened.fontSize * fonts.scaleMultiplier
|
||||
}
|
||||
|
||||
return (
|
||||
<UITextView
|
||||
style={[s.black, typography, lineHeightStyle, style]}
|
||||
style={flattened}
|
||||
selectable={selectable}
|
||||
uiTextView
|
||||
{...props}>
|
||||
@@ -45,15 +63,26 @@ export function Text({
|
||||
)
|
||||
}
|
||||
|
||||
const flattened = StyleSheet.flatten([
|
||||
s.black,
|
||||
typography,
|
||||
isWeb && fontFamilyStyle,
|
||||
lineHeightStyle,
|
||||
style,
|
||||
])
|
||||
|
||||
applyFonts(flattened, fonts.family)
|
||||
|
||||
// should always be defined on `typography`
|
||||
// @ts-ignore
|
||||
if (flattened.fontSize) {
|
||||
// @ts-ignore
|
||||
flattened.fontSize = flattened.fontSize * fonts.scaleMultiplier
|
||||
}
|
||||
|
||||
return (
|
||||
<RNText
|
||||
style={[
|
||||
s.black,
|
||||
typography,
|
||||
isWeb && fontFamilyStyle,
|
||||
lineHeightStyle,
|
||||
style,
|
||||
]}
|
||||
style={flattened}
|
||||
// @ts-ignore web only -esb
|
||||
dataSet={Object.assign({tooltip: title}, dataSet || {})}
|
||||
selectable={selectable}
|
||||
|
||||
@@ -17,7 +17,106 @@
|
||||
<link rel="preconnect" href="https://bsky.social">
|
||||
<link rel="preconnect" href="https://bsky.network">
|
||||
<title>%WEB_TITLE%</title>
|
||||
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Italic.95778eb0c75dc956257e.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Medium.296aa2d65964269836b3.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBold.2277990330981b8409bb.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Bold.8d330503e1d034ad68de.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Black.66e9a87f1c921e844ed4.otf">
|
||||
<link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf">
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Inter-Regular";
|
||||
src: local("Inter-Regular"), url(/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf) format("font/otf");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Italic";
|
||||
src: local("Inter-Italic"), url(/static/media/Inter-Italic.95778eb0c75dc956257e.otf) format("font/otf");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Medium";
|
||||
src: local("Inter-Medium"), url(/static/media/Inter-Medium.296aa2d65964269836b3.otf) format("font/otf");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-MediumItalic";
|
||||
src: local("Inter-MediumItalic"), url(/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf) format("font/otf");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-SemiBold";
|
||||
src: local("Inter-SemiBold"), url(/static/media/Inter-SemiBold.2277990330981b8409bb.otf) format("font/otf");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-SemiBoldItalic";
|
||||
src: local("Inter-SemiBoldItalic"), url(/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf) format("font/otf");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Bold";
|
||||
src: local("Inter-Bold"), url(/static/media/Inter-Bold.8d330503e1d034ad68de.otf) format("font/otf");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-BoldItalic";
|
||||
src: local("Inter-BoldItalic"), url(/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf) format("font/otf");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-ExtraBold";
|
||||
src: local("Inter-ExtraBold"), url(/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf) format("font/otf");
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-ExtraBoldItalic";
|
||||
src: local("Inter-ExtraBoldItalic"), url(/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf) format("font/otf");
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-Black";
|
||||
src: local("Inter-Black"), url(/static/media/Inter-Black.66e9a87f1c921e844ed4.otf) format("font/otf");
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter-BlackItalic";
|
||||
src: local("Inter-BlackItalic"), url(/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf) format("font/otf");
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the react-native-web reset:
|
||||
* https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
|
||||
@@ -153,7 +252,6 @@
|
||||
|
||||
/* ProseMirror */
|
||||
.ProseMirror {
|
||||
font: 18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Liberation Sans", Helvetica, Arial, sans-serif;
|
||||
min-height: 140px;
|
||||
}
|
||||
.ProseMirror-dark {
|
||||
|
||||
@@ -3887,7 +3887,7 @@
|
||||
dependencies:
|
||||
cross-spawn "^6.0.5"
|
||||
|
||||
"@expo/spawn-async@^1.5.0", "@expo/spawn-async@^1.7.0", "@expo/spawn-async@^1.7.2":
|
||||
"@expo/spawn-async@^1.5.0", "@expo/spawn-async@^1.7.2":
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.2.tgz#fcfe66c3e387245e72154b1a7eae8cada6a47f58"
|
||||
integrity sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==
|
||||
@@ -6006,188 +6006,181 @@
|
||||
dset "^3.1.1"
|
||||
tiny-hashes "^1.0.1"
|
||||
|
||||
"@sentry-internal/tracing@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.52.0.tgz#c4e0750ad0c3949c5bb4b59cbb708b0fef274080"
|
||||
integrity sha512-o1YPcRGtC9tjeFCvWRJsbgK94zpExhzfxWaldAKvi3PuWEmPeewSdO/Q5pBIY1QonvSI+Q3gysLRcVlLYHhO5A==
|
||||
"@sentry-internal/feedback@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.119.0.tgz#429b3ea0fd34e928d2e7de5dcbe9377272a3f221"
|
||||
integrity sha512-om8TkAU5CQGO8nkmr7qsSBVkP+/vfeS4JgtW3sjoTK0fhj26+DljR6RlfCGWtYQdPSP6XV7atcPTjbSnsmG9FQ==
|
||||
dependencies:
|
||||
"@sentry/core" "7.52.0"
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry-internal/tracing@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.52.1.tgz#c98823afd2f9814466fa26f24a1a54fe63b27c24"
|
||||
integrity sha512-6N99rE+Ek0LgbqSzI/XpsKSLUyJjQ9nychViy+MP60p1x+hllukfTsDbNtUNrPlW0Bx+vqUrWKkAqmTFad94TQ==
|
||||
"@sentry-internal/replay-canvas@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.119.0.tgz#85669d184ba79150e64d05de02f5e2b616e68371"
|
||||
integrity sha512-NL02VQx6ekPxtVRcsdp1bp5Tb5w6vnfBKSIfMKuDRBy5A10Uc3GSoy/c3mPyHjOxB84452A+xZSx6bliEzAnuA==
|
||||
dependencies:
|
||||
"@sentry/core" "7.52.1"
|
||||
"@sentry/types" "7.52.1"
|
||||
"@sentry/utils" "7.52.1"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/replay" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/browser@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.52.0.tgz#55d266c89ed668389ff687e5cc885c27016ea85c"
|
||||
integrity sha512-Sib0T24cQCqqqAhg+nZdfI7qNYGE03jiM3RbY7yG5UoycdnJzWEwrBVSzRTgg3Uya9TRTEGJ+d9vxPIU5TL7TA==
|
||||
"@sentry-internal/tracing@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.119.0.tgz#201561af2a4ad1837333287c26050a5e688537ca"
|
||||
integrity sha512-oKdFJnn+56f0DHUADlL8o9l8jTib3VDLbWQBVkjD9EprxfaCwt2m8L5ACRBdQ8hmpxCEo4I8/6traZ7qAdBUqA==
|
||||
dependencies:
|
||||
"@sentry-internal/tracing" "7.52.0"
|
||||
"@sentry/core" "7.52.0"
|
||||
"@sentry/replay" "7.52.0"
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/browser@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.52.1.tgz#f112ca4170bb5023f050bdcbcce5621b475a46eb"
|
||||
integrity sha512-HrCOfieX68t+Wj42VIkraLYwx8kN5311SdBkHccevWs2Y2dZU7R9iLbI87+nb5kpOPQ7jVWW7d6QI/yZmliYgQ==
|
||||
"@sentry/babel-plugin-component-annotate@2.20.1":
|
||||
version "2.20.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.20.1.tgz#204c63ed006a048f48f633876e1b8bacf87a9722"
|
||||
integrity sha512-4mhEwYTK00bIb5Y9UWIELVUfru587Vaeg0DQGswv4aIRHIiMKLyNqCEejaaybQ/fNChIZOKmvyqXk430YVd7Qg==
|
||||
|
||||
"@sentry/browser@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.119.0.tgz#65004015c107be5d2f49a852ebcffc5d19d90e0d"
|
||||
integrity sha512-WwmW1Y4D764kVGeKmdsNvQESZiAn9t8LmCWO0ucBksrjL2zw9gBPtOpRcO6l064sCLeSxxzCN+kIxhRm1gDFEA==
|
||||
dependencies:
|
||||
"@sentry-internal/tracing" "7.52.1"
|
||||
"@sentry/core" "7.52.1"
|
||||
"@sentry/replay" "7.52.1"
|
||||
"@sentry/types" "7.52.1"
|
||||
"@sentry/utils" "7.52.1"
|
||||
tslib "^1.9.3"
|
||||
"@sentry-internal/feedback" "7.119.0"
|
||||
"@sentry-internal/replay-canvas" "7.119.0"
|
||||
"@sentry-internal/tracing" "7.119.0"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/integrations" "7.119.0"
|
||||
"@sentry/replay" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/cli@2.17.5":
|
||||
version "2.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.17.5.tgz#d41e24893a843bcd41e14274044a7ddea9332824"
|
||||
integrity sha512-0tXjLDpaKB46851EMJ6NbP0o9/gdEaDSLAyjEtXxlVO6+RyhUj6x6jDwn0vis8n/7q0AvbIjAcJrot+TbZP+WQ==
|
||||
"@sentry/cli-darwin@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.36.1.tgz#786adf6984dbe3c6fb7dac51b625c314117b807d"
|
||||
integrity sha512-JOHQjVD8Kqxm1jUKioAP5ohLOITf+Dh6+DBz4gQjCNdotsvNW5m63TKROwq2oB811p+Jzv5304ujmN4cAqW1Ww==
|
||||
|
||||
"@sentry/cli-linux-arm64@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.36.1.tgz#ff449d7e7e715166257998c02cf635ca02acbadd"
|
||||
integrity sha512-R//3ZEkbzvoStr3IA7nxBZNiBYyxOljOqAhgiTnejXHmnuwDzM3TBA2n5vKPE/kBFxboEBEw0UTzTIRb1T0bgw==
|
||||
|
||||
"@sentry/cli-linux-arm@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.36.1.tgz#1ae5d335a1b4cd217a34c2bd6c6f5e0670136eb3"
|
||||
integrity sha512-gvEOKN0fWL2AVqUBKHNXPRZfJNvKTs8kQhS8cQqahZGgZHiPCI4BqW45cKMq+ZTt1UUbLmt6khx5Dz7wi+0i5A==
|
||||
|
||||
"@sentry/cli-linux-i686@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.36.1.tgz#112b9e26357e918cbbba918114ec8cdab07cdf60"
|
||||
integrity sha512-R7sW5Vk/HacVy2YgQoQB+PwccvFYf2CZVPSFSFm2z7MEfNe77UYHWUq+sjJ4vxWG6HDWGVmaX0fjxyDkE01JRA==
|
||||
|
||||
"@sentry/cli-linux-x64@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.36.1.tgz#c3e5bdb0c9a4bb44c83927c62a3cd7e006709bf7"
|
||||
integrity sha512-UMr3ik8ksA7zQfbzsfwCb+ztenLnaeAbX94Gp+bzANZwPfi/vVHf2bLyqsBs4OyVt9SPlN1bbM/RTGfMjZ3JOw==
|
||||
|
||||
"@sentry/cli-win32-i686@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.36.1.tgz#819573320e885e1dbf59b0a01d3bd370c84c1708"
|
||||
integrity sha512-CflvhnvxPEs5GWQuuDtYSLqPrBaPbcSJFlBuUIb+8WNzRxvVfjgw1qzfZmkQqABqiy/YEsEekllOoMFZAvCcVA==
|
||||
|
||||
"@sentry/cli-win32-x64@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.36.1.tgz#80779b4bffb4e2e32944eae72c60e6f40151b4dc"
|
||||
integrity sha512-wWqht2xghcK3TGnooHZSzA3WSjdtno/xFjZLvWmw38rblGwgKMxLZnlxV6uDyS+OJ6CbfDTlCRay/0TIqA0N8g==
|
||||
|
||||
"@sentry/cli@2.36.1":
|
||||
version "2.36.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.36.1.tgz#a9146b798cb6d2f782a7a48d74633ddcd88dc8d3"
|
||||
integrity sha512-gzK5uQKDWKhyH5udoB5+oaUNrS//urWyaXgKvHKz4gFfl744HuKY9dpLPP2nMnf0zLGmGM6xJnMXLqILq0mtxw==
|
||||
dependencies:
|
||||
https-proxy-agent "^5.0.0"
|
||||
node-fetch "^2.6.7"
|
||||
progress "^2.0.3"
|
||||
proxy-from-env "^1.1.0"
|
||||
which "^2.0.2"
|
||||
optionalDependencies:
|
||||
"@sentry/cli-darwin" "2.36.1"
|
||||
"@sentry/cli-linux-arm" "2.36.1"
|
||||
"@sentry/cli-linux-arm64" "2.36.1"
|
||||
"@sentry/cli-linux-i686" "2.36.1"
|
||||
"@sentry/cli-linux-x64" "2.36.1"
|
||||
"@sentry/cli-win32-i686" "2.36.1"
|
||||
"@sentry/cli-win32-x64" "2.36.1"
|
||||
|
||||
"@sentry/core@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.52.0.tgz#6c820ca48fe2f06bfd6b290044c96de2375f2ad4"
|
||||
integrity sha512-BWdG6vCMeUeMhF4ILpxXTmw70JJvT1MGJcnv09oSupWHTmqy6I19YP6YcEyFuBL4jXPN51eCl7luIdLGJrPbOg==
|
||||
"@sentry/core@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.119.0.tgz#a6e41119bb03ec27689f9ad04e79d1fba5b7fc37"
|
||||
integrity sha512-CS2kUv9rAJJEjiRat6wle3JATHypB0SyD7pt4cpX5y0dN5dZ1JrF57oLHRMnga9fxRivydHz7tMTuBhSSwhzjw==
|
||||
dependencies:
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/core@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.52.1.tgz#4de702937ba8944802bb06eb8dfdf089c39f6bab"
|
||||
integrity sha512-36clugQu5z/9jrit1gzI7KfKbAUimjRab39JeR0mJ6pMuKLTTK7PhbpUAD4AQBs9qVeXN2c7h9SVZiSA0UDvkg==
|
||||
"@sentry/hub@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.119.0.tgz#a94d657b9d3cfd4cc061c5c238f86faefb55d5d8"
|
||||
integrity sha512-183h5B/rZosLxpB+ZYOvFdHk0rwZbKskxqKFtcyPbDAfpCUgCass41UTqyxF6aH1qLgCRxX8GcLRF7frIa/SOg==
|
||||
dependencies:
|
||||
"@sentry/types" "7.52.1"
|
||||
"@sentry/utils" "7.52.1"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/hub@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.52.0.tgz#ffc087d58c745d57108862faa0f701b15503dcc2"
|
||||
integrity sha512-w3d8Pmp3Fx2zbbjz6hAeIbsFEkLyrUs9YTGG2y8oCoTlAtGK+AjdG+Z0H/clAZONflD/je2EmFHCI0EuXE9tEw==
|
||||
"@sentry/integrations@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.119.0.tgz#5b25c603026dbacfe1ae7bb8d768506a129149fb"
|
||||
integrity sha512-OHShvtsRW0A+ZL/ZbMnMqDEtJddPasndjq+1aQXw40mN+zeP7At/V1yPZyFaURy86iX7Ucxw5BtmzuNy7hLyTA==
|
||||
dependencies:
|
||||
"@sentry/core" "7.52.0"
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/integrations@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.52.0.tgz#632aa5e54bdfdab910a24057c2072634a2670409"
|
||||
integrity sha512-tqxYzgc71XdFD8MTCsVMCPef08lPY9jULE5Zi7TzjyV2AItDRJPkixG0qjwjOGwCtN/6KKz0lGPGYU8ZDxvsbg==
|
||||
dependencies:
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
localforage "^1.8.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/integrations@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.52.1.tgz#e8a5988477e8d295fa1d90ce5628c1a7794c2a09"
|
||||
integrity sha512-4uejF01723wzEHjcP5AcNcV+Z/6U27b1LyaDu0jY3XDry98MMjhS/ASzecLpaEFxi3dh/jMTUrNp1u7WMj59Lg==
|
||||
"@sentry/react-native@5.32.0":
|
||||
version "5.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-5.32.0.tgz#14c46a65f7359f5e74a9cef7edb9d7bf9a0a449d"
|
||||
integrity sha512-Rh5EEYuWUyPaTaL8b/tl3okGiWb3LSvfYiS/WkvTYH+pFYr2RNtrZSCxhP5TpWSqkoy8VVXeYhSmlBvjfD/uDg==
|
||||
dependencies:
|
||||
"@sentry/types" "7.52.1"
|
||||
"@sentry/utils" "7.52.1"
|
||||
localforage "^1.8.1"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/babel-plugin-component-annotate" "2.20.1"
|
||||
"@sentry/browser" "7.119.0"
|
||||
"@sentry/cli" "2.36.1"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/hub" "7.119.0"
|
||||
"@sentry/integrations" "7.119.0"
|
||||
"@sentry/react" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/react-native@5.5.0":
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-5.5.0.tgz#b1283f68465b1772ad6059ebba149673cef33f2d"
|
||||
integrity sha512-xrES+OAIu3HFhoQSuJjd16Hh02/mByuNoKUjF7e4WDGIiTew3aqlqeLjU7x4npmg5Vbt+ND5jR12u/NmdfArwg==
|
||||
"@sentry/react@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.119.0.tgz#79f2c9d94322a3afbfa8af9f5b872f7c2e9b0820"
|
||||
integrity sha512-cf8Cei+qdSA26gx+IMAuc/k44PeBImNzIpXi3930SLhUe44ypT5OZ/44L6xTODHZzTIyMSJPduf59vT2+eW9yg==
|
||||
dependencies:
|
||||
"@sentry/browser" "7.52.0"
|
||||
"@sentry/cli" "2.17.5"
|
||||
"@sentry/core" "7.52.0"
|
||||
"@sentry/hub" "7.52.0"
|
||||
"@sentry/integrations" "7.52.0"
|
||||
"@sentry/react" "7.52.0"
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
|
||||
"@sentry/react@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.52.0.tgz#d12d270ec82dea0474e69deb9112181affe7c524"
|
||||
integrity sha512-VQxquyFFlvB81k7UER7tTJxjzbczNI2jqsw6nN1TVDrAIDt8/hT2x7m/M0FlWc88roBKuaMmbvzfNGWaL9abyQ==
|
||||
dependencies:
|
||||
"@sentry/browser" "7.52.0"
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
"@sentry/browser" "7.119.0"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
hoist-non-react-statics "^3.3.2"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/react@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.52.1.tgz#5f30919f4680493558c5233165b2092d2b59f6d1"
|
||||
integrity sha512-RRH+GJE5TNg5QS86bSjSZuR2snpBTOO5/SU9t4BOqZMknzhMVTClGMm84hffJa9pMPMJPQ2fWQAbhrlD8RcF6w==
|
||||
"@sentry/replay@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.119.0.tgz#50881079d013c77f87a994331d8bcad1d49e0960"
|
||||
integrity sha512-BnNsYL+X5I4WCH6wOpY6HQtp4MgVt0NVlhLUsEyrvMUiTs0bPkDBrulsgZQBUKJsbOr3l9nHrFoNVB/0i6WNLA==
|
||||
dependencies:
|
||||
"@sentry/browser" "7.52.1"
|
||||
"@sentry/types" "7.52.1"
|
||||
"@sentry/utils" "7.52.1"
|
||||
hoist-non-react-statics "^3.3.2"
|
||||
tslib "^1.9.3"
|
||||
"@sentry-internal/tracing" "7.119.0"
|
||||
"@sentry/core" "7.119.0"
|
||||
"@sentry/types" "7.119.0"
|
||||
"@sentry/utils" "7.119.0"
|
||||
|
||||
"@sentry/replay@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.52.0.tgz#4d78e88282d2c1044ea4b648a68d1b22173e810d"
|
||||
integrity sha512-RRPALjDST2s7MHiMcUJ7Wo4WW7EWfUDYSG0LuhMT8DNc+ZsxQoFsLYX/yz8b3f0IUSr7xKBXP+aPeIy3jDAS2g==
|
||||
"@sentry/types@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.119.0.tgz#8b3d7a1405c362e75cd900d46089df4e70919d2a"
|
||||
integrity sha512-27qQbutDBPKGbuJHROxhIWc1i0HJaGLA90tjMu11wt0E4UNxXRX+UQl4Twu68v4EV3CPvQcEpQfgsViYcXmq+w==
|
||||
|
||||
"@sentry/utils@7.119.0":
|
||||
version "7.119.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.119.0.tgz#debe29020f6ef3786a5bd855cf1b97116b7be826"
|
||||
integrity sha512-ZwyXexWn2ZIe2bBoYnXJVPc2esCSbKpdc6+0WJa8eutXfHq3FRKg4ohkfCBpfxljQGEfP1+kfin945lA21Ka+A==
|
||||
dependencies:
|
||||
"@sentry/core" "7.52.0"
|
||||
"@sentry/types" "7.52.0"
|
||||
"@sentry/utils" "7.52.0"
|
||||
|
||||
"@sentry/replay@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.52.1.tgz#272a0bcb79bb9ffce99b5dcaf864f18d729ce0da"
|
||||
integrity sha512-A+RaUmpU9/yBHnU3ATemc6wAvobGno0yf5R6fZYkAFoo2FCR2YG6AXxkTazymIf8v2DnLGaSDORYDPdhQClU9A==
|
||||
dependencies:
|
||||
"@sentry/core" "7.52.1"
|
||||
"@sentry/types" "7.52.1"
|
||||
"@sentry/utils" "7.52.1"
|
||||
|
||||
"@sentry/types@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.52.0.tgz#b7d5372f17355e3991cbe818ad567f3fe277cc6b"
|
||||
integrity sha512-XnEWpS6P6UdP1FqbmeqhI96Iowqd2jM5R7zJ97txTdAd5NmdHHH0pODTR9NiQViA1WlsXDut7ZLxgPzC9vIcMA==
|
||||
|
||||
"@sentry/types@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.52.1.tgz#bcff6d0462d9b9b7b9ec31c0068fe02d44f25da2"
|
||||
integrity sha512-OMbGBPrJsw0iEXwZ2bJUYxewI1IEAU2e1aQGc0O6QW5+6hhCh+8HO8Xl4EymqwejjztuwStkl6G1qhK+Q0/Row==
|
||||
|
||||
"@sentry/utils@7.52.0":
|
||||
version "7.52.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.52.0.tgz#cacc36d905036ba7084c14965e964fc44239d7f0"
|
||||
integrity sha512-X1NHYuqW0qpZfP731YcVe+cn36wJdAeBHPYPIkXCl4o4GePCJfH/CM/+9V9cZykNjyLrs2Xy/TavSAHNCj8j7w==
|
||||
dependencies:
|
||||
"@sentry/types" "7.52.0"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/utils@7.52.1":
|
||||
version "7.52.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.52.1.tgz#4a3e49b918f78dba4524c924286210259020cac5"
|
||||
integrity sha512-MPt1Xu/jluulknW8CmZ2naJ53jEdtdwCBSo6fXJvOTI0SDqwIPbXDVrsnqLAhVJuIN7xbkj96nuY/VBR6S5sWg==
|
||||
dependencies:
|
||||
"@sentry/types" "7.52.1"
|
||||
tslib "^1.9.3"
|
||||
"@sentry/types" "7.119.0"
|
||||
|
||||
"@sideway/address@^4.1.3":
|
||||
version "4.1.4"
|
||||
@@ -12226,6 +12219,13 @@ expo-file-system@^17.0.1, expo-file-system@~17.0.1:
|
||||
resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-17.0.1.tgz#b9f8af8c1c06ec71d96fd7a0d2567fa9e1c88f15"
|
||||
integrity sha512-dYpnZJqTGj6HCYJyXAgpFkQWsiCH3HY1ek2cFZVHFoEc5tLz9gmdEgTF6nFHurvmvfmXqxi7a5CXyVm0aFYJBw==
|
||||
|
||||
expo-font@~12.0.10:
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-12.0.10.tgz#62deaf1f46159d7839f01305f44079268781b1db"
|
||||
integrity sha512-Q1i2NuYri3jy32zdnBaHHCya1wH1yMAsI+3CCmj9zlQzlhsS9Bdwcj2W3c5eU5FvH2hsNQy4O+O1NnM6o/pDaQ==
|
||||
dependencies:
|
||||
fontfaceobserver "^2.1.0"
|
||||
|
||||
expo-font@~12.0.5:
|
||||
version "12.0.5"
|
||||
resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-12.0.5.tgz#3451c2bd3f98859b127a6484d3474a292889b93f"
|
||||
@@ -19032,10 +19032,10 @@ react-native-get-random-values@~1.11.0:
|
||||
dependencies:
|
||||
fast-base64-decode "^1.0.0"
|
||||
|
||||
react-native-image-crop-picker@0.40.3:
|
||||
version "0.40.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-crop-picker/-/react-native-image-crop-picker-0.40.3.tgz#a6b135cd1218a33ad126c1a148ec5a1bd01737ff"
|
||||
integrity sha512-45PKcTnsnLS+E36YwoXutllQdRSOuOsMN0IRcAcwsFXOuAQIOtugXlAuGGL28JHKb/ATaSSPvqCSrdG65Jv3GA==
|
||||
react-native-image-crop-picker@0.41.2:
|
||||
version "0.41.2"
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-crop-picker/-/react-native-image-crop-picker-0.41.2.tgz#824fa8fee8391fbb3e0b5ae2973221a2dff0cafb"
|
||||
integrity sha512-GcDu/adXU/1y/MrxsbOfqcGRGWC2pTttt5VGy/jyRJ6GXfoC29fTQf8SG5kGtc5schSR6K+mKYO4uW6eJPljlQ==
|
||||
|
||||
react-native-ios-context-menu@^1.15.3:
|
||||
version "1.15.3"
|
||||
@@ -20067,19 +20067,6 @@ send@0.18.0, send@^0.18.0:
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
sentry-expo@~7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/sentry-expo/-/sentry-expo-7.0.1.tgz#025f0e90ab7f7cba1e00c892fabc027de21bc5bc"
|
||||
integrity sha512-8vmOy4R+qM1peQA9EP8rDGUMBhgMU1D5FyuWY9kfNGatmWuvEmlZpVgaXoXaNPIhPgf2TMrvQIlbqLHtTkoeSA==
|
||||
dependencies:
|
||||
"@expo/spawn-async" "^1.7.0"
|
||||
"@sentry/integrations" "7.52.1"
|
||||
"@sentry/react" "7.52.1"
|
||||
"@sentry/react-native" "5.5.0"
|
||||
"@sentry/types" "7.52.1"
|
||||
mkdirp "^1.0.4"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
serialize-error@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
|
||||
@@ -21361,7 +21348,7 @@ tsconfig-paths@^3.14.2:
|
||||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||