mirror of https://github.com/tooot-app/app
Compare commits
No commits in common. "6644ca64d70ce9be576ae83be95203ded10b6daf" and "a70e1af5355b2d05db8daedd0f2b5ef1b679c547" have entirely different histories.
6644ca64d7
...
a70e1af535
32
Gemfile.lock
32
Gemfile.lock
|
@ -17,16 +17,16 @@ GEM
|
||||||
artifactory (3.0.15)
|
artifactory (3.0.15)
|
||||||
atomos (0.1.3)
|
atomos (0.1.3)
|
||||||
aws-eventstream (1.2.0)
|
aws-eventstream (1.2.0)
|
||||||
aws-partitions (1.598.0)
|
aws-partitions (1.582.0)
|
||||||
aws-sdk-core (3.131.1)
|
aws-sdk-core (3.130.2)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.525.0)
|
aws-partitions (~> 1, >= 1.525.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
jmespath (~> 1, >= 1.6.1)
|
jmespath (~> 1.0)
|
||||||
aws-sdk-kms (1.57.0)
|
aws-sdk-kms (1.56.0)
|
||||||
aws-sdk-core (~> 3, >= 3.127.0)
|
aws-sdk-core (~> 3, >= 3.127.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sdk-s3 (1.114.0)
|
aws-sdk-s3 (1.113.2)
|
||||||
aws-sdk-core (~> 3, >= 3.127.0)
|
aws-sdk-core (~> 3, >= 3.127.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.4)
|
aws-sigv4 (~> 1.4)
|
||||||
|
@ -106,8 +106,8 @@ GEM
|
||||||
faraday-em_synchrony (1.0.0)
|
faraday-em_synchrony (1.0.0)
|
||||||
faraday-excon (1.1.0)
|
faraday-excon (1.1.0)
|
||||||
faraday-httpclient (1.0.1)
|
faraday-httpclient (1.0.1)
|
||||||
faraday-multipart (1.0.4)
|
faraday-multipart (1.0.3)
|
||||||
multipart-post (~> 2)
|
multipart-post (>= 1.2, < 3)
|
||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.1)
|
||||||
faraday-net_http_persistent (1.2.0)
|
faraday-net_http_persistent (1.2.0)
|
||||||
faraday-patron (1.0.0)
|
faraday-patron (1.0.0)
|
||||||
|
@ -116,7 +116,7 @@ GEM
|
||||||
faraday_middleware (1.2.0)
|
faraday_middleware (1.2.0)
|
||||||
faraday (~> 1.0)
|
faraday (~> 1.0)
|
||||||
fastimage (2.2.6)
|
fastimage (2.2.6)
|
||||||
fastlane (2.206.2)
|
fastlane (2.205.2)
|
||||||
CFPropertyList (>= 2.3, < 4.0.0)
|
CFPropertyList (>= 2.3, < 4.0.0)
|
||||||
addressable (>= 2.8, < 3.0.0)
|
addressable (>= 2.8, < 3.0.0)
|
||||||
artifactory (~> 3.0)
|
artifactory (~> 3.0)
|
||||||
|
@ -163,9 +163,9 @@ GEM
|
||||||
fourflusher (2.3.1)
|
fourflusher (2.3.1)
|
||||||
fuzzy_match (2.0.4)
|
fuzzy_match (2.0.4)
|
||||||
gh_inspector (1.1.3)
|
gh_inspector (1.1.3)
|
||||||
google-apis-androidpublisher_v3 (0.21.0)
|
google-apis-androidpublisher_v3 (0.19.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
google-apis-core (0.5.0)
|
google-apis-core (0.4.2)
|
||||||
addressable (~> 2.5, >= 2.5.1)
|
addressable (~> 2.5, >= 2.5.1)
|
||||||
googleauth (>= 0.16.2, < 2.a)
|
googleauth (>= 0.16.2, < 2.a)
|
||||||
httpclient (>= 2.8.1, < 3.a)
|
httpclient (>= 2.8.1, < 3.a)
|
||||||
|
@ -178,7 +178,7 @@ GEM
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
google-apis-playcustomapp_v1 (0.7.0)
|
google-apis-playcustomapp_v1 (0.7.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
google-apis-storage_v1 (0.14.0)
|
google-apis-storage_v1 (0.13.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
google-cloud-core (1.6.0)
|
google-cloud-core (1.6.0)
|
||||||
google-cloud-env (~> 1.0)
|
google-cloud-env (~> 1.0)
|
||||||
|
@ -202,14 +202,14 @@ GEM
|
||||||
os (>= 0.9, < 2.0)
|
os (>= 0.9, < 2.0)
|
||||||
signet (>= 0.16, < 2.a)
|
signet (>= 0.16, < 2.a)
|
||||||
highline (2.0.3)
|
highline (2.0.3)
|
||||||
http-cookie (1.0.5)
|
http-cookie (1.0.4)
|
||||||
domain_name (~> 0.5)
|
domain_name (~> 0.5)
|
||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
i18n (1.10.0)
|
i18n (1.10.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
jmespath (1.6.1)
|
jmespath (1.6.1)
|
||||||
json (2.6.2)
|
json (2.6.1)
|
||||||
jwt (2.4.1)
|
jwt (2.3.0)
|
||||||
memoist (0.16.2)
|
memoist (0.16.2)
|
||||||
mini_magick (4.11.0)
|
mini_magick (4.11.0)
|
||||||
mini_mime (1.1.2)
|
mini_mime (1.1.2)
|
||||||
|
@ -226,7 +226,7 @@ GEM
|
||||||
plist (3.6.0)
|
plist (3.6.0)
|
||||||
public_suffix (4.0.7)
|
public_suffix (4.0.7)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
representable (3.2.0)
|
representable (3.1.1)
|
||||||
declarative (< 0.1.0)
|
declarative (< 0.1.0)
|
||||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||||
uber (< 0.2.0)
|
uber (< 0.2.0)
|
||||||
|
@ -260,7 +260,7 @@ GEM
|
||||||
uber (0.1.0)
|
uber (0.1.0)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.8.2)
|
unf_ext (0.0.8.1)
|
||||||
unicode-display_width (1.8.0)
|
unicode-display_width (1.8.0)
|
||||||
webrick (1.7.0)
|
webrick (1.7.0)
|
||||||
word_wrap (1.0.0)
|
word_wrap (1.0.0)
|
||||||
|
|
|
@ -15,5 +15,3 @@
|
||||||
[@luizpicolo](https://github.com/luizpicolo) for Brazilian Portuguese
|
[@luizpicolo](https://github.com/luizpicolo) for Brazilian Portuguese
|
||||||
|
|
||||||
[@duy@mas.to](https://mas.to/@duy) for Vietnamese translation
|
[@duy@mas.to](https://mas.to/@duy) for Vietnamese translation
|
||||||
|
|
||||||
[@jk@mastodon.social](https://mastodon.social/@jk) for the famous Mastodon boop sound
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ PODS:
|
||||||
- DoubleConversion (1.1.6)
|
- DoubleConversion (1.1.6)
|
||||||
- EASClient (0.2.1):
|
- EASClient (0.2.1):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXApplication (4.1.0):
|
|
||||||
- ExpoModulesCore
|
|
||||||
- EXAV (11.2.3):
|
- EXAV (11.2.3):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- React-runtimeexecutor
|
- React-runtimeexecutor
|
||||||
|
@ -25,8 +23,6 @@ PODS:
|
||||||
- EXFirebaseCore (5.0.0):
|
- EXFirebaseCore (5.0.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- Firebase/Core (= 8.14.0)
|
- Firebase/Core (= 8.14.0)
|
||||||
- EXFont (10.1.0):
|
|
||||||
- ExpoModulesCore
|
|
||||||
- EXImageLoader (3.2.0):
|
- EXImageLoader (3.2.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- React-Core
|
- React-Core
|
||||||
|
@ -41,13 +37,8 @@ PODS:
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoHaptics (11.2.0):
|
- ExpoHaptics (11.2.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoImageManipulator (10.3.1):
|
|
||||||
- EXImageLoader
|
|
||||||
- ExpoModulesCore
|
|
||||||
- ExpoImagePicker (13.1.1):
|
- ExpoImagePicker (13.1.1):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoKeepAwake (10.1.1):
|
|
||||||
- ExpoModulesCore
|
|
||||||
- ExpoLocalization (13.0.0):
|
- ExpoLocalization (13.0.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoModulesCore (0.9.2):
|
- ExpoModulesCore (0.9.2):
|
||||||
|
@ -599,7 +590,6 @@ DEPENDENCIES:
|
||||||
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
|
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
|
||||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||||
- EASClient (from `../node_modules/expo-eas-client/ios`)
|
- EASClient (from `../node_modules/expo-eas-client/ios`)
|
||||||
- EXApplication (from `../node_modules/expo-application/ios`)
|
|
||||||
- EXAV (from `../node_modules/expo-av/ios`)
|
- EXAV (from `../node_modules/expo-av/ios`)
|
||||||
- EXConstants (from `../node_modules/expo-constants/ios`)
|
- EXConstants (from `../node_modules/expo-constants/ios`)
|
||||||
- EXDevice (from `../node_modules/expo-device/ios`)
|
- EXDevice (from `../node_modules/expo-device/ios`)
|
||||||
|
@ -607,7 +597,6 @@ DEPENDENCIES:
|
||||||
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
|
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
|
||||||
- EXFirebaseAnalytics (from `../node_modules/expo-firebase-analytics/ios`)
|
- EXFirebaseAnalytics (from `../node_modules/expo-firebase-analytics/ios`)
|
||||||
- EXFirebaseCore (from `../node_modules/expo-firebase-core/ios`)
|
- EXFirebaseCore (from `../node_modules/expo-firebase-core/ios`)
|
||||||
- EXFont (from `../node_modules/expo-font/ios`)
|
|
||||||
- EXImageLoader (from `../node_modules/expo-image-loader/ios`)
|
- EXImageLoader (from `../node_modules/expo-image-loader/ios`)
|
||||||
- EXJSONUtils (from `../node_modules/expo-json-utils/ios`)
|
- EXJSONUtils (from `../node_modules/expo-json-utils/ios`)
|
||||||
- EXManifests (from `../node_modules/expo-manifests/ios`)
|
- EXManifests (from `../node_modules/expo-manifests/ios`)
|
||||||
|
@ -615,9 +604,7 @@ DEPENDENCIES:
|
||||||
- Expo (from `../node_modules/expo/ios`)
|
- Expo (from `../node_modules/expo/ios`)
|
||||||
- ExpoCrypto (from `../node_modules/expo-crypto/ios`)
|
- ExpoCrypto (from `../node_modules/expo-crypto/ios`)
|
||||||
- ExpoHaptics (from `../node_modules/expo-haptics/ios`)
|
- ExpoHaptics (from `../node_modules/expo-haptics/ios`)
|
||||||
- ExpoImageManipulator (from `../node_modules/expo-image-manipulator/ios`)
|
|
||||||
- ExpoImagePicker (from `../node_modules/expo-image-picker/ios`)
|
- ExpoImagePicker (from `../node_modules/expo-image-picker/ios`)
|
||||||
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
|
|
||||||
- ExpoLocalization (from `../node_modules/expo-localization/ios`)
|
- ExpoLocalization (from `../node_modules/expo-localization/ios`)
|
||||||
- ExpoModulesCore (from `../node_modules/expo-modules-core/ios`)
|
- ExpoModulesCore (from `../node_modules/expo-modules-core/ios`)
|
||||||
- ExpoRandom (from `../node_modules/expo-random/ios`)
|
- ExpoRandom (from `../node_modules/expo-random/ios`)
|
||||||
|
@ -714,8 +701,6 @@ EXTERNAL SOURCES:
|
||||||
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
||||||
EASClient:
|
EASClient:
|
||||||
:path: "../node_modules/expo-eas-client/ios"
|
:path: "../node_modules/expo-eas-client/ios"
|
||||||
EXApplication:
|
|
||||||
:path: "../node_modules/expo-application/ios"
|
|
||||||
EXAV:
|
EXAV:
|
||||||
:path: "../node_modules/expo-av/ios"
|
:path: "../node_modules/expo-av/ios"
|
||||||
EXConstants:
|
EXConstants:
|
||||||
|
@ -730,8 +715,6 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/expo-firebase-analytics/ios"
|
:path: "../node_modules/expo-firebase-analytics/ios"
|
||||||
EXFirebaseCore:
|
EXFirebaseCore:
|
||||||
:path: "../node_modules/expo-firebase-core/ios"
|
:path: "../node_modules/expo-firebase-core/ios"
|
||||||
EXFont:
|
|
||||||
:path: "../node_modules/expo-font/ios"
|
|
||||||
EXImageLoader:
|
EXImageLoader:
|
||||||
:path: "../node_modules/expo-image-loader/ios"
|
:path: "../node_modules/expo-image-loader/ios"
|
||||||
EXJSONUtils:
|
EXJSONUtils:
|
||||||
|
@ -746,12 +729,8 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/expo-crypto/ios"
|
:path: "../node_modules/expo-crypto/ios"
|
||||||
ExpoHaptics:
|
ExpoHaptics:
|
||||||
:path: "../node_modules/expo-haptics/ios"
|
:path: "../node_modules/expo-haptics/ios"
|
||||||
ExpoImageManipulator:
|
|
||||||
:path: "../node_modules/expo-image-manipulator/ios"
|
|
||||||
ExpoImagePicker:
|
ExpoImagePicker:
|
||||||
:path: "../node_modules/expo-image-picker/ios"
|
:path: "../node_modules/expo-image-picker/ios"
|
||||||
ExpoKeepAwake:
|
|
||||||
:path: "../node_modules/expo-keep-awake/ios"
|
|
||||||
ExpoLocalization:
|
ExpoLocalization:
|
||||||
:path: "../node_modules/expo-localization/ios"
|
:path: "../node_modules/expo-localization/ios"
|
||||||
ExpoModulesCore:
|
ExpoModulesCore:
|
||||||
|
@ -880,7 +859,6 @@ SPEC CHECKSUMS:
|
||||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||||
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
|
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
|
||||||
EASClient: 93565f4d024559b75eac62bc7d50acaa354614f6
|
EASClient: 93565f4d024559b75eac62bc7d50acaa354614f6
|
||||||
EXApplication: d6562af1204162e0ac46d341a7d4e5dc720b33de
|
|
||||||
EXAV: 88f61c5af8415715b7ee51f084c1020235b85c56
|
EXAV: 88f61c5af8415715b7ee51f084c1020235b85c56
|
||||||
EXConstants: fdbe52259365b6a6faaa5e99a3b82cfa6bc2eb61
|
EXConstants: fdbe52259365b6a6faaa5e99a3b82cfa6bc2eb61
|
||||||
EXDevice: 0115b360059ccd32c1701744e374e3259ffbdd3c
|
EXDevice: 0115b360059ccd32c1701744e374e3259ffbdd3c
|
||||||
|
@ -888,7 +866,6 @@ SPEC CHECKSUMS:
|
||||||
EXFileSystem: 2aa2d9289f84bca9532b9ccbd81504fa31eb1ded
|
EXFileSystem: 2aa2d9289f84bca9532b9ccbd81504fa31eb1ded
|
||||||
EXFirebaseAnalytics: aeefc63f92277313c3ee86da6a7ecf892f345ed1
|
EXFirebaseAnalytics: aeefc63f92277313c3ee86da6a7ecf892f345ed1
|
||||||
EXFirebaseCore: bdfa87df74fa1b74a6b38957561456aabad28a4f
|
EXFirebaseCore: bdfa87df74fa1b74a6b38957561456aabad28a4f
|
||||||
EXFont: 04235cc22e6fef86028feb67db452978dc6f240f
|
|
||||||
EXImageLoader: b88e053d760f85a82405b1db2de4abf11978fc9f
|
EXImageLoader: b88e053d760f85a82405b1db2de4abf11978fc9f
|
||||||
EXJSONUtils: 2a74b8f40f1523cc3f92af99c91aa78201737a77
|
EXJSONUtils: 2a74b8f40f1523cc3f92af99c91aa78201737a77
|
||||||
EXManifests: 0c6134b7b6f3236a93a778c3f44ba1cfb3f9fa3d
|
EXManifests: 0c6134b7b6f3236a93a778c3f44ba1cfb3f9fa3d
|
||||||
|
@ -896,9 +873,7 @@ SPEC CHECKSUMS:
|
||||||
Expo: b9fff0a1eac0f424fc68ea49b4347fb308e52e17
|
Expo: b9fff0a1eac0f424fc68ea49b4347fb308e52e17
|
||||||
ExpoCrypto: d0d0f3e20875dc450b4ec88f0fb608da5c2c6c17
|
ExpoCrypto: d0d0f3e20875dc450b4ec88f0fb608da5c2c6c17
|
||||||
ExpoHaptics: ad58ec96a25e57579c14a47c7d71f0de0de8656a
|
ExpoHaptics: ad58ec96a25e57579c14a47c7d71f0de0de8656a
|
||||||
ExpoImageManipulator: b55580bbc7b10099c7707949903e7176a8542ee8
|
|
||||||
ExpoImagePicker: d9d6b4f29db437fc7796f13cee5f133f5b4b5f7c
|
ExpoImagePicker: d9d6b4f29db437fc7796f13cee5f133f5b4b5f7c
|
||||||
ExpoKeepAwake: c0c494b442ecd8122974c13b93ccfb57bd408e88
|
|
||||||
ExpoLocalization: 8f619bb6eec64575cd5220bfabbd7b4e2d6f33f8
|
ExpoLocalization: 8f619bb6eec64575cd5220bfabbd7b4e2d6f33f8
|
||||||
ExpoModulesCore: e4278a668e8c13c0269ed8b8a4200989deea2973
|
ExpoModulesCore: e4278a668e8c13c0269ed8b8a4200989deea2973
|
||||||
ExpoRandom: 14df0976aa363a71a730ceb7655250f3047c0e42
|
ExpoRandom: 14df0976aa363a71a730ceb7655250f3047c0e42
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
"expo-file-system": "14.0.0",
|
"expo-file-system": "14.0.0",
|
||||||
"expo-firebase-analytics": "7.0.0",
|
"expo-firebase-analytics": "7.0.0",
|
||||||
"expo-haptics": "11.2.0",
|
"expo-haptics": "11.2.0",
|
||||||
"expo-image-manipulator": "^10.3.1",
|
|
||||||
"expo-image-picker": "13.1.1",
|
"expo-image-picker": "13.1.1",
|
||||||
"expo-linking": "3.1.0",
|
"expo-linking": "3.1.0",
|
||||||
"expo-localization": "13.0.0",
|
"expo-localization": "13.0.0",
|
||||||
|
@ -154,4 +153,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,11 +178,11 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let text: string | undefined = undefined
|
let text: string | undefined = undefined
|
||||||
let media: { uri: string; mime: string }[] = []
|
let media: { path: string; mime: string }[] = []
|
||||||
|
|
||||||
const typesImage = ['png', 'jpg', 'jpeg', 'gif']
|
const typesImage = ['png', 'jpg', 'jpeg', 'gif']
|
||||||
const typesVideo = ['mp4', 'm4v', 'mov', 'webm', 'mpeg']
|
const typesVideo = ['mp4', 'm4v', 'mov', 'webm', 'mpeg']
|
||||||
const filterMedia = ({ uri, mime }: { uri: string; mime: string }) => {
|
const filterMedia = ({ path, mime }: { path: string; mime: string }) => {
|
||||||
if (mime.startsWith('image/')) {
|
if (mime.startsWith('image/')) {
|
||||||
if (!typesImage.includes(mime.split('/')[1])) {
|
if (!typesImage.includes(mime.split('/')[1])) {
|
||||||
console.warn('Image type not supported:', mime.split('/')[1])
|
console.warn('Image type not supported:', mime.split('/')[1])
|
||||||
|
@ -195,7 +195,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
media.push({ uri, mime })
|
media.push({ path, mime })
|
||||||
} else if (mime.startsWith('video/')) {
|
} else if (mime.startsWith('video/')) {
|
||||||
if (!typesVideo.includes(mime.split('/')[1])) {
|
if (!typesVideo.includes(mime.split('/')[1])) {
|
||||||
console.warn('Video type not supported:', mime.split('/')[1])
|
console.warn('Video type not supported:', mime.split('/')[1])
|
||||||
|
@ -208,17 +208,17 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
media.push({ uri, mime })
|
media.push({ path, mime })
|
||||||
} else {
|
} else {
|
||||||
if (typesImage.includes(uri.split('.').pop() || '')) {
|
if (typesImage.includes(path.split('.').pop() || '')) {
|
||||||
media.push({ uri, mime: 'image/jpg' })
|
media.push({ path: path, mime: 'image/jpg' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (typesVideo.includes(uri.split('.').pop() || '')) {
|
if (typesVideo.includes(path.split('.').pop() || '')) {
|
||||||
media.push({ uri, mime: 'video/mp4' })
|
media.push({ path: path, mime: 'video/mp4' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
text = !text ? uri : text.concat(text, `\n${uri}`)
|
text = !text ? path : text.concat(text, `\n${path}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
|
|
||||||
for (const d of item.data) {
|
for (const d of item.data) {
|
||||||
if (typeof d !== 'string') {
|
if (typeof d !== 'string') {
|
||||||
filterMedia({ uri: d.data, mime: d.mimeType })
|
filterMedia({ path: d.data, mime: d.mimeType })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -245,7 +245,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
tempData = item.data
|
tempData = item.data
|
||||||
}
|
}
|
||||||
for (const d of item.data) {
|
for (const d of item.data) {
|
||||||
filterMedia({ uri: d, mime: item.mimeType })
|
filterMedia({ path: d, mime: item.mimeType })
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,8 @@ const apiGeneral = async <T = unknown>({
|
||||||
error.response.data.error
|
error.response.data.error
|
||||||
)
|
)
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
status: error?.response.status,
|
status: error.response.status,
|
||||||
message: error?.response.data.error
|
message: error.response.data.error
|
||||||
})
|
})
|
||||||
} else if (error?.request) {
|
} else if (error?.request) {
|
||||||
// The request was made but no response was received
|
// The request was made but no response was received
|
||||||
|
|
|
@ -110,8 +110,8 @@ const apiInstance = async <T = unknown>({
|
||||||
error.response.data.error
|
error.response.data.error
|
||||||
)
|
)
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
status: error?.response.status,
|
status: error.response.status,
|
||||||
message: error?.response.data.error
|
message: error.response.data.error
|
||||||
})
|
})
|
||||||
} else if (error?.request) {
|
} else if (error?.request) {
|
||||||
// The request was made but no response was received
|
// The request was made but no response was received
|
||||||
|
|
|
@ -66,7 +66,7 @@ const apiTooot = async <T = unknown>({
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (sentry) {
|
if (sentry && Math.random() < 0.1) {
|
||||||
Sentry.Native.setExtras({
|
Sentry.Native.setExtras({
|
||||||
API: 'tooot',
|
API: 'tooot',
|
||||||
...(error?.response && { response: error.response }),
|
...(error?.response && { response: error.response }),
|
||||||
|
@ -85,8 +85,8 @@ const apiTooot = async <T = unknown>({
|
||||||
error.response.data.error
|
error.response.data.error
|
||||||
)
|
)
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
status: error?.response.status,
|
status: error.response.status,
|
||||||
message: error?.response.data.error
|
message: error.response.data.error
|
||||||
})
|
})
|
||||||
} else if (error?.request) {
|
} else if (error?.request) {
|
||||||
// The request was made but no response was received
|
// The request was made but no response was received
|
||||||
|
|
|
@ -49,7 +49,7 @@ const renderNode = ({
|
||||||
const href = node.attribs.href
|
const href = node.attribs.href
|
||||||
if (classes) {
|
if (classes) {
|
||||||
if (classes.includes('hashtag')) {
|
if (classes.includes('hashtag')) {
|
||||||
const tag = href?.split(new RegExp(/\/tag\/(.*)|\/tags\/(.*)/))
|
const tag = href.split(new RegExp(/\/tag\/(.*)|\/tags\/(.*)/))
|
||||||
const differentTag = routeParams?.hashtag
|
const differentTag = routeParams?.hashtag
|
||||||
? routeParams.hashtag !== tag[1] && routeParams.hashtag !== tag[2]
|
? routeParams.hashtag !== tag[1] && routeParams.hashtag !== tag[2]
|
||||||
: true
|
: true
|
||||||
|
@ -107,7 +107,7 @@ const renderNode = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const domain = href?.split(new RegExp(/:\/\/(.[^\/]+)/))
|
const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/))
|
||||||
// Need example here
|
// Need example here
|
||||||
const content =
|
const content =
|
||||||
node.children && node.children[0] && node.children[0].data
|
node.children && node.children[0] && node.children[0].data
|
||||||
|
@ -124,15 +124,11 @@ const renderNode = ({
|
||||||
}}
|
}}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
analytics('status_link_press')
|
analytics('status_link_press')
|
||||||
if (!disableDetails) {
|
!disableDetails && !shouldBeTag
|
||||||
if (shouldBeTag) {
|
? await openLink(href, navigation)
|
||||||
navigation.push('Tab-Shared-Hashtag', {
|
: navigation.push('Tab-Shared-Hashtag', {
|
||||||
hashtag: content.substring(1)
|
hashtag: content.substring(1)
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
await openLink(href, navigation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(content && content !== href && content) ||
|
{(content && content !== href && content) ||
|
||||||
|
|
|
@ -22,7 +22,7 @@ const TimelineActioned = React.memo(
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const navigation =
|
const navigation =
|
||||||
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
|
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
|
||||||
const name = account?.display_name || account?.username
|
const name = account?.display_name || account.username
|
||||||
const iconColor = colors.primaryDefault
|
const iconColor = colors.primaryDefault
|
||||||
|
|
||||||
const content = (content: string) => (
|
const content = (content: string) => (
|
||||||
|
|
|
@ -27,7 +27,7 @@ const HeaderSharedAccount = React.memo(
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
>
|
>
|
||||||
<ParseEmojis
|
<ParseEmojis
|
||||||
content={account?.display_name || account?.username}
|
content={account?.display_name || account.username}
|
||||||
emojis={account.emojis}
|
emojis={account.emojis}
|
||||||
fontBold
|
fontBold
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,10 +2,9 @@ import analytics from '@components/analytics'
|
||||||
import { ActionSheetOptions } from '@expo/react-native-action-sheet'
|
import { ActionSheetOptions } from '@expo/react-native-action-sheet'
|
||||||
import { store } from '@root/store'
|
import { store } from '@root/store'
|
||||||
import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/instancesSlice'
|
import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/instancesSlice'
|
||||||
import { manipulateAsync, SaveFormat } from 'expo-image-manipulator'
|
|
||||||
import * as ExpoImagePicker from 'expo-image-picker'
|
import * as ExpoImagePicker from 'expo-image-picker'
|
||||||
import i18next from 'i18next'
|
import i18next from 'i18next'
|
||||||
import { Alert, Linking, Platform } from 'react-native'
|
import { Alert, Linking } from 'react-native'
|
||||||
import ImagePicker, {
|
import ImagePicker, {
|
||||||
Image,
|
Image,
|
||||||
ImageOrVideo
|
ImageOrVideo
|
||||||
|
@ -28,7 +27,7 @@ const mediaSelector = async ({
|
||||||
maximum,
|
maximum,
|
||||||
indicateMaximum = false,
|
indicateMaximum = false,
|
||||||
showActionSheetWithOptions
|
showActionSheetWithOptions
|
||||||
}: Props): Promise<({ uri: string } & Omit<ImageOrVideo, 'path'>)[]> => {
|
}: Props): Promise<ImageOrVideo[]> => {
|
||||||
const checkLibraryPermission = async (): Promise<boolean> => {
|
const checkLibraryPermission = async (): Promise<boolean> => {
|
||||||
const { status } =
|
const { status } =
|
||||||
await ExpoImagePicker.requestMediaLibraryPermissionsAsync()
|
await ExpoImagePicker.requestMediaLibraryPermissionsAsync()
|
||||||
|
@ -111,40 +110,17 @@ const mediaSelector = async ({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
minFiles: 1,
|
minFiles: 1,
|
||||||
maxFiles: _maximum,
|
maxFiles: _maximum,
|
||||||
smartAlbums: ['UserLibrary'],
|
loadingLabelText: '',
|
||||||
writeTempFile: false,
|
compressImageMaxWidth: 4096,
|
||||||
loadingLabelText: ''
|
compressImageMaxHeight: 4096
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
|
|
||||||
if (!images) {
|
if (!images) {
|
||||||
return reject()
|
return reject()
|
||||||
}
|
}
|
||||||
|
|
||||||
// react-native-image-crop-picker may return HEIC as JPG that causes upload failure
|
|
||||||
if (Platform.OS === 'ios') {
|
|
||||||
for (const [index, image] of images.entries()) {
|
|
||||||
if (image.mime === 'image/heic') {
|
|
||||||
const converted = await manipulateAsync(image.sourceURL!, [], {
|
|
||||||
base64: false,
|
|
||||||
compress: 0.8,
|
|
||||||
format: SaveFormat.JPEG
|
|
||||||
})
|
|
||||||
images[index] = {
|
|
||||||
...images[index],
|
|
||||||
sourceURL: converted.uri,
|
|
||||||
mime: 'image/jpeg'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resize) {
|
if (!resize) {
|
||||||
return resolve(
|
return resolve(images)
|
||||||
images.map(image => ({
|
|
||||||
...image,
|
|
||||||
uri: image.sourceURL || `file://${image.path}`
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const croppedImages: Image[] = []
|
const croppedImages: Image[] = []
|
||||||
for (const image of images) {
|
for (const image of images) {
|
||||||
|
@ -159,12 +135,7 @@ const mediaSelector = async ({
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
croppedImage && croppedImages.push(croppedImage)
|
croppedImage && croppedImages.push(croppedImage)
|
||||||
}
|
}
|
||||||
return resolve(
|
return resolve(croppedImages)
|
||||||
croppedImages.map(image => ({
|
|
||||||
...image,
|
|
||||||
uri: `file://${image.path}`
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const selectVideo = async () => {
|
const selectVideo = async () => {
|
||||||
|
@ -175,9 +146,7 @@ const mediaSelector = async ({
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
|
|
||||||
if (video) {
|
if (video) {
|
||||||
return resolve([
|
return resolve([video])
|
||||||
{ ...video, uri: video.sourceURL || `file://${video.path}` }
|
|
||||||
])
|
|
||||||
} else {
|
} else {
|
||||||
return reject()
|
return reject()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
import { store } from '@root/store'
|
|
||||||
import { getInstanceConfigurationMediaAttachments } from '@utils/slices/instancesSlice'
|
|
||||||
import { Action, manipulateAsync, SaveFormat } from 'expo-image-manipulator'
|
|
||||||
import i18next from 'i18next'
|
|
||||||
import { Platform } from 'react-native'
|
|
||||||
import ImagePicker from 'react-native-image-crop-picker'
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
type: 'image' | 'video'
|
|
||||||
uri: string // This can be pure path or uri starting with file://
|
|
||||||
mime?: string
|
|
||||||
transform: {
|
|
||||||
imageFormat?: SaveFormat.JPEG | SaveFormat.PNG
|
|
||||||
resize?: boolean
|
|
||||||
width?: number
|
|
||||||
height?: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getFileExtension = (uri: string) => {
|
|
||||||
const extension = uri.split('.').pop()
|
|
||||||
// Using mime type standard of jpeg
|
|
||||||
return extension === 'jpg' ? 'jpeg' : extension
|
|
||||||
}
|
|
||||||
|
|
||||||
const mediaTransformation = async ({
|
|
||||||
type,
|
|
||||||
uri,
|
|
||||||
mime,
|
|
||||||
transform
|
|
||||||
}: Props): Promise<{
|
|
||||||
uri: string
|
|
||||||
mime: string
|
|
||||||
width: number
|
|
||||||
height: number
|
|
||||||
}> => {
|
|
||||||
const configurationMediaAttachments =
|
|
||||||
getInstanceConfigurationMediaAttachments(store.getState())
|
|
||||||
|
|
||||||
const fileExtension = getFileExtension(uri)
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'image':
|
|
||||||
if (mime === 'image/gif' || fileExtension === 'gif') {
|
|
||||||
return Promise.reject('GIFs should not be transformed')
|
|
||||||
}
|
|
||||||
let targetFormat: SaveFormat.JPEG | SaveFormat.PNG = SaveFormat.JPEG
|
|
||||||
|
|
||||||
const supportedImageTypes =
|
|
||||||
configurationMediaAttachments.supported_mime_types.filter(mime =>
|
|
||||||
mime.startsWith('image/')
|
|
||||||
)
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const transformations: Action[] = [
|
|
||||||
!transform.resize && (transform.width || transform.height)
|
|
||||||
? {
|
|
||||||
resize: { width: transform.width, height: transform.height }
|
|
||||||
}
|
|
||||||
: null
|
|
||||||
].filter(t => !!t)
|
|
||||||
|
|
||||||
if (mime) {
|
|
||||||
if (
|
|
||||||
mime !== `image/${fileExtension}` ||
|
|
||||||
!supportedImageTypes.includes(mime)
|
|
||||||
) {
|
|
||||||
targetFormat = transform.imageFormat || SaveFormat.JPEG
|
|
||||||
} else {
|
|
||||||
targetFormat = mime.split('/').pop() as any
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!fileExtension) {
|
|
||||||
return Promise.reject('Unable to get file extension')
|
|
||||||
}
|
|
||||||
if (!supportedImageTypes.includes(`image/${fileExtension}`)) {
|
|
||||||
targetFormat = transform.imageFormat || SaveFormat.JPEG
|
|
||||||
} else {
|
|
||||||
targetFormat = fileExtension as any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const converted = await manipulateAsync(uri, transformations, {
|
|
||||||
base64: false,
|
|
||||||
compress: Platform.OS === 'ios' ? 0.8 : 1,
|
|
||||||
format: targetFormat
|
|
||||||
})
|
|
||||||
|
|
||||||
if (transform.resize) {
|
|
||||||
const resized = await ImagePicker.openCropper({
|
|
||||||
mediaType: 'photo',
|
|
||||||
path: converted.uri,
|
|
||||||
width: transform.width,
|
|
||||||
height: transform.height,
|
|
||||||
cropperChooseText: i18next.t('common:buttons.apply'),
|
|
||||||
cropperCancelText: i18next.t('common:buttons.cancel'),
|
|
||||||
hideBottomControls: true
|
|
||||||
})
|
|
||||||
if (!resized) {
|
|
||||||
return Promise.reject('Resize failed')
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
uri: resized.path,
|
|
||||||
mime: resized.mime,
|
|
||||||
width: resized.width,
|
|
||||||
height: resized.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
uri: converted.uri,
|
|
||||||
mime: transform.imageFormat || SaveFormat.JPEG,
|
|
||||||
width: converted.width,
|
|
||||||
height: converted.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 'video':
|
|
||||||
const supportedVideoTypes =
|
|
||||||
configurationMediaAttachments.supported_mime_types.filter(mime =>
|
|
||||||
mime.startsWith('video/')
|
|
||||||
)
|
|
||||||
|
|
||||||
if (mime) {
|
|
||||||
if (mime !== `video/${fileExtension}`) {
|
|
||||||
console.warn('Video mime type and file extension does not match')
|
|
||||||
}
|
|
||||||
if (!supportedVideoTypes.includes(mime)) {
|
|
||||||
return Promise.reject('Video file type is not supported')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!fileExtension) {
|
|
||||||
return Promise.reject('Unable to get file extension')
|
|
||||||
}
|
|
||||||
if (!supportedVideoTypes.includes(`video/${fileExtension}`)) {
|
|
||||||
return Promise.reject('Video file type is not supported')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
uri: uri,
|
|
||||||
mime: mime || `video/${fileExtension}`,
|
|
||||||
width: 0,
|
|
||||||
height: 0
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default mediaTransformation
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"accessibilityHint": "Ações para este toot, como o seu usuário publicado",
|
"accessibilityHint": "Ações para este toot, como o seu usuário publicado",
|
||||||
"account": {
|
"account": {
|
||||||
"title": "Ações do Usuário",
|
"title": "",
|
||||||
"mute": {
|
"mute": {
|
||||||
"action": "Silenciar usuário"
|
"action": "Silenciar usuário"
|
||||||
},
|
},
|
||||||
|
@ -13,11 +13,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"instance": {
|
"instance": {
|
||||||
"title": "Ação da Instância",
|
"title": "",
|
||||||
"block": {
|
"block": {
|
||||||
"action": "Bloquear a instância {{instance}}",
|
"action": "Bloquear a instância {{instance}}",
|
||||||
"alert": {
|
"alert": {
|
||||||
"title": "Confirmar o bloqueio da instância {{instance}}?",
|
"title": "",
|
||||||
"message": "Na maioria das vezes, você pode silenciar ou bloquear determinado usuário.\n\nDepois de bloquear a instância, todo seu conteúdo, incluindo seguidores, será removido!",
|
"message": "Na maioria das vezes, você pode silenciar ou bloquear determinado usuário.\n\nDepois de bloquear a instância, todo seu conteúdo, incluindo seguidores, será removido!",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"confirm": "Confirmar"
|
"confirm": "Confirmar"
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"title": "Ações do toot",
|
"title": "",
|
||||||
"edit": {
|
"edit": {
|
||||||
"action": "Editar toot"
|
"action": "Editar toot"
|
||||||
},
|
},
|
||||||
|
@ -42,29 +42,29 @@
|
||||||
"action": "Remover toot",
|
"action": "Remover toot",
|
||||||
"alert": {
|
"alert": {
|
||||||
"title": "Confirme a exclusão?",
|
"title": "Confirme a exclusão?",
|
||||||
"message": "Todos os boosts e favoritos serão limpos, incluindo todas as respostas.",
|
"message": "",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"confirm": "Confirmar"
|
"confirm": "Confirmar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteEdit": {
|
"deleteEdit": {
|
||||||
"action": "Excluir toot e repostar",
|
"action": "",
|
||||||
"alert": {
|
"alert": {
|
||||||
"title": "Confirmar exclusão e repostagem?",
|
"title": "",
|
||||||
"message": "Todos os boosts e favoritos serão limpos, incluindo todas as respostas.",
|
"message": "",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"confirm": "Confirmar"
|
"confirm": "Confirmar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mute": {
|
"mute": {
|
||||||
"action-muted_false": "Silenciar este toot e respostas",
|
"action-muted_false": "",
|
||||||
"action-muted_true": "Desbloquear este toot e respostas"
|
"action-muted_true": ""
|
||||||
},
|
},
|
||||||
"pin": {
|
"pin": {
|
||||||
"action-pinned_false": "Toot fixado",
|
"action-pinned_false": "",
|
||||||
"action-pinned_true": "Desafixar toot"
|
"action-pinned_true": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"title": "Selecionar fonte de mídia",
|
"title": "Selecionar fonte de mídia",
|
||||||
"options": {
|
"options": {
|
||||||
"image": "Enviar fotos",
|
"image": "",
|
||||||
"image_max": "Carregar fotos (máx. {{max}})",
|
"image_max": "",
|
||||||
"video": "Enviar vídeo",
|
"video": "",
|
||||||
"video_max": "Carregar vídeo (máx. {{max}})"
|
"video_max": ""
|
||||||
},
|
},
|
||||||
"library": {
|
"library": {
|
||||||
"alert": {
|
"alert": {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
"default": "{{name}} boostou",
|
"default": "{{name}} boostou",
|
||||||
"notification": "{{name}} deu boost no teu toot"
|
"notification": "{{name}} deu boost no teu toot"
|
||||||
},
|
},
|
||||||
"update": "Toot foi editado"
|
"update": ""
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"reply": {
|
"reply": {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"button": {
|
"button": {
|
||||||
"default": "Toot",
|
"default": "Toot",
|
||||||
"conversation": "Toot DM",
|
"conversation": "Toot DM",
|
||||||
"reply": "Responder",
|
"reply": "Resposta de toot",
|
||||||
"deleteEdit": "Toot",
|
"deleteEdit": "Toot",
|
||||||
"edit": "Toot",
|
"edit": "Toot",
|
||||||
"share": "Toot"
|
"share": "Toot"
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
"me": {
|
"me": {
|
||||||
"stacks": {
|
"stacks": {
|
||||||
"bookmarks": {
|
"bookmarks": {
|
||||||
"name": "Salvos"
|
"name": "Favoritos"
|
||||||
},
|
},
|
||||||
"conversations": {
|
"conversations": {
|
||||||
"name": "Mensagens diretas"
|
"name": "Mensagens diretas"
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
"demo": "<p>Esta é uma demonstração também😊. Você pode escolher entre várias opções abaixo.<br /><br />Esta configuração afeta apenas o conteúdo principal dos toots, mas não os tamanhos de outra fonte.</p>",
|
"demo": "<p>Esta é uma demonstração também😊. Você pode escolher entre várias opções abaixo.<br /><br />Esta configuração afeta apenas o conteúdo principal dos toots, mas não os tamanhos de outra fonte.</p>",
|
||||||
"availableSizes": "Tamanhos disponíveis",
|
"availableSizes": "Tamanhos disponíveis",
|
||||||
"sizes": {
|
"sizes": {
|
||||||
"S": "P",
|
"S": "S",
|
||||||
"M": "M - Padrão",
|
"M": "M - Padrão",
|
||||||
"L": "Grande",
|
"L": "Grande",
|
||||||
"XL": "Extra grande",
|
"XL": "Extra grande",
|
||||||
|
|
|
@ -49,7 +49,7 @@ const ActionsStatus: React.FC<Props> = ({
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(`shared.header.actions.status.${theFunction}.function`)
|
function: t(`shared.header.actions.status.${theFunction}.function`)
|
||||||
}),
|
}),
|
||||||
...(err?.status &&
|
...(err.status &&
|
||||||
typeof err.status === 'number' &&
|
typeof err.status === 'number' &&
|
||||||
err.data &&
|
err.data &&
|
||||||
err.data.error &&
|
err.data.error &&
|
||||||
|
|
|
@ -128,8 +128,8 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
||||||
height: imageDimensionis.height
|
height: imageDimensionis.height
|
||||||
}}
|
}}
|
||||||
source={{
|
source={{
|
||||||
uri: theAttachmentLocal?.uri
|
uri: theAttachmentLocal?.path
|
||||||
? theAttachmentLocal.uri
|
? `file://${theAttachmentLocal?.path}`
|
||||||
: theAttachmentRemote?.preview_url
|
: theAttachmentRemote?.preview_url
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -34,7 +34,7 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
|
||||||
video={
|
video={
|
||||||
video.local
|
video.local
|
||||||
? ({
|
? ({
|
||||||
url: video.local.uri,
|
url: `file://${video.local.path}`,
|
||||||
preview_url: video.local.local_thumbnail,
|
preview_url: video.local.local_thumbnail,
|
||||||
blurhash: video.remote?.blurhash
|
blurhash: video.remote?.blurhash
|
||||||
} as Mastodon.AttachmentVideo)
|
} as Mastodon.AttachmentVideo)
|
||||||
|
|
|
@ -22,25 +22,28 @@ export const uploadAttachment = async ({
|
||||||
media
|
media
|
||||||
}: {
|
}: {
|
||||||
composeDispatch: Dispatch<ComposeAction>
|
composeDispatch: Dispatch<ComposeAction>
|
||||||
media: { uri: string } & Pick<ImageOrVideo, 'mime' | 'width' | 'height'>
|
media: Pick<ImageOrVideo, 'path' | 'mime' | 'width' | 'height'>
|
||||||
}) => {
|
}) => {
|
||||||
const hash = await Crypto.digestStringAsync(
|
const hash = await Crypto.digestStringAsync(
|
||||||
Crypto.CryptoDigestAlgorithm.SHA256,
|
Crypto.CryptoDigestAlgorithm.SHA256,
|
||||||
media.uri + Math.random()
|
media.path + Math.random()
|
||||||
)
|
)
|
||||||
|
let attachmentType: string
|
||||||
|
|
||||||
switch (media.mime.split('/')[0]) {
|
switch (media.mime.split('/')[0]) {
|
||||||
case 'image':
|
case 'image':
|
||||||
|
attachmentType = `image/${media.path.split('.')[1]}`
|
||||||
composeDispatch({
|
composeDispatch({
|
||||||
type: 'attachment/upload/start',
|
type: 'attachment/upload/start',
|
||||||
payload: {
|
payload: {
|
||||||
local: { ...media, type: 'image', local_thumbnail: media.uri, hash },
|
local: { ...media, type: 'image', local_thumbnail: media.path, hash },
|
||||||
uploading: true
|
uploading: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'video':
|
case 'video':
|
||||||
VideoThumbnails.getThumbnailAsync(media.uri)
|
attachmentType = `video/${media.path.split('.')[1]}`
|
||||||
|
VideoThumbnails.getThumbnailAsync(media.path)
|
||||||
.then(({ uri, width, height }) =>
|
.then(({ uri, width, height }) =>
|
||||||
composeDispatch({
|
composeDispatch({
|
||||||
type: 'attachment/upload/start',
|
type: 'attachment/upload/start',
|
||||||
|
@ -68,6 +71,7 @@ export const uploadAttachment = async ({
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
attachmentType = 'unknown'
|
||||||
composeDispatch({
|
composeDispatch({
|
||||||
type: 'attachment/upload/start',
|
type: 'attachment/upload/start',
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -101,9 +105,9 @@ export const uploadAttachment = async ({
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', {
|
formData.append('file', {
|
||||||
uri: media.uri,
|
uri: `file://${media.path}`,
|
||||||
name: media.uri.match(new RegExp(/.*\/(.*)/))?.[1] || 'file.jpg',
|
name: attachmentType,
|
||||||
type: media.mime
|
type: attachmentType
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
return apiInstance<Mastodon.Attachment>({
|
return apiInstance<Mastodon.Attachment>({
|
||||||
|
|
|
@ -90,7 +90,7 @@ const ComposeTextInput: React.FC = () => {
|
||||||
uploadAttachment({
|
uploadAttachment({
|
||||||
composeDispatch,
|
composeDispatch,
|
||||||
media: {
|
media: {
|
||||||
uri: file.uri,
|
path: file.uri,
|
||||||
mime: file.type,
|
mime: file.type,
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100
|
height: 100
|
||||||
|
|
|
@ -58,7 +58,7 @@ const composeReducer = (
|
||||||
attachments: {
|
attachments: {
|
||||||
...state.attachments,
|
...state.attachments,
|
||||||
uploads: state.attachments.uploads.map(upload =>
|
uploads: state.attachments.uploads.map(upload =>
|
||||||
upload.local?.uri === action.payload.local?.uri
|
upload.local?.path === action.payload.local?.path
|
||||||
? { ...upload, remote: action.payload.remote, uploading: false }
|
? { ...upload, remote: action.payload.remote, uploading: false }
|
||||||
: upload
|
: upload
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,11 +2,11 @@ import { ImageOrVideo } from 'react-native-image-crop-picker'
|
||||||
|
|
||||||
export type ExtendedAttachment = {
|
export type ExtendedAttachment = {
|
||||||
remote?: Mastodon.Attachment
|
remote?: Mastodon.Attachment
|
||||||
local?: { uri: string } & Pick<ImageOrVideo, 'width' | 'height' | 'mime'> & {
|
local?: Pick<ImageOrVideo, 'path' | 'width' | 'height' | 'mime'> & {
|
||||||
type: 'image' | 'video' | 'unknown'
|
type: 'image' | 'video' | 'unknown'
|
||||||
local_thumbnail?: string
|
local_thumbnail?: string
|
||||||
hash?: string
|
hash?: string
|
||||||
}
|
}
|
||||||
uploading?: boolean
|
uploading?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ export type ComposeAction =
|
||||||
type: 'attachment/upload/end'
|
type: 'attachment/upload/end'
|
||||||
payload: {
|
payload: {
|
||||||
remote: Mastodon.Attachment
|
remote: Mastodon.Attachment
|
||||||
local: { uri: string } & Pick<ImageOrVideo, 'width' | 'height' | 'mime'>
|
local: Pick<ImageOrVideo, 'path' | 'width' | 'height' | 'mime'>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
|
|
|
@ -46,7 +46,7 @@ const ProfileAvatarHeader: React.FC<Props> = ({ type, messageRef }) => {
|
||||||
failed: true
|
failed: true
|
||||||
},
|
},
|
||||||
type,
|
type,
|
||||||
data: image[0].uri
|
data: image[0].path
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -42,7 +42,7 @@ export type RootStackParamList = {
|
||||||
| {
|
| {
|
||||||
type: 'share'
|
type: 'share'
|
||||||
text?: string
|
text?: string
|
||||||
media?: { uri: string; mime: string }[]
|
media?: { path: string; mime: string }[]
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
'Screen-ImagesViewer': {
|
'Screen-ImagesViewer': {
|
||||||
|
|
|
@ -249,7 +249,7 @@ const instancesSlice = createSlice({
|
||||||
// Update Instance Configuration
|
// Update Instance Configuration
|
||||||
.addCase(updateConfiguration.fulfilled, (state, action) => {
|
.addCase(updateConfiguration.fulfilled, (state, action) => {
|
||||||
const activeIndex = findInstanceActive(state.instances)
|
const activeIndex = findInstanceActive(state.instances)
|
||||||
state.instances[activeIndex].version = action.payload?.version || '0'
|
state.instances[activeIndex].version = action.payload.version
|
||||||
state.instances[activeIndex].configuration =
|
state.instances[activeIndex].configuration =
|
||||||
action.payload.configuration
|
action.payload.configuration
|
||||||
})
|
})
|
||||||
|
@ -316,7 +316,7 @@ const instancesSlice = createSlice({
|
||||||
state.instances[activeIndex].frequentEmojis = state.instances[
|
state.instances[activeIndex].frequentEmojis = state.instances[
|
||||||
activeIndex
|
activeIndex
|
||||||
].frequentEmojis?.filter(emoji => {
|
].frequentEmojis?.filter(emoji => {
|
||||||
return action.payload?.find(
|
return action.payload.find(
|
||||||
e =>
|
e =>
|
||||||
e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url
|
e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url
|
||||||
)
|
)
|
||||||
|
@ -381,43 +381,6 @@ export const getInstanceConfigurationStatusCharsURL = ({
|
||||||
instances[findInstanceActive(instances)]?.configuration?.statuses
|
instances[findInstanceActive(instances)]?.configuration?.statuses
|
||||||
.characters_reserved_per_url || 23
|
.characters_reserved_per_url || 23
|
||||||
|
|
||||||
export const getInstanceConfigurationMediaAttachments = ({
|
|
||||||
instances: { instances }
|
|
||||||
}: RootState) =>
|
|
||||||
instances[findInstanceActive(instances)]?.configuration
|
|
||||||
?.media_attachments || {
|
|
||||||
supported_mime_types: [
|
|
||||||
'image/jpeg',
|
|
||||||
'image/png',
|
|
||||||
'image/gif',
|
|
||||||
'video/webm',
|
|
||||||
'video/mp4',
|
|
||||||
'video/quicktime',
|
|
||||||
'video/ogg',
|
|
||||||
'audio/wave',
|
|
||||||
'audio/wav',
|
|
||||||
'audio/x-wav',
|
|
||||||
'audio/x-pn-wave',
|
|
||||||
'audio/ogg',
|
|
||||||
'audio/vorbis',
|
|
||||||
'audio/mpeg',
|
|
||||||
'audio/mp3',
|
|
||||||
'audio/webm',
|
|
||||||
'audio/flac',
|
|
||||||
'audio/aac',
|
|
||||||
'audio/m4a',
|
|
||||||
'audio/x-m4a',
|
|
||||||
'audio/mp4',
|
|
||||||
'audio/3gpp',
|
|
||||||
'video/x-ms-asf'
|
|
||||||
],
|
|
||||||
image_size_limit: 10485760,
|
|
||||||
image_matrix_limit: 16777216,
|
|
||||||
video_size_limit: 41943040,
|
|
||||||
video_frame_rate_limit: 60,
|
|
||||||
video_matrix_limit: 2304000
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getInstanceConfigurationPoll = ({
|
export const getInstanceConfigurationPoll = ({
|
||||||
instances: { instances }
|
instances: { instances }
|
||||||
}: RootState) =>
|
}: RootState) =>
|
||||||
|
|
|
@ -4428,13 +4428,6 @@ expo-image-loader@~3.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/expo-image-loader/-/expo-image-loader-3.2.0.tgz#d98b021660edef7243f7c5ec011b8d0545626d41"
|
resolved "https://registry.yarnpkg.com/expo-image-loader/-/expo-image-loader-3.2.0.tgz#d98b021660edef7243f7c5ec011b8d0545626d41"
|
||||||
integrity sha512-LU3Q2prn64/HxdToDmxgMIRXS1ZvD9Q3iCxRVTZn1fPQNNDciIQFE5okaa74Ogx20DFHs90r6WoUd7w9Af1OGQ==
|
integrity sha512-LU3Q2prn64/HxdToDmxgMIRXS1ZvD9Q3iCxRVTZn1fPQNNDciIQFE5okaa74Ogx20DFHs90r6WoUd7w9Af1OGQ==
|
||||||
|
|
||||||
expo-image-manipulator@^10.3.1:
|
|
||||||
version "10.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/expo-image-manipulator/-/expo-image-manipulator-10.3.1.tgz#e16dd76a550c7f5d653a2a666f26429eba311a6b"
|
|
||||||
integrity sha512-D08dMD6MerxBu23DmCIhurySQih+eLP7VxKvY5mWqYz9payjDOS1cAGs3HvXPrEDusPQFQ0uIfqc+oqeMNFBIA==
|
|
||||||
dependencies:
|
|
||||||
expo-image-loader "~3.2.0"
|
|
||||||
|
|
||||||
expo-image-picker@13.1.1:
|
expo-image-picker@13.1.1:
|
||||||
version "13.1.1"
|
version "13.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-13.1.1.tgz#e039bf9748ccb7b89370ff2969c3ef07cc949192"
|
resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-13.1.1.tgz#e039bf9748ccb7b89370ff2969c3ef07cc949192"
|
||||||
|
|
Loading…
Reference in New Issue