From a79d24db037ffe745881451d2cfe72e2fb5e426d Mon Sep 17 00:00:00 2001 From: xan.lol Date: Wed, 26 Nov 2025 02:19:10 +0000 Subject: [PATCH] Merge remote-tracking branch 'upstream/main' --- package.json | 4 ++-- yarn.lock | 124 ++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------ patches/react-native+0.81.5+001+initial.patch | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ patches/react-native+0.81.5+002+ScrollForwarder.patch | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ patches/react-native+0.81.5+003+ScrollView-disable-recycling.patch | 16 ++++++++++++++++ patches/react-native+0.81.5.patch | 136 ---------------------------------------------------------------------------------------------------------------------------------------- src/view/icons/Logo.tsx | 10 ++++++---- src/locale/locales/en/messages.po | 2 +- src/view/shell/bottom-bar/BottomBar.tsx | 9 ++++++--- src/view/shell/bottom-bar/BottomBarStyles.tsx | 7 ------- src/view/shell/bottom-bar/BottomBarWeb.tsx | 7 ++++++- src/view/com/util/fab/FABInner.tsx | 40 ++++++++++++++++++---------------------- modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt | 35 +++++++++++++++++++++++++++-------- 13 file(s) changed, 266 insertion(s)(+), 262 deletion(s)(-) diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "witchsky-app", - "version": "1.110.1", + "version": "1.111.0", "private": true, "engines": { "node": ">=18" @@ -176,7 +176,7 @@ "multiformats": "9.9.0", "nanoid": "^5.0.5", "normalize-url": "^8.0.0", - "patch-package": "^6.5.1", + "patch-package": "^8.0.1", "postinstall-postinstall": "^2.1.0", "psl": "^1.9.0", "radix-ui": "^1.4.3", diff --git a/yarn.lock b/yarn.lock --- a/yarn.lock +++ b/yarn.lock @@ -8579,11 +8579,6 @@ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - atomic-sleep@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" @@ -9368,6 +9363,11 @@ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== +ci-info@^3.7.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + cjs-module-lexer@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" @@ -9769,17 +9769,6 @@ integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== dependencies: node-fetch "^2.6.12" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" @@ -11974,21 +11963,20 @@ resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-extra@^11.2.0: - version "11.3.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" - integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== +fs-extra@^11.2.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== dependencies: - at-least-node "^1.0.0" graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" @@ -12961,13 +12949,6 @@ version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" is-ci@^3.0.1: version "3.0.1" @@ -14077,6 +14058,17 @@ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stable-stringify@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" + integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + isarray "^2.0.5" + jsonify "^0.0.1" + object-keys "^1.1.1" + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -14097,6 +14089,11 @@ universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: version "3.3.5" @@ -15117,11 +15114,6 @@ resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz#d2cc9fc5235ddb371fc44d506234339c8e4b0a4b" integrity sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -15680,25 +15672,25 @@ ansi-escapes "^4.3.2" cross-spawn "^7.0.3" -patch-package@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== +patch-package@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.1.tgz#79d02f953f711e06d1f8949c8a13e5d3d7ba1a60" + integrity sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw== dependencies: "@yarnpkg/lockfile" "^1.1.0" chalk "^4.1.2" - cross-spawn "^6.0.5" + ci-info "^3.7.0" + cross-spawn "^7.0.3" find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - is-ci "^2.0.0" + fs-extra "^10.0.0" + json-stable-stringify "^1.0.2" klaw-sync "^6.0.0" minimist "^1.2.6" open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" + semver "^7.5.3" slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" + tmp "^0.2.4" + yaml "^2.2.2" path-exists@^3.0.0: version "3.0.0" @@ -15719,11 +15711,6 @@ version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" @@ -17785,11 +17772,6 @@ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -semver@^5.5.0, semver@^5.6.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -18008,24 +17990,12 @@ "@img/sharp-win32-ia32" "0.33.5" "@img/sharp-win32-x64" "0.33.5" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== shebang-regex@^3.0.0: version "3.0.0" @@ -18952,6 +18922,11 @@ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" + +tmp@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8" + integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== tmpl@1.0.5: version "1.0.5" @@ -19947,13 +19922,6 @@ has-tostringtag "^1.0.0" is-typed-array "^1.1.10" -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -20142,7 +20110,7 @@ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.6.1: +yaml@^2.2.2, yaml@^2.6.1: version "2.8.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.1.tgz#1870aa02b631f7e8328b93f8bc574fac5d6c4d79" integrity sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw== diff --git a/patches/react-native+0.81.5+001+initial.patch b/patches/react-native+0.81.5+001+initial.patch new file mode 100644 --- /dev/null +++ b/patches/react-native+0.81.5+001+initial.patch @@ -0,0 +1,71 @@ +diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h +index e9b330f..5fbb2e0 100644 +--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h ++++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h +@@ -15,5 +15,6 @@ + @property (nonatomic, copy) NSString *title; + @property (nonatomic, copy) RCTDirectEventBlock onRefresh; + @property (nonatomic, weak) UIScrollView *scrollView; ++@property (nonatomic, copy) UIColor *customTintColor; + + @end +diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m +index 53bfd04..e2e0c9f 100644 +--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m ++++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m +@@ -23,6 +23,7 @@ @implementation RCTRefreshControl { + UIColor *_titleColor; + CGFloat _progressViewOffset; + BOOL _hasMovedToWindow; ++ UIColor *_customTintColor; + } + + - (instancetype)init +@@ -58,6 +59,12 @@ - (void)layoutSubviews + _isInitialRender = false; + } + ++- (void)didMoveToSuperview ++{ ++ [super didMoveToSuperview]; ++ [self setTintColor:_customTintColor]; ++} ++ + - (void)didMoveToWindow + { + [super didMoveToWindow]; +@@ -221,4 +228,16 @@ - (void)refreshControlValueChanged + } + } + ++// Fix for https://github.com/facebook/react-native/issues/43388 ++// A bug in iOS 17.4 causes the haptic to not play when refreshing if the tintColor ++// is set before the refresh control gets added to the scrollview. We'll call this ++// function whenever the superview changes. We'll also call it if the value of customTintColor ++// changes. ++- (void)setTintColor:(UIColor *)tintColor ++{ ++ if ([self.superview isKindOfClass:[UIScrollView class]] && self.tintColor != tintColor) { ++ [super setTintColor:tintColor]; ++ } ++} ++ + @end +diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m +index 40aaf9c..1c60164 100644 +--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m ++++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m +@@ -22,11 +22,12 @@ - (UIView *)view + + RCT_EXPORT_VIEW_PROPERTY(onRefresh, RCTDirectEventBlock) + RCT_EXPORT_VIEW_PROPERTY(refreshing, BOOL) +-RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor) + RCT_EXPORT_VIEW_PROPERTY(title, NSString) + RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor) + RCT_EXPORT_VIEW_PROPERTY(progressViewOffset, CGFloat) + ++RCT_REMAP_VIEW_PROPERTY(tintColor, customTintColor, UIColor) ++ + RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing) + { + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { diff --git a/patches/react-native+0.81.5+002+ScrollForwarder.patch b/patches/react-native+0.81.5+002+ScrollForwarder.patch new file mode 100644 --- /dev/null +++ b/patches/react-native+0.81.5+002+ScrollForwarder.patch @@ -0,0 +1,67 @@ +diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h +index 914a249..0deac55 100644 +--- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h ++++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h +@@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN + */ + @interface RCTPullToRefreshViewComponentView : RCTViewComponentView + ++- (void)beginRefreshingProgrammatically; ++ + @end + + NS_ASSUME_NONNULL_END +diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h +index 5fbb2e0..ec5f58c 100644 +--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h ++++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h +@@ -17,4 +17,6 @@ + @property (nonatomic, weak) UIScrollView *scrollView; + @property (nonatomic, copy) UIColor *customTintColor; + ++- (void)forwarderBeginRefreshing; ++ + @end +diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m +index e2e0c9f..ff1b1ed 100644 +--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m ++++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m +@@ -240,4 +240,38 @@ - (void)setTintColor:(UIColor *)tintColor + } + } + ++// This method is used by Bluesky's ExpoScrollForwarder. This allows other React Native ++// libraries to perform a refresh of a scrollview and access the refresh control's onRefresh ++// function. ++- (void)forwarderBeginRefreshing ++{ ++ _refreshingProgrammatically = NO; ++ ++ [self sizeToFit]; ++ ++ if (!self.scrollView) { ++ return; ++ } ++ ++ UIScrollView *scrollView = (UIScrollView *)self.scrollView; ++ ++ [UIView animateWithDuration:0.3 ++ delay:0 ++ options:UIViewAnimationOptionBeginFromCurrentState ++ animations:^(void) { ++ // Whenever we call this method, the scrollview will always be at a position of ++ // -130 or less. Scrolling back to -65 simulates the default behavior of RCTRefreshControl ++ [scrollView setContentOffset:CGPointMake(0, -65)]; ++ } ++ completion:^(__unused BOOL finished) { ++ [super beginRefreshing]; ++ [self setCurrentRefreshingState:super.refreshing]; ++ ++ if (self->_onRefresh) { ++ self->_onRefresh(nil); ++ } ++ } ++ ]; ++} ++ + @end diff --git a/patches/react-native+0.81.5+003+ScrollView-disable-recycling.patch b/patches/react-native+0.81.5+003+ScrollView-disable-recycling.patch new file mode 100644 --- /dev/null +++ b/patches/react-native+0.81.5+003+ScrollView-disable-recycling.patch @@ -0,0 +1,16 @@ +diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +index d029337..0f63ea3 100644 +--- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm ++++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +@@ -1038,6 +1038,11 @@ - (void)_adjustForMaintainVisibleContentPosition + } + } + +++ (BOOL)shouldBeRecycled ++{ ++ return NO; ++} ++ + @end + + Class RCTScrollViewCls(void) diff --git a/patches/react-native+0.81.5.patch b/patches/react-native+0.81.5.patch deleted file mode 100644 --- a/patches/react-native+0.81.5.patch +++ /dev/null @@ -1,136 +0,0 @@ -diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h -index 914a249..0deac55 100644 ---- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h -+++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h -@@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN - */ - @interface RCTPullToRefreshViewComponentView : RCTViewComponentView - -+- (void)beginRefreshingProgrammatically; -+ - @end - - NS_ASSUME_NONNULL_END -diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm -index d029337..0f63ea3 100644 ---- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm -+++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm -@@ -1038,6 +1038,11 @@ - (void)_adjustForMaintainVisibleContentPosition - } - } - -++ (BOOL)shouldBeRecycled -+{ -+ return NO; -+} -+ - @end - - Class RCTScrollViewCls(void) -diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h -index e9b330f..ec5f58c 100644 ---- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h -+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h -@@ -15,5 +15,8 @@ - @property (nonatomic, copy) NSString *title; - @property (nonatomic, copy) RCTDirectEventBlock onRefresh; - @property (nonatomic, weak) UIScrollView *scrollView; -+@property (nonatomic, copy) UIColor *customTintColor; -+ -+- (void)forwarderBeginRefreshing; - - @end -diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m -index 53bfd04..ff1b1ed 100644 ---- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m -+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m -@@ -23,6 +23,7 @@ @implementation RCTRefreshControl { - UIColor *_titleColor; - CGFloat _progressViewOffset; - BOOL _hasMovedToWindow; -+ UIColor *_customTintColor; - } - - - (instancetype)init -@@ -58,6 +59,12 @@ - (void)layoutSubviews - _isInitialRender = false; - } - -+- (void)didMoveToSuperview -+{ -+ [super didMoveToSuperview]; -+ [self setTintColor:_customTintColor]; -+} -+ - - (void)didMoveToWindow - { - [super didMoveToWindow]; -@@ -221,4 +228,50 @@ - (void)refreshControlValueChanged - } - } - -+// Fix for https://github.com/facebook/react-native/issues/43388 -+// A bug in iOS 17.4 causes the haptic to not play when refreshing if the tintColor -+// is set before the refresh control gets added to the scrollview. We'll call this -+// function whenever the superview changes. We'll also call it if the value of customTintColor -+// changes. -+- (void)setTintColor:(UIColor *)tintColor -+{ -+ if ([self.superview isKindOfClass:[UIScrollView class]] && self.tintColor != tintColor) { -+ [super setTintColor:tintColor]; -+ } -+} -+ -+// This method is used by Bluesky's ExpoScrollForwarder. This allows other React Native -+// libraries to perform a refresh of a scrollview and access the refresh control's onRefresh -+// function. -+- (void)forwarderBeginRefreshing -+{ -+ _refreshingProgrammatically = NO; -+ -+ [self sizeToFit]; -+ -+ if (!self.scrollView) { -+ return; -+ } -+ -+ UIScrollView *scrollView = (UIScrollView *)self.scrollView; -+ -+ [UIView animateWithDuration:0.3 -+ delay:0 -+ options:UIViewAnimationOptionBeginFromCurrentState -+ animations:^(void) { -+ // Whenever we call this method, the scrollview will always be at a position of -+ // -130 or less. Scrolling back to -65 simulates the default behavior of RCTRefreshControl -+ [scrollView setContentOffset:CGPointMake(0, -65)]; -+ } -+ completion:^(__unused BOOL finished) { -+ [super beginRefreshing]; -+ [self setCurrentRefreshingState:super.refreshing]; -+ -+ if (self->_onRefresh) { -+ self->_onRefresh(nil); -+ } -+ } -+ ]; -+} -+ - @end -diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m -index 40aaf9c..1c60164 100644 ---- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m -+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m -@@ -22,11 +22,12 @@ - (UIView *)view - - RCT_EXPORT_VIEW_PROPERTY(onRefresh, RCTDirectEventBlock) - RCT_EXPORT_VIEW_PROPERTY(refreshing, BOOL) --RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor) - RCT_EXPORT_VIEW_PROPERTY(title, NSString) - RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor) - RCT_EXPORT_VIEW_PROPERTY(progressViewOffset, CGFloat) - -+RCT_REMAP_VIEW_PROPERTY(tintColor, customTintColor, UIColor) -+ - RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing) - { - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { diff --git a/src/view/icons/Logo.tsx b/src/view/icons/Logo.tsx --- a/src/view/icons/Logo.tsx +++ b/src/view/icons/Logo.tsx @@ -9,9 +9,8 @@ type SvgProps, } from 'react-native-svg' -import {colors} from '#/lib/styles' //import {useKawaiiMode} from '#/state/preferences/kawaii' -import {flatten} from '#/alf' +import {flatten, useTheme} from '#/alf' const ratio = 512 / 512 @@ -21,12 +20,15 @@ } & Omit export const Logo = React.forwardRef(function LogoImpl(props: Props, ref) { + const t = useTheme() const {fill, ...rest} = props const gradient = fill === 'sky' const styles = flatten(props.style) - const _fill = gradient ? 'url(#sky)' : fill || styles?.color || colors.blue3 + const _fill = gradient + ? 'url(#sky)' + : fill || styles?.color || t.palette.primary_500 // @ts-ignore it's fiiiiine - const size = parseInt(rest.width || 32) + const size = parseInt(rest.width || 32, 10) // const isKawaii = useKawaiiMode() diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -422,7 +422,7 @@ msgid "{minutes, plural, one {# minute} other {# minutes}}" msgstr "" -#: src/view/shell/bottom-bar/BottomBarWeb.tsx:277 +#: src/view/shell/bottom-bar/BottomBarWeb.tsx:282 msgid "{notificationCount, plural, one {# unread item} other {# unread items}}" msgstr "" diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx --- a/src/view/shell/bottom-bar/BottomBar.tsx +++ b/src/view/shell/bottom-bar/BottomBar.tsx @@ -29,11 +29,10 @@ import {useLoggedOutViewControls} from '#/state/shell/logged-out' import {useShellLayout} from '#/state/shell/shell-layout' import {useCloseAllActiveElements} from '#/state/util' -import {Text} from '#/view/com/util/text/Text' import {UserAvatar} from '#/view/com/util/UserAvatar' import {Logo} from '#/view/icons/Logo' import {Logotype} from '#/view/icons/Logotype' -import {atoms as a} from '#/alf' +import {atoms as a, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import {useDialogControl} from '#/components/Dialog' import {SwitchAccountDialog} from '#/components/dialogs/SwitchAccount' @@ -51,6 +50,7 @@ Message_Stroke2_Corner0_Rounded as Message, Message_Stroke2_Corner0_Rounded_Filled as MessageFilled, } from '#/components/icons/Message' +import {Text} from '#/components/Typography' import {useDemoMode} from '#/storage/hooks/demo-mode' import {styles} from './BottomBarStyles' @@ -398,6 +398,8 @@ accessibilityLabel, }: BtnProps) { const enableSquareButtons = useEnableSquareButtons() + const t = useTheme() + return ( - {notificationCount} + 1 ) : hasNew ? ( = ({children, href, routeName, hasNew, notificationCount}) => { + const t = useTheme() const {_} = useLingui() const {currentAccount} = useSession() const currentRoute = useNavigationState(state => { @@ -272,7 +273,11 @@ {children({isActive})} {notificationCount ? ( { @@ -28,15 +25,16 @@ export function FABInner({testID, icon, onPress, style, ...props}: FABProps) { const insets = useSafeAreaInsets() - const {isMobile, isTablet} = useWebMediaQueries() + const {gtMobile} = useBreakpoints() + const t = useTheme() const playHaptic = useHaptics() const fabMinimalShellTransform = useMinimalShellFabTransform() const enableSquareButtons = useEnableSquareButtons() - const size = isTablet ? styles.sizeLarge : styles.sizeRegular + const size = gtMobile ? styles.sizeLarge : styles.sizeRegular - const tabletSpacing = isTablet + const tabletSpacing = gtMobile ? {right: 50, bottom: 50} : {right: 24, bottom: clamp(insets.bottom, 15, 60) + 15} @@ -46,7 +44,7 @@ styles.outer, size, tabletSpacing, - isMobile && fabMinimalShellTransform, + !gtMobile && fabMinimalShellTransform, ]}> - - {icon} - + {icon} ) @@ -76,8 +76,8 @@ const styles = StyleSheet.create({ sizeRegular: { - width: 60, - height: 60, + width: 56, + height: 56, borderRadius: 30, }, sizeLarge: { @@ -90,9 +90,5 @@ position: isWeb ? 'fixed' : 'absolute', zIndex: 1, cursor: 'pointer', - }, - inner: { - justifyContent: 'center', - alignItems: 'center', }, }) diff --git a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt --- a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt +++ b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt @@ -78,10 +78,12 @@ intent.getParcelableExtra(Intent.EXTRA_STREAM) } + val text = intent.getStringExtra(Intent.EXTRA_TEXT) + uri?.let { when (type) { - AttachmentType.IMAGE -> handleImageIntents(listOf(it)) - AttachmentType.VIDEO -> handleVideoIntents(listOf(it)) + AttachmentType.IMAGE -> handleImageIntents(listOf(it), text) + AttachmentType.VIDEO -> handleVideoIntents(listOf(it), text) } } } @@ -103,15 +105,20 @@ ?.take(4) } + val text = intent.getStringExtra(Intent.EXTRA_TEXT) + uris?.let { when (type) { - AttachmentType.IMAGE -> handleImageIntents(it) + AttachmentType.IMAGE -> handleImageIntents(it, text) else -> return } } } - private fun handleImageIntents(uris: List) { + private fun handleImageIntents( + uris: List, + text: String? + ) { var allParams = "" uris.forEachIndexed { index, uri -> @@ -124,15 +131,22 @@ } } - val encoded = URLEncoder.encode(allParams, "UTF-8") + val encodedUris = URLEncoder.encode(allParams, "UTF-8") + val encodedText = text?.let { URLEncoder.encode(it, "UTF-8") } - "bluesky://intent/compose?imageUris=$encoded".toUri().let { + var composeIntent = "bluesky://intent/compose?imageUris=$encodedUris" + encodedText?.let { composeIntent += "&text=$it" } + + composeIntent.toUri().let { val newIntent = Intent(Intent.ACTION_VIEW, it) appContext.currentActivity?.startActivity(newIntent) } } - private fun handleVideoIntents(uris: List) { + private fun handleVideoIntents( + uris: List, + text: String? + ) { val uri = uris[0] // If there is no extension for the file, substringAfterLast returns the original string - not // null, so we check for that below @@ -151,7 +165,12 @@ val info = getVideoInfo(uri) ?: return - "bluesky://intent/compose?videoUri=${URLEncoder.encode(file.path, "UTF-8")}|${info["width"]}|${info["height"]}".toUri().let { + val encodedText = text?.let { URLEncoder.encode(it, "UTF-8") } + + var composeIntent = "bluesky://intent/compose?videoUri=${URLEncoder.encode(file.path, "UTF-8")}|${info["width"]}|${info["height"]}" + encodedText?.let { composeIntent += "&text=$it" } + + composeIntent.toUri().let { val newIntent = Intent(Intent.ACTION_VIEW, it) appContext.currentActivity?.startActivity(newIntent) } -- tangled.sh