diff --git a/.gitignore b/.gitignore
index 8297efc2..3c7af134 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,9 +13,10 @@ web-build/
# macOS
.DS_Store
-.env
+.envrc
coverage/
builds/
+
# @generated expo-cli sync-28e2ab0e9ece60556eaf932abe52d017ec33db50
# The following patterns were generated by expo-cli
diff --git a/android/app/build.gradle b/android/app/build.gradle
index c409f52f..2f3bfb6c 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -78,7 +78,7 @@ import com.android.build.OutputFile
*/
project.ext.react = [
- enableHermes: false
+ enableHermes: true
]
apply from: '../../node_modules/react-native-unimodules/gradle.groovy'
diff --git a/android/app/src/main/java/com/xmflsct/app/tooot/MainApplication.java b/android/app/src/main/java/com/xmflsct/app/tooot/MainApplication.java
index 7c5f1e8a..7bf44f4e 100644
--- a/android/app/src/main/java/com/xmflsct/app/tooot/MainApplication.java
+++ b/android/app/src/main/java/com/xmflsct/app/tooot/MainApplication.java
@@ -28,6 +28,9 @@ import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
+ import com.facebook.react.bridge.JSIModulePackage; // <- react-native-reanimated-v2
+ import com.swmansion.reanimated.ReanimatedJSIModulePackage; // <- react-native-reanimated-v2
+
public class MainApplication extends Application implements ReactApplication {
private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(
new BasePackageList().getPackageList()
@@ -51,6 +54,11 @@ public class MainApplication extends Application implements ReactApplication {
return "index";
}
+ @Override // <- react-native-reanimated-v2
+ protected JSIModulePackage getJSIModulePackage() {
+ return new ReanimatedJSIModulePackage();
+ }
+
@Override
protected @Nullable String getJSBundleFile() {
if (BuildConfig.DEBUG) {
diff --git a/app.config.ts b/app.config.ts
index b233ea7e..4880dc5e 100644
--- a/app.config.ts
+++ b/app.config.ts
@@ -3,7 +3,7 @@ import 'dotenv/config'
export default (): ExpoConfig => ({
name: 'tooot',
- description: 'tooot for mastodon',
+ description: 'tooot for Mastodon',
slug: 'tooot',
privacy: 'hidden',
sdkVersion: '40.0.0',
diff --git a/build/android.sh b/build/android.sh
deleted file mode 100755
index 35d32812..00000000
--- a/build/android.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-if [ $# -ne 1 ]; then
- echo "Arguments incorrect. Use 'xxx'"
- exit 1
-fi
-
-JAVA_HOME=`/usr/libexec/java_home -v 1.8.0` \
-EXPO_USERNAME='xmflsct' \
-EXPO_PASSWORD=',8d_AJ1HmYJo8lbve&QoB40t3ImGdF)Dd' \
-EXPO_ANDROID_KEYSTORE_PASSWORD="9c54265087704801ba5d3d88809110a1" \
-EXPO_ANDROID_KEY_PASSWORD="748bb2e11529497dad7831c409175b94" \
-turtle build:android \
- --release-channel $1 \
- --type app-bundle \
- --keystore-path ./tooot.jks \
- --keystore-alias "QHhtZmxzY3QvdG9vb3Q=" \
- --build-dir ./builds
\ No newline at end of file
diff --git a/index.js b/index.js
index 9d5d25a6..5c94d2cb 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,6 @@
import { registerRootComponent } from 'expo';
-import App from './App';
+import App from '@root/App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in the Expo client or in a native build,
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 1e7db969..2e4d6e59 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -7,14 +7,12 @@ PODS:
- UMCore
- UMFileSystemInterface
- UMPermissionsInterface
- - EXBlur (8.2.2):
- - UMCore
- EXConstants (10.0.1):
- UMConstantsInterface
- UMCore
- EXCrypto (8.4.0):
- UMCore
- - EXDevice (2.4.0):
+ - EXDevice (3.1.1):
- UMCore
- EXErrorRecovery (1.4.0):
- UMCore
@@ -25,7 +23,7 @@ PODS:
- EXFirebaseCore
- Firebase/Core (= 6.14.0)
- UMCore
- - EXFirebaseCore (1.3.0):
+ - EXFirebaseCore (1.2.0):
- Firebase/Core (= 6.14.0)
- UMCore
- EXFont (8.4.0):
@@ -66,8 +64,8 @@ PODS:
- UMFileSystemInterface
- EXStoreReview (2.3.0):
- UMCore
- - EXUpdates (0.4.1):
- - React-Core
+ - EXUpdates (0.3.5):
+ - React
- UMCore
- EXVideoThumbnails (4.4.0):
- UMCore
@@ -332,15 +330,17 @@ PODS:
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsinspector (0.63.4)
+ - react-native-blur (0.8.0):
+ - React
- react-native-blurhash (1.0.29):
- React
- react-native-netinfo (5.9.10):
- React-Core
- react-native-safe-area-context (3.1.9):
- React-Core
- - react-native-segmented-control (2.2.1):
+ - react-native-segmented-control (2.2.2):
- React-Core
- - react-native-viewpager (4.2.0):
+ - react-native-viewpager (4.2.2):
- React-Core
- React-RCTActionSheet (0.63.4):
- React-Core/RCTActionSheetHeaders (= 0.63.4)
@@ -410,9 +410,9 @@ PODS:
- React-Core
- SDWebImage (~> 5.8)
- SDWebImageWebPCoder (~> 0.6.1)
- - RNGestureHandler (1.8.0):
- - React
- - RNReanimated (2.0.0-rc.0):
+ - RNGestureHandler (1.9.0):
+ - React-Core
+ - RNReanimated (2.0.0-rc.2):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
@@ -441,11 +441,13 @@ PODS:
- React-RCTVibration
- ReactCommon/turbomodule/core
- Yoga
- - RNScreens (2.15.2):
+ - RNScreens (2.17.1):
- React-Core
- RNSentry (2.1.1):
- React-Core
- Sentry (= 6.0.9)
+ - RNSharedElement (0.7.0):
+ - React
- RNSVG (12.1.0):
- React
- SDWebImage (5.10.3):
@@ -480,8 +482,7 @@ DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- EXApplication (from `../node_modules/expo-application/ios`)
- EXAV (from `../node_modules/expo-av/ios`)
- - EXBlur (from `../node_modules/expo-blur/ios`)
- - EXConstants (from `../node_modules/expo-constants/ios`)
+ - EXConstants (from `../node_modules/sentry-expo/node_modules/expo-constants/ios`)
- EXCrypto (from `../node_modules/expo-crypto/ios`)
- EXDevice (from `../node_modules/expo-device/ios`)
- EXErrorRecovery (from `../node_modules/expo-error-recovery/ios`)
@@ -521,6 +522,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
+ - "react-native-blur (from `../node_modules/@react-native-community/blur`)"
- react-native-blurhash (from `../node_modules/react-native-blurhash`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
@@ -543,6 +545,7 @@ DEPENDENCIES:
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- "RNSentry (from `../node_modules/@sentry/react-native`)"
+ - RNSharedElement (from `../node_modules/react-native-shared-element`)
- RNSVG (from `../node_modules/react-native-svg`)
- UMAppLoader (from `../node_modules/unimodules-app-loader/ios`)
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
@@ -586,10 +589,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-application/ios"
EXAV:
:path: "../node_modules/expo-av/ios"
- EXBlur:
- :path: "../node_modules/expo-blur/ios"
EXConstants:
- :path: "../node_modules/expo-constants/ios"
+ :path: "../node_modules/sentry-expo/node_modules/expo-constants/ios"
EXCrypto:
:path: "../node_modules/expo-crypto/ios"
EXDevice:
@@ -664,6 +665,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
+ react-native-blur:
+ :path: "../node_modules/@react-native-community/blur"
react-native-blurhash:
:path: "../node_modules/react-native-blurhash"
react-native-netinfo:
@@ -708,6 +711,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-screens"
RNSentry:
:path: "../node_modules/@sentry/react-native"
+ RNSharedElement:
+ :path: "../node_modules/react-native-shared-element"
RNSVG:
:path: "../node_modules/react-native-svg"
UMAppLoader:
@@ -744,14 +749,13 @@ SPEC CHECKSUMS:
DoubleConversion: cde416483dac037923206447da6e1454df403714
EXApplication: e3c201e7b913d081bbd37bd3c5d0e2cdc21733b4
EXAV: e32adf44c10a82f723172d5b01d5693890888dd6
- EXBlur: 569d38c2b0b7b000866d928bc36acadfdc02ea8e
EXConstants: d9483a8fe0a963dd7ee3389f371303773e6ecd37
EXCrypto: 81948191c3d2caf18fb32f18ee88d87d42532d62
- EXDevice: 01f54314f618aa4098893f66cd8f2a8a411f33ee
+ EXDevice: 101eddd9bc28faba8246ba0c499a65a4821a6b5e
EXErrorRecovery: b46af4b91e2b4ec598ab1fa51d2cf088aaf5511f
EXFileSystem: 0e4974ab77bff04cda68d2886d070cbe64b93a6b
EXFirebaseAnalytics: d72f553dc0c0a8ee451714499fac21883c3f7369
- EXFirebaseCore: f986c71bdd1cb5941c9cfa686b2395fe588a53d0
+ EXFirebaseCore: d5befdb22015f9b71168ed89dda0b50dbb07fed1
EXFont: 30c64ed8735a180e3f20046e4fdac4ea074d71d3
EXHaptics: 6d2e09387f0eb4d3c8dc97ae905cbea8afe33651
EXImageLoader: f96ec9992733a4224418bbd9382e5485c8948944
@@ -766,7 +770,7 @@ SPEC CHECKSUMS:
EXSplashScreen: 8c7c1112ce7611a853486af4737fe2298eda7657
EXSQLite: bda6a286dded0637bb312ee781239dcca163ff4b
EXStoreReview: 9b161bd86c172a9755c787982bfc32c7193cf803
- EXUpdates: 28368049118dbe4ceaf4422ec72e0ad5f770df1f
+ EXUpdates: 74b39409f68eca207075d87b0077bdf37865a8bf
EXVideoThumbnails: 8ff241784f1d89fdd451bcdb7f733d06361d44a8
EXWebBrowser: cb4811e6c883876d2e2ba1c10527de96963d410a
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
@@ -796,11 +800,12 @@ SPEC CHECKSUMS:
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
+ react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
react-native-blurhash: 90886ae897cafbbdf2773cb3654656bcb34e8f43
react-native-netinfo: 30fb89fa913c342be82a887b56e96be6d71201dd
react-native-safe-area-context: b6e0e284002381d2ff29fa4fff42b4d8282e3c94
- react-native-segmented-control: eb9e25fbfbce226ecf66d643428fbe97601e691a
- react-native-viewpager: c1a686e7b5e164a52387f1522358623c4f52070f
+ react-native-segmented-control: 65df6cd0619b780b3843d574a72d4c7cec396097
+ react-native-viewpager: ea945e2881ce9a4a8bcdc84de4ec65ff23c90f6e
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
@@ -814,10 +819,11 @@ SPEC CHECKSUMS:
RNCAsyncStorage: da95b83e241a7f5efe3da1a949b3ec3175380be0
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
RNFastImage: d4870d58f5936111c56218dbd7fcfc18e65b58ff
- RNGestureHandler: 7a5833d0f788dbd107fbb913e09aa0c1ff333c39
- RNReanimated: b9c929bfff7dedc9c89ab1875f1c6151023358d9
- RNScreens: 3d682bcaba69a4f8e55543d90818704f34338db1
+ RNGestureHandler: 9b7e605a741412e20e13c512738a31bd1611759b
+ RNReanimated: e8a1520b15df106c96214161078c69e4a23b8b29
+ RNScreens: b6c9607e6fe47c1b6e2f1910d2acd46dd7ecea3a
RNSentry: 6b46b6fc1d715a378fbaa5d7d43bc9ce99b500e5
+ RNSharedElement: 00b1a1420d213a34459bb9a5aacabb38107d7948
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
SDWebImage: e378178472b735e84b007bfb55514c97948a0598
SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21
diff --git a/ios/tooot.xcodeproj/project.pbxproj b/ios/tooot.xcodeproj/project.pbxproj
index 266106d6..89650a2d 100644
--- a/ios/tooot.xcodeproj/project.pbxproj
+++ b/ios/tooot.xcodeproj/project.pbxproj
@@ -177,6 +177,7 @@
LastUpgradeCheck = 1130;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
+ DevelopmentTeam = 8EGBLQ2MA6;
LastSwiftMigration = 1120;
};
};
@@ -229,7 +230,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n../node_modules/expo-constants/scripts/get-app-config-ios.sh\n../node_modules/expo-updates/scripts/create-manifest-ios.sh\n../node_modules/expo-constants/scripts/get-app-config-ios.sh\n";
+ shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n../node_modules/expo-constants/scripts/get-app-config-ios.sh\n../node_modules/expo-updates/scripts/create-manifest-ios.sh\n";
};
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@@ -325,6 +326,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = tooot/tooot.entitlements;
CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 8EGBLQ2MA6;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -332,7 +334,7 @@
"FB_SONARKIT_ENABLED=1",
);
INFOPLIST_FILE = tooot/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
@@ -356,9 +358,10 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = tooot/tooot.entitlements;
CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 8EGBLQ2MA6;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
INFOPLIST_FILE = tooot/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
@@ -421,7 +424,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
LIBRARY_SEARCH_PATHS = (
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
@@ -475,7 +478,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
LIBRARY_SEARCH_PATHS = (
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
diff --git a/ios/tooot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/tooot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/ios/tooot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ios/tooot.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/tooot.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..f9b0d7c5
--- /dev/null
+++ b/ios/tooot.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/package.json b/package.json
index 5c0cd633..7e4a0dd7 100644
--- a/package.json
+++ b/package.json
@@ -6,95 +6,91 @@
"web": "expo start --web",
"eject": "expo eject",
"test": "jest --watchAll",
- "release": "./publish/publish.sh"
+ "release": "scripts/release.sh"
},
"dependencies": {
"@expo/react-native-action-sheet": "^3.8.0",
"@neverdull-agency/expo-unlimited-secure-store": "^1.0.10",
- "@react-native-async-storage/async-storage": "^1.13.2",
+ "@react-native-async-storage/async-storage": "^1.13.3",
+ "@react-native-community/blur": "^3.6.0",
"@react-native-community/masked-view": "0.1.10",
- "@react-native-community/netinfo": "^5.9.7",
- "@react-native-community/segmented-control": "2.2.1",
- "@react-native-community/viewpager": "4.2.0",
- "@react-navigation/bottom-tabs": "^5.11.2",
- "@react-navigation/native": "^5.8.10",
+ "@react-native-community/netinfo": "^5.9.10",
+ "@react-native-community/segmented-control": "2.2.2",
+ "@react-native-community/viewpager": "4.2.2",
+ "@react-navigation/bottom-tabs": "^5.11.7",
+ "@react-navigation/native": "^5.9.2",
+ "@react-navigation/stack": "^5.14.2",
"@reduxjs/toolkit": "^1.5.0",
"@sentry/react-native": "^2.1.1",
- "@sharcoux/slider": "^5.0.1",
+ "@sharcoux/slider": "^5.0.4",
"axios": "^0.21.1",
- "expo": "^40.0.0",
+ "expo": "^40.0.1",
"expo-auth-session": "~3.0.0",
"expo-av": "~8.7.0",
- "expo-blur": "~8.2.2",
- "expo-constants": "~10.0.1",
"expo-crypto": "~8.4.0",
"expo-firebase-analytics": "~2.6.0",
- "expo-firebase-core": "~1.3.0",
"expo-haptics": "~8.4.0",
"expo-image-picker": "~9.2.0",
"expo-linear-gradient": "~8.4.0",
- "expo-linking": "~2.0.0",
+ "expo-linking": "~2.0.1",
"expo-localization": "~9.1.0",
"expo-random": "~10.0.0",
"expo-secure-store": "~9.3.0",
"expo-splash-screen": "~0.8.1",
"expo-status-bar": "~1.0.3",
"expo-store-review": "~2.3.0",
- "expo-updates": "~0.4.0",
"expo-video-thumbnails": "~4.4.0",
"expo-web-browser": "~8.6.0",
- "i18next": "^19.8.4",
+ "i18next": "^19.8.5",
"lodash": "^4.17.20",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-i18next": "^11.8.5",
"react-native": "~0.63.4",
- "react-native-animated-spinkit": "^1.4.2",
+ "react-native-animated-spinkit": "^1.5.1",
"react-native-blurhash": "^1.0.29",
"react-native-fast-image": "^8.3.4",
"react-native-feather": "^1.0.2",
- "react-native-gesture-handler": "~1.8.0",
+ "react-native-gesture-handler": "~1.9.0",
"react-native-htmlview": "^0.16.0",
"react-native-image-zoom-viewer": "^3.0.1",
- "react-native-reanimated": "2.0.0-rc.0",
+ "react-native-reanimated": "^2.0.0-rc.2",
"react-native-safe-area-context": "3.1.9",
- "react-native-screens": "~2.15.0",
+ "react-native-screens": "~2.17.1",
+ "react-native-shared-element": "^0.7.0",
"react-native-svg": "12.1.0",
"react-native-tab-view": "^2.15.2",
"react-native-tab-view-viewpager-adapter": "^1.1.0",
- "react-native-toast-message": "^1.4.2",
+ "react-native-toast-message": "^1.4.3",
"react-native-unimodules": "~0.12.0",
- "react-native-web": "~0.13.12",
- "react-navigation": "^4.4.3",
- "react-query": "^3.5.6",
+ "react-navigation-shared-element": "^3.0.0",
+ "react-query": "^3.6.0",
"react-redux": "^7.2.2",
"react-timeago": "^5.2.0",
"redux-persist": "^6.0.0",
"rn-placeholder": "^3.0.3",
"sentry-expo": "^3.0.4",
- "tslib": "^2.0.3"
+ "tslib": "^2.1.0"
},
"devDependencies": {
- "@babel/core": "~7.9.0",
- "@babel/plugin-proposal-optional-chaining": "^7.12.1",
+ "@babel/core": "~7.12.10",
+ "@babel/plugin-proposal-optional-chaining": "^7.12.7",
"@babel/preset-typescript": "^7.12.7",
- "@expo/config": "^3.3.15",
+ "@expo/config": "^3.3.26",
"@jest/types": "^26.6.2",
- "@react-navigation/stack": "^5.12.8",
"@testing-library/jest-native": "^3.4.3",
"@testing-library/react-hooks": "^3.7.0",
"@testing-library/react-native": "^7.1.0",
- "@types/crypto-js": "^4.0.1",
"@types/jest": "^26.0.19",
"@types/lodash": "^4.14.164",
"@types/react": "~16.9.35",
"@types/react-dom": "~16.9.8",
- "@types/react-native": "~0.63.2",
+ "@types/react-native": "~0.63.46",
"@types/react-navigation": "^3.4.0",
- "@types/react-redux": "^7.1.12",
+ "@types/react-redux": "^7.1.16",
"@types/react-test-renderer": "^17.0.0",
"@types/react-timeago": "^4.1.2",
- "@welldone-software/why-did-you-render": "^6.0.4",
+ "@welldone-software/why-did-you-render": "^6.0.5",
"babel-jest": "~25.2.6",
"babel-plugin-module-resolver": "^4.1.0",
"chalk": "^4.1.0",
@@ -102,6 +98,8 @@
"jest": "^26.6.3",
"jest-expo": "^40.0.1",
"nock": "^13.0.5",
+ "react-navigation": "^4.4.3",
+ "react-navigation-stack": "^2.10.2",
"react-test-renderer": "^16.13.1",
"typescript": "~4.1.3"
},
diff --git a/publish/publish.sh b/scripts/release.sh
similarity index 63%
rename from publish/publish.sh
rename to scripts/release.sh
index 26d261ba..8ba2bfd1 100755
--- a/publish/publish.sh
+++ b/scripts/release.sh
@@ -5,4 +5,4 @@ if [ $# -ne 1 ]; then
exit 1
fi
-expo publish --release-channel=$1
\ No newline at end of file
+expo publish --target bare --release-channel=$1
\ No newline at end of file
diff --git a/src/@types/react-navigation.d.ts b/src/@types/react-navigation.d.ts
index 23c36e7e..9c0a9187 100644
--- a/src/@types/react-navigation.d.ts
+++ b/src/@types/react-navigation.d.ts
@@ -1,19 +1,22 @@
+interface IImageInfo {
+ url: string
+ width?: number
+ height?: number
+ originUrl?: string
+ props?: any
+}
+
declare namespace Nav {
type RootStackParamList = {
- 'Screen-Local': undefined
- 'Screen-Public': undefined
- 'Screen-Post': undefined
- 'Screen-Notifications': undefined
- 'Screen-Me': undefined
- }
-
- type SharedStackParamList = {
- 'Screen-Shared-Account': {
- account: Mastodon.Account | Mastodon.Mention
+ 'Screen-Tabs': undefined
+ 'Screen-Actions': {
+ queryKey: QueryKeyTimeline
+ status: Mastodon.Status
+ url?: string
+ type?: 'status' | 'account'
}
- 'Screen-Shared-Announcements': { showAll?: boolean }
- 'Screen-Shared-Attachments': { account: Mastodon.Account }
- 'Screen-Shared-Compose':
+ 'Screen-Announcements': { showAll: boolean }
+ 'Screen-Compose':
| {
type: 'edit'
incomingStatus: Mastodon.Status
@@ -48,54 +51,71 @@ declare namespace Nav {
accts: Mastodon.Account['acct'][]
}
| undefined
- 'Screen-Shared-Hashtag': {
- hashtag: Mastodon.Tag['name']
- }
- 'Screen-Shared-ImagesViewer': {
- imageUrls: ({
- url: string
- width?: number
- height?: number
- originUrl?: string
- props?: any
- } & {
+ 'Screen-ImagesViewer': {
+ imageUrls: (IImageInfo & {
preview_url: Mastodon.AttachmentImage['preview_url']
- remote_url: Mastodon.AttachmentImage['remote_url']
+ remote_url?: Mastodon.AttachmentImage['remote_url']
imageIndex: number
})[]
imageIndex: number
}
- 'Screen-Shared-Relationships': {
+ }
+
+ type ScreenTabsStackParamList = {
+ 'Tab-Local': undefined
+ 'Tab-Public': undefined
+ 'Tab-Compose': undefined
+ 'Tab-Notifications': undefined
+ 'Tab-Me': undefined
+ }
+
+ type TabSharedStackParamList = {
+ 'Tab-Shared-Account': {
+ account: Mastodon.Account | Mastodon.Mention
+ }
+ 'Tab-Shared-Attachments': { account: Mastodon.Account }
+ 'Tab-Shared-Hashtag': {
+ hashtag: Mastodon.Tag['name']
+ }
+ 'Tab-Shared-Relationships': {
account: Mastodon.Account
initialType: 'following' | 'followers'
}
- 'Screen-Shared-Search': undefined
- 'Screen-Shared-Toot': {
+ 'Tab-Shared-Search': undefined
+ 'Tab-Shared-Toot': {
toot: Mastodon.Status
}
}
- type LocalStackParamList = {
- 'Screen-Local-Root': undefined
- } & SharedStackParamList
+ type TabLocalStackParamList = {
+ 'Tab-Local-Root': undefined
+ } & TabSharedStackParamList
- type RemoteStackParamList = {
- 'Screen-Remote-Root': undefined
- } & SharedStackParamList
+ type TabPublicStackParamList = {
+ 'Tab-Public-Root': undefined
+ } & TabSharedStackParamList
- type NotificationsStackParamList = {
- 'Screen-Notifications-Root': undefined
- } & SharedStackParamList
+ type TabComposeStackParamList = {
+ 'Tab-Compose-Root': undefined
+ 'Tab-Compose-EditAttachment': unknown
+ }
- type MeStackParamList = {
- 'Screen-Me-Root': { navigateAway?: 'Screen-Me-Settings-UpdateRemote' }
- 'Screen-Me-Bookmarks': undefined
- 'Screen-Me-Conversations': undefined
- 'Screen-Me-Favourites': undefined
- 'Screen-Me-Lists': undefined
- 'Screen-Me-Lists-List': undefined
- 'Screen-Me-Settings': undefined
- 'Screen-Me-Settings-UpdateRemote': undefined
- 'Screen-Me-Switch': undefined
- } & SharedStackParamList
+ type TabNotificationsStackParamList = {
+ 'Tab-Notifications-Root': undefined
+ } & TabSharedStackParamList
+
+ type TabMeStackParamList = {
+ 'Tab-Me-Root': undefined
+ 'Tab-Me-Bookmarks': undefined
+ 'Tab-Me-Conversations': undefined
+ 'Tab-Me-Favourites': undefined
+ 'Tab-Me-Lists': undefined
+ 'Tab-Me-Lists-List': {
+ list: Mastodon.List['id']
+ title: Mastodon.List['title']
+ }
+ 'Tab-Me-Settings': undefined
+ 'Tab-Me-Settings-UpdateRemote': undefined
+ 'Tab-Me-Switch': undefined
+ } & TabSharedStackParamList
}
diff --git a/App.tsx b/src/App.tsx
similarity index 98%
rename from App.tsx
rename to src/App.tsx
index 102ac0b8..55498b1b 100644
--- a/App.tsx
+++ b/src/App.tsx
@@ -1,6 +1,6 @@
import { ActionSheetProvider } from '@expo/react-native-action-sheet'
import i18n from '@root/i18n/i18n'
-import Index from '@root/Index'
+import Index from '@root/Screens'
import audio from '@root/startup/audio'
import dev from '@root/startup/dev'
import log from '@root/startup/log'
diff --git a/src/Index.tsx b/src/Index.tsx
deleted file mode 100644
index 81eae379..00000000
--- a/src/Index.tsx
+++ /dev/null
@@ -1,324 +0,0 @@
-import client from '@api/client'
-import haptics from '@components/haptics'
-import Icon from '@components/Icon'
-import { toast, toastConfig } from '@components/toast'
-import {
- BottomTabNavigationOptions,
- createBottomTabNavigator
-} from '@react-navigation/bottom-tabs'
-import {
- getFocusedRouteNameFromRoute,
- NavigationContainer,
- NavigationContainerRef
-} from '@react-navigation/native'
-import ScreenLocal from '@screens/Local'
-import ScreenMe from '@screens/Me'
-import ScreenNotifications from '@screens/Notifications'
-import ScreenPublic from '@screens/Public'
-import { useTimelineQuery } from '@utils/queryHooks/timeline'
-import {
- getLocalAccount,
- getLocalActiveIndex,
- getLocalNotification,
- localUpdateAccountPreferences,
- localUpdateNotification
-} from '@utils/slices/instancesSlice'
-import { useTheme } from '@utils/styles/ThemeManager'
-import { themes } from '@utils/styles/themes'
-import * as Analytics from 'expo-firebase-analytics'
-import React, {
- createRef,
- useCallback,
- useEffect,
- useMemo,
- useRef
-} from 'react'
-import { useTranslation } from 'react-i18next'
-import { Image, Platform, StatusBar } from 'react-native'
-import Toast from 'react-native-toast-message'
-import { useDispatch, useSelector } from 'react-redux'
-
-const Tab = createBottomTabNavigator()
-
-export interface Props {
- localCorrupt?: string
-}
-
-export const navigationRef = createRef()
-
-const Index: React.FC = ({ localCorrupt }) => {
- const dispatch = useDispatch()
- const localActiveIndex = useSelector(getLocalActiveIndex)
- const { mode, theme } = useTheme()
- enum barStyle {
- light = 'dark-content',
- dark = 'light-content'
- }
-
- const routeNameRef = useRef()
-
- // const isConnected = useNetInfo().isConnected
- // const [firstRender, setFirstRender] = useState(false)
- // useEffect(() => {
- // if (firstRender) {
- // // bug in netInfo on first render as false
- // if (isConnected !== false) {
- // toast({ type: 'error', content: 'ζζΊποΈη½η»', autoHide: false })
- // }
- // } else {
- // setFirstRender(true)
- // }
- // }, [isConnected, firstRender])
-
- // On launch display login credentials corrupt information
- const { t } = useTranslation('common')
- useEffect(() => {
- const showLocalCorrect = localCorrupt
- ? toast({
- type: 'error',
- message: t('index.localCorrupt'),
- description: localCorrupt.length ? localCorrupt : undefined,
- autoHide: false
- })
- : undefined
- return showLocalCorrect
- }, [localCorrupt])
-
- // On launch check if there is any unread announcements
- useEffect(() => {
- console.log('Checking announcements')
- localActiveIndex !== null &&
- client({
- method: 'get',
- instance: 'local',
- url: `announcements`
- })
- .then(res => {
- if (res?.filter(announcement => !announcement.read).length) {
- navigationRef.current?.navigate('Screen-Shared-Announcements', {
- showAll: false
- })
- }
- })
- .catch(() => {})
- }, [])
-
- // On launch check if there is any unread noficiations
- const queryNotification = useTimelineQuery({
- page: 'Notifications',
- options: {
- enabled: localActiveIndex !== null ? true : false,
- refetchInterval: 1000 * 60,
- refetchIntervalInBackground: true
- }
- })
- const prevNotification = useSelector(getLocalNotification)
- useEffect(() => {
- if (queryNotification.data?.pages) {
- const flattenData = queryNotification.data.pages.flatMap(d => [...d])
- const latestNotificationTime = flattenData.length
- ? (flattenData[0] as Mastodon.Notification).created_at
- : undefined
-
- if (!prevNotification || !prevNotification.latestTime) {
- dispatch(
- localUpdateNotification({
- unread: false
- })
- )
- } else if (
- latestNotificationTime &&
- new Date(prevNotification.latestTime) < new Date(latestNotificationTime)
- ) {
- dispatch(
- localUpdateNotification({
- unread: true,
- latestTime: latestNotificationTime
- })
- )
- }
- }
- }, [queryNotification.data?.pages])
-
- // Lazily update users's preferences, for e.g. composing default visibility
- useEffect(() => {
- if (localActiveIndex !== null) {
- dispatch(localUpdateAccountPreferences())
- }
- }, [])
-
- // Callbacks
- const navigationContainerOnReady = useCallback(
- () =>
- (routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name),
- []
- )
- const navigationContainerOnStateChange = useCallback(() => {
- const previousRouteName = routeNameRef.current
- const currentRouteName = navigationRef.current?.getCurrentRoute()?.name
-
- if (previousRouteName !== currentRouteName) {
- Analytics.setCurrentScreen(currentRouteName)
- }
-
- routeNameRef.current = currentRouteName
- }, [])
- const localAccount = useSelector(getLocalAccount)
- const tabNavigatorScreenOptions = useCallback(
- ({ route }): BottomTabNavigationOptions => ({
- tabBarIcon: ({
- focused,
- color,
- size
- }: {
- focused: boolean
- color: string
- size: number
- }) => {
- switch (route.name) {
- case 'Screen-Local':
- return
- case 'Screen-Public':
- return
- case 'Screen-Post':
- return
- case 'Screen-Notifications':
- return
- case 'Screen-Me':
- return localActiveIndex !== null ? (
-
- ) : (
-
- )
- default:
- return
- }
- },
- ...(Platform.OS === 'android' && {
- tabBarVisible:
- getFocusedRouteNameFromRoute(route) !== 'Screen-Shared-Compose' &&
- getFocusedRouteNameFromRoute(route) !==
- 'Screen-Shared-Announcements' &&
- getFocusedRouteNameFromRoute(route) !==
- 'Screen-Shared-ImagesViewer' &&
- getFocusedRouteNameFromRoute(route) !== 'Screen-Me-Switch'
- })
- }),
- [localActiveIndex, localAccount]
- )
- const tabNavigatorTabBarOptions = useMemo(
- () => ({
- activeTintColor: theme.primary,
- inactiveTintColor:
- localActiveIndex !== null ? theme.secondary : theme.disabled,
- showLabel: false,
- ...(Platform.OS === 'android' && { keyboardHidesTabBar: true })
- }),
- [theme, localActiveIndex]
- )
- const tabScreenLocalListeners = useCallback(
- () => ({
- tabPress: (e: any) => {
- if (!(localActiveIndex !== null)) {
- e.preventDefault()
- }
- }
- }),
- [localActiveIndex]
- )
- const tabScreenComposeListeners = useMemo(
- () => ({
- tabPress: (e: any) => {
- e.preventDefault()
- if (localActiveIndex !== null) {
- haptics('Medium')
- navigationRef.current?.navigate('Screen-Shared-Compose')
- }
- }
- }),
- [localActiveIndex]
- )
- const tabScreenComposeComponent = useCallback(() => null, [])
- const tabScreenNotificationsListeners = useCallback(
- () => ({
- tabPress: (e: any) => {
- if (!(localActiveIndex !== null)) {
- e.preventDefault()
- }
- }
- }),
- [localActiveIndex]
- )
- return (
- <>
-
-
-
-
-
-
-
-
-
-
- {Platform.OS === 'ios' ? (
-
- ) : null}
-
- >
- )
-}
-
-export default React.memo(Index, () => true)
diff --git a/src/Screens.tsx b/src/Screens.tsx
new file mode 100644
index 00000000..322e8580
--- /dev/null
+++ b/src/Screens.tsx
@@ -0,0 +1,216 @@
+import client from '@api/client'
+import { HeaderLeft } from '@components/Header'
+import { toast, toastConfig } from '@components/toast'
+import {
+ NavigationContainer,
+ NavigationContainerRef
+} from '@react-navigation/native'
+import ScreenActions from '@screens/Actions'
+import ScreenAnnouncements from '@screens/Announcements'
+import ScreenCompose from '@screens/Compose'
+import ScreenImagesViewer from '@screens/ImagesViewer'
+import ScreenTabs from '@screens/Tabs'
+import {
+ getLocalActiveIndex,
+ localUpdateAccountPreferences
+} from '@utils/slices/instancesSlice'
+import { useTheme } from '@utils/styles/ThemeManager'
+import { themes } from '@utils/styles/themes'
+import * as Analytics from 'expo-firebase-analytics'
+import React, { createRef, useCallback, useEffect, useRef } from 'react'
+import { useTranslation } from 'react-i18next'
+import { Platform, StatusBar } from 'react-native'
+import Toast from 'react-native-toast-message'
+import { createSharedElementStackNavigator } from 'react-navigation-shared-element'
+import { useDispatch, useSelector } from 'react-redux'
+
+const Stack = createSharedElementStackNavigator()
+
+export interface Props {
+ localCorrupt?: string
+}
+
+export const navigationRef = createRef()
+
+const Index: React.FC = ({ localCorrupt }) => {
+ const dispatch = useDispatch()
+ const localActiveIndex = useSelector(getLocalActiveIndex)
+ const { mode, theme } = useTheme()
+ enum barStyle {
+ light = 'dark-content',
+ dark = 'light-content'
+ }
+
+ const routeNameRef = useRef()
+
+ // const isConnected = useNetInfo().isConnected
+ // const [firstRender, setFirstRender] = useState(false)
+ // useEffect(() => {
+ // if (firstRender) {
+ // // bug in netInfo on first render as false
+ // if (isConnected !== false) {
+ // toast({ type: 'error', content: 'ζζΊποΈη½η»', autoHide: false })
+ // }
+ // } else {
+ // setFirstRender(true)
+ // }
+ // }, [isConnected, firstRender])
+
+ // On launch display login credentials corrupt information
+ const { t } = useTranslation('common')
+ useEffect(() => {
+ const showLocalCorrect = localCorrupt
+ ? toast({
+ type: 'error',
+ message: t('index.localCorrupt'),
+ description: localCorrupt.length ? localCorrupt : undefined,
+ autoHide: false
+ })
+ : undefined
+ return showLocalCorrect
+ }, [localCorrupt])
+
+ // On launch check if there is any unread announcements
+ useEffect(() => {
+ localActiveIndex !== null &&
+ client({
+ method: 'get',
+ instance: 'local',
+ url: `announcements`
+ })
+ .then(res => {
+ if (res?.filter(announcement => !announcement.read).length) {
+ navigationRef.current?.navigate('Screen-Announcements', {
+ showAll: false
+ })
+ }
+ })
+ .catch(() => {})
+ }, [])
+
+ // Lazily update users's preferences, for e.g. composing default visibility
+ useEffect(() => {
+ if (localActiveIndex !== null) {
+ dispatch(localUpdateAccountPreferences())
+ }
+ }, [])
+
+ // Callbacks
+ const navigationContainerOnReady = useCallback(
+ () =>
+ (routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name),
+ []
+ )
+ const navigationContainerOnStateChange = useCallback(() => {
+ const previousRouteName = routeNameRef.current
+ const currentRouteName = navigationRef.current?.getCurrentRoute()?.name
+
+ if (previousRouteName !== currentRouteName) {
+ Analytics.setCurrentScreen(currentRouteName)
+ }
+
+ routeNameRef.current = currentRouteName
+ }, [])
+
+ return (
+ <>
+
+
+
+
+
+ ({
+ cardStyle: {
+ opacity: progress.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 1]
+ })
+ }
+ })
+ }}
+ />
+ (
+ navigationRef.current?.goBack()}
+ />
+ ),
+ animationTypeForReplace: 'pop',
+ cardStyle: { backgroundColor: 'transparent' },
+ cardStyleInterpolator: ({ current: { progress } }) => ({
+ cardStyle: {
+ opacity: progress.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 1]
+ })
+ }
+ })
+ }}
+ />
+
+ (
+ navigationRef.current?.goBack()}
+ />
+ ),
+ cardStyle: { backgroundColor: 'transparent' },
+ cardStyleInterpolator: ({ current: { progress } }) => ({
+ cardStyle: {
+ opacity: progress.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 1]
+ })
+ }
+ })
+ }}
+ sharedElements={route => {
+ const { imageIndex, imageUrls } = route.params
+ return [{ id: `image.${imageUrls[imageIndex].url}`, debug: true }]
+ }}
+ />
+
+
+ {Platform.OS === 'ios' ? (
+
+ ) : null}
+
+ >
+ )
+}
+
+export default React.memo(Index, () => true)
diff --git a/src/components/Account.tsx b/src/components/Account.tsx
index 8ad34895..dfff5f0f 100644
--- a/src/components/Account.tsx
+++ b/src/components/Account.tsx
@@ -21,12 +21,12 @@ const ComponentAccount: React.FC = ({
}) => {
const { theme } = useTheme()
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
- navigation.push('Screen-Shared-Account', { account })
+ navigation.push('Tab-Shared-Account', { account })
}, [])
return (
diff --git a/src/components/BottomSheet.tsx b/src/components/BottomSheet.tsx
deleted file mode 100644
index 52feccb2..00000000
--- a/src/components/BottomSheet.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-import React from 'react'
-import { Dimensions, Modal, StyleSheet, View } from 'react-native'
-import { useSafeAreaInsets } from 'react-native-safe-area-context'
-import { useTheme } from '@utils/styles/ThemeManager'
-import { StyleConstants } from '@utils/styles/constants'
-import Button from '@components/Button'
-import {
- PanGestureHandler,
- State,
- TapGestureHandler
-} from 'react-native-gesture-handler'
-import Animated, {
- Extrapolate,
- interpolate,
- runOnJS,
- useAnimatedGestureHandler,
- useAnimatedStyle,
- useSharedValue,
- withTiming
-} from 'react-native-reanimated'
-import analytics from './analytics'
-
-export interface Props {
- children: React.ReactNode
- visible: boolean
- handleDismiss: () => void
-}
-
-const BottomSheet: React.FC = ({ children, visible, handleDismiss }) => {
- const { theme } = useTheme()
- const insets = useSafeAreaInsets()
-
- const screenHeight = Dimensions.get('screen').height
- const panY = useSharedValue(0)
- const styleTop = useAnimatedStyle(() => {
- return {
- top: interpolate(
- panY.value,
- [0, screenHeight],
- [0, screenHeight],
- Extrapolate.CLAMP
- )
- }
- })
- const callDismiss = () => {
- analytics('bottomsheet_swipe_close')
- handleDismiss()
- }
- const onGestureEvent = useAnimatedGestureHandler({
- onActive: ({ translationY }) => {
- panY.value = translationY
- },
- onEnd: ({ velocityY }) => {
- if (velocityY > 500) {
- runOnJS(callDismiss)()
- } else {
- panY.value = withTiming(0)
- }
- }
- })
-
- return (
-
- {
- if (nativeEvent.state === State.ACTIVE) {
- callDismiss()
- }
- }}
- >
-
-
-
-
- {children}
-
-
-
-
-
- )
-}
-
-const styles = StyleSheet.create({
- overlay: {
- flex: 1,
- justifyContent: 'flex-end'
- },
- container: {
- paddingTop: StyleConstants.Spacing.M
- },
- handle: {
- alignSelf: 'center',
- width: StyleConstants.Spacing.S * 8,
- height: StyleConstants.Spacing.S / 2,
- borderRadius: 100,
- top: -StyleConstants.Spacing.M * 2
- },
- button: {
- marginHorizontal: StyleConstants.Spacing.Global.PagePadding * 2
- }
-})
-
-export default BottomSheet
diff --git a/src/components/GracefullyImage.tsx b/src/components/GracefullyImage.tsx
index a87b0bcf..958da4b6 100644
--- a/src/components/GracefullyImage.tsx
+++ b/src/components/GracefullyImage.tsx
@@ -9,9 +9,11 @@ import {
} from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import FastImage from 'react-native-fast-image'
+import { SharedElement } from 'react-navigation-shared-element'
import { useTheme } from '@utils/styles/ThemeManager'
export interface Props {
+ sharedElement?: string
hidden?: boolean
uri: { preview?: string; original: string; remote?: string }
blurhash?: string
@@ -22,6 +24,7 @@ export interface Props {
}
const GracefullyImage: React.FC = ({
+ sharedElement,
hidden = false,
uri,
blurhash,
@@ -36,11 +39,21 @@ const GracefullyImage: React.FC = ({
const children = useCallback(() => {
return (
<>
- setImageLoaded(true)}
- />
+ {sharedElement ? (
+
+ setImageLoaded(true)}
+ />
+
+ ) : (
+ setImageLoaded(true)}
+ />
+ )}
{blurhash && (hidden || !imageLoaded) ? (
= ({
}) => {
const { theme } = useTheme()
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
- navigation.push('Screen-Shared-Hashtag', { hashtag: hashtag.name })
+ navigation.push('Tab-Shared-Hashtag', { hashtag: hashtag.name })
}, [])
return (
diff --git a/src/components/Header/Left.tsx b/src/components/Header/Left.tsx
index 40c20289..7fea3d82 100644
--- a/src/components/Header/Left.tsx
+++ b/src/components/Header/Left.tsx
@@ -7,11 +7,17 @@ import { Pressable, StyleSheet, Text } from 'react-native'
export interface Props {
type?: 'icon' | 'text'
content?: string
+ native?: boolean
onPress: () => void
}
-const HeaderLeft: React.FC = ({ type = 'icon', content, onPress }) => {
+const HeaderLeft: React.FC = ({
+ type = 'icon',
+ content,
+ native = true,
+ onPress
+}) => {
const { theme } = useTheme()
const children = useMemo(() => {
@@ -42,7 +48,11 @@ const HeaderLeft: React.FC = ({ type = 'icon', content, onPress }) => {
styles.base,
{
backgroundColor: theme.backgroundGradientStart,
- ...(type === 'icon' && { height: 44, width: 44, marginLeft: -9 })
+ ...(type === 'icon' && {
+ height: 44,
+ width: 44,
+ marginLeft: native ? -9 : 9
+ })
}
]}
/>
diff --git a/src/components/Header/Right.tsx b/src/components/Header/Right.tsx
index d22508c1..be302bf1 100644
--- a/src/components/Header/Right.tsx
+++ b/src/components/Header/Right.tsx
@@ -9,6 +9,7 @@ import { Chase } from 'react-native-animated-spinkit'
export interface Props {
type?: 'icon' | 'text'
content: string
+ native?: boolean
loading?: boolean
disabled?: boolean
@@ -19,6 +20,7 @@ export interface Props {
const HeaderRight: React.FC = ({
type = 'icon',
content,
+ native = true,
loading,
disabled,
onPress
@@ -88,7 +90,11 @@ const HeaderRight: React.FC = ({
styles.base,
{
backgroundColor: theme.backgroundGradientStart,
- ...(type === 'icon' && { height: 44, width: 44, marginRight: -9 })
+ ...(type === 'icon' && {
+ height: 44,
+ width: 44,
+ marginRight: native ? -9 : 9
+ })
}
]}
/>
diff --git a/src/components/Instance.tsx b/src/components/Instance.tsx
index 7dc6488a..933fd2f9 100644
--- a/src/components/Instance.tsx
+++ b/src/components/Instance.tsx
@@ -230,12 +230,6 @@ const ComponentInstance: React.FC = ({
content={instanceQuery.data?.title || undefined}
potentialWidth={2}
/>
-
()
+const Stack = createNativeStackNavigator()
const Timelines: React.FC = () => {
const { t, i18n } = useTranslation()
@@ -28,7 +28,7 @@ const Timelines: React.FC = () => {
const onPressSearch = useCallback(() => {
analytics('search_tap', { page: pages[segment].page })
- navigation.navigate('Screen-Public', { screen: 'Screen-Shared-Search' })
+ navigation.navigate('Tab-Public', { screen: 'Tab-Shared-Search' })
}, [])
const routes = pages.map(p => ({ key: p.page }))
diff --git a/src/components/Timelines/Timeline.tsx b/src/components/Timelines/Timeline.tsx
index 8f27391e..acdd3f11 100644
--- a/src/components/Timelines/Timeline.tsx
+++ b/src/components/Timelines/Timeline.tsx
@@ -18,7 +18,6 @@ import TimelineConversation from './Timeline/Conversation'
import TimelineDefault from './Timeline/Default'
import TimelineEmpty from './Timeline/Empty'
import TimelineEnd from './Timeline/End'
-import TimelineHeader from './Timeline/Header'
import TimelineNotifications from './Timeline/Notifications'
export interface Props {
@@ -155,7 +154,6 @@ const Timeline: React.FC = ({
() => !disableInfinity && !isFetchingNextPage && fetchNextPage(),
[isFetchingNextPage]
)
- const ListHeaderComponent = useCallback(() => , [])
const ListFooterComponent = useCallback(
() => ,
[hasNextPage]
diff --git a/src/components/Timelines/Timeline/Conversation.tsx b/src/components/Timelines/Timeline/Conversation.tsx
index 91f9f0cd..e33114a7 100644
--- a/src/components/Timelines/Timeline/Conversation.tsx
+++ b/src/components/Timelines/Timeline/Conversation.tsx
@@ -76,13 +76,13 @@ const TimelineConversation: React.FC = ({
})
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const onPress = useCallback(() => {
analytics('timeline_conversation_press')
if (conversation.last_status) {
conversation.unread && mutate()
- navigation.push('Screen-Shared-Toot', {
+ navigation.push('Tab-Shared-Toot', {
toot: conversation.last_status
})
}
diff --git a/src/components/Timelines/Timeline/Default.tsx b/src/components/Timelines/Timeline/Default.tsx
index f09f5357..08eba47d 100644
--- a/src/components/Timelines/Timeline/Default.tsx
+++ b/src/components/Timelines/Timeline/Default.tsx
@@ -36,7 +36,7 @@ const TimelineDefault: React.FC = ({
}) => {
const localAccount = useSelector(getLocalAccount)
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
let actualStatus = item.reblog ? item.reblog : item
@@ -47,7 +47,7 @@ const TimelineDefault: React.FC = ({
})
!disableOnPress &&
!highlighted &&
- navigation.push('Screen-Shared-Toot', {
+ navigation.push('Tab-Shared-Toot', {
toot: actualStatus
})
}, [])
diff --git a/src/components/Timelines/Timeline/Header.tsx b/src/components/Timelines/Timeline/Header.tsx
deleted file mode 100644
index ea512589..00000000
--- a/src/components/Timelines/Timeline/Header.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import analytics from '@components/analytics'
-import { useNavigation } from '@react-navigation/native'
-import Icon from '@root/components/Icon'
-import { StyleConstants } from '@root/utils/styles/constants'
-import { useTheme } from '@root/utils/styles/ThemeManager'
-import { updatePublicRemoteNotice } from '@utils/slices/contextsSlice'
-import React from 'react'
-import { useTranslation } from 'react-i18next'
-import { StyleSheet, Text, View } from 'react-native'
-import { useDispatch } from 'react-redux'
-
-const TimelineHeader = React.memo(
- () => {
- const { t } = useTranslation('componentTimeline')
- const dispatch = useDispatch()
- const navigation = useNavigation()
- const { theme } = useTheme()
-
- return (
-
-
- {t('header.explanation')}
- {
- analytics('timeline_remote_header_press')
- dispatch(updatePublicRemoteNotice(1))
- navigation.navigate('Screen-Me', {
- screen: 'Screen-Me-Root',
- params: { navigateAway: 'Screen-Me-Settings-UpdateRemote' }
- })
- }}
- >
- {t('header.button')}
-
-
-
-
- )
- },
- () => true
-)
-
-const styles = StyleSheet.create({
- base: {
- margin: StyleConstants.Spacing.Global.PagePadding,
- paddingHorizontal: StyleConstants.Spacing.M,
- paddingVertical: StyleConstants.Spacing.S,
- borderWidth: 1,
- borderRadius: 6
- },
- text: {
- ...StyleConstants.FontStyle.S
- }
-})
-
-export default TimelineHeader
diff --git a/src/components/Timelines/Timeline/Notifications.tsx b/src/components/Timelines/Timeline/Notifications.tsx
index 037f9797..2d749a74 100644
--- a/src/components/Timelines/Timeline/Notifications.tsx
+++ b/src/components/Timelines/Timeline/Notifications.tsx
@@ -29,7 +29,7 @@ const TimelineNotifications: React.FC = ({
}) => {
const localAccount = useSelector(getLocalAccount)
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const actualAccount = notification.status
? notification.status.account
@@ -38,7 +38,7 @@ const TimelineNotifications: React.FC = ({
const onPress = useCallback(() => {
analytics('timeline_notification_press')
notification.status &&
- navigation.push('Screen-Shared-Toot', {
+ navigation.push('Tab-Shared-Toot', {
toot: notification.status
})
}, [])
diff --git a/src/components/Timelines/Timeline/Shared/Actioned.tsx b/src/components/Timelines/Timeline/Shared/Actioned.tsx
index 153de50b..a07ac447 100644
--- a/src/components/Timelines/Timeline/Shared/Actioned.tsx
+++ b/src/components/Timelines/Timeline/Shared/Actioned.tsx
@@ -23,7 +23,7 @@ const TimelineActioned: React.FC = ({
const { t } = useTranslation('componentTimeline')
const { theme } = useTheme()
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const name = account.display_name || account.username
const iconColor = theme.primary
@@ -34,7 +34,7 @@ const TimelineActioned: React.FC = ({
const onPress = useCallback(() => {
analytics('timeline_shared_actioned_press', { action })
- navigation.push('Screen-Shared-Account', { account })
+ navigation.push('Tab-Shared-Account', { account })
}, [])
const children = useMemo(() => {
diff --git a/src/components/Timelines/Timeline/Shared/Actions.tsx b/src/components/Timelines/Timeline/Shared/Actions.tsx
index 719e046e..960146e0 100644
--- a/src/components/Timelines/Timeline/Shared/Actions.tsx
+++ b/src/components/Timelines/Timeline/Shared/Actions.tsx
@@ -104,7 +104,7 @@ const TimelineActions: React.FC = ({
page: queryKey[1].page,
count: status.replies_count
})
- navigation.navigate('Screen-Shared-Compose', {
+ navigation.navigate('Screen-Compose', {
type: 'reply',
incomingStatus: status,
accts,
diff --git a/src/components/Timelines/Timeline/Shared/Attachment.tsx b/src/components/Timelines/Timeline/Shared/Attachment.tsx
index 75a6c509..d50db0c8 100644
--- a/src/components/Timelines/Timeline/Shared/Attachment.tsx
+++ b/src/components/Timelines/Timeline/Shared/Attachment.tsx
@@ -40,7 +40,7 @@ const TimelineAttachment: React.FC = ({ status }) => {
})[] = []
const navigation = useNavigation()
const navigateToImagesViewer = (imageIndex: number) =>
- navigation.navigate('Screen-Shared-ImagesViewer', {
+ navigation.navigate('Screen-ImagesViewer', {
imageUrls,
imageIndex
})
diff --git a/src/components/Timelines/Timeline/Shared/Attachment/Image.tsx b/src/components/Timelines/Timeline/Shared/Attachment/Image.tsx
index 3eef7815..ba4739d1 100644
--- a/src/components/Timelines/Timeline/Shared/Attachment/Image.tsx
+++ b/src/components/Timelines/Timeline/Shared/Attachment/Image.tsx
@@ -33,6 +33,7 @@ const AttachmentImage: React.FC = ({
original: image.url,
remote: image.remote_url
}}
+ sharedElement={image.url}
blurhash={image.blurhash}
onPress={onPress}
style={[
diff --git a/src/components/Timelines/Timeline/Shared/Avatar.tsx b/src/components/Timelines/Timeline/Shared/Avatar.tsx
index 5806ef97..0292d415 100644
--- a/src/components/Timelines/Timeline/Shared/Avatar.tsx
+++ b/src/components/Timelines/Timeline/Shared/Avatar.tsx
@@ -13,12 +13,14 @@ export interface Props {
const TimelineAvatar: React.FC = ({ queryKey, account }) => {
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
// Need to fix go back root
const onPress = useCallback(() => {
- analytics('timeline_shared_avatar_press', { page: queryKey[1].page })
- queryKey && navigation.push('Screen-Shared-Account', { account })
+ analytics('timeline_shared_avatar_press', {
+ page: queryKey && queryKey[1].page
+ })
+ queryKey && navigation.push('Tab-Shared-Account', { account })
}, [])
return (
diff --git a/src/components/Timelines/Timeline/Shared/HeaderActions/Root.tsx b/src/components/Timelines/Timeline/Shared/HeaderActions/Root.tsx
index 3221d2b9..24da7c0c 100644
--- a/src/components/Timelines/Timeline/Shared/HeaderActions/Root.tsx
+++ b/src/components/Timelines/Timeline/Shared/HeaderActions/Root.tsx
@@ -1,5 +1,5 @@
import analytics from '@components/analytics'
-import BottomSheet from '@components/BottomSheet'
+import BottomSheet from '@screens/Tabs/Shared/node_modules/@screens/Actions/BottomSheet'
import Icon from '@components/Icon'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getLocalAccount, getLocalUrl } from '@utils/slices/instancesSlice'
diff --git a/src/components/Timelines/Timeline/Shared/HeaderActions/Status.tsx b/src/components/Timelines/Timeline/Shared/HeaderActions/Status.tsx
index 61937bbf..379e7a3d 100644
--- a/src/components/Timelines/Timeline/Shared/HeaderActions/Status.tsx
+++ b/src/components/Timelines/Timeline/Shared/HeaderActions/Status.tsx
@@ -106,7 +106,7 @@ const HeaderActionsStatus: React.FC = ({
id: status.id
})
if (res.id) {
- navigation.navigate('Screen-Shared-Compose', {
+ navigation.navigate('Screen-Compose', {
type: 'edit',
incomingStatus: res,
queryKey
diff --git a/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx b/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx
index 060279ab..9432407b 100644
--- a/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx
+++ b/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx
@@ -1,13 +1,15 @@
import { StyleConstants } from '@utils/styles/constants'
import React from 'react'
-import { StyleSheet, View } from 'react-native'
+import { Pressable, StyleSheet, View } from 'react-native'
import HeaderSharedAccount from './HeaderShared/Account'
import HeaderSharedApplication from './HeaderShared/Application'
import HeaderSharedCreated from './HeaderShared/Created'
import HeaderSharedVisibility from './HeaderShared/Visibility'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import HeaderSharedMuted from './HeaderShared/Muted'
-import HeaderActions from './HeaderActions/Root'
+import { useNavigation } from '@react-navigation/native'
+import Icon from '@components/Icon'
+import { useTheme } from '@utils/styles/ThemeManager'
export interface Props {
queryKey?: QueryKeyTimeline
@@ -15,6 +17,9 @@ export interface Props {
}
const TimelineHeaderDefault: React.FC = ({ queryKey, status }) => {
+ const navigation = useNavigation()
+ const { theme } = useTheme()
+
return (
@@ -28,11 +33,28 @@ const TimelineHeaderDefault: React.FC = ({ queryKey, status }) => {
{queryKey ? (
-
+ navigation.navigate('Screen-Actions', {
+ queryKey,
+ status,
+ url: status.url || status.uri,
+ type: 'status'
+ })
+ }
+ children={
+
+ }
/>
) : null}
diff --git a/src/components/Timelines/Timeline/Shared/HeaderNotification.tsx b/src/components/Timelines/Timeline/Shared/HeaderNotification.tsx
index 63d9bf19..e83fc52c 100644
--- a/src/components/Timelines/Timeline/Shared/HeaderNotification.tsx
+++ b/src/components/Timelines/Timeline/Shared/HeaderNotification.tsx
@@ -8,8 +8,8 @@ import HeaderSharedCreated from './HeaderShared/Created'
import HeaderSharedVisibility from './HeaderShared/Visibility'
import RelationshipIncoming from '@root/components/Relationship/Incoming'
import HeaderSharedMuted from './HeaderShared/Muted'
-import HeaderActions from './HeaderActions/Root'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
+import ScreenActions from '@screens/Actions'
export interface Props {
queryKey: QueryKeyTimeline
@@ -28,7 +28,7 @@ const TimelineHeaderNotification: React.FC = ({
return
default:
return notification.status ? (
-
+
) : null
}
}, [notification.type])
diff --git a/src/i18n/en/_all.ts b/src/i18n/en/_all.ts
index 46550ad4..0a26f7f1 100644
--- a/src/i18n/en/_all.ts
+++ b/src/i18n/en/_all.ts
@@ -18,6 +18,7 @@ export default {
sharedAccount: require('./screens/sharedAccount').default,
sharedAnnouncements: require('./screens/sharedAnnouncements').default,
+ sharedAttachments: require('./screens/sharedAttachments').default,
sharedCompose: require('./screens/sharedCompose').default,
sharedRelationships: require('./screens/sharedRelationships').default,
sharedSearch: require('./screens/sharedSearch').default,
diff --git a/src/i18n/en/screens/sharedAttachments.ts b/src/i18n/en/screens/sharedAttachments.ts
new file mode 100644
index 00000000..2a580889
--- /dev/null
+++ b/src/i18n/en/screens/sharedAttachments.ts
@@ -0,0 +1,3 @@
+export default {
+ heading: '<0 />\'s <1>media1>'
+}
diff --git a/src/i18n/zh-Hans/_all.ts b/src/i18n/zh-Hans/_all.ts
index 46550ad4..0a26f7f1 100644
--- a/src/i18n/zh-Hans/_all.ts
+++ b/src/i18n/zh-Hans/_all.ts
@@ -18,6 +18,7 @@ export default {
sharedAccount: require('./screens/sharedAccount').default,
sharedAnnouncements: require('./screens/sharedAnnouncements').default,
+ sharedAttachments: require('./screens/sharedAttachments').default,
sharedCompose: require('./screens/sharedCompose').default,
sharedRelationships: require('./screens/sharedRelationships').default,
sharedSearch: require('./screens/sharedSearch').default,
diff --git a/src/i18n/zh-Hans/screens/sharedAttachments.ts b/src/i18n/zh-Hans/screens/sharedAttachments.ts
new file mode 100644
index 00000000..e3873f60
--- /dev/null
+++ b/src/i18n/zh-Hans/screens/sharedAttachments.ts
@@ -0,0 +1,3 @@
+export default {
+ heading: '<0 /> <1>ηεͺδ½1>'
+}
diff --git a/src/screens/Actions.tsx b/src/screens/Actions.tsx
new file mode 100644
index 00000000..34c1123f
--- /dev/null
+++ b/src/screens/Actions.tsx
@@ -0,0 +1,175 @@
+import { StackScreenProps } from '@react-navigation/stack'
+import { getLocalAccount, getLocalUrl } from '@utils/slices/instancesSlice'
+import { StyleConstants } from '@utils/styles/constants'
+import { useTheme } from '@utils/styles/ThemeManager'
+import React, { useCallback, useEffect } from 'react'
+import { Dimensions, StyleSheet, View } from 'react-native'
+import {
+ PanGestureHandler,
+ State,
+ TapGestureHandler
+} from 'react-native-gesture-handler'
+import Animated, {
+ Extrapolate,
+ interpolate,
+ runOnJS,
+ useAnimatedGestureHandler,
+ useAnimatedStyle,
+ useSharedValue,
+ withTiming
+} from 'react-native-reanimated'
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
+import { useSelector } from 'react-redux'
+import ActionsAccount from './Actions/Account'
+import ActionsDomain from './Actions/Domain'
+import ActionsShare from './Actions/Share'
+import ActionsStatus from './Actions/Status'
+
+export type ScreenAccountProp = StackScreenProps<
+ Nav.RootStackParamList,
+ 'Screen-Actions'
+>
+
+const ScreenActions = React.memo(
+ ({
+ route: {
+ params: { queryKey, status, url, type }
+ },
+ navigation
+ }: ScreenAccountProp) => {
+ const localAccount = useSelector(getLocalAccount)
+ const sameAccount = localAccount?.id === status.account.id
+
+ const localDomain = useSelector(getLocalUrl)
+ const statusDomain = status.uri
+ ? status.uri.split(new RegExp(/\/\/(.*?)\//))[1]
+ : ''
+ const sameDomain = localDomain === statusDomain
+
+ const { theme } = useTheme()
+ const insets = useSafeAreaInsets()
+
+ const DEFAULT_VALUE = 350
+ const screenHeight = Dimensions.get('screen').height
+ const panY = useSharedValue(DEFAULT_VALUE)
+ useEffect(() => {
+ panY.value = withTiming(0)
+ }, [])
+ const styleTop = useAnimatedStyle(() => {
+ return {
+ bottom: interpolate(
+ panY.value,
+ [0, screenHeight],
+ [0, -screenHeight],
+ Extrapolate.CLAMP
+ )
+ }
+ })
+ const dismiss = useCallback(() => {
+ panY.value = withTiming(DEFAULT_VALUE)
+ navigation.goBack()
+ }, [])
+ const onGestureEvent = useAnimatedGestureHandler({
+ onActive: ({ translationY }) => {
+ panY.value = translationY
+ },
+ onEnd: ({ velocityY }) => {
+ if (velocityY > 500) {
+ runOnJS(dismiss)()
+ } else {
+ panY.value = withTiming(0)
+ }
+ }
+ })
+
+ return (
+
+ {
+ if (nativeEvent.state === State.ACTIVE) {
+ dismiss()
+ }
+ }}
+ >
+
+
+
+
+ {!sameAccount && (
+
+ )}
+
+ {sameAccount && (
+
+ )}
+
+ {!sameDomain && (
+
+ )}
+
+ {url && type ? (
+
+ ) : null}
+
+
+
+
+
+ )
+ },
+ () => true
+)
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ justifyContent: 'flex-end'
+ },
+ container: {
+ paddingTop: StyleConstants.Spacing.M
+ },
+ handle: {
+ alignSelf: 'center',
+ width: StyleConstants.Spacing.S * 8,
+ height: StyleConstants.Spacing.S / 2,
+ borderRadius: 100,
+ top: -StyleConstants.Spacing.M * 2
+ },
+ button: {
+ marginHorizontal: StyleConstants.Spacing.Global.PagePadding * 2
+ }
+})
+
+export default ScreenActions
diff --git a/src/screens/Actions/Account.tsx b/src/screens/Actions/Account.tsx
new file mode 100644
index 00000000..f87adc76
--- /dev/null
+++ b/src/screens/Actions/Account.tsx
@@ -0,0 +1,126 @@
+import analytics from '@components/analytics'
+import haptics from '@components/haptics'
+import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
+import { toast } from '@components/toast'
+import {
+ MutationVarsTimelineUpdateAccountProperty,
+ QueryKeyTimeline,
+ useTimelineMutation
+} from '@utils/queryHooks/timeline'
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import { useQueryClient } from 'react-query'
+
+export interface Props {
+ queryKey?: QueryKeyTimeline
+ account: Mastodon.Account
+ dismiss: () => void
+}
+
+const ActionsAccount: React.FC = ({ queryKey, account, dismiss }) => {
+ const { t } = useTranslation('componentTimeline')
+
+ const queryClient = useQueryClient()
+ const mutateion = useTimelineMutation({
+ queryClient,
+ onSuccess: (_, params) => {
+ const theParams = params as MutationVarsTimelineUpdateAccountProperty
+ haptics('Success')
+ toast({
+ type: 'success',
+ message: t('common:toastMessage.success.message', {
+ function: t(
+ `shared.header.actions.account.${theParams.payload.property}.function`,
+ {
+ acct: account.acct
+ }
+ )
+ })
+ })
+ },
+ onError: (err: any, params) => {
+ const theParams = params as MutationVarsTimelineUpdateAccountProperty
+ haptics('Error')
+ toast({
+ type: 'error',
+ message: t('common:toastMessage.error.message', {
+ function: t(
+ `shared.header.actions.account.${theParams.payload.property}.function`
+ )
+ }),
+ ...(err.status &&
+ typeof err.status === 'number' &&
+ err.data &&
+ err.data.error &&
+ typeof err.data.error === 'string' && {
+ description: err.data.error
+ })
+ })
+ },
+ onSettled: () => {
+ queryKey && queryClient.invalidateQueries(queryKey)
+ }
+ })
+
+ return (
+
+
+ {
+ analytics('timeline_shared_headeractions_account_mute_press', {
+ page: queryKey && queryKey[1].page
+ })
+ dismiss()
+ mutateion.mutate({
+ type: 'updateAccountProperty',
+ queryKey,
+ id: account.id,
+ payload: { property: 'mute' }
+ })
+ }}
+ iconFront='EyeOff'
+ title={t('shared.header.actions.account.mute.button', {
+ acct: account.acct
+ })}
+ />
+ {
+ analytics('timeline_shared_headeractions_account_block_press', {
+ page: queryKey && queryKey[1].page
+ })
+ dismiss()
+ mutateion.mutate({
+ type: 'updateAccountProperty',
+ queryKey,
+ id: account.id,
+ payload: { property: 'block' }
+ })
+ }}
+ iconFront='XCircle'
+ title={t('shared.header.actions.account.block.button', {
+ acct: account.acct
+ })}
+ />
+ {
+ analytics('timeline_shared_headeractions_account_reports_press', {
+ page: queryKey && queryKey[1].page
+ })
+ dismiss()
+ mutateion.mutate({
+ type: 'updateAccountProperty',
+ queryKey,
+ id: account.id,
+ payload: { property: 'reports' }
+ })
+ }}
+ iconFront='Flag'
+ title={t('shared.header.actions.account.reports.button', {
+ acct: account.acct
+ })}
+ />
+
+ )
+}
+
+export default ActionsAccount
diff --git a/src/screens/Actions/Domain.tsx b/src/screens/Actions/Domain.tsx
new file mode 100644
index 00000000..ffae7de6
--- /dev/null
+++ b/src/screens/Actions/Domain.tsx
@@ -0,0 +1,83 @@
+import analytics from '@components/analytics'
+import MenuContainer from '@components/Menu/Container'
+import MenuHeader from '@components/Menu/Header'
+import MenuRow from '@components/Menu/Row'
+import { toast } from '@components/toast'
+import {
+ QueryKeyTimeline,
+ useTimelineMutation
+} from '@utils/queryHooks/timeline'
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import { Alert } from 'react-native'
+import { useQueryClient } from 'react-query'
+
+export interface Props {
+ queryKey: QueryKeyTimeline
+ domain: string
+ dismiss: () => void
+}
+
+const ActionsDomain: React.FC = ({ queryKey, domain, dismiss }) => {
+ const { t } = useTranslation('componentTimeline')
+ const queryClient = useQueryClient()
+ const mutation = useTimelineMutation({
+ queryClient,
+ onSettled: () => {
+ toast({
+ type: 'success',
+ message: t('common:toastMessage.success.message', {
+ function: t(`shared.header.actions.domain.block.function`)
+ })
+ })
+ queryClient.invalidateQueries(queryKey)
+ }
+ })
+
+ return (
+
+
+ {
+ analytics('timeline_shared_headeractions_domain_block_press', {
+ page: queryKey[1].page
+ })
+ Alert.alert(
+ t('shared.header.actions.domain.alert.title', { domain }),
+ t('shared.header.actions.domain.alert.message'),
+ [
+ {
+ text: t('shared.header.actions.domain.alert.buttons.cancel'),
+ style: 'cancel'
+ },
+ {
+ text: t('shared.header.actions.domain.alert.buttons.confirm'),
+ style: 'destructive',
+ onPress: () => {
+ analytics(
+ 'timeline_shared_headeractions_domain_block_confirm',
+ {
+ page: queryKey && queryKey[1].page
+ }
+ )
+ dismiss()
+ mutation.mutate({
+ type: 'domainBlock',
+ queryKey,
+ domain: domain
+ })
+ }
+ }
+ ]
+ )
+ }}
+ iconFront='CloudOff'
+ title={t(`shared.header.actions.domain.block.button`, {
+ domain
+ })}
+ />
+
+ )
+}
+
+export default ActionsDomain
diff --git a/src/screens/Actions/Share.tsx b/src/screens/Actions/Share.tsx
new file mode 100644
index 00000000..9bad4c3e
--- /dev/null
+++ b/src/screens/Actions/Share.tsx
@@ -0,0 +1,45 @@
+import analytics from '@components/analytics'
+import MenuContainer from '@components/Menu/Container'
+import MenuHeader from '@components/Menu/Header'
+import MenuRow from '@components/Menu/Row'
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import { Platform, Share } from 'react-native'
+
+export interface Props {
+ type: 'status' | 'account'
+ url: string
+ dismiss: () => void
+}
+
+const ActionsShare: React.FC = ({ type, url, dismiss }) => {
+ const { t } = useTranslation('componentTimeline')
+
+ return (
+
+
+ {
+ analytics('timeline_shared_headeractions_share_press')
+ switch (Platform.OS) {
+ case 'ios':
+ await Share.share({
+ url
+ })
+ break
+ case 'android':
+ await Share.share({
+ message: url
+ })
+ break
+ }
+ dismiss()
+ }}
+ />
+
+ )
+}
+
+export default ActionsShare
diff --git a/src/screens/Actions/Status.tsx b/src/screens/Actions/Status.tsx
new file mode 100644
index 00000000..169d0970
--- /dev/null
+++ b/src/screens/Actions/Status.tsx
@@ -0,0 +1,181 @@
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import { Alert } from 'react-native'
+import { useQueryClient } from 'react-query'
+import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
+import { toast } from '@components/toast'
+import {
+ MutationVarsTimelineUpdateStatusProperty,
+ QueryKeyTimeline,
+ useTimelineMutation
+} from '@utils/queryHooks/timeline'
+import analytics from '@components/analytics'
+import { StackNavigationProp } from '@react-navigation/stack'
+
+export interface Props {
+ navigation: StackNavigationProp
+ queryKey: QueryKeyTimeline
+ status: Mastodon.Status
+ dismiss: () => void
+}
+
+const ActionsStatus: React.FC = ({
+ navigation,
+ queryKey,
+ status,
+ dismiss
+}) => {
+ const { t } = useTranslation('componentTimeline')
+
+ const queryClient = useQueryClient()
+ const mutation = useTimelineMutation({
+ queryClient,
+ onMutate: true,
+ onError: (err: any, params, oldData) => {
+ const theFunction = (params as MutationVarsTimelineUpdateStatusProperty)
+ .payload
+ ? (params as MutationVarsTimelineUpdateStatusProperty).payload.property
+ : 'delete'
+ toast({
+ type: 'error',
+ message: t('common:toastMessage.error.message', {
+ function: t(`shared.header.actions.status.${theFunction}.function`)
+ }),
+ ...(err.status &&
+ typeof err.status === 'number' &&
+ err.data &&
+ err.data.error &&
+ typeof err.data.error === 'string' && {
+ description: err.data.error
+ })
+ })
+ queryClient.setQueryData(queryKey, oldData)
+ }
+ })
+
+ return (
+
+
+ {
+ analytics('timeline_shared_headeractions_status_delete_press', {
+ page: queryKey && queryKey[1].page
+ })
+ dismiss()
+ mutation.mutate({
+ type: 'deleteItem',
+ source: 'statuses',
+ queryKey,
+ id: status.id
+ })
+ }}
+ iconFront='Trash'
+ title={t('shared.header.actions.status.delete.button')}
+ />
+ {
+ analytics('timeline_shared_headeractions_status_deleteedit_press', {
+ page: queryKey && queryKey[1].page
+ })
+ Alert.alert(
+ t('shared.header.actions.status.edit.alert.title'),
+ t('shared.header.actions.status.edit.alert.message'),
+ [
+ {
+ text: t(
+ 'shared.header.actions.status.edit.alert.buttons.cancel'
+ ),
+ style: 'cancel'
+ },
+ {
+ text: t(
+ 'shared.header.actions.status.edit.alert.buttons.confirm'
+ ),
+ style: 'destructive',
+ onPress: async () => {
+ analytics(
+ 'timeline_shared_headeractions_status_deleteedit_confirm',
+ {
+ page: queryKey && queryKey[1].page
+ }
+ )
+ dismiss()
+ const res = (await mutation.mutateAsync({
+ type: 'deleteItem',
+ source: 'statuses',
+ queryKey,
+ id: status.id
+ })) as Mastodon.Status
+ if (res.id) {
+ navigation.navigate('Screen-Compose', {
+ type: 'edit',
+ incomingStatus: res,
+ queryKey
+ })
+ }
+ }
+ }
+ ]
+ )
+ }}
+ iconFront='Edit'
+ title={t('shared.header.actions.status.edit.button')}
+ />
+ {
+ analytics('timeline_shared_headeractions_status_mute_press', {
+ page: queryKey && queryKey[1].page
+ })
+ dismiss()
+ mutation.mutate({
+ type: 'updateStatusProperty',
+ queryKey,
+ id: status.id,
+ payload: {
+ property: 'muted',
+ currentValue: status.muted,
+ propertyCount: undefined,
+ countValue: undefined
+ }
+ })
+ }}
+ iconFront='VolumeX'
+ title={
+ status.muted
+ ? t('shared.header.actions.status.mute.button.negative')
+ : t('shared.header.actions.status.mute.button.positive')
+ }
+ />
+ {/* Also note that reblogs cannot be pinned. */}
+ {(status.visibility === 'public' || status.visibility === 'unlisted') && (
+ {
+ analytics('timeline_shared_headeractions_status_pin_press', {
+ page: queryKey && queryKey[1].page
+ })
+ dismiss()
+ mutation.mutate({
+ type: 'updateStatusProperty',
+ queryKey,
+ id: status.id,
+ payload: {
+ property: 'pinned',
+ currentValue: status.pinned,
+ propertyCount: undefined,
+ countValue: undefined
+ }
+ })
+ }}
+ iconFront='Anchor'
+ title={
+ status.pinned
+ ? t('shared.header.actions.status.pin.button.negative')
+ : t('shared.header.actions.status.pin.button.positive')
+ }
+ />
+ )}
+
+ )
+}
+
+export default ActionsStatus
diff --git a/src/screens/Shared/Announcements.tsx b/src/screens/Announcements.tsx
similarity index 79%
rename from src/screens/Shared/Announcements.tsx
rename to src/screens/Announcements.tsx
index e2c4dac7..cb3aa8f7 100644
--- a/src/screens/Shared/Announcements.tsx
+++ b/src/screens/Announcements.tsx
@@ -3,7 +3,8 @@ import Button from '@components/Button'
import haptics from '@components/haptics'
import { ParseHTML } from '@components/Parse'
import RelativeTime from '@components/RelativeTime'
-import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'
+import { BlurView } from '@react-native-community/blur'
+import { StackScreenProps } from '@react-navigation/stack'
import {
useAnnouncementMutation,
useAnnouncementQuery
@@ -23,16 +24,19 @@ import {
import { Chase } from 'react-native-animated-spinkit'
import { FlatList, ScrollView } from 'react-native-gesture-handler'
import { SafeAreaView } from 'react-native-safe-area-context'
-import { SharedAnnouncementsProp } from './sharedScreens'
-const ScreenSharedAnnouncements: React.FC = ({
+export type ScreenAnnouncementsProp = StackScreenProps<
+ Nav.RootStackParamList,
+ 'Screen-Announcements'
+>
+
+const ScreenAnnouncements: React.FC = ({
route: {
params: { showAll = false }
},
navigation
}) => {
- const { theme } = useTheme()
- const bottomTabBarHeight = useBottomTabBarHeight()
+ const { mode, theme } = useTheme()
const [index, setIndex] = useState(0)
const { t } = useTranslation('sharedAnnouncements')
@@ -60,13 +64,7 @@ const ScreenSharedAnnouncements: React.FC = ({
const renderItem = useCallback(
({ item, index }: { item: Mastodon.Announcement; index: number }) => (
-
+
navigation.goBack()}
@@ -199,40 +197,44 @@ const ScreenSharedAnnouncements: React.FC = ({
}, [])
return (
-
-
- ε
¬ε
-
-
-
- {query.data && query.data.length > 1 ? (
- <>
- {query.data.map((d, i) => (
-
- ))}
- >
- ) : null}
-
-
+
+
+
+
+ {query.data && query.data.length > 1 ? (
+ <>
+ {query.data.map((d, i) => (
+
+ ))}
+ >
+ ) : null}
+
+
+
)
}
@@ -241,14 +243,6 @@ const styles = StyleSheet.create({
flex: 1
},
invisibleTextInput: { ...StyleSheet.absoluteFillObject },
- header: {
- justifyContent: 'center',
- alignItems: 'center'
- },
- headerText: {
- ...StyleConstants.FontStyle.L,
- fontWeight: StyleConstants.Font.Weight.Bold
- },
announcementContainer: {
width: Dimensions.get('screen').width,
padding: StyleConstants.Spacing.Global.PagePadding,
@@ -297,7 +291,8 @@ const styles = StyleSheet.create({
indicators: {
flexDirection: 'row',
justifyContent: 'center',
- alignItems: 'center'
+ alignItems: 'center',
+ minHeight: 49
},
indicator: {
width: StyleConstants.Spacing.S,
@@ -307,4 +302,4 @@ const styles = StyleSheet.create({
}
})
-export default ScreenSharedAnnouncements
+export default ScreenAnnouncements
diff --git a/src/screens/Shared/Compose.tsx b/src/screens/Compose.tsx
similarity index 93%
rename from src/screens/Shared/Compose.tsx
rename to src/screens/Compose.tsx
index d21cbd98..cb35829b 100644
--- a/src/screens/Shared/Compose.tsx
+++ b/src/screens/Compose.tsx
@@ -1,9 +1,10 @@
import analytics from '@components/analytics'
import { HeaderLeft, HeaderRight } from '@components/Header'
+import { StackScreenProps } from '@react-navigation/stack'
import haptics from '@root/components/haptics'
import { store } from '@root/store'
-import formatText from '@screens/Shared/Compose/formatText'
-import ComposeRoot from '@screens/Shared/Compose/Root'
+import formatText from '@screens/Compose/formatText'
+import ComposeRoot from '@screens/Compose/Root'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { updateStoreReview } from '@utils/slices/contextsSlice'
import { getLocalAccount } from '@utils/slices/instancesSlice'
@@ -30,11 +31,15 @@ import composeInitialState from './Compose/utils/initialState'
import composeParseState from './Compose/utils/parseState'
import composePost from './Compose/utils/post'
import composeReducer from './Compose/utils/reducer'
-import { SharedComposeProp } from './sharedScreens'
+
+export type ScreenComposeProp = StackScreenProps<
+ Nav.RootStackParamList,
+ 'Screen-Compose'
+>
const Stack = createNativeStackNavigator()
-const Compose: React.FC = ({
+const ScreenCompose: React.FC = ({
route: { params },
navigation
}) => {
@@ -224,22 +229,22 @@ const Compose: React.FC = ({
return (
@@ -251,10 +256,11 @@ const Compose: React.FC = ({
}
const styles = StyleSheet.create({
+ base: { flex: 1 },
count: {
textAlign: 'center',
...StyleConstants.FontStyle.M
}
})
-export default Compose
+export default ScreenCompose
diff --git a/src/screens/Shared/Compose/EditAttachment.tsx b/src/screens/Compose/EditAttachment.tsx
similarity index 98%
rename from src/screens/Shared/Compose/EditAttachment.tsx
rename to src/screens/Compose/EditAttachment.tsx
index 6f03222d..44103178 100644
--- a/src/screens/Shared/Compose/EditAttachment.tsx
+++ b/src/screens/Compose/EditAttachment.tsx
@@ -168,7 +168,7 @@ const ComposeEditAttachment: React.FC = ({
null }}
/>
diff --git a/src/screens/Shared/Compose/EditAttachment/Image.tsx b/src/screens/Compose/EditAttachment/Image.tsx
similarity index 100%
rename from src/screens/Shared/Compose/EditAttachment/Image.tsx
rename to src/screens/Compose/EditAttachment/Image.tsx
diff --git a/src/screens/Shared/Compose/EditAttachment/Root.tsx b/src/screens/Compose/EditAttachment/Root.tsx
similarity index 100%
rename from src/screens/Shared/Compose/EditAttachment/Root.tsx
rename to src/screens/Compose/EditAttachment/Root.tsx
diff --git a/src/screens/Shared/Compose/Posting.tsx b/src/screens/Compose/Posting.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Posting.tsx
rename to src/screens/Compose/Posting.tsx
diff --git a/src/screens/Shared/Compose/Root.tsx b/src/screens/Compose/Root.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root.tsx
rename to src/screens/Compose/Root.tsx
diff --git a/src/screens/Shared/Compose/Root/Actions.tsx b/src/screens/Compose/Root/Actions.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Actions.tsx
rename to src/screens/Compose/Root/Actions.tsx
diff --git a/src/screens/Shared/Compose/Root/Footer.tsx b/src/screens/Compose/Root/Footer.tsx
similarity index 56%
rename from src/screens/Shared/Compose/Root/Footer.tsx
rename to src/screens/Compose/Root/Footer.tsx
index b87a6c6a..31079810 100644
--- a/src/screens/Shared/Compose/Root/Footer.tsx
+++ b/src/screens/Compose/Root/Footer.tsx
@@ -1,9 +1,9 @@
import React, { useContext } from 'react'
-import ComposeAttachments from '@screens/Shared/Compose/Root/Footer/Attachments'
-import ComposeEmojis from '@screens/Shared/Compose/Root/Footer/Emojis'
-import ComposePoll from '@screens/Shared/Compose/Root/Footer/Poll'
-import ComposeReply from '@screens/Shared/Compose/Root/Footer/Reply'
-import ComposeContext from '@screens/Shared/Compose//utils/createContext'
+import ComposeAttachments from '@screens/Compose/Root/Footer/Attachments'
+import ComposeEmojis from '@screens/Compose/Root/Footer/Emojis'
+import ComposePoll from '@screens/Compose/Root/Footer/Poll'
+import ComposeReply from '@screens/Compose/Root/Footer/Reply'
+import ComposeContext from '@screens/Compose/utils/createContext'
const ComposeRootFooter: React.FC = () => {
const { composeState } = useContext(ComposeContext)
diff --git a/src/screens/Shared/Compose/Root/Footer/Attachments.tsx b/src/screens/Compose/Root/Footer/Attachments.tsx
similarity index 99%
rename from src/screens/Shared/Compose/Root/Footer/Attachments.tsx
rename to src/screens/Compose/Root/Footer/Attachments.tsx
index 9b5459d6..f8678533 100644
--- a/src/screens/Shared/Compose/Root/Footer/Attachments.tsx
+++ b/src/screens/Compose/Root/Footer/Attachments.tsx
@@ -177,7 +177,7 @@ const ComposeAttachments: React.FC = () => {
overlay
onPress={() => {
analytics('compose_attachment_edit')
- navigation.navigate('Screen-Shared-Compose-EditAttachment', {
+ navigation.navigate('Screen-Compose-EditAttachment', {
index
})
}}
diff --git a/src/screens/Shared/Compose/Root/Footer/Emojis.tsx b/src/screens/Compose/Root/Footer/Emojis.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Footer/Emojis.tsx
rename to src/screens/Compose/Root/Footer/Emojis.tsx
diff --git a/src/screens/Shared/Compose/Root/Footer/Poll.tsx b/src/screens/Compose/Root/Footer/Poll.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Footer/Poll.tsx
rename to src/screens/Compose/Root/Footer/Poll.tsx
diff --git a/src/screens/Shared/Compose/Root/Footer/Reply.tsx b/src/screens/Compose/Root/Footer/Reply.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Footer/Reply.tsx
rename to src/screens/Compose/Root/Footer/Reply.tsx
diff --git a/src/screens/Shared/Compose/Root/Footer/addAttachment.ts b/src/screens/Compose/Root/Footer/addAttachment.ts
similarity index 100%
rename from src/screens/Shared/Compose/Root/Footer/addAttachment.ts
rename to src/screens/Compose/Root/Footer/addAttachment.ts
diff --git a/src/screens/Shared/Compose/Root/Header.tsx b/src/screens/Compose/Root/Header.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Header.tsx
rename to src/screens/Compose/Root/Header.tsx
diff --git a/src/screens/Shared/Compose/Root/Header/PostingAs.tsx b/src/screens/Compose/Root/Header/PostingAs.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Header/PostingAs.tsx
rename to src/screens/Compose/Root/Header/PostingAs.tsx
diff --git a/src/screens/Shared/Compose/Root/Header/SpoilerInput.tsx b/src/screens/Compose/Root/Header/SpoilerInput.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Header/SpoilerInput.tsx
rename to src/screens/Compose/Root/Header/SpoilerInput.tsx
diff --git a/src/screens/Shared/Compose/Root/Header/TextInput.tsx b/src/screens/Compose/Root/Header/TextInput.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Header/TextInput.tsx
rename to src/screens/Compose/Root/Header/TextInput.tsx
diff --git a/src/screens/Shared/Compose/Root/Suggestion.tsx b/src/screens/Compose/Root/Suggestion.tsx
similarity index 100%
rename from src/screens/Shared/Compose/Root/Suggestion.tsx
rename to src/screens/Compose/Root/Suggestion.tsx
diff --git a/src/screens/Shared/Compose/formatText.tsx b/src/screens/Compose/formatText.tsx
similarity index 100%
rename from src/screens/Shared/Compose/formatText.tsx
rename to src/screens/Compose/formatText.tsx
diff --git a/src/screens/Shared/Compose/updateText.ts b/src/screens/Compose/updateText.ts
similarity index 100%
rename from src/screens/Shared/Compose/updateText.ts
rename to src/screens/Compose/updateText.ts
diff --git a/src/screens/Shared/Compose/utils/createContext.ts b/src/screens/Compose/utils/createContext.ts
similarity index 100%
rename from src/screens/Shared/Compose/utils/createContext.ts
rename to src/screens/Compose/utils/createContext.ts
diff --git a/src/screens/Shared/Compose/utils/initialState.ts b/src/screens/Compose/utils/initialState.ts
similarity index 100%
rename from src/screens/Shared/Compose/utils/initialState.ts
rename to src/screens/Compose/utils/initialState.ts
diff --git a/src/screens/Shared/Compose/utils/parseState.ts b/src/screens/Compose/utils/parseState.ts
similarity index 96%
rename from src/screens/Shared/Compose/utils/parseState.ts
rename to src/screens/Compose/utils/parseState.ts
index 04ad4328..ca515d59 100644
--- a/src/screens/Shared/Compose/utils/parseState.ts
+++ b/src/screens/Compose/utils/parseState.ts
@@ -4,7 +4,7 @@ import composeInitialState from './initialState'
import { ComposeState } from './types'
const composeParseState = (
- params: NonNullable
+ params: NonNullable
): ComposeState => {
switch (params.type) {
case 'edit':
diff --git a/src/screens/Shared/Compose/utils/post.ts b/src/screens/Compose/utils/post.ts
similarity index 93%
rename from src/screens/Shared/Compose/utils/post.ts
rename to src/screens/Compose/utils/post.ts
index 2464c870..7b21f6b1 100644
--- a/src/screens/Shared/Compose/utils/post.ts
+++ b/src/screens/Compose/utils/post.ts
@@ -1,6 +1,6 @@
import client from '@root/api/client'
-import { ComposeState } from '@screens/Shared/Compose/utils/types'
-import { SharedComposeProp } from '@screens/Shared/sharedScreens'
+import { ComposeState } from '@screens/Compose/utils/types'
+import { SharedComposeProp } from '@screens/Tabs/Shared/sharedScreens'
import * as Crypto from 'expo-crypto'
const composePost = async (
diff --git a/src/screens/Shared/Compose/utils/reducer.ts b/src/screens/Compose/utils/reducer.ts
similarity index 100%
rename from src/screens/Shared/Compose/utils/reducer.ts
rename to src/screens/Compose/utils/reducer.ts
diff --git a/src/screens/Shared/Compose/utils/types.d.ts b/src/screens/Compose/utils/types.d.ts
similarity index 100%
rename from src/screens/Shared/Compose/utils/types.d.ts
rename to src/screens/Compose/utils/types.d.ts
diff --git a/src/screens/ImagesViewer.tsx b/src/screens/ImagesViewer.tsx
new file mode 100644
index 00000000..36ccd544
--- /dev/null
+++ b/src/screens/ImagesViewer.tsx
@@ -0,0 +1,93 @@
+import analytics from '@components/analytics'
+import { HeaderRight } from '@components/Header'
+import { StackScreenProps } from '@react-navigation/stack'
+import { StyleConstants } from '@utils/styles/constants'
+import { useTheme } from '@utils/styles/ThemeManager'
+import { findIndex } from 'lodash'
+import React, { useCallback, useLayoutEffect, useState } from 'react'
+import { Platform, Share, StyleSheet, Text } from 'react-native'
+import FastImage from 'react-native-fast-image'
+import ImageViewer from 'react-native-image-zoom-viewer'
+import { SharedElement } from 'react-navigation-shared-element'
+
+export type ScreenImagesViewerProp = StackScreenProps<
+ Nav.RootStackParamList,
+ 'Screen-ImagesViewer'
+>
+
+const ScreenImagesViewer = React.memo(
+ ({
+ route: {
+ params: { imageUrls, imageIndex }
+ },
+ navigation
+ }: ScreenImagesViewerProp) => {
+ const { theme } = useTheme()
+ const [currentIndex, setCurrentIndex] = useState(
+ findIndex(imageUrls, ['imageIndex', imageIndex])
+ )
+
+ const onPress = useCallback(() => {
+ analytics('imageviewer_share_press')
+ switch (Platform.OS) {
+ case 'ios':
+ return Share.share({ url: imageUrls[currentIndex].url })
+ case 'android':
+ return Share.share({ message: imageUrls[currentIndex].url })
+ }
+ }, [currentIndex])
+
+ useLayoutEffect(
+ () =>
+ navigation.setOptions({
+ headerTitle: () => (
+
+ {currentIndex + 1} / {imageUrls.length}
+
+ ),
+ headerRight: () => (
+
+ )
+ }),
+ [currentIndex]
+ )
+
+ const renderImage = useCallback(
+ prop => (
+
+
+
+ ),
+ []
+ )
+
+ return (
+ <>>}
+ saveToLocalByLongPress={false}
+ onSwipeDown={() => navigation.goBack()}
+ style={{ flex: 1 }}
+ onChange={index => index !== undefined && setCurrentIndex(index)}
+ renderImage={renderImage}
+ />
+ )
+ },
+ () => true
+)
+
+const styles = StyleSheet.create({
+ headerCenter: {
+ color: 'white',
+ ...StyleConstants.FontStyle.M
+ }
+})
+
+export default ScreenImagesViewer
diff --git a/src/screens/Shared/ImagesViewer.tsx b/src/screens/Shared/ImagesViewer.tsx
deleted file mode 100644
index 5ab24203..00000000
--- a/src/screens/Shared/ImagesViewer.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import analytics from '@components/analytics'
-import { HeaderLeft, HeaderRight } from '@components/Header'
-import { StyleConstants } from '@utils/styles/constants'
-import { findIndex } from 'lodash'
-import React, { useCallback, useState } from 'react'
-import {
- Image,
- Platform,
- Share,
- StatusBar,
- StyleSheet,
- Text
-} from 'react-native'
-import ImageViewer from 'react-native-image-zoom-viewer'
-import { useSafeAreaInsets } from 'react-native-safe-area-context'
-import { createNativeStackNavigator } from 'react-native-screens/native-stack'
-import { SharedImagesViewerProp } from './sharedScreens'
-
-const Stack = createNativeStackNavigator()
-
-const ScreenSharedImagesViewer: React.FC = ({
- route: {
- params: { imageUrls, imageIndex }
- },
- navigation
-}) => {
- const safeAreaInsets = useSafeAreaInsets()
-
- const initialIndex = findIndex(imageUrls, ['imageIndex', imageIndex])
- const [currentIndex, setCurrentIndex] = useState(initialIndex)
-
- const component = useCallback(
- () => (
- <>
-
- <>>}
- saveToLocalByLongPress={false}
- onSwipeDown={() => navigation.goBack()}
- style={{ flex: 1, marginBottom: 44 + safeAreaInsets.bottom }}
- onChange={index => index !== undefined && setCurrentIndex(index)}
- renderImage={prop => {
- return
- }}
- />
- >
- ),
- []
- )
-
- const onPress = useCallback(() => {
- analytics('imageviewer_share_press')
- switch (Platform.OS) {
- case 'ios':
- return Share.share({ url: imageUrls[currentIndex].url })
- case 'android':
- return Share.share({ message: imageUrls[currentIndex].url })
- }
- }, [currentIndex])
-
- return (
-
- (
- navigation.goBack()} />
- ),
- headerCenter: () => (
-
- {currentIndex + 1} / {imageUrls.length}
-
- ),
- headerRight: () =>
- }}
- />
-
- )
-}
-
-const styles = StyleSheet.create({
- headerCenter: {
- color: 'white',
- ...StyleConstants.FontStyle.M
- }
-})
-
-export default React.memo(ScreenSharedImagesViewer, () => true)
diff --git a/src/screens/Shared/Relationships.tsx b/src/screens/Shared/Relationships.tsx
deleted file mode 100644
index b8323ff2..00000000
--- a/src/screens/Shared/Relationships.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import SegmentedControl from '@react-native-community/segmented-control'
-import { useNavigation } from '@react-navigation/native'
-import { useTheme } from '@utils/styles/ThemeManager'
-import React, { useEffect, useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { Dimensions, StyleSheet, View } from 'react-native'
-import { TabView } from 'react-native-tab-view'
-import RelationshipsList from './Relationships/List'
-import { SharedRelationshipsProp } from './sharedScreens'
-
-const ScreenSharedRelationships: React.FC = ({
- route: {
- params: { account, initialType }
- }
-}) => {
- const { t } = useTranslation('sharedRelationships')
- const { mode } = useTheme()
- const navigation = useNavigation()
-
- const [segment, setSegment] = useState(initialType === 'following' ? 0 : 1)
- useEffect(() => {
- const updateHeaderRight = () =>
- navigation.setOptions({
- headerCenter: () => (
-
-
- setSegment(nativeEvent.selectedSegmentIndex)
- }
- />
-
- )
- })
- return updateHeaderRight()
- }, [segment, mode])
-
- const routes: {
- key: SharedRelationshipsProp['route']['params']['initialType']
- }[] = [{ key: 'following' }, { key: 'followers' }]
-
- const renderScene = ({
- route
- }: {
- route: {
- key: SharedRelationshipsProp['route']['params']['initialType']
- }
- }) => {
- return
- }
-
- return (
- null}
- onIndexChange={index => setSegment(index)}
- navigationState={{ index: segment, routes }}
- initialLayout={{ width: Dimensions.get('screen').width }}
- />
- )
-}
-
-const styles = StyleSheet.create({
- segmentsContainer: {
- flexBasis: '60%'
- }
-})
-
-export default React.memo(ScreenSharedRelationships, () => true)
diff --git a/src/screens/Tabs.tsx b/src/screens/Tabs.tsx
new file mode 100644
index 00000000..cdc7fb40
--- /dev/null
+++ b/src/screens/Tabs.tsx
@@ -0,0 +1,213 @@
+import haptics from '@components/haptics'
+import Icon from '@components/Icon'
+import {
+ BottomTabNavigationOptions,
+ createBottomTabNavigator
+} from '@react-navigation/bottom-tabs'
+import { NavigatorScreenParams } from '@react-navigation/native'
+import { StackScreenProps } from '@react-navigation/stack'
+import { useTimelineQuery } from '@utils/queryHooks/timeline'
+import {
+ getLocalAccount,
+ getLocalActiveIndex,
+ getLocalNotification,
+ localUpdateNotification
+} from '@utils/slices/instancesSlice'
+import { useTheme } from '@utils/styles/ThemeManager'
+import React, { useCallback, useEffect, useMemo } from 'react'
+import { Platform } from 'react-native'
+import FastImage from 'react-native-fast-image'
+import { useDispatch, useSelector } from 'react-redux'
+import TabLocal from './Tabs/Local'
+import TabMe from './Tabs/Me'
+import TabNotifications from './Tabs/Notifications'
+import TabPublic from './Tabs/Public'
+
+export type ScreenTabsParamList = {
+ 'Tab-Local': NavigatorScreenParams
+ 'Tab-Public': NavigatorScreenParams
+ 'Tab-Compose': NavigatorScreenParams
+ 'Tab-Notifications': NavigatorScreenParams
+ 'Tab-Me': NavigatorScreenParams
+}
+
+export type ScreenTabsProp = StackScreenProps<
+ Nav.RootStackParamList,
+ 'Screen-Tabs'
+>
+
+const Tab = createBottomTabNavigator()
+
+const ScreenTabs: React.FC = ({ navigation }) => {
+ const { theme } = useTheme()
+ const dispatch = useDispatch()
+ const localActiveIndex = useSelector(getLocalActiveIndex)
+ const localAccount = useSelector(getLocalAccount)
+
+ const screenOptions = useCallback(
+ ({ route }): BottomTabNavigationOptions => ({
+ tabBarIcon: ({
+ focused,
+ color,
+ size
+ }: {
+ focused: boolean
+ color: string
+ size: number
+ }) => {
+ switch (route.name) {
+ case 'Tab-Local':
+ return
+ case 'Tab-Public':
+ return
+ case 'Tab-Compose':
+ return
+ case 'Tab-Notifications':
+ return
+ case 'Tab-Me':
+ return localActiveIndex !== null ? (
+
+ ) : (
+
+ )
+ default:
+ return
+ }
+ }
+ }),
+ [localActiveIndex, localAccount]
+ )
+ const tabNavigatorTabBarOptions = useMemo(
+ () => ({
+ activeTintColor: theme.primary,
+ inactiveTintColor:
+ localActiveIndex !== null ? theme.secondary : theme.disabled,
+ showLabel: false,
+ ...(Platform.OS === 'android' && { keyboardHidesTabBar: true })
+ }),
+ [theme, localActiveIndex]
+ )
+ const tabScreenLocalListeners = useCallback(
+ () => ({
+ tabPress: (e: any) => {
+ if (!(localActiveIndex !== null)) {
+ e.preventDefault()
+ }
+ }
+ }),
+ [localActiveIndex]
+ )
+ const tabScreenComposeListeners = useMemo(
+ () => ({
+ tabPress: (e: any) => {
+ e.preventDefault()
+ if (localActiveIndex !== null) {
+ haptics('Light')
+ navigation.navigate('Screen-Compose')
+ }
+ }
+ }),
+ [localActiveIndex]
+ )
+ const tabScreenComposeComponent = useCallback(() => null, [])
+ const tabScreenNotificationsListeners = useCallback(
+ () => ({
+ tabPress: (e: any) => {
+ if (!(localActiveIndex !== null)) {
+ e.preventDefault()
+ }
+ }
+ }),
+ [localActiveIndex]
+ )
+
+ // On launch check if there is any unread noficiations
+ const queryNotification = useTimelineQuery({
+ page: 'Notifications',
+ options: {
+ enabled: localActiveIndex !== null ? true : false,
+ refetchInterval: 1000 * 60,
+ refetchIntervalInBackground: true
+ }
+ })
+ const prevNotification = useSelector(getLocalNotification)
+ useEffect(() => {
+ if (queryNotification.data?.pages) {
+ const flattenData = queryNotification.data.pages.flatMap(d => [...d])
+ const latestNotificationTime = flattenData.length
+ ? (flattenData[0] as Mastodon.Notification).created_at
+ : undefined
+
+ if (!prevNotification || !prevNotification.latestTime) {
+ dispatch(localUpdateNotification({ unread: false }))
+ } else if (
+ latestNotificationTime &&
+ new Date(prevNotification.latestTime) < new Date(latestNotificationTime)
+ ) {
+ dispatch(
+ localUpdateNotification({
+ unread: true,
+ latestTime: latestNotificationTime
+ })
+ )
+ }
+ }
+ }, [queryNotification.data?.pages])
+
+ return (
+
+
+
+
+
+
+
+ )
+}
+
+export default ScreenTabs
diff --git a/src/screens/Local.tsx b/src/screens/Tabs/Local.tsx
similarity index 65%
rename from src/screens/Local.tsx
rename to src/screens/Tabs/Local.tsx
index 1b88b412..5af4c9e4 100644
--- a/src/screens/Local.tsx
+++ b/src/screens/Tabs/Local.tsx
@@ -1,7 +1,8 @@
import analytics from '@components/analytics'
import { HeaderCenter, HeaderRight } from '@components/Header'
import Timeline from '@components/Timelines/Timeline'
-import { useNavigation } from '@react-navigation/native'
+import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
+import { ScreenTabsParamList } from '@screens/Tabs'
import { getLocalActiveIndex } from '@utils/slices/instancesSlice'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
@@ -10,26 +11,27 @@ import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { useSelector } from 'react-redux'
import sharedScreens from './Shared/sharedScreens'
-const Stack = createNativeStackNavigator()
+export type TabLocalProp = BottomTabScreenProps<
+ ScreenTabsParamList,
+ 'Tab-Local'
+>
-const ScreenLocal = React.memo(
- () => {
+const Stack = createNativeStackNavigator()
+
+const TabLocal = React.memo(
+ ({ navigation }: TabLocalProp) => {
const { t } = useTranslation('local')
- const navigation = useNavigation()
const localActiveIndex = useSelector(getLocalActiveIndex)
const onPressSearch = useCallback(() => {
analytics('search_tap', { page: 'Local' })
- navigation.navigate('Screen-Local', { screen: 'Screen-Shared-Search' })
+ navigation.navigate('Tab-Local', { screen: 'Tab-Shared-Search' })
}, [])
return (
- null,
- headerRight: () => (
-
- ),
headerTitle: t('heading'),
...(Platform.OS === 'android' && {
headerCenter: () =>
@@ -38,7 +40,14 @@ const ScreenLocal = React.memo(
headerTopInsetEnabled: false
}}
>
-
+ (
+
+ )
+ }}
+ >
{() =>
localActiveIndex !== null ? : null
}
@@ -51,4 +60,4 @@ const ScreenLocal = React.memo(
() => true
)
-export default ScreenLocal
+export default TabLocal
diff --git a/src/screens/Me.tsx b/src/screens/Tabs/Me.tsx
similarity index 79%
rename from src/screens/Me.tsx
rename to src/screens/Tabs/Me.tsx
index ae867b44..595cc3f1 100644
--- a/src/screens/Me.tsx
+++ b/src/screens/Tabs/Me.tsx
@@ -1,21 +1,21 @@
import { HeaderCenter, HeaderLeft } from '@components/Header'
-import ScreenMeBookmarks from '@screens/Me/Bookmarks'
-import ScreenMeConversations from '@screens/Me/Cconversations'
-import ScreenMeFavourites from '@screens/Me/Favourites'
-import ScreenMeLists from '@screens/Me/Lists'
-import ScreenMeRoot from '@screens/Me/Root'
-import ScreenMeListsList from '@screens/Me/Root/Lists/List'
-import ScreenMeSettings from '@screens/Me/Settings'
-import ScreenMeSwitch from '@screens/Me/Switch'
-import sharedScreens from '@screens/Shared/sharedScreens'
+import ScreenMeBookmarks from '@screens/Tabs/Me/Bookmarks'
+import ScreenMeConversations from '@screens/Tabs/Me/Cconversations'
+import ScreenMeFavourites from '@screens/Tabs/Me/Favourites'
+import ScreenMeLists from '@screens/Tabs/Me/Lists'
+import ScreenMeRoot from '@screens/Tabs/Me/Root'
+import ScreenMeListsList from '@screens/Tabs/Me/Root/Lists/List'
+import ScreenMeSettings from '@screens/Tabs/Me/Settings'
+import ScreenMeSwitch from '@screens/Tabs/Me/Switch'
+import sharedScreens from '@screens/Tabs/Shared/sharedScreens'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Platform } from 'react-native'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
-const Stack = createNativeStackNavigator()
+const Stack = createNativeStackNavigator()
-const ScreenMe: React.FC = () => {
+const TabMe: React.FC = () => {
const { t } = useTranslation()
return (
@@ -23,7 +23,7 @@ const ScreenMe: React.FC = () => {
screenOptions={{ headerHideShadow: true, headerTopInsetEnabled: false }}
>
{
}}
/>
({
headerTitle: t('meBookmarks:heading'),
@@ -45,7 +45,7 @@ const ScreenMe: React.FC = () => {
})}
/>
({
headerTitle: t('meConversations:heading'),
@@ -58,7 +58,7 @@ const ScreenMe: React.FC = () => {
})}
/>
({
headerTitle: t('meFavourites:heading'),
@@ -71,7 +71,7 @@ const ScreenMe: React.FC = () => {
})}
/>
({
headerTitle: t('meLists:heading'),
@@ -82,7 +82,7 @@ const ScreenMe: React.FC = () => {
})}
/>
({
headerTitle: t('meListsList:heading', { list: route.params.title }),
@@ -97,7 +97,7 @@ const ScreenMe: React.FC = () => {
})}
/>
({
headerTitle: t('meSettings:heading'),
@@ -110,10 +110,10 @@ const ScreenMe: React.FC = () => {
})}
/>
({
- stackPresentation: 'fullScreenModal',
+ stackPresentation: 'modal',
headerShown: false,
headerLeft: () => navigation.pop(1)} />
})}
@@ -124,4 +124,4 @@ const ScreenMe: React.FC = () => {
)
}
-export default ScreenMe
+export default TabMe
diff --git a/src/screens/Me/Bookmarks.tsx b/src/screens/Tabs/Me/Bookmarks.tsx
similarity index 100%
rename from src/screens/Me/Bookmarks.tsx
rename to src/screens/Tabs/Me/Bookmarks.tsx
diff --git a/src/screens/Me/Cconversations.tsx b/src/screens/Tabs/Me/Cconversations.tsx
similarity index 100%
rename from src/screens/Me/Cconversations.tsx
rename to src/screens/Tabs/Me/Cconversations.tsx
diff --git a/src/screens/Me/Favourites.tsx b/src/screens/Tabs/Me/Favourites.tsx
similarity index 100%
rename from src/screens/Me/Favourites.tsx
rename to src/screens/Tabs/Me/Favourites.tsx
diff --git a/src/screens/Me/Lists.tsx b/src/screens/Tabs/Me/Lists.tsx
similarity index 76%
rename from src/screens/Me/Lists.tsx
rename to src/screens/Tabs/Me/Lists.tsx
index f682f426..13c47435 100644
--- a/src/screens/Me/Lists.tsx
+++ b/src/screens/Tabs/Me/Lists.tsx
@@ -1,11 +1,13 @@
import { MenuRow } from '@components/Menu'
-import { useNavigation } from '@react-navigation/native'
+import { StackScreenProps } from '@react-navigation/stack'
import TimelineEmpty from '@root/components/Timelines/Timeline/Empty'
import { useListsQuery } from '@utils/queryHooks/lists'
import React, { useMemo } from 'react'
-const ScreenMeLists: React.FC = () => {
- const navigation = useNavigation()
+const ScreenMeLists: React.FC> = ({ navigation }) => {
const { status, data, refetch } = useListsQuery({})
const children = useMemo(() => {
@@ -16,7 +18,7 @@ const ScreenMeLists: React.FC = () => {
iconFront='List'
title={d.title}
onPress={() =>
- navigation.navigate('Screen-Me-Lists-List', {
+ navigation.navigate('Tab-Me-Lists-List', {
list: d.id,
title: d.title
})
diff --git a/src/screens/Me/Root.tsx b/src/screens/Tabs/Me/Root.tsx
similarity index 65%
rename from src/screens/Me/Root.tsx
rename to src/screens/Tabs/Me/Root.tsx
index ebdac897..4e751c0d 100644
--- a/src/screens/Me/Root.tsx
+++ b/src/screens/Tabs/Me/Root.tsx
@@ -1,31 +1,22 @@
+import ComponentInstance from '@components/Instance'
import { useScrollToTop } from '@react-navigation/native'
-import Collections from '@screens/Me/Root/Collections'
-import MyInfo from '@screens/Me/Root/MyInfo'
-import Settings from '@screens/Me/Root/Settings'
-import Logout from '@screens/Me/Root/Logout'
-import AccountNav from '@screens/Shared/Account/Nav'
-import accountReducer from '@screens/Shared/Account/utils/reducer'
-import accountInitialState from '@screens/Shared/Account/utils/initialState'
-import AccountContext from '@screens/Shared/Account/utils/createContext'
+import Collections from '@screens/Tabs/Me/Root/Collections'
+import Logout from '@screens/Tabs/Me/Root/Logout'
+import MyInfo from '@screens/Tabs/Me/Root/MyInfo'
+import Settings from '@screens/Tabs/Me/Root/Settings'
+import AccountNav from '@screens/Tabs/Shared/Account/Nav'
+import AccountContext from '@screens/Tabs/Shared/Account/utils/createContext'
+import accountInitialState from '@screens/Tabs/Shared/Account/utils/initialState'
+import accountReducer from '@screens/Tabs/Shared/Account/utils/reducer'
import { getLocalActiveIndex } from '@utils/slices/instancesSlice'
-import React, { useEffect, useReducer, useRef, useState } from 'react'
-import { useSelector } from 'react-redux'
+import React, { useReducer, useRef, useState } from 'react'
import Animated, {
useAnimatedScrollHandler,
useSharedValue
} from 'react-native-reanimated'
-import ComponentInstance from '@components/Instance'
-import { StackScreenProps } from '@react-navigation/stack'
+import { useSelector } from 'react-redux'
-const ScreenMeRoot: React.FC> = ({ route: { params }, navigation }) => {
- useEffect(() => {
- if (params && params.navigateAway) {
- navigation.navigate(params.navigateAway)
- }
- }, [params])
+const ScreenMeRoot: React.FC = () => {
const localActiveIndex = useSelector(getLocalActiveIndex)
const scrollRef = useRef(null)
diff --git a/src/screens/Me/Root/Collections.tsx b/src/screens/Tabs/Me/Root/Collections.tsx
similarity index 83%
rename from src/screens/Me/Root/Collections.tsx
rename to src/screens/Tabs/Me/Root/Collections.tsx
index af55da15..2bfad115 100644
--- a/src/screens/Me/Root/Collections.tsx
+++ b/src/screens/Tabs/Me/Root/Collections.tsx
@@ -27,25 +27,25 @@ const Collections: React.FC = () => {
iconFront='Mail'
iconBack='ChevronRight'
title={t('content.collections.conversations')}
- onPress={() => navigation.navigate('Screen-Me-Conversations')}
+ onPress={() => navigation.navigate('Tab-Me-Conversations')}
/>
navigation.navigate('Screen-Me-Bookmarks')}
+ onPress={() => navigation.navigate('Tab-Me-Bookmarks')}
/>
navigation.navigate('Screen-Me-Favourites')}
+ onPress={() => navigation.navigate('Tab-Me-Favourites')}
/>
navigation.navigate('Screen-Me-Lists')}
+ onPress={() => navigation.navigate('Tab-Me-Lists')}
/>
{
onPress={() =>
data &&
data.length &&
- navigation.navigate('Screen-Shared-Announcements', { showAll: true })
+ navigation.navigate('Screen-Announcements', { showAll: true })
}
/>
diff --git a/src/screens/Me/Root/Lists/List.tsx b/src/screens/Tabs/Me/Root/Lists/List.tsx
similarity index 100%
rename from src/screens/Me/Root/Lists/List.tsx
rename to src/screens/Tabs/Me/Root/Lists/List.tsx
diff --git a/src/screens/Me/Root/Logout.tsx b/src/screens/Tabs/Me/Root/Logout.tsx
similarity index 100%
rename from src/screens/Me/Root/Logout.tsx
rename to src/screens/Tabs/Me/Root/Logout.tsx
diff --git a/src/screens/Me/Root/MyInfo.tsx b/src/screens/Tabs/Me/Root/MyInfo.tsx
similarity index 83%
rename from src/screens/Me/Root/MyInfo.tsx
rename to src/screens/Tabs/Me/Root/MyInfo.tsx
index 26f5d731..d094b89f 100644
--- a/src/screens/Me/Root/MyInfo.tsx
+++ b/src/screens/Tabs/Me/Root/MyInfo.tsx
@@ -1,5 +1,5 @@
-import AccountHeader from '@screens/Shared/Account/Header'
-import AccountInformation from '@screens/Shared/Account/Information'
+import AccountHeader from '@screens/Tabs/Shared/Account/Header'
+import AccountInformation from '@screens/Tabs/Shared/Account/Information'
import { useAccountQuery } from '@utils/queryHooks/account'
import { getLocalAccount } from '@utils/slices/instancesSlice'
import React, { useEffect } from 'react'
diff --git a/src/screens/Me/Root/Settings.tsx b/src/screens/Tabs/Me/Root/Settings.tsx
similarity index 91%
rename from src/screens/Me/Root/Settings.tsx
rename to src/screens/Tabs/Me/Root/Settings.tsx
index b42aeb85..026345cb 100644
--- a/src/screens/Me/Root/Settings.tsx
+++ b/src/screens/Tabs/Me/Root/Settings.tsx
@@ -21,7 +21,7 @@ const Settings: React.FC = () => {
iconFront='Settings'
iconBack='ChevronRight'
title={t('content.settings')}
- onPress={() => navigation.navigate('Screen-Me-Settings')}
+ onPress={() => navigation.navigate('Tab-Me-Settings')}
/>
)
diff --git a/src/screens/Me/Settings.tsx b/src/screens/Tabs/Me/Settings.tsx
similarity index 100%
rename from src/screens/Me/Settings.tsx
rename to src/screens/Tabs/Me/Settings.tsx
diff --git a/src/screens/Me/Settings/Analytics.tsx b/src/screens/Tabs/Me/Settings/Analytics.tsx
similarity index 100%
rename from src/screens/Me/Settings/Analytics.tsx
rename to src/screens/Tabs/Me/Settings/Analytics.tsx
diff --git a/src/screens/Me/Settings/App.tsx b/src/screens/Tabs/Me/Settings/App.tsx
similarity index 100%
rename from src/screens/Me/Settings/App.tsx
rename to src/screens/Tabs/Me/Settings/App.tsx
diff --git a/src/screens/Me/Settings/Dev.tsx b/src/screens/Tabs/Me/Settings/Dev.tsx
similarity index 100%
rename from src/screens/Me/Settings/Dev.tsx
rename to src/screens/Tabs/Me/Settings/Dev.tsx
diff --git a/src/screens/Me/Settings/Tooot.tsx b/src/screens/Tabs/Me/Settings/Tooot.tsx
similarity index 97%
rename from src/screens/Me/Settings/Tooot.tsx
rename to src/screens/Tabs/Me/Settings/Tooot.tsx
index 09aae44f..9e87138b 100644
--- a/src/screens/Me/Settings/Tooot.tsx
+++ b/src/screens/Tabs/Me/Settings/Tooot.tsx
@@ -68,7 +68,7 @@ const SettingsTooot: React.FC = () => {
account => account.acct === 'tooot@xmflsct.com'
)
if (foundAccounts?.length === 1) {
- navigation.navigate('Screen-Shared-Compose', {
+ navigation.navigate('Screen-Compose', {
type: 'conversation',
accts: [foundAccounts[0].acct]
})
diff --git a/src/screens/Me/Switch.tsx b/src/screens/Tabs/Me/Switch.tsx
similarity index 100%
rename from src/screens/Me/Switch.tsx
rename to src/screens/Tabs/Me/Switch.tsx
diff --git a/src/screens/Me/Switch/Root.tsx b/src/screens/Tabs/Me/Switch/Root.tsx
similarity index 100%
rename from src/screens/Me/Switch/Root.tsx
rename to src/screens/Tabs/Me/Switch/Root.tsx
diff --git a/src/screens/Notifications.tsx b/src/screens/Tabs/Notifications.tsx
similarity index 80%
rename from src/screens/Notifications.tsx
rename to src/screens/Tabs/Notifications.tsx
index deb2efac..0da41e1a 100644
--- a/src/screens/Notifications.tsx
+++ b/src/screens/Tabs/Notifications.tsx
@@ -1,6 +1,6 @@
import { HeaderCenter } from '@components/Header'
import Timeline from '@components/Timelines/Timeline'
-import sharedScreens from '@screens/Shared/sharedScreens'
+import sharedScreens from '@screens/Tabs/Shared/sharedScreens'
import { getLocalActiveIndex } from '@utils/slices/instancesSlice'
import React from 'react'
import { useTranslation } from 'react-i18next'
@@ -8,9 +8,9 @@ import { Platform } from 'react-native'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { useSelector } from 'react-redux'
-const Stack = createNativeStackNavigator()
+const Stack = createNativeStackNavigator()
-const ScreenNotifications: React.FC = () => {
+const TabNotifications: React.FC = () => {
const { t } = useTranslation()
const localActiveIndex = useSelector(getLocalActiveIndex)
@@ -28,7 +28,7 @@ const ScreenNotifications: React.FC = () => {
headerTopInsetEnabled: false
}}
>
-
+
{() =>
localActiveIndex !== null ? : null
}
@@ -39,4 +39,4 @@ const ScreenNotifications: React.FC = () => {
)
}
-export default ScreenNotifications
+export default TabNotifications
diff --git a/src/screens/Public.tsx b/src/screens/Tabs/Public.tsx
similarity index 67%
rename from src/screens/Public.tsx
rename to src/screens/Tabs/Public.tsx
index 402a007b..448eeeb9 100644
--- a/src/screens/Public.tsx
+++ b/src/screens/Tabs/Public.tsx
@@ -1,11 +1,11 @@
import Timelines from '@components/Timelines'
import React from 'react'
-const ScreenPublic = React.memo(
+const TabPublic = React.memo(
() => {
return
},
() => true
)
-export default ScreenPublic
+export default TabPublic
diff --git a/src/screens/Shared/Account.tsx b/src/screens/Tabs/Shared/Account.tsx
similarity index 93%
rename from src/screens/Shared/Account.tsx
rename to src/screens/Tabs/Shared/Account.tsx
index a3ab21bd..7b226c5b 100644
--- a/src/screens/Shared/Account.tsx
+++ b/src/screens/Tabs/Shared/Account.tsx
@@ -1,5 +1,4 @@
import analytics from '@components/analytics'
-import BottomSheet from '@components/BottomSheet'
import { HeaderRight } from '@components/Header'
import Timeline from '@components/Timelines/Timeline'
import HeaderActionsAccount from '@components/Timelines/Timeline/Shared/HeaderActions/Account'
@@ -26,7 +25,7 @@ import accountInitialState from './Account/utils/initialState'
import accountReducer from './Account/utils/reducer'
import { SharedAccountProp } from './sharedScreens'
-const ScreenSharedAccount: React.FC = ({
+const TabSharedAccount: React.FC = ({
route: {
params: { account }
},
@@ -91,11 +90,11 @@ const ScreenSharedAccount: React.FC = ({
}}
/>
- setBottomSheetVisible(false)}
>
- {/* ζ·»ε ε°ε葨 */}
+ ζ·»ε ε°ε葨
{localAccount?.id !== account.id && (
= ({
type='account'
setBottomSheetVisible={setBottomSheetVisible}
/>
-
+ */}
)
}
@@ -119,4 +118,4 @@ const styles = StyleSheet.create({
}
})
-export default ScreenSharedAccount
+export default TabSharedAccount
diff --git a/src/screens/Shared/Account/Attachments.tsx b/src/screens/Tabs/Shared/Account/Attachments.tsx
similarity index 95%
rename from src/screens/Shared/Account/Attachments.tsx
rename to src/screens/Tabs/Shared/Account/Attachments.tsx
index 8427002a..a4b72947 100644
--- a/src/screens/Shared/Account/Attachments.tsx
+++ b/src/screens/Tabs/Shared/Account/Attachments.tsx
@@ -25,7 +25,7 @@ export interface Props {
const AccountAttachments = React.memo(
({ account }: Props) => {
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const { theme } = useTheme()
@@ -65,7 +65,7 @@ const AccountAttachments = React.memo(
onPress={() => {
analytics('account_attachment_more_press')
account &&
- navigation.push('Screen-Shared-Attachments', { account })
+ navigation.push('Tab-Shared-Attachments', { account })
}}
children={
{
analytics('account_attachment_item_press')
- navigation.push('Screen-Shared-Toot', { toot: item })
+ navigation.push('Tab-Shared-Toot', { toot: item })
}}
/>
)
diff --git a/src/screens/Shared/Account/Header.tsx b/src/screens/Tabs/Shared/Account/Header.tsx
similarity index 100%
rename from src/screens/Shared/Account/Header.tsx
rename to src/screens/Tabs/Shared/Account/Header.tsx
diff --git a/src/screens/Shared/Account/Information.tsx b/src/screens/Tabs/Shared/Account/Information.tsx
similarity index 100%
rename from src/screens/Shared/Account/Information.tsx
rename to src/screens/Tabs/Shared/Account/Information.tsx
diff --git a/src/screens/Shared/Account/Information/Account.tsx b/src/screens/Tabs/Shared/Account/Information/Account.tsx
similarity index 100%
rename from src/screens/Shared/Account/Information/Account.tsx
rename to src/screens/Tabs/Shared/Account/Information/Account.tsx
diff --git a/src/screens/Shared/Account/Information/Actions.tsx b/src/screens/Tabs/Shared/Account/Information/Actions.tsx
similarity index 91%
rename from src/screens/Shared/Account/Information/Actions.tsx
rename to src/screens/Tabs/Shared/Account/Information/Actions.tsx
index 443cfba3..eecf9c14 100644
--- a/src/screens/Shared/Account/Information/Actions.tsx
+++ b/src/screens/Tabs/Shared/Account/Information/Actions.tsx
@@ -17,7 +17,7 @@ export interface Props {
const GoToMoved = ({ accountMoved }: { accountMoved: Mastodon.Account }) => {
const { t } = useTranslation('sharedAccount')
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
return (
@@ -26,7 +26,7 @@ const GoToMoved = ({ accountMoved }: { accountMoved: Mastodon.Account }) => {
content={t('content.moved')}
onPress={() => {
analytics('account_gotomoved_press')
- navigation.push('Screen-Shared-Account', { account: accountMoved })
+ navigation.push('Tab-Shared-Account', { account: accountMoved })
}}
/>
)
@@ -44,7 +44,7 @@ const Conversation = ({ account }: { account: Mastodon.Account }) => {
style={styles.actionConversation}
onPress={() => {
analytics('account_DM_press')
- navigation.navigate('Screen-Shared-Compose', {
+ navigation.navigate('Screen-Compose', {
type: 'conversation',
accts: [account.acct]
})
diff --git a/src/screens/Shared/Account/Information/Avatar.tsx b/src/screens/Tabs/Shared/Account/Information/Avatar.tsx
similarity index 91%
rename from src/screens/Shared/Account/Information/Avatar.tsx
rename to src/screens/Tabs/Shared/Account/Information/Avatar.tsx
index 6dc5b61f..1c838913 100644
--- a/src/screens/Shared/Account/Information/Avatar.tsx
+++ b/src/screens/Tabs/Shared/Account/Information/Avatar.tsx
@@ -13,7 +13,7 @@ export interface Props {
const AccountInformationAvatar: React.FC = ({ account, myInfo }) => {
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const dimension = useMemo(
() => ({
@@ -30,7 +30,7 @@ const AccountInformationAvatar: React.FC = ({ account, myInfo }) => {
analytics('account_avatar_press')
myInfo &&
account &&
- navigation.push('Screen-Shared-Account', { account })
+ navigation.push('Tab-Shared-Account', { account })
}}
>
= ({ account, myInfo }) => {
const navigation = useNavigation<
- StackNavigationProp
+ StackNavigationProp
>()
const { theme } = useTheme()
const { t } = useTranslation('sharedAccount')
@@ -32,7 +32,7 @@ const AccountInformationStats: React.FC = ({ account, myInfo }) => {
analytics('account_stats_toots_press', {
count: account.statuses_count
})
- myInfo && navigation.push('Screen-Shared-Account', { account })
+ myInfo && navigation.push('Tab-Shared-Account', { account })
}}
/>
) : (
@@ -54,7 +54,7 @@ const AccountInformationStats: React.FC = ({ account, myInfo }) => {
analytics('account_stats_following_press', {
count: account.following_count
})
- navigation.push('Screen-Shared-Relationships', {
+ navigation.push('Tab-Shared-Relationships', {
account,
initialType: 'following'
})
@@ -79,7 +79,7 @@ const AccountInformationStats: React.FC = ({ account, myInfo }) => {
analytics('account_stats_followers_press', {
count: account.followers_count
})
- navigation.push('Screen-Shared-Relationships', {
+ navigation.push('Tab-Shared-Relationships', {
account,
initialType: 'followers'
})
diff --git a/src/screens/Shared/Account/Information/Switch.tsx b/src/screens/Tabs/Shared/Account/Information/Switch.tsx
similarity index 87%
rename from src/screens/Shared/Account/Information/Switch.tsx
rename to src/screens/Tabs/Shared/Account/Information/Switch.tsx
index ba61c4c3..24d4b68a 100644
--- a/src/screens/Shared/Account/Information/Switch.tsx
+++ b/src/screens/Tabs/Shared/Account/Information/Switch.tsx
@@ -11,7 +11,7 @@ const AccountInformationSwitch: React.FC = () => {