This commit is contained in:
xmflsct 2022-11-29 23:44:11 +01:00
parent 75800598c2
commit de7498b218
75 changed files with 289 additions and 1421 deletions

View File

@ -337,5 +337,3 @@ def isNewArchitectureEnabled() {
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
} }
apply plugin: 'com.google.gms.google-services'

View File

@ -1,46 +0,0 @@
{
"project_info": {
"project_number": "661638997772",
"project_id": "xmflsct-mastodon-app",
"storage_bucket": "xmflsct-mastodon-app.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:661638997772:android:4fd02851f757f8fa9f8b29",
"android_client_info": {
"package_name": "com.xmflsct.app.tooot"
}
},
"oauth_client": [
{
"client_id": "661638997772-6aiqk97aema0rt280i7nfar3ha2mlgno.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDUw4s-mhQsHvs4hdIsldsi68ZIygM5MC4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "661638997772-6aiqk97aema0rt280i7nfar3ha2mlgno.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "661638997772-sqa4raeghhrieqt9guljhcul9b51dvna.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.xmflsct.app.mastodon"
}
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@ -22,7 +22,6 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.google.gms:google-services:4.3.3'
classpath("com.android.tools.build:gradle:7.2.1") classpath("com.android.tools.build:gradle:7.2.1")
classpath("com.facebook.react:react-native-gradle-plugin") classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:5.0.1") classpath("de.undercouch:gradle-download-task:5.0.1")

View File

@ -15,7 +15,6 @@ export default (): ExpoConfig => ({
}, },
android: { android: {
package: 'com.xmflsct.app.tooot', package: 'com.xmflsct.app.tooot',
googleServicesFile: './configs/google-services.json',
permissions: ['CAMERA', 'VIBRATE'], permissions: ['CAMERA', 'VIBRATE'],
blockedPermissions: ['USE_BIOMETRIC', 'USE_FINGERPRINT'] blockedPermissions: ['USE_BIOMETRIC', 'USE_FINGERPRINT']
}, },

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>661638997772-65g8ce369ugck3ii4ulk6jhb3ijg51kl.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.661638997772-65g8ce369ugck3ii4ulk6jhb3ijg51kl</string>
<key>API_KEY</key>
<string>AIzaSyAOS1Yq_uNVctG89LB6Dl1PVhb_FAQRbRg</string>
<key>GCM_SENDER_ID</key>
<string>661638997772</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.xmflsct.app.tooot</string>
<key>PROJECT_ID</key>
<string>xmflsct-mastodon-app</string>
<key>STORAGE_BUCKET</key>
<string>xmflsct-mastodon-app.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:661638997772:ios:c8d2e09264a344b09f8b29</string>
</dict>
</plist>

View File

@ -1,46 +0,0 @@
{
"project_info": {
"project_number": "661638997772",
"project_id": "xmflsct-mastodon-app",
"storage_bucket": "xmflsct-mastodon-app.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:661638997772:android:4fd02851f757f8fa9f8b29",
"android_client_info": {
"package_name": "com.xmflsct.app.tooot"
}
},
"oauth_client": [
{
"client_id": "661638997772-6aiqk97aema0rt280i7nfar3ha2mlgno.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDUw4s-mhQsHvs4hdIsldsi68ZIygM5MC4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "661638997772-6aiqk97aema0rt280i7nfar3ha2mlgno.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "661638997772-sqa4raeghhrieqt9guljhcul9b51dvna.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.xmflsct.app.mastodon"
}
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@ -15,12 +15,6 @@ target 'tooot' do
# Flags change depending on the env values. # Flags change depending on the env values.
flags = get_default_flags() flags = get_default_flags()
# https://stackoverflow.com/questions/72289521/swift-pods-cannot-yet-be-integrated-as-static-libraries-firebasecoreinternal-lib/72969220#72969220
pod 'Firebase', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
$RNFirebaseAsStaticFramework = true
use_react_native!( use_react_native!(
:path => config[:reactNativePath], :path => config[:reactNativePath],
:hermes_enabled => true, :hermes_enabled => true,

View File

@ -12,13 +12,6 @@ PODS:
- ExpoModulesCore - ExpoModulesCore
- EXFileSystem (15.1.1): - EXFileSystem (15.1.1):
- ExpoModulesCore - ExpoModulesCore
- EXFirebaseAnalytics (8.0.0):
- EXFirebaseCore
- ExpoModulesCore
- Firebase/Core (= 9.5.0)
- EXFirebaseCore (6.0.0):
- ExpoModulesCore
- Firebase/Core (= 9.5.0)
- EXFont (11.0.1): - EXFont (11.0.1):
- ExpoModulesCore - ExpoModulesCore
- EXNotifications (0.17.0): - EXNotifications (0.17.0):
@ -59,107 +52,8 @@ PODS:
- React-Core (= 0.70.6) - React-Core (= 0.70.6)
- React-jsi (= 0.70.6) - React-jsi (= 0.70.6)
- ReactCommon/turbomodule/core (= 0.70.6) - ReactCommon/turbomodule/core (= 0.70.6)
- Firebase (9.5.0):
- Firebase/Core (= 9.5.0)
- Firebase/Core (9.5.0):
- Firebase/CoreOnly
- FirebaseAnalytics (~> 9.5.0)
- Firebase/CoreOnly (9.5.0):
- FirebaseCore (= 9.5.0)
- FirebaseAnalytics (9.5.0):
- FirebaseAnalytics/AdIdSupport (= 9.5.0)
- FirebaseCore (~> 9.0)
- FirebaseInstallations (~> 9.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (9.5.0):
- FirebaseCore (~> 9.0)
- FirebaseInstallations (~> 9.0)
- GoogleAppMeasurement (= 9.5.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseCore (9.5.0):
- FirebaseCoreDiagnostics (~> 9.0)
- FirebaseCoreInternal (~> 9.0)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Logger (~> 7.7)
- FirebaseCoreDiagnostics (9.6.0):
- GoogleDataTransport (< 10.0.0, >= 9.1.4)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Logger (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseCoreInternal (9.6.0):
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- FirebaseInstallations (9.6.0):
- FirebaseCore (~> 9.0)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/UserDefaults (~> 7.7)
- PromisesObjC (~> 2.1)
- fmt (6.2.1) - fmt (6.2.1)
- glog (0.3.5) - glog (0.3.5)
- GoogleAppMeasurement (9.5.0):
- GoogleAppMeasurement/AdIdSupport (= 9.5.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (9.5.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 9.5.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (9.5.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleDataTransport (9.2.0):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities (7.10.0):
- GoogleUtilities/AppDelegateSwizzler (= 7.10.0)
- GoogleUtilities/Environment (= 7.10.0)
- GoogleUtilities/ISASwizzler (= 7.10.0)
- GoogleUtilities/Logger (= 7.10.0)
- GoogleUtilities/MethodSwizzler (= 7.10.0)
- GoogleUtilities/Network (= 7.10.0)
- "GoogleUtilities/NSData+zlib (= 7.10.0)"
- GoogleUtilities/Reachability (= 7.10.0)
- GoogleUtilities/SwizzlerTestHelpers (= 7.10.0)
- GoogleUtilities/UserDefaults (= 7.10.0)
- GoogleUtilities/AppDelegateSwizzler (7.10.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (7.10.0):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/ISASwizzler (7.10.0)
- GoogleUtilities/Logger (7.10.0):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (7.10.0):
- GoogleUtilities/Logger
- GoogleUtilities/Network (7.10.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.10.0)"
- GoogleUtilities/Reachability (7.10.0):
- GoogleUtilities/Logger
- GoogleUtilities/SwizzlerTestHelpers (7.10.0):
- GoogleUtilities/MethodSwizzler
- GoogleUtilities/UserDefaults (7.10.0):
- GoogleUtilities/Logger
- hermes-engine (0.70.6) - hermes-engine (0.70.6)
- libevent (2.1.12) - libevent (2.1.12)
- libwebp (1.2.4): - libwebp (1.2.4):
@ -171,12 +65,6 @@ PODS:
- libwebp/mux (1.2.4): - libwebp/mux (1.2.4):
- libwebp/demux - libwebp/demux
- libwebp/webp (1.2.4) - libwebp/webp (1.2.4)
- nanopb (2.30909.0):
- nanopb/decode (= 2.30909.0)
- nanopb/encode (= 2.30909.0)
- nanopb/decode (2.30909.0)
- nanopb/encode (2.30909.0)
- PromisesObjC (2.1.1)
- RCT-Folly (2021.07.22.00): - RCT-Folly (2021.07.22.00):
- boost - boost
- DoubleConversion - DoubleConversion
@ -563,8 +451,6 @@ DEPENDENCIES:
- EXConstants (from `../node_modules/expo-constants/ios`) - EXConstants (from `../node_modules/expo-constants/ios`)
- EXErrorRecovery (from `../node_modules/expo-error-recovery/ios`) - EXErrorRecovery (from `../node_modules/expo-error-recovery/ios`)
- EXFileSystem (from `../node_modules/expo-file-system/ios`) - EXFileSystem (from `../node_modules/expo-file-system/ios`)
- EXFirebaseAnalytics (from `../node_modules/expo-firebase-analytics/ios`)
- EXFirebaseCore (from `../node_modules/expo-firebase-core/ios`)
- EXFont (from `../node_modules/expo-font/ios`) - EXFont (from `../node_modules/expo-font/ios`)
- EXNotifications (from `../node_modules/expo-notifications/ios`) - EXNotifications (from `../node_modules/expo-notifications/ios`)
- Expo (from `../node_modules/expo`) - Expo (from `../node_modules/expo`)
@ -582,10 +468,7 @@ DEPENDENCIES:
- EXVideoThumbnails (from `../node_modules/expo-video-thumbnails/ios`) - EXVideoThumbnails (from `../node_modules/expo-video-thumbnails/ios`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- Firebase
- FirebaseCore
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- GoogleUtilities
- hermes-engine (from `../node_modules/react-native/sdks/hermes/hermes-engine.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes/hermes-engine.podspec`)
- libevent (~> 2.1.12) - libevent (~> 2.1.12)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
@ -641,20 +524,9 @@ DEPENDENCIES:
SPEC REPOS: SPEC REPOS:
trunk: trunk:
- Firebase
- FirebaseAnalytics
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseCoreInternal
- FirebaseInstallations
- fmt - fmt
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleUtilities
- libevent - libevent
- libwebp - libwebp
- nanopb
- PromisesObjC
- SDWebImage - SDWebImage
- SDWebImageWebPCoder - SDWebImageWebPCoder
- Sentry - Sentry
@ -675,10 +547,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-error-recovery/ios" :path: "../node_modules/expo-error-recovery/ios"
EXFileSystem: EXFileSystem:
:path: "../node_modules/expo-file-system/ios" :path: "../node_modules/expo-file-system/ios"
EXFirebaseAnalytics:
:path: "../node_modules/expo-firebase-analytics/ios"
EXFirebaseCore:
:path: "../node_modules/expo-firebase-core/ios"
EXFont: EXFont:
:path: "../node_modules/expo-font/ios" :path: "../node_modules/expo-font/ios"
EXNotifications: EXNotifications:
@ -824,8 +692,6 @@ SPEC CHECKSUMS:
EXConstants: 3c86653c422dd77e40d10cbbabb3025003977415 EXConstants: 3c86653c422dd77e40d10cbbabb3025003977415
EXErrorRecovery: ae43433feb0608a64dc5b1c8363b3e7769a9ea24 EXErrorRecovery: ae43433feb0608a64dc5b1c8363b3e7769a9ea24
EXFileSystem: 60602b6eefa6873f97172c684b7537c9760b50d6 EXFileSystem: 60602b6eefa6873f97172c684b7537c9760b50d6
EXFirebaseAnalytics: 58d70e698859b070b2450ad8664d7b5bc6c6e3e1
EXFirebaseCore: d0d88cb904e893af07f809ab08c0892489bc6956
EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80 EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80
EXNotifications: babce2a87b7922051354fcfe7a74dd279b7e272a EXNotifications: babce2a87b7922051354fcfe7a74dd279b7e272a
Expo: 36b5f625d36728adbdd1934d4d57182f319ab832 Expo: 36b5f625d36728adbdd1934d4d57182f319ab832
@ -843,22 +709,11 @@ SPEC CHECKSUMS:
EXVideoThumbnails: 8b3e48f3716679dd0cbf949217a31eab5c555799 EXVideoThumbnails: 8b3e48f3716679dd0cbf949217a31eab5c555799
FBLazyVector: 48289402952f4f7a4e235de70a9a590aa0b79ef4 FBLazyVector: 48289402952f4f7a4e235de70a9a590aa0b79ef4
FBReactNativeSpec: dd1186fd05255e3457baa2f4ca65e94c2cd1e3ac FBReactNativeSpec: dd1186fd05255e3457baa2f4ca65e94c2cd1e3ac
Firebase: 800f16f07af493d98d017446a315c27af0552f41
FirebaseAnalytics: 1b60984a408320dda637306f3f733699ef8473d7
FirebaseCore: 25c0400b670fd1e2f2104349cd3b5dcce8d9418f
FirebaseCoreDiagnostics: 99a495094b10a57eeb3ae8efa1665700ad0bdaa6
FirebaseCoreInternal: bca76517fe1ed381e989f5e7d8abb0da8d85bed3
FirebaseInstallations: 0a115432c4e223c5ab20b0dbbe4cbefa793a0e8e
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
GoogleAppMeasurement: 6ee231473fbd75c11221dfce489894334024eead
GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f
GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95
hermes-engine: 2af7b7a59128f250adfd86f15aa1d5a2ecd39995 hermes-engine: 2af7b7a59128f250adfd86f15aa1d5a2ecd39995
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
RCTRequired: e1866f61af7049eb3d8e08e8b133abd38bc1ca7a RCTRequired: e1866f61af7049eb3d8e08e8b133abd38bc1ca7a
RCTTypeSafety: 27c2ac1b00609a432ced1ae701247593f07f901e RCTTypeSafety: 27c2ac1b00609a432ced1ae701247593f07f901e
@ -913,6 +768,6 @@ SPEC CHECKSUMS:
Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b
Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc
PODFILE CHECKSUM: e4191b63c8f15031b2365226730770e7978dca41 PODFILE CHECKSUM: 05bf71d31ba782dfda5a6b47d38e98a6f6bc079a
COCOAPODS: 1.11.3 COCOAPODS: 1.11.3

View File

@ -17,7 +17,6 @@
5EE088C926297820007E5FEC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5EE088CB26297820007E5FEC /* InfoPlist.strings */; }; 5EE088C926297820007E5FEC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5EE088CB26297820007E5FEC /* InfoPlist.strings */; };
5EE44DD62600124E00A9BCED /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EE44DD52600124E00A9BCED /* File.swift */; }; 5EE44DD62600124E00A9BCED /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EE44DD52600124E00A9BCED /* File.swift */; };
96905EF65AED1B983A6B3ABC /* libPods-tooot.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-tooot.a */; }; 96905EF65AED1B983A6B3ABC /* libPods-tooot.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-tooot.a */; };
DA8B5B7F0DED488CAC0FF169 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B96B72E5384D44A7B240B27E /* GoogleService-Info.plist */; };
E3BC22F5F8ABE515E14CF199 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D878F932AF7A9974E06E461 /* ExpoModulesProvider.swift */; }; E3BC22F5F8ABE515E14CF199 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D878F932AF7A9974E06E461 /* ExpoModulesProvider.swift */; };
E613A80B28282A01003C97D6 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E613A80A28282A01003C97D6 /* AppDelegate.mm */; }; E613A80B28282A01003C97D6 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E613A80A28282A01003C97D6 /* AppDelegate.mm */; };
E633A42B281EAEAB000E540F /* ShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E633A420281EAEAB000E540F /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; E633A42B281EAEAB000E540F /* ShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E633A420281EAEAB000E540F /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -69,7 +68,6 @@
7A4D352CD337FB3A3BF06240 /* Pods-tooot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tooot.release.xcconfig"; path = "Target Support Files/Pods-tooot/Pods-tooot.release.xcconfig"; sourceTree = "<group>"; }; 7A4D352CD337FB3A3BF06240 /* Pods-tooot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tooot.release.xcconfig"; path = "Target Support Files/Pods-tooot/Pods-tooot.release.xcconfig"; sourceTree = "<group>"; };
9D878F932AF7A9974E06E461 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-tooot/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; 9D878F932AF7A9974E06E461 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-tooot/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = tooot/SplashScreen.storyboard; sourceTree = "<group>"; }; AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = tooot/SplashScreen.storyboard; sourceTree = "<group>"; };
B96B72E5384D44A7B240B27E /* GoogleService-Info.plist */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "tooot/GoogleService-Info.plist"; sourceTree = "<group>"; };
DF8133F098604A10B0D94952 /* boop.mp3 */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = boop.mp3; path = tooot/boop.mp3; sourceTree = "<group>"; }; DF8133F098604A10B0D94952 /* boop.mp3 */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = boop.mp3; path = tooot/boop.mp3; sourceTree = "<group>"; };
E613A80A28282A01003C97D6 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = tooot/AppDelegate.mm; sourceTree = "<group>"; }; E613A80A28282A01003C97D6 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = tooot/AppDelegate.mm; sourceTree = "<group>"; };
E633A420281EAEAB000E540F /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E633A420281EAEAB000E540F /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@ -122,7 +120,6 @@
13B07FB71A68108700A75B9A /* main.m */, 13B07FB71A68108700A75B9A /* main.m */,
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */, AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
5E36538225C9B8BD009F93EE /* RootViewColor.xcassets */, 5E36538225C9B8BD009F93EE /* RootViewColor.xcassets */,
B96B72E5384D44A7B240B27E /* GoogleService-Info.plist */,
5EE088CB26297820007E5FEC /* InfoPlist.strings */, 5EE088CB26297820007E5FEC /* InfoPlist.strings */,
DF8133F098604A10B0D94952 /* boop.mp3 */, DF8133F098604A10B0D94952 /* boop.mp3 */,
); );
@ -319,7 +316,6 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */, 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
DA8B5B7F0DED488CAC0FF169 /* GoogleService-Info.plist in Resources */,
4986628FD0DD4630BFE5F388 /* boop.mp3 in Resources */, 4986628FD0DD4630BFE5F388 /* boop.mp3 in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>661638997772-65g8ce369ugck3ii4ulk6jhb3ijg51kl.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.661638997772-65g8ce369ugck3ii4ulk6jhb3ijg51kl</string>
<key>API_KEY</key>
<string>AIzaSyAOS1Yq_uNVctG89LB6Dl1PVhb_FAQRbRg</string>
<key>GCM_SENDER_ID</key>
<string>661638997772</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.xmflsct.app.tooot</string>
<key>PROJECT_ID</key>
<string>xmflsct-mastodon-app</string>
<key>STORAGE_BUCKET</key>
<string>xmflsct-mastodon-app.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:661638997772:ios:c8d2e09264a344b09f8b29</string>
</dict>
</plist>

View File

@ -47,7 +47,6 @@
"expo-constants": "^14.0.2", "expo-constants": "^14.0.2",
"expo-crypto": "^12.0.0", "expo-crypto": "^12.0.0",
"expo-file-system": "^15.1.1", "expo-file-system": "^15.1.1",
"expo-firebase-analytics": "^8.0.0",
"expo-haptics": "^12.0.1", "expo-haptics": "^12.0.1",
"expo-linking": "^3.2.3", "expo-linking": "^3.2.3",
"expo-localization": "^14.0.0", "expo-localization": "^14.0.0",

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { HeaderLeft } from '@components/Header' import { HeaderLeft } from '@components/Header'
import { displayMessage, Message } from '@components/Message' import { displayMessage, Message } from '@components/Message'
import navigationRef from '@helpers/navigationRef' import navigationRef from '@helpers/navigationRef'
@ -113,7 +112,6 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
} }
if (previousRoute?.name !== currentRoute?.name) { if (previousRoute?.name !== currentRoute?.name) {
analytics('screen_view', { screen_name: currentRoute?.name })
Sentry.setContext('page', { Sentry.setContext('page', {
previous: previousRoute, previous: previousRoute,
current: currentRoute current: currentRoute

View File

@ -6,29 +6,19 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { Pressable, View } from 'react-native' import { Pressable, View } from 'react-native'
import analytics from './analytics'
import GracefullyImage from './GracefullyImage' import GracefullyImage from './GracefullyImage'
import CustomText from './Text' import CustomText from './Text'
export interface Props { export interface Props {
account: Mastodon.Account account: Mastodon.Account
onPress?: () => void onPress?: () => void
origin?: string
} }
const ComponentAccount: React.FC<Props> = ({ const ComponentAccount: React.FC<Props> = ({ account, onPress: customOnPress }) => {
account,
onPress: customOnPress,
origin
}) => {
const { colors } = useTheme() const { colors } = useTheme()
const navigation = const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const onPress = useCallback(() => { const onPress = useCallback(() => navigation.push('Tab-Shared-Account', { account }), [])
analytics('search_account_press', { page: origin })
navigation.push('Tab-Shared-Account', { account })
}, [])
return ( return (
<Pressable <Pressable

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { useRelationshipQuery } from '@utils/queryHooks/relationship' import { useRelationshipQuery } from '@utils/queryHooks/relationship'
import { import {
@ -135,9 +134,6 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
return // For Android return // For Android
} }
if (actions[index].id === 'account-mute') { if (actions[index].id === 'account-mute') {
analytics('timeline_shared_headeractions_account_mute_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'updateAccountProperty', type: 'updateAccountProperty',
queryKey, queryKey,
@ -149,9 +145,6 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
actions[index].id === 'account-block' || actions[index].id === 'account-block' ||
(actions[index].id === 'account' && actions[index].actions?.[0].id === 'account-block') (actions[index].id === 'account' && actions[index].actions?.[0].id === 'account-block')
) { ) {
analytics('timeline_shared_headeractions_account_block_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'updateAccountProperty', type: 'updateAccountProperty',
queryKey, queryKey,
@ -163,9 +156,6 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
actions[index].id === 'account-reports' || actions[index].id === 'account-reports' ||
(actions[index].id === 'account' && actions[index].actions?.[0].id === 'account-reports') (actions[index].id === 'account' && actions[index].actions?.[0].id === 'account-reports')
) { ) {
analytics('timeline_shared_headeractions_account_reports_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'updateAccountProperty', type: 'updateAccountProperty',
queryKey, queryKey,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline' import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
import { getInstanceUrl } from '@utils/slices/instancesSlice' import { getInstanceUrl } from '@utils/slices/instancesSlice'
@ -71,9 +70,6 @@ const contextMenuInstance = ({ actions, status, queryKey, rootQueryKey }: Props)
actions[index].id === 'instance-block' || actions[index].id === 'instance-block' ||
(actions[index].id === 'instance' && actions[index].actions?.[0].id === 'instance-block') (actions[index].id === 'instance' && actions[index].actions?.[0].id === 'instance-block')
) { ) {
analytics('timeline_shared_headeractions_domain_block_press', {
page: queryKey[1].page
})
Alert.alert( Alert.alert(
t('instance.block.alert.title', { instance }), t('instance.block.alert.title', { instance }),
t('instance.block.alert.message'), t('instance.block.alert.message'),
@ -82,9 +78,6 @@ const contextMenuInstance = ({ actions, status, queryKey, rootQueryKey }: Props)
text: t('instance.block.alert.buttons.confirm'), text: t('instance.block.alert.buttons.confirm'),
style: 'destructive', style: 'destructive',
onPress: () => { onPress: () => {
analytics('timeline_shared_headeractions_domain_block_confirm', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'domainBlock', type: 'domainBlock',
queryKey, queryKey,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import Clipboard from '@react-native-clipboard/clipboard' import Clipboard from '@react-native-clipboard/clipboard'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
@ -39,7 +38,6 @@ const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
return // For Android return // For Android
} }
if (actions[index].id === 'copy') { if (actions[index].id === 'copy') {
analytics('timeline_shared_headeractions_copy_press')
Clipboard.setString(copiableContent?.current.content || '') Clipboard.setString(copiableContent?.current.content || '')
displayMessage({ displayMessage({
theme, theme,
@ -48,7 +46,6 @@ const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
}) })
} }
if (actions[index].id === 'share') { if (actions[index].id === 'share') {
analytics('timeline_shared_headeractions_share_press')
switch (Platform.OS) { switch (Platform.OS) {
case 'ios': case 'ios':
Share.share({ url }) Share.share({ url })

View File

@ -1,5 +1,4 @@
import apiInstance from '@api/instance' import apiInstance from '@api/instance'
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { NativeStackNavigationProp } from '@react-navigation/native-stack' import { NativeStackNavigationProp } from '@react-navigation/native-stack'
@ -107,17 +106,11 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
return // For Android return // For Android
} }
if (actions[index].id === 'status-delete') { if (actions[index].id === 'status-delete') {
analytics('timeline_shared_headeractions_status_delete_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(t('status.delete.alert.title'), t('status.delete.alert.message'), [ Alert.alert(t('status.delete.alert.title'), t('status.delete.alert.message'), [
{ {
text: t('status.delete.alert.buttons.confirm'), text: t('status.delete.alert.buttons.confirm'),
style: 'destructive', style: 'destructive',
onPress: async () => { onPress: async () => {
analytics('timeline_shared_headeractions_status_delete_confirm', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'deleteItem', type: 'deleteItem',
source: 'statuses', source: 'statuses',
@ -133,17 +126,11 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
]) ])
} }
if (actions[index].id === 'status-delete-edit') { if (actions[index].id === 'status-delete-edit') {
analytics('timeline_shared_headeractions_status_deleteedit_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(t('status.deleteEdit.alert.title'), t('status.deleteEdit.alert.message'), [ Alert.alert(t('status.deleteEdit.alert.title'), t('status.deleteEdit.alert.message'), [
{ {
text: t('status.deleteEdit.alert.buttons.confirm'), text: t('status.deleteEdit.alert.buttons.confirm'),
style: 'destructive', style: 'destructive',
onPress: async () => { onPress: async () => {
analytics('timeline_shared_headeractions_status_deleteedit_confirm', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) { if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({ replyToStatus = await apiInstance<Mastodon.Status>({
@ -174,9 +161,6 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
]) ])
} }
if (actions[index].id === 'status-mute') { if (actions[index].id === 'status-mute') {
analytics('timeline_shared_headeractions_status_mute_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -191,9 +175,6 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
}) })
} }
if (actions[index].id === 'status-edit') { if (actions[index].id === 'status-edit') {
analytics('timeline_shared_headeractions_status_edit_press', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) { if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({ replyToStatus = await apiInstance<Mastodon.Status>({
@ -224,9 +205,6 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
} }
if (actions[index].id === 'status-pin') { if (actions[index].id === 'status-pin') {
// Also note that reblogs cannot be pinned. // Also note that reblogs cannot be pinned.
analytics('timeline_shared_headeractions_status_pin_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,

View File

@ -5,7 +5,6 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { Pressable } from 'react-native' import { Pressable } from 'react-native'
import analytics from './analytics'
import CustomText from './Text' import CustomText from './Text'
export interface Props { export interface Props {
@ -24,7 +23,6 @@ const ComponentHashtag: React.FC<Props> = ({
useNavigation<StackNavigationProp<TabLocalStackParamList>>() useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const onPress = useCallback(() => { const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
navigation.push('Tab-Shared-Hashtag', { hashtag: hashtag.name }) navigation.push('Tab-Shared-Hashtag', { hashtag: hashtag.name })
}, []) }, [])

View File

@ -9,18 +9,10 @@ import * as WebBrowser from 'expo-web-browser'
import { debounce } from 'lodash' import { debounce } from 'lodash'
import React, { RefObject, useCallback, useMemo, useState } from 'react' import React, { RefObject, useCallback, useMemo, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { import { Alert, Image, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
Alert,
Image,
KeyboardAvoidingView,
Platform,
TextInput,
View
} from 'react-native'
import { ScrollView } from 'react-native-gesture-handler' import { ScrollView } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { Placeholder } from 'rn-placeholder' import { Placeholder } from 'rn-placeholder'
import analytics from './analytics'
import InstanceAuth from './Instance/Auth' import InstanceAuth from './Instance/Auth'
import InstanceInfo from './Instance/Info' import InstanceInfo from './Instance/Info'
import CustomText from './Text' import CustomText from './Text'
@ -65,11 +57,7 @@ const ComponentInstance: React.FC<Props> = ({
const processUpdate = useCallback(() => { const processUpdate = useCallback(() => {
if (domain) { if (domain) {
analytics('instance_login') if (instances && instances.filter(instance => instance.url === domain).length) {
if (
instances &&
instances.filter(instance => instance.url === domain).length
) {
Alert.alert(t('update.alert.title'), t('update.alert.message'), [ Alert.alert(t('update.alert.title'), t('update.alert.message'), [
{ {
text: t('update.alert.buttons.cancel'), text: t('update.alert.buttons.cancel'),
@ -142,9 +130,7 @@ const ComponentInstance: React.FC<Props> = ({
borderBottomWidth: 1, borderBottomWidth: 1,
...StyleConstants.FontStyle.M, ...StyleConstants.FontStyle.M,
color: colors.primaryDefault, color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError borderBottomColor: instanceQuery.isError ? colors.red : colors.border
? colors.red
: colors.border
}} }}
editable={false} editable={false}
defaultValue='https://' defaultValue='https://'
@ -156,9 +142,7 @@ const ComponentInstance: React.FC<Props> = ({
...StyleConstants.FontStyle.M, ...StyleConstants.FontStyle.M,
marginRight: StyleConstants.Spacing.M, marginRight: StyleConstants.Spacing.M,
color: colors.primaryDefault, color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError borderBottomColor: instanceQuery.isError ? colors.red : colors.border
? colors.red
: colors.border
}} }}
onChangeText={onChangeText} onChangeText={onChangeText}
autoCapitalize='none' autoCapitalize='none'
@ -166,7 +150,6 @@ const ComponentInstance: React.FC<Props> = ({
keyboardType='url' keyboardType='url'
textContentType='URL' textContentType='URL'
onSubmitEditing={({ nativeEvent: { text } }) => { onSubmitEditing={({ nativeEvent: { text } }) => {
analytics('instance_textinput_submit', { match: text === domain })
if ( if (
text === domain && text === domain &&
instanceQuery.isSuccess && instanceQuery.isSuccess &&
@ -182,11 +165,7 @@ const ComponentInstance: React.FC<Props> = ({
keyboardAppearance={mode} keyboardAppearance={mode}
{...(scrollViewRef && { {...(scrollViewRef && {
onFocus: () => onFocus: () =>
setTimeout( setTimeout(() => scrollViewRef.current?.scrollTo({ y: 0, animated: true }), 150)
() =>
scrollViewRef.current?.scrollTo({ y: 0, animated: true }),
150
)
})} })}
autoCorrect={false} autoCorrect={false}
spellCheck={false} spellCheck={false}
@ -211,27 +190,19 @@ const ComponentInstance: React.FC<Props> = ({
<InstanceInfo <InstanceInfo
style={{ alignItems: 'flex-start' }} style={{ alignItems: 'flex-start' }}
header={t('server.information.accounts')} header={t('server.information.accounts')}
content={ content={instanceQuery.data?.stats?.user_count?.toString() || undefined}
instanceQuery.data?.stats?.user_count?.toString() || undefined
}
potentialWidth={4} potentialWidth={4}
/> />
<InstanceInfo <InstanceInfo
style={{ alignItems: 'center' }} style={{ alignItems: 'center' }}
header={t('server.information.statuses')} header={t('server.information.statuses')}
content={ content={instanceQuery.data?.stats?.status_count?.toString() || undefined}
instanceQuery.data?.stats?.status_count?.toString() ||
undefined
}
potentialWidth={4} potentialWidth={4}
/> />
<InstanceInfo <InstanceInfo
style={{ alignItems: 'flex-end' }} style={{ alignItems: 'flex-end' }}
header={t('server.information.domains')} header={t('server.information.domains')}
content={ content={instanceQuery.data?.stats?.domain_count?.toString() || undefined}
instanceQuery.data?.stats?.domain_count?.toString() ||
undefined
}
potentialWidth={4} potentialWidth={4}
/> />
</View> </View>
@ -248,17 +219,11 @@ const ComponentInstance: React.FC<Props> = ({
size={StyleConstants.Font.Size.S} size={StyleConstants.Font.Size.S}
color={colors.secondary} color={colors.secondary}
style={{ style={{
marginTop: marginTop: (StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
(StyleConstants.Font.LineHeight.S -
StyleConstants.Font.Size.S) /
2,
marginRight: StyleConstants.Spacing.XS marginRight: StyleConstants.Spacing.XS
}} }}
/> />
<CustomText <CustomText fontStyle='S' style={{ flex: 1, color: colors.secondary }}>
fontStyle='S'
style={{ flex: 1, color: colors.secondary }}
>
{t('server.disclaimer.base')} {t('server.disclaimer.base')}
</CustomText> </CustomText>
</View> </View>
@ -274,10 +239,7 @@ const ComponentInstance: React.FC<Props> = ({
size={StyleConstants.Font.Size.S} size={StyleConstants.Font.Size.S}
color={colors.secondary} color={colors.secondary}
style={{ style={{
marginTop: marginTop: (StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
(StyleConstants.Font.LineHeight.S -
StyleConstants.Font.Size.S) /
2,
marginRight: StyleConstants.Spacing.XS marginRight: StyleConstants.Spacing.XS
}} }}
/> />
@ -292,22 +254,14 @@ const ComponentInstance: React.FC<Props> = ({
<CustomText <CustomText
accessible accessible
style={{ color: colors.blue }} style={{ color: colors.blue }}
onPress={() => { onPress={() => WebBrowser.openBrowserAsync('https://tooot.app/privacy-policy')}
analytics('view_privacy')
WebBrowser.openBrowserAsync(
'https://tooot.app/privacy-policy'
)
}}
/>, />,
<CustomText <CustomText
accessible accessible
style={{ color: colors.blue }} style={{ color: colors.blue }}
onPress={() => { onPress={() =>
analytics('view_tos') WebBrowser.openBrowserAsync('https://tooot.app/terms-of-service')
WebBrowser.openBrowserAsync( }
'https://tooot.app/terms-of-service'
)
}}
/> />
]} ]}
/> />

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import openLink from '@components/openLink' import openLink from '@components/openLink'
import ParseEmojis from '@components/Parse/Emojis' import ParseEmojis from '@components/Parse/Emojis'
@ -63,7 +62,6 @@ const renderNode = ({
lineHeight: adaptedLineheight lineHeight: adaptedLineheight
}} }}
onPress={() => { onPress={() => {
analytics('status_hashtag_press')
!disableDetails && !disableDetails &&
differentTag && differentTag &&
navigation.push('Tab-Shared-Hashtag', { navigation.push('Tab-Shared-Hashtag', {
@ -89,7 +87,6 @@ const renderNode = ({
lineHeight: adaptedLineheight lineHeight: adaptedLineheight
}} }}
onPress={() => { onPress={() => {
analytics('status_mention_press')
accountIndex !== -1 && accountIndex !== -1 &&
!disableDetails && !disableDetails &&
differentAccount && differentAccount &&
@ -118,7 +115,6 @@ const renderNode = ({
lineHeight: adaptedLineheight lineHeight: adaptedLineheight
}} }}
onPress={async () => { onPress={async () => {
analytics('status_link_press')
if (!disableDetails) { if (!disableDetails) {
if (shouldBeTag) { if (shouldBeTag) {
navigation.push('Tab-Shared-Hashtag', { navigation.push('Tab-Shared-Hashtag', {
@ -255,7 +251,6 @@ const ParseHTML = React.memo(
<Pressable <Pressable
accessibilityLabel={t('HTML.accessibilityHint')} accessibilityLabel={t('HTML.accessibilityHint')}
onPress={() => { onPress={() => {
analytics('status_readmore', { totalLines, expanded })
layoutAnimation() layoutAnimation()
setExpanded(!expanded) setExpanded(!expanded)
}} }}

View File

@ -1,11 +1,7 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { import { QueryKeyRelationship, useRelationshipMutation } from '@utils/queryHooks/relationship'
QueryKeyRelationship,
useRelationshipMutation
} from '@utils/queryHooks/relationship'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
@ -23,17 +19,12 @@ const RelationshipIncoming: React.FC<Props> = ({ id }) => {
const { t } = useTranslation() const { t } = useTranslation()
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }] const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }]
const queryKeyNotification: QueryKeyTimeline = [ const queryKeyNotification: QueryKeyTimeline = ['Timeline', { page: 'Notifications' }]
'Timeline',
{ page: 'Notifications' }
]
const queryClient = useQueryClient() const queryClient = useQueryClient()
const mutation = useRelationshipMutation({ const mutation = useRelationshipMutation({
onSuccess: res => { onSuccess: res => {
haptics('Success') haptics('Success')
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [ queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
res
])
queryClient.refetchQueries(queryKeyNotification) queryClient.refetchQueries(queryKeyNotification)
}, },
onError: (err: any, { type }) => { onError: (err: any, { type }) => {
@ -62,28 +53,26 @@ const RelationshipIncoming: React.FC<Props> = ({ id }) => {
type='icon' type='icon'
content='X' content='X'
loading={mutation.isLoading} loading={mutation.isLoading}
onPress={() => { onPress={() =>
analytics('relationship_incoming_press_reject')
mutation.mutate({ mutation.mutate({
id, id,
type: 'incoming', type: 'incoming',
payload: { action: 'reject' } payload: { action: 'reject' }
}) })
}} }
/> />
<Button <Button
round round
type='icon' type='icon'
content='Check' content='Check'
loading={mutation.isLoading} loading={mutation.isLoading}
onPress={() => { onPress={() =>
analytics('relationship_incoming_press_authorize')
mutation.mutate({ mutation.mutate({
id, id,
type: 'incoming', type: 'incoming',
payload: { action: 'authorize' } payload: { action: 'authorize' }
}) })
}} }
style={styles.approve} style={styles.approve}
/> />
</View> </View>

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
@ -29,10 +28,7 @@ const RelationshipOutgoing = React.memo(
const mutation = useRelationshipMutation({ const mutation = useRelationshipMutation({
onSuccess: (res, { payload: { action } }) => { onSuccess: (res, { payload: { action } }) => {
haptics('Success') haptics('Success')
queryClient.setQueryData<Mastodon.Relationship[]>( queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
queryKeyRelationship,
[res]
)
if (action === 'block') { if (action === 'block') {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }] const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }]
queryClient.invalidateQueries(queryKey) queryClient.invalidateQueries(queryKey)
@ -64,17 +60,12 @@ const RelationshipOutgoing = React.memo(
onPress = () => {} onPress = () => {}
} else { } else {
if (query.data?.blocked_by) { if (query.data?.blocked_by) {
analytics('relationship_outgoing_blocked_by')
content = t('button.blocked_by') content = t('button.blocked_by')
onPress = () => { onPress = () => {}
analytics('relationship_outgoing_blocked_by_press')
}
} else { } else {
if (query.data?.blocking) { if (query.data?.blocking) {
analytics('relationship_outgoing_blocking')
content = t('button.blocking') content = t('button.blocking')
onPress = () => { onPress = () => {
analytics('relationship_outgoing_blocking_press')
mutation.mutate({ mutation.mutate({
id, id,
type: 'outgoing', type: 'outgoing',
@ -86,10 +77,8 @@ const RelationshipOutgoing = React.memo(
} }
} else { } else {
if (query.data?.following) { if (query.data?.following) {
analytics('relationship_outgoing_following')
content = t('button.following') content = t('button.following')
onPress = () => { onPress = () => {
analytics('relationship_outgoing_following_press')
mutation.mutate({ mutation.mutate({
id, id,
type: 'outgoing', type: 'outgoing',
@ -101,10 +90,8 @@ const RelationshipOutgoing = React.memo(
} }
} else { } else {
if (query.data?.requested) { if (query.data?.requested) {
analytics('relationship_outgoing_requested')
content = t('button.requested') content = t('button.requested')
onPress = () => { onPress = () => {
analytics('relationship_outgoing_requested_press')
mutation.mutate({ mutation.mutate({
id, id,
type: 'outgoing', type: 'outgoing',
@ -115,10 +102,8 @@ const RelationshipOutgoing = React.memo(
}) })
} }
} else { } else {
analytics('relationship_outgoing_default')
content = t('button.default') content = t('button.default')
onPress = () => { onPress = () => {
analytics('relationship_outgoing_default_press')
mutation.mutate({ mutation.mutate({
id, id,
type: 'outgoing', type: 'outgoing',

View File

@ -1,5 +1,4 @@
import apiInstance from '@api/instance' import apiInstance from '@api/instance'
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack' import { StackNavigationProp } from '@react-navigation/stack'
@ -79,7 +78,6 @@ const TimelineConversation = React.memo(
const navigation = const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>() useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const onPress = useCallback(() => { const onPress = useCallback(() => {
analytics('timeline_conversation_press')
if (conversation.last_status) { if (conversation.last_status) {
conversation.unread && mutate() conversation.unread && mutate()
navigation.push('Tab-Shared-Toot', { navigation.push('Tab-Shared-Toot', {

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import TimelineActioned from '@components/Timeline/Shared/Actioned' import TimelineActioned from '@components/Timeline/Shared/Actioned'
import TimelineActions from '@components/Timeline/Shared/Actions' import TimelineActions from '@components/Timeline/Shared/Actions'
import TimelineAttachment from '@components/Timeline/Shared/Attachment' import TimelineAttachment from '@components/Timeline/Shared/Attachment'
@ -17,7 +16,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { uniqBy } from 'lodash' import { uniqBy } from 'lodash'
import React, { useRef } from 'react' import React, { useRef } from 'react'
import { Platform, Pressable, StyleProp, View, ViewStyle } from 'react-native' import { Pressable, StyleProp, View, ViewStyle } from 'react-native'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import TimelineContextMenu from './Shared/ContextMenu' import TimelineContextMenu from './Shared/ContextMenu'
import TimelineFeedback from './Shared/Feedback' import TimelineFeedback from './Shared/Feedback'
@ -29,7 +28,6 @@ export interface Props {
item: Mastodon.Status & { _pinned?: boolean } // For account page, internal property item: Mastodon.Status & { _pinned?: boolean } // For account page, internal property
queryKey?: QueryKeyTimeline queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline
origin?: string
highlighted?: boolean highlighted?: boolean
disableDetails?: boolean disableDetails?: boolean
disableOnPress?: boolean disableOnPress?: boolean
@ -40,7 +38,6 @@ const TimelineDefault: React.FC<Props> = ({
item, item,
queryKey, queryKey,
rootQueryKey, rootQueryKey,
origin,
highlighted = false, highlighted = false,
disableDetails = false, disableDetails = false,
disableOnPress = false disableOnPress = false
@ -65,9 +62,6 @@ const TimelineDefault: React.FC<Props> = ({
const onPress = () => { const onPress = () => {
if (highlighted) return if (highlighted) return
analytics('timeline_default_press', {
page: queryKey ? queryKey[1].page : origin
})
navigation.push('Tab-Shared-Toot', { navigation.push('Tab-Shared-Toot', {
toot: actualStatus, toot: actualStatus,
rootQueryKey: queryKey rootQueryKey: queryKey

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import CustomText from '@components/Text' import CustomText from '@components/Text'
@ -27,20 +26,11 @@ const TimelineEmpty = React.memo(
const children = () => { const children = () => {
switch (status) { switch (status) {
case 'loading': case 'loading':
return ( return <Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
<Circle
size={StyleConstants.Font.Size.L}
color={colors.secondary}
/>
)
case 'error': case 'error':
return ( return (
<> <>
<Icon <Icon name='Frown' size={StyleConstants.Font.Size.L} color={colors.primaryDefault} />
name='Frown'
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<CustomText <CustomText
fontStyle='M' fontStyle='M'
style={{ style={{
@ -51,14 +41,7 @@ const TimelineEmpty = React.memo(
> >
{t('empty.error.message')} {t('empty.error.message')}
</CustomText> </CustomText>
<Button <Button type='text' content={t('empty.error.button')} onPress={() => refetch()} />
type='text'
content={t('empty.error.button')}
onPress={() => {
analytics('timeline_error_press_refetch')
refetch()
}}
/>
</> </>
) )
case 'success': case 'success':

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import TimelineActioned from '@components/Timeline/Shared/Actioned' import TimelineActioned from '@components/Timeline/Shared/Actioned'
import TimelineActions from '@components/Timeline/Shared/Actions' import TimelineActions from '@components/Timeline/Shared/Actions'
import TimelineAttachment from '@components/Timeline/Shared/Attachment' import TimelineAttachment from '@components/Timeline/Shared/Attachment'
@ -15,7 +14,7 @@ import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getInstanceAccount } from '@utils/slices/instancesSlice' import { getInstanceAccount } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { isEqual, uniqBy } from 'lodash' import { uniqBy } from 'lodash'
import React, { useCallback, useRef } from 'react' import React, { useCallback, useRef } from 'react'
import { Platform, Pressable, View } from 'react-native' import { Platform, Pressable, View } from 'react-native'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
@ -57,7 +56,6 @@ const TimelineNotifications: React.FC<Props> = ({
const actualAccount = notification.status ? notification.status.account : notification.account const actualAccount = notification.status ? notification.status.account : notification.account
const onPress = useCallback(() => { const onPress = useCallback(() => {
analytics('timeline_notification_press')
notification.status && notification.status &&
navigation.push('Tab-Shared-Toot', { navigation.push('Tab-Shared-Toot', {
toot: notification.status, toot: notification.status,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { ParseEmojis } from '@components/Parse' import { ParseEmojis } from '@components/Parse'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
@ -6,7 +5,7 @@ import { StackNavigationProp } from '@react-navigation/stack'
import { TabLocalStackParamList } from '@utils/navigation/navigators' import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Pressable, StyleSheet, View } from 'react-native' import { Pressable, StyleSheet, View } from 'react-native'
@ -20,8 +19,7 @@ const TimelineActioned = React.memo(
({ account, action, notification = false }: Props) => { ({ account, action, notification = false }: Props) => {
const { t } = useTranslation('componentTimeline') const { t } = useTranslation('componentTimeline')
const { colors } = useTheme() const { colors } = useTheme()
const navigation = const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const name = account?.display_name || account?.username const name = account?.display_name || account?.username
const iconColor = colors.primaryDefault const iconColor = colors.primaryDefault
@ -29,10 +27,7 @@ const TimelineActioned = React.memo(
<ParseEmojis content={content} emojis={account.emojis} size='S' /> <ParseEmojis content={content} emojis={account.emojis} size='S' />
) )
const onPress = useCallback(() => { const onPress = () => navigation.push('Tab-Shared-Account', { account })
analytics('timeline_shared_actioned_press', { action })
navigation.push('Tab-Shared-Account', { account })
}, [])
const children = () => { const children = () => {
switch (action) { switch (action) {

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import CustomText from '@components/Text' import CustomText from '@components/Text'
@ -84,18 +83,16 @@ const TimelineActions: React.FC<Props> = ({
} }
}) })
const onPressReply = useCallback(() => { const onPressReply = useCallback(
analytics('timeline_shared_actions_reply_press', { () =>
page: queryKey[1].page, navigation.navigate('Screen-Compose', {
count: status.replies_count type: 'reply',
}) incomingStatus: status,
navigation.navigate('Screen-Compose', { accts,
type: 'reply', queryKey
incomingStatus: status, }),
accts, [status.replies_count]
queryKey )
})
}, [status.replies_count])
const { showActionSheetWithOptions } = useActionSheet() const { showActionSheetWithOptions } = useActionSheet()
const onPressReblog = useCallback(() => { const onPressReblog = useCallback(() => {
if (!status.reblogged) { if (!status.reblogged) {
@ -112,11 +109,6 @@ const TimelineActions: React.FC<Props> = ({
(selectedIndex: number) => { (selectedIndex: number) => {
switch (selectedIndex) { switch (selectedIndex) {
case 0: case 0:
analytics('timeline_shared_actions_reblog_public_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -133,11 +125,6 @@ const TimelineActions: React.FC<Props> = ({
}) })
break break
case 1: case 1:
analytics('timeline_shared_actions_reblog_unlisted_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -157,11 +144,6 @@ const TimelineActions: React.FC<Props> = ({
} }
) )
} else { } else {
analytics('timeline_shared_actions_reblog_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -179,11 +161,6 @@ const TimelineActions: React.FC<Props> = ({
} }
}, [status.reblogged, status.reblogs_count]) }, [status.reblogged, status.reblogs_count])
const onPressFavourite = useCallback(() => { const onPressFavourite = useCallback(() => {
analytics('timeline_shared_actions_favourite_press', {
page: queryKey[1].page,
count: status.favourites_count,
current: status.favourited
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -199,10 +176,6 @@ const TimelineActions: React.FC<Props> = ({
}) })
}, [status.favourited, status.favourites_count]) }, [status.favourited, status.favourites_count])
const onPressBookmark = useCallback(() => { const onPressBookmark = useCallback(() => {
analytics('timeline_shared_actions_bookmark_press', {
page: queryKey[1].page,
current: status.bookmarked
})
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import AttachmentAudio from '@components/Timeline/Shared/Attachment/Audio' import AttachmentAudio from '@components/Timeline/Shared/Attachment/Audio'
@ -195,7 +194,6 @@ const TimelineAttachment = React.memo(
content={t('shared.attachment.sensitive.button')} content={t('shared.attachment.sensitive.button')}
overlay overlay
onPress={() => { onPress={() => {
analytics('timeline_shared_attachment_blurview_press_show')
layoutAnimation() layoutAnimation()
setSensitiveShown(false) setSensitiveShown(false)
haptics('Light') haptics('Light')
@ -209,7 +207,6 @@ const TimelineAttachment = React.memo(
round round
overlay overlay
onPress={() => { onPress={() => {
analytics('timeline_shared_attachment_blurview_press_hide')
setSensitiveShown(true) setSensitiveShown(true)
haptics('Light') haptics('Light')
}} }}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import { Slider } from '@sharcoux/slider' import { Slider } from '@sharcoux/slider'
@ -25,7 +24,6 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
const [audioPlaying, setAudioPlaying] = useState(false) const [audioPlaying, setAudioPlaying] = useState(false)
const [audioPosition, setAudioPosition] = useState(0) const [audioPosition, setAudioPosition] = useState(0)
const playAudio = useCallback(async () => { const playAudio = useCallback(async () => {
analytics('timeline_shared_attachment_audio_play_press', { id: audio.id })
if (!audioPlayer) { if (!audioPlayer) {
const { sound } = await Audio.Sound.createAsync( const { sound } = await Audio.Sound.createAsync(
{ uri: audio.url }, { uri: audio.url },
@ -41,7 +39,6 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
} }
}, [audioPlayer, audioPosition]) }, [audioPlayer, audioPosition])
const pauseAudio = useCallback(async () => { const pauseAudio = useCallback(async () => {
analytics('timeline_shared_attachment_audio_pause_press', { id: audio.id })
audioPlayer!.pauseAsync() audioPlayer!.pauseAsync()
setAudioPlaying(false) setAudioPlaying(false)
}, [audioPlayer]) }, [audioPlayer])

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import React from 'react' import React from 'react'
@ -34,27 +33,17 @@ const AttachmentImage = ({
hidden={sensitiveShown} hidden={sensitiveShown}
uri={{ original: image.preview_url, remote: image.remote_url }} uri={{ original: image.preview_url, remote: image.remote_url }}
blurhash={image.blurhash} blurhash={image.blurhash}
onPress={() => { onPress={() => navigateToImagesViewer(image.id)}
analytics('timeline_shared_attachment_image_press', {
id: image.id
})
navigateToImagesViewer(image.id)
}}
style={{ style={{
aspectRatio: aspectRatio:
total > 1 || total > 1 || !image.meta?.original?.width || !image.meta?.original?.height
!image.meta?.original?.width ||
!image.meta?.original?.height
? attachmentAspectRatio({ total, index }) ? attachmentAspectRatio({ total, index })
: image.meta.original.height / image.meta.original.width > 1 : image.meta.original.height / image.meta.original.width > 1
? 1 ? 1
: image.meta.original.width / image.meta.original.height : image.meta.original.width / image.meta.original.height
}} }}
/> />
<AttachmentAltText <AttachmentAltText sensitiveShown={sensitiveShown} text={image.description} />
sensitiveShown={sensitiveShown}
text={image.description}
/>
</View> </View>
) )
} }

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import openLink from '@components/openLink' import openLink from '@components/openLink'
import CustomText from '@components/Text' import CustomText from '@components/Text'
@ -18,12 +17,7 @@ export interface Props {
attachment: Mastodon.AttachmentUnknown attachment: Mastodon.AttachmentUnknown
} }
const AttachmentUnsupported: React.FC<Props> = ({ const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown, attachment }) => {
total,
index,
sensitiveShown,
attachment
}) => {
const { t } = useTranslation('componentTimeline') const { t } = useTranslation('componentTimeline')
const { colors } = useTheme() const { colors } = useTheme()
@ -55,9 +49,7 @@ const AttachmentUnsupported: React.FC<Props> = ({
style={{ style={{
textAlign: 'center', textAlign: 'center',
marginBottom: StyleConstants.Spacing.S, marginBottom: StyleConstants.Spacing.S,
color: attachment.blurhash color: attachment.blurhash ? colors.backgroundDefault : colors.primaryDefault
? colors.backgroundDefault
: colors.primaryDefault
}} }}
> >
{t('shared.attachment.unsupported.text')} {t('shared.attachment.unsupported.text')}
@ -69,17 +61,13 @@ const AttachmentUnsupported: React.FC<Props> = ({
size='S' size='S'
overlay overlay
onPress={() => { onPress={() => {
analytics('timeline_shared_attachment_unsupported_press')
attachment.remote_url && openLink(attachment.remote_url) attachment.remote_url && openLink(attachment.remote_url)
}} }}
/> />
) : null} ) : null}
</> </>
) : null} ) : null}
<AttachmentAltText <AttachmentAltText sensitiveShown={sensitiveShown} text={attachment.description} />
sensitiveShown={sensitiveShown}
text={attachment.description}
/>
</View> </View>
) )
} }

View File

@ -5,7 +5,6 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'
import { AppState, AppStateStatus, Pressable, View } from 'react-native' import { AppState, AppStateStatus, Pressable, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash' import { Blurhash } from 'react-native-blurhash'
import attachmentAspectRatio from './aspectRatio' import attachmentAspectRatio from './aspectRatio'
import analytics from '@components/analytics'
import AttachmentAltText from './AltText' import AttachmentAltText from './AltText'
import { Platform } from 'expo-modules-core' import { Platform } from 'expo-modules-core'
@ -30,13 +29,6 @@ const AttachmentVideo: React.FC<Props> = ({
const [videoPosition, setVideoPosition] = useState<number>(0) const [videoPosition, setVideoPosition] = useState<number>(0)
const [videoResizeMode, setVideoResizeMode] = useState<ResizeMode>(ResizeMode.COVER) const [videoResizeMode, setVideoResizeMode] = useState<ResizeMode>(ResizeMode.COVER)
const playOnPress = useCallback(async () => { const playOnPress = useCallback(async () => {
analytics('timeline_shared_attachment_video_length', {
length: video.meta?.length
})
analytics('timeline_shared_attachment_vide_play_press', {
id: video.id,
timestamp: Date.now()
})
setVideoLoading(true) setVideoLoading(true)
if (!videoLoaded) { if (!videoLoaded) {
await videoPlayer.current?.loadAsync({ uri: video.url }) await videoPlayer.current?.loadAsync({ uri: video.url })

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack' import { StackNavigationProp } from '@react-navigation/stack'
@ -14,43 +13,37 @@ export interface Props {
highlighted: boolean highlighted: boolean
} }
const TimelineAvatar = React.memo( const TimelineAvatar = React.memo(({ queryKey, account, highlighted }: Props) => {
({ queryKey, account, highlighted }: Props) => { const { t } = useTranslation('componentTimeline')
const { t } = useTranslation('componentTimeline') const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const navigation = // Need to fix go back root
useNavigation<StackNavigationProp<TabLocalStackParamList>>() const onPress = useCallback(() => {
// Need to fix go back root queryKey && navigation.push('Tab-Shared-Account', { account })
const onPress = useCallback(() => { }, [])
analytics('timeline_shared_avatar_press', {
page: queryKey && queryKey[1].page
})
queryKey && navigation.push('Tab-Shared-Account', { account })
}, [])
return ( return (
<GracefullyImage <GracefullyImage
{...(highlighted && { {...(highlighted && {
accessibilityLabel: t('shared.avatar.accessibilityLabel', { accessibilityLabel: t('shared.avatar.accessibilityLabel', {
name: account.display_name name: account.display_name
}), }),
accessibilityHint: t('shared.avatar.accessibilityHint', { accessibilityHint: t('shared.avatar.accessibilityHint', {
name: account.display_name name: account.display_name
}) })
})} })}
onPress={onPress} onPress={onPress}
uri={{ original: account?.avatar, static: account?.avatar_static }} uri={{ original: account?.avatar, static: account?.avatar_static }}
dimension={{ dimension={{
width: StyleConstants.Avatar.M, width: StyleConstants.Avatar.M,
height: StyleConstants.Avatar.M height: StyleConstants.Avatar.M
}} }}
style={{ style={{
borderRadius: StyleConstants.Avatar.M, borderRadius: StyleConstants.Avatar.M,
overflow: 'hidden', overflow: 'hidden',
marginRight: StyleConstants.Spacing.S marginRight: StyleConstants.Spacing.S
}} }}
/> />
) )
} })
)
export default TimelineAvatar export default TimelineAvatar

View File

@ -1,5 +1,4 @@
import ComponentAccount from '@components/Account' import ComponentAccount from '@components/Account'
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import openLink from '@components/openLink' import openLink from '@components/openLink'
import CustomText from '@components/Text' import CustomText from '@components/Text'
@ -130,10 +129,10 @@ const TimelineCard = React.memo(({ card }: Props) => {
) )
} }
if (isStatus && foundStatus) { if (isStatus && foundStatus) {
return <TimelineDefault item={foundStatus} disableDetails disableOnPress origin='card' /> return <TimelineDefault item={foundStatus} disableDetails disableOnPress />
} }
if (isAccount && foundAccount) { if (isAccount && foundAccount) {
return <ComponentAccount account={foundAccount} origin='card' /> return <ComponentAccount account={foundAccount} />
} }
return ( return (
<> <>
@ -193,10 +192,7 @@ const TimelineCard = React.memo(({ card }: Props) => {
overflow: 'hidden', overflow: 'hidden',
borderColor: colors.border borderColor: colors.border
}} }}
onPress={async () => { onPress={async () => await openLink(card.url, navigation)}
analytics('timeline_shared_card_press')
await openLink(card.url, navigation)
}}
children={cardContent} children={cardContent}
/> />
) )

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack' import { StackNavigationProp } from '@react-navigation/stack'
@ -11,10 +10,7 @@ import { useTranslation } from 'react-i18next'
import { StyleSheet, View } from 'react-native' import { StyleSheet, View } from 'react-native'
export interface Props { export interface Props {
status: Pick< status: Pick<Mastodon.Status, 'id' | 'edited_at' | 'reblogs_count' | 'favourites_count'>
Mastodon.Status,
'id' | 'edited_at' | 'reblogs_count' | 'favourites_count'
>
highlighted: boolean highlighted: boolean
} }
@ -26,8 +22,7 @@ const TimelineFeedback = React.memo(
const { t } = useTranslation('componentTimeline') const { t } = useTranslation('componentTimeline')
const { colors } = useTheme() const { colors } = useTheme()
const navigation = const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const { data } = useStatusHistory({ const { data } = useStatusHistory({
id: status.id, id: status.id,
@ -39,28 +34,20 @@ const TimelineFeedback = React.memo(
<View style={{ flexDirection: 'row' }}> <View style={{ flexDirection: 'row' }}>
{status.reblogs_count > 0 ? ( {status.reblogs_count > 0 ? (
<CustomText <CustomText
accessibilityLabel={t( accessibilityLabel={t('shared.actionsUsers.reblogged_by.accessibilityLabel', {
'shared.actionsUsers.reblogged_by.accessibilityLabel', count: status.reblogs_count
{ })}
count: status.reblogs_count accessibilityHint={t('shared.actionsUsers.reblogged_by.accessibilityHint')}
}
)}
accessibilityHint={t(
'shared.actionsUsers.reblogged_by.accessibilityHint'
)}
accessibilityRole='button' accessibilityRole='button'
style={[styles.text, { color: colors.blue }]} style={[styles.text, { color: colors.blue }]}
onPress={() => { onPress={() =>
analytics('timeline_shared_feedback_press_reblog', {
count: status.reblogs_count
})
navigation.push('Tab-Shared-Users', { navigation.push('Tab-Shared-Users', {
reference: 'statuses', reference: 'statuses',
id: status.id, id: status.id,
type: 'reblogged_by', type: 'reblogged_by',
count: status.reblogs_count count: status.reblogs_count
}) })
}} }
> >
{t('shared.actionsUsers.reblogged_by.text', { {t('shared.actionsUsers.reblogged_by.text', {
count: status.reblogs_count count: status.reblogs_count
@ -69,28 +56,20 @@ const TimelineFeedback = React.memo(
) : null} ) : null}
{status.favourites_count > 0 ? ( {status.favourites_count > 0 ? (
<CustomText <CustomText
accessibilityLabel={t( accessibilityLabel={t('shared.actionsUsers.favourited_by.accessibilityLabel', {
'shared.actionsUsers.favourited_by.accessibilityLabel', count: status.reblogs_count
{ })}
count: status.reblogs_count accessibilityHint={t('shared.actionsUsers.favourited_by.accessibilityHint')}
}
)}
accessibilityHint={t(
'shared.actionsUsers.favourited_by.accessibilityHint'
)}
accessibilityRole='button' accessibilityRole='button'
style={[styles.text, { color: colors.blue }]} style={[styles.text, { color: colors.blue }]}
onPress={() => { onPress={() =>
analytics('timeline_shared_feedback_press_favourite', {
count: status.favourites_count
})
navigation.push('Tab-Shared-Users', { navigation.push('Tab-Shared-Users', {
reference: 'statuses', reference: 'statuses',
id: status.id, id: status.id,
type: 'favourited_by', type: 'favourited_by',
count: status.favourites_count count: status.favourites_count
}) })
}} }
> >
{t('shared.actionsUsers.favourited_by.text', { {t('shared.actionsUsers.favourited_by.text', {
count: status.favourites_count count: status.favourites_count
@ -101,23 +80,13 @@ const TimelineFeedback = React.memo(
<View> <View>
{data && data.length > 1 ? ( {data && data.length > 1 ? (
<CustomText <CustomText
accessibilityLabel={t( accessibilityLabel={t('shared.actionsUsers.history.accessibilityLabel', {
'shared.actionsUsers.history.accessibilityLabel', count: data.length - 1
{ })}
count: data.length - 1 accessibilityHint={t('shared.actionsUsers.history.accessibilityHint')}
}
)}
accessibilityHint={t(
'shared.actionsUsers.history.accessibilityHint'
)}
accessibilityRole='button' accessibilityRole='button'
style={[styles.text, { marginRight: 0, color: colors.blue }]} style={[styles.text, { marginRight: 0, color: colors.blue }]}
onPress={() => { onPress={() => navigation.push('Tab-Shared-History', { id: status.id })}
analytics('timeline_shared_feedback_press_history', {
count: data.length - 1
})
navigation.push('Tab-Shared-History', { id: status.id })
}}
> >
{t('shared.actionsUsers.history.text', { {t('shared.actionsUsers.history.text', {
count: data.length - 1 count: data.length - 1

View File

@ -1,15 +1,11 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { ParseEmojis } from '@components/Parse' import { ParseEmojis } from '@components/Parse'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native' import { Pressable, View } from 'react-native'
import { useQueryClient } from 'react-query' import { useQueryClient } from 'react-query'
@ -71,27 +67,6 @@ const HeaderConversation = ({ queryKey, conversation }: Props) => {
} }
}) })
const actionOnPress = useCallback(() => {
analytics('timeline_conversation_delete_press')
mutation.mutate({
type: 'deleteItem',
source: 'conversations',
queryKey,
id: conversation.id
})
}, [])
const actionChildren = useMemo(
() => (
<Icon
name='Trash'
color={colors.secondary}
size={StyleConstants.Font.Size.L}
/>
),
[]
)
return ( return (
<View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ flex: 1, flexDirection: 'row' }}>
<View style={{ flex: 3 }}> <View style={{ flex: 3 }}>
@ -116,8 +91,15 @@ const HeaderConversation = ({ queryKey, conversation }: Props) => {
<Pressable <Pressable
style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }} style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }}
onPress={actionOnPress} onPress={() =>
children={actionChildren} mutation.mutate({
type: 'deleteItem',
source: 'conversations',
queryKey,
id: conversation.id
})
}
children={<Icon name='Trash' color={colors.secondary} size={StyleConstants.Font.Size.L} />}
/> />
</View> </View>
) )

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import openLink from '@components/openLink' import openLink from '@components/openLink'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
@ -20,9 +19,6 @@ const HeaderSharedApplication = React.memo(
fontStyle='S' fontStyle='S'
accessibilityRole='link' accessibilityRole='link'
onPress={async () => { onPress={async () => {
analytics('timeline_shared_header_application_press', {
application
})
application.website && (await openLink(application.website)) application.website && (await openLink(application.website))
}} }}
style={{ style={{

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
@ -40,9 +39,7 @@ const TimelinePoll: React.FC<Props> = ({
const { colors, theme } = useTheme() const { colors, theme } = useTheme()
const { t, i18n } = useTranslation('componentTimeline') const { t, i18n } = useTranslation('componentTimeline')
const [allOptions, setAllOptions] = useState( const [allOptions, setAllOptions] = useState(new Array(poll.options.length).fill(false))
new Array(poll.options.length).fill(false)
)
const queryClient = useQueryClient() const queryClient = useQueryClient()
const mutation = useTimelineMutation({ const mutation = useTimelineMutation({
@ -86,8 +83,7 @@ const TimelinePoll: React.FC<Props> = ({
return ( return (
<View style={{ marginRight: StyleConstants.Spacing.S }}> <View style={{ marginRight: StyleConstants.Spacing.S }}>
<Button <Button
onPress={() => { onPress={() =>
analytics('timeline_shared_vote_vote_press')
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -101,7 +97,7 @@ const TimelinePoll: React.FC<Props> = ({
options: allOptions options: allOptions
} }
}) })
}} }
type='text' type='text'
content={t('shared.poll.meta.button.vote')} content={t('shared.poll.meta.button.vote')}
loading={mutation.isLoading} loading={mutation.isLoading}
@ -113,8 +109,7 @@ const TimelinePoll: React.FC<Props> = ({
return ( return (
<View style={{ marginRight: StyleConstants.Spacing.S }}> <View style={{ marginRight: StyleConstants.Spacing.S }}>
<Button <Button
onPress={() => { onPress={() =>
analytics('timeline_shared_vote_refresh_press')
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
queryKey, queryKey,
@ -127,7 +122,7 @@ const TimelinePoll: React.FC<Props> = ({
type: 'refresh' type: 'refresh'
} }
}) })
}} }
type='text' type='text'
content={t('shared.poll.meta.button.refresh')} content={t('shared.poll.meta.button.refresh')}
loading={mutation.isLoading} loading={mutation.isLoading}
@ -136,14 +131,7 @@ const TimelinePoll: React.FC<Props> = ({
) )
} }
} }
}, [ }, [theme, i18n.language, poll.expired, poll.voted, allOptions, mutation.isLoading])
theme,
i18n.language,
poll.expired,
poll.voted,
allOptions,
mutation.isLoading
])
const isSelected = useCallback( const isSelected = useCallback(
(index: number): string => (index: number): string =>
@ -154,20 +142,13 @@ const TimelinePoll: React.FC<Props> = ({
) )
const pollBodyDisallow = useMemo(() => { const pollBodyDisallow = useMemo(() => {
const maxValue = maxBy( const maxValue = maxBy(poll.options, option => option.votes_count)?.votes_count
poll.options,
option => option.votes_count
)?.votes_count
return poll.options.map((option, index) => ( return poll.options.map((option, index) => (
<View <View key={index} style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}>
key={index}
style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}
>
<View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ flex: 1, flexDirection: 'row' }}>
<Icon <Icon
style={{ style={{
paddingTop: paddingTop: StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S marginRight: StyleConstants.Spacing.S
}} }}
name={ name={
@ -176,9 +157,7 @@ const TimelinePoll: React.FC<Props> = ({
}` as any }` as any
} }
size={StyleConstants.Font.Size.M} size={StyleConstants.Font.Size.M}
color={ color={poll.own_votes?.includes(index) ? colors.blue : colors.disabled}
poll.own_votes?.includes(index) ? colors.blue : colors.disabled
}
/> />
<CustomText style={{ flex: 1 }}> <CustomText style={{ flex: 1 }}>
<ParseEmojis content={option.title} emojis={poll.emojis} /> <ParseEmojis content={option.title} emojis={poll.emojis} />
@ -194,11 +173,7 @@ const TimelinePoll: React.FC<Props> = ({
}} }}
> >
{poll.votes_count {poll.votes_count
? Math.round( ? Math.round((option.votes_count / (poll.voters_count || poll.votes_count)) * 100)
(option.votes_count /
(poll.voters_count || poll.votes_count)) *
100
)
: 0} : 0}
% %
</CustomText> </CustomText>
@ -213,11 +188,9 @@ const TimelinePoll: React.FC<Props> = ({
marginTop: StyleConstants.Spacing.XS, marginTop: StyleConstants.Spacing.XS,
marginBottom: StyleConstants.Spacing.S, marginBottom: StyleConstants.Spacing.S,
width: `${Math.round( width: `${Math.round(
(option.votes_count / (poll.voters_count || poll.votes_count)) * (option.votes_count / (poll.voters_count || poll.votes_count)) * 100
100
)}%`, )}%`,
backgroundColor: backgroundColor: option.votes_count === maxValue ? colors.blue : colors.disabled
option.votes_count === maxValue ? colors.blue : colors.disabled
}} }}
/> />
</View> </View>
@ -229,21 +202,15 @@ const TimelinePoll: React.FC<Props> = ({
key={index} key={index}
style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }} style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}
onPress={() => { onPress={() => {
analytics('timeline_shared_vote_option_press')
!allOptions[index] && haptics('Light') !allOptions[index] && haptics('Light')
if (poll.multiple) { if (poll.multiple) {
setAllOptions(allOptions.map((o, i) => (i === index ? !o : o))) setAllOptions(allOptions.map((o, i) => (i === index ? !o : o)))
} else { } else {
{ {
const otherOptions = const otherOptions = allOptions[index] === false ? false : undefined
allOptions[index] === false ? false : undefined
setAllOptions( setAllOptions(
allOptions.map((o, i) => allOptions.map((o, i) =>
i === index i === index ? !o : otherOptions !== undefined ? otherOptions : o
? !o
: otherOptions !== undefined
? otherOptions
: o
) )
) )
} }
@ -253,8 +220,7 @@ const TimelinePoll: React.FC<Props> = ({
<View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ flex: 1, flexDirection: 'row' }}>
<Icon <Icon
style={{ style={{
paddingTop: paddingTop: StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S marginRight: StyleConstants.Spacing.S
}} }}
name={isSelected(index)} name={isSelected(index)}
@ -271,13 +237,9 @@ const TimelinePoll: React.FC<Props> = ({
const pollVoteCounts = () => { const pollVoteCounts = () => {
if (poll.voters_count !== null) { if (poll.voters_count !== null) {
return ( return t('shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • '
t('shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • '
)
} else if (poll.votes_count !== null) { } else if (poll.votes_count !== null) {
return ( return t('shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • '
t('shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • '
)
} }
} }
@ -308,10 +270,7 @@ const TimelinePoll: React.FC<Props> = ({
}} }}
> >
{pollButton} {pollButton}
<CustomText <CustomText fontStyle='S' style={{ flexShrink: 1, color: colors.secondary }}>
fontStyle='S'
style={{ flexShrink: 1, color: colors.secondary }}
>
{pollVoteCounts()} {pollVoteCounts()}
{pollExpiration()} {pollExpiration()}
</CustomText> </CustomText>

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { ParseHTML } from '@components/Parse' import { ParseHTML } from '@components/Parse'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import getLanguage from '@helpers/getLanguage' import getLanguage from '@helpers/getLanguage'
@ -85,15 +84,9 @@ const TimelineTranslate = React.memo(
onPress={() => { onPress={() => {
if (enabled) { if (enabled) {
if (!isSuccess) { if (!isSuccess) {
analytics('timeline_shared_translate_retry', {
language: detectedLanguage
})
refetch() refetch()
} }
} else { } else {
analytics('timeline_shared_translate', {
language: detectedLanguage
})
setEnabled(true) setEnabled(true)
} }
}} }}

View File

@ -1,7 +0,0 @@
import * as Analytics from 'expo-firebase-analytics'
const analytics = (event: string, params?: { [key: string]: any }) => {
Analytics.logEvent(event, params).catch(() => {})
}
export default analytics

View File

@ -275,10 +275,6 @@
"contact": { "contact": {
"heading": "Contact tooot" "heading": "Contact tooot"
}, },
"analytics": {
"heading": "Help us improve",
"description": "Collecting only non-user relative usage"
},
"version": "Version v{{version}}", "version": "Version v{{version}}",
"instanceVersion": "Mastodon version v{{version}}" "instanceVersion": "Mastodon version v{{version}}"
}, },

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { import {
@ -74,9 +73,6 @@ const ActionsAccount: React.FC<Props> = ({
<MenuHeader heading={t('shared.header.actions.account.heading')} /> <MenuHeader heading={t('shared.header.actions.account.heading')} />
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_account_mute_press', {
page: queryKey && queryKey[1].page
})
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'updateAccountProperty', type: 'updateAccountProperty',
@ -92,9 +88,6 @@ const ActionsAccount: React.FC<Props> = ({
/> />
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_account_block_press', {
page: queryKey && queryKey[1].page
})
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'updateAccountProperty', type: 'updateAccountProperty',
@ -110,9 +103,6 @@ const ActionsAccount: React.FC<Props> = ({
/> />
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_account_reports_press', {
page: queryKey && queryKey[1].page
})
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'updateAccountProperty', type: 'updateAccountProperty',

View File

@ -1,12 +1,8 @@
import analytics from '@components/analytics'
import MenuContainer from '@components/Menu/Container' import MenuContainer from '@components/Menu/Container'
import MenuHeader from '@components/Menu/Header' import MenuHeader from '@components/Menu/Header'
import MenuRow from '@components/Menu/Row' import MenuRow from '@components/Menu/Row'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -20,12 +16,7 @@ export interface Props {
dismiss: () => void dismiss: () => void
} }
const ActionsDomain: React.FC<Props> = ({ const ActionsDomain: React.FC<Props> = ({ queryKey, rootQueryKey, domain, dismiss }) => {
queryKey,
rootQueryKey,
domain,
dismiss
}) => {
const { theme } = useTheme() const { theme } = useTheme()
const { t } = useTranslation('componentTimeline') const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient() const queryClient = useQueryClient()
@ -47,10 +38,7 @@ const ActionsDomain: React.FC<Props> = ({
<MenuContainer> <MenuContainer>
<MenuHeader heading={t(`shared.header.actions.domain.heading`)} /> <MenuHeader heading={t(`shared.header.actions.domain.heading`)} />
<MenuRow <MenuRow
onPress={() => { onPress={() =>
analytics('timeline_shared_headeractions_domain_block_press', {
page: queryKey[1].page
})
Alert.alert( Alert.alert(
t('shared.header.actions.domain.alert.title', { domain }), t('shared.header.actions.domain.alert.title', { domain }),
t('shared.header.actions.domain.alert.message'), t('shared.header.actions.domain.alert.message'),
@ -63,12 +51,6 @@ const ActionsDomain: React.FC<Props> = ({
text: t('shared.header.actions.domain.alert.buttons.confirm'), text: t('shared.header.actions.domain.alert.buttons.confirm'),
style: 'destructive', style: 'destructive',
onPress: () => { onPress: () => {
analytics(
'timeline_shared_headeractions_domain_block_confirm',
{
page: queryKey && queryKey[1].page
}
)
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'domainBlock', type: 'domainBlock',
@ -79,7 +61,7 @@ const ActionsDomain: React.FC<Props> = ({
} }
] ]
) )
}} }
iconFront='CloudOff' iconFront='CloudOff'
title={t(`shared.header.actions.domain.block.button`, { title={t(`shared.header.actions.domain.block.button`, {
domain domain

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import MenuContainer from '@components/Menu/Container' import MenuContainer from '@components/Menu/Container'
import MenuHeader from '@components/Menu/Header' import MenuHeader from '@components/Menu/Header'
import MenuRow from '@components/Menu/Row' import MenuRow from '@components/Menu/Row'
@ -22,7 +21,6 @@ const ActionsShare: React.FC<Props> = ({ type, url, dismiss }) => {
iconFront='Share2' iconFront='Share2'
title={t(`shared.header.actions.share.${type}.button`)} title={t(`shared.header.actions.share.${type}.button`)}
onPress={async () => { onPress={async () => {
analytics('timeline_shared_headeractions_share_press')
switch (Platform.OS) { switch (Platform.OS) {
case 'ios': case 'ios':
await Share.share({ await Share.share({

View File

@ -8,7 +8,6 @@ import {
QueryKeyTimeline, QueryKeyTimeline,
useTimelineMutation useTimelineMutation
} from '@utils/queryHooks/timeline' } from '@utils/queryHooks/timeline'
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message' import { displayMessage } from '@components/Message'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import apiInstance from '@api/instance' import apiInstance from '@api/instance'
@ -69,9 +68,6 @@ const ActionsStatus: React.FC<Props> = ({
{canEditPost ? ( {canEditPost ? (
<MenuRow <MenuRow
onPress={async () => { onPress={async () => {
analytics('timeline_shared_headeractions_status_edit_press', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) { if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({ replyToStatus = await apiInstance<Mastodon.Status>({
@ -107,9 +103,6 @@ const ActionsStatus: React.FC<Props> = ({
) : null} ) : null}
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_status_delete_press', {
page: queryKey && queryKey[1].page
})
Alert.alert( Alert.alert(
t('shared.header.actions.status.delete.alert.title'), t('shared.header.actions.status.delete.alert.title'),
t('shared.header.actions.status.delete.alert.message'), t('shared.header.actions.status.delete.alert.message'),
@ -126,12 +119,6 @@ const ActionsStatus: React.FC<Props> = ({
), ),
style: 'destructive', style: 'destructive',
onPress: async () => { onPress: async () => {
analytics(
'timeline_shared_headeractions_status_delete_confirm',
{
page: queryKey && queryKey[1].page
}
)
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'deleteItem', type: 'deleteItem',
@ -150,9 +137,6 @@ const ActionsStatus: React.FC<Props> = ({
/> />
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_status_deleteedit_press', {
page: queryKey && queryKey[1].page
})
Alert.alert( Alert.alert(
t('shared.header.actions.status.deleteEdit.alert.title'), t('shared.header.actions.status.deleteEdit.alert.title'),
t('shared.header.actions.status.deleteEdit.alert.message'), t('shared.header.actions.status.deleteEdit.alert.message'),
@ -169,12 +153,6 @@ const ActionsStatus: React.FC<Props> = ({
), ),
style: 'destructive', style: 'destructive',
onPress: async () => { onPress: async () => {
analytics(
'timeline_shared_headeractions_status_deleteedit_confirm',
{
page: queryKey && queryKey[1].page
}
)
let replyToStatus: Mastodon.Status | undefined = undefined let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) { if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({ replyToStatus = await apiInstance<Mastodon.Status>({
@ -208,9 +186,6 @@ const ActionsStatus: React.FC<Props> = ({
/> />
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_status_mute_press', {
page: queryKey && queryKey[1].page
})
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',
@ -236,9 +211,6 @@ const ActionsStatus: React.FC<Props> = ({
{(status.visibility === 'public' || status.visibility === 'unlisted') && ( {(status.visibility === 'public' || status.visibility === 'unlisted') && (
<MenuRow <MenuRow
onPress={() => { onPress={() => {
analytics('timeline_shared_headeractions_status_pin_press', {
page: queryKey && queryKey[1].page
})
dismiss() dismiss()
mutation.mutate({ mutation.mutate({
type: 'updateStatusProperty', type: 'updateStatusProperty',

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { ParseHTML } from '@components/Parse' import { ParseHTML } from '@components/Parse'
@ -7,10 +6,7 @@ import CustomText from '@components/Text'
import { BlurView } from '@react-native-community/blur' import { BlurView } from '@react-native-community/blur'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { RootStackScreenProps } from '@utils/navigation/navigators' import { RootStackScreenProps } from '@utils/navigation/navigators'
import { import { useAnnouncementMutation, useAnnouncementQuery } from '@utils/queryHooks/announcement'
useAnnouncementMutation,
useAnnouncementQuery
} from '@utils/queryHooks/announcement'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
@ -29,9 +25,7 @@ import FastImage from 'react-native-fast-image'
import { FlatList, ScrollView } from 'react-native-gesture-handler' import { FlatList, ScrollView } from 'react-native-gesture-handler'
import { SafeAreaView } from 'react-native-safe-area-context' import { SafeAreaView } from 'react-native-safe-area-context'
const ScreenAnnouncements: React.FC< const ScreenAnnouncements: React.FC<RootStackScreenProps<'Screen-Announcements'>> = ({
RootStackScreenProps<'Screen-Announcements'>
> = ({
route: { route: {
params: { showAll = false } params: { showAll = false }
}, },
@ -46,9 +40,7 @@ const ScreenAnnouncements: React.FC<
showAll, showAll,
options: { options: {
select: announcements => select: announcements =>
announcements.filter(announcement => announcements.filter(announcement => (showAll ? announcement : !announcement.read))
showAll ? announcement : !announcement.read
)
} }
}) })
const mutation = useAnnouncementMutation({ const mutation = useAnnouncementMutation({
@ -75,10 +67,7 @@ const ScreenAnnouncements: React.FC<
justifyContent: 'center' justifyContent: 'center'
}} }}
> >
<Pressable <Pressable style={StyleSheet.absoluteFillObject} onPress={() => navigation.goBack()} />
style={StyleSheet.absoluteFillObject}
onPress={() => navigation.goBack()}
/>
<View <View
style={{ style={{
flexShrink: 1, flexShrink: 1,
@ -136,31 +125,22 @@ const ScreenAnnouncements: React.FC<
marginRight: StyleConstants.Spacing.M, marginRight: StyleConstants.Spacing.M,
borderRadius: 6, borderRadius: 6,
flexDirection: 'row', flexDirection: 'row',
borderColor: reaction.me borderColor: reaction.me ? colors.disabled : colors.primaryDefault,
? colors.disabled backgroundColor: reaction.me ? colors.disabled : colors.backgroundDefault
: colors.primaryDefault,
backgroundColor: reaction.me
? colors.disabled
: colors.backgroundDefault
}} }}
onPress={() => { onPress={() =>
analytics('announcement_reaction_press', {
current: reaction.me
})
mutation.mutate({ mutation.mutate({
id: item.id, id: item.id,
type: 'reaction', type: 'reaction',
name: reaction.name, name: reaction.name,
me: reaction.me me: reaction.me
}) })
}} }
> >
{reaction.url ? ( {reaction.url ? (
<FastImage <FastImage
source={{ source={{
uri: reduceMotionEnabled uri: reduceMotionEnabled ? reaction.static_url : reaction.url
? reaction.static_url
: reaction.url
}} }}
style={{ style={{
width: StyleConstants.Font.LineHeight.M + 3, width: StyleConstants.Font.LineHeight.M + 3,
@ -183,27 +163,14 @@ const ScreenAnnouncements: React.FC<
) : null} ) : null}
</Pressable> </Pressable>
))} ))}
{/* <Pressable
style={[styles.reaction, { borderColor: colors.primaryDefault }]}
onPress={() => invisibleTextInputRef.current?.focus()}
>
<Icon
name='Plus'
size={StyleConstants.Font.Size.M}
color={colors.primaryDefault}
/>
</Pressable> */}
</View> </View>
) : null} ) : null}
<Button <Button
type='text' type='text'
content={ content={item.read ? t('content.button.read') : t('content.button.unread')}
item.read ? t('content.button.read') : t('content.button.unread')
}
loading={mutation.isLoading} loading={mutation.isLoading}
disabled={item.read} disabled={item.read}
onPress={() => { onPress={() => {
analytics('announcement_read_press')
!item.read && !item.read &&
mutation.mutate({ mutation.mutate({
id: item.id, id: item.id,
@ -279,10 +246,8 @@ const ScreenAnnouncements: React.FC<
borderRadius: StyleConstants.Spacing.S, borderRadius: StyleConstants.Spacing.S,
borderWidth: 1, borderWidth: 1,
borderColor: colors.primaryDefault, borderColor: colors.primaryDefault,
backgroundColor: backgroundColor: i === index ? colors.primaryDefault : undefined,
i === index ? colors.primaryDefault : undefined, marginLeft: i === query.data.length ? 0 : StyleConstants.Spacing.S
marginLeft:
i === query.data.length ? 0 : StyleConstants.Spacing.S
}} }}
/> />
))} ))}
@ -292,9 +257,7 @@ const ScreenAnnouncements: React.FC<
</SafeAreaView> </SafeAreaView>
</BlurView> </BlurView>
) : ( ) : (
<SafeAreaView <SafeAreaView style={{ flex: 1, backgroundColor: colors.backgroundDefault }}>
style={{ flex: 1, backgroundColor: colors.backgroundDefault }}
>
<FlatList <FlatList
horizontal horizontal
data={query.data} data={query.data}
@ -323,10 +286,8 @@ const ScreenAnnouncements: React.FC<
borderRadius: StyleConstants.Spacing.S, borderRadius: StyleConstants.Spacing.S,
borderWidth: 1, borderWidth: 1,
borderColor: colors.primaryDefault, borderColor: colors.primaryDefault,
backgroundColor: backgroundColor: i === index ? colors.primaryDefault : undefined,
i === index ? colors.primaryDefault : undefined, marginLeft: i === query.data.length ? 0 : StyleConstants.Spacing.S
marginLeft:
i === query.data.length ? 0 : StyleConstants.Spacing.S
}} }}
/> />
))} ))}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { ComponentEmojis } from '@components/Emojis' import { ComponentEmojis } from '@components/Emojis'
import { EmojisState } from '@components/Emojis/helpers/EmojisContext' import { EmojisState } from '@components/Emojis/helpers/EmojisContext'
import { HeaderLeft, HeaderRight } from '@components/Header' import { HeaderLeft, HeaderRight } from '@components/Header'
@ -209,19 +208,15 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
type='text' type='text'
content={t('heading.left.button')} content={t('heading.left.button')}
onPress={() => { onPress={() => {
analytics('compose_header_back_press')
if (!composeState.dirty) { if (!composeState.dirty) {
analytics('compose_header_back_empty')
navigation.goBack() navigation.goBack()
return return
} else { } else {
analytics('compose_header_back_state_occupied')
Alert.alert(t('heading.left.alert.title'), undefined, [ Alert.alert(t('heading.left.alert.title'), undefined, [
{ {
text: t('heading.left.alert.buttons.delete'), text: t('heading.left.alert.buttons.delete'),
style: 'destructive', style: 'destructive',
onPress: () => { onPress: () => {
analytics('compose_header_back_occupied_save')
removeDraft() removeDraft()
navigation.goBack() navigation.goBack()
} }
@ -229,17 +224,13 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
{ {
text: t('heading.left.alert.buttons.save'), text: t('heading.left.alert.buttons.save'),
onPress: () => { onPress: () => {
analytics('compose_header_back_occupied_delete')
saveDraft() saveDraft()
navigation.goBack() navigation.goBack()
} }
}, },
{ {
text: t('heading.left.alert.buttons.cancel'), text: t('heading.left.alert.buttons.cancel'),
style: 'cancel', style: 'cancel'
onPress: () => {
analytics('compose_header_back_occupied_cancel')
}
} }
]) ])
} }
@ -272,7 +263,6 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
: t('heading.right.button.default') : t('heading.right.button.default')
} }
onPress={() => { onPress={() => {
analytics('compose_header_post_press')
composeDispatch({ type: 'posting', payload: true }) composeDispatch({ type: 'posting', payload: true })
composePost(params, composeState) composePost(params, composeState)

View File

@ -1,5 +1,4 @@
import apiInstance from '@api/instance' import apiInstance from '@api/instance'
import analytics from '@components/analytics'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { HeaderRight } from '@components/Header' import { HeaderRight } from '@components/Header'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
@ -29,8 +28,6 @@ const ComposeEditAttachmentSubmit: React.FC<Props> = ({ index }) => {
content='Save' content='Save'
loading={isSubmitting} loading={isSubmitting}
onPress={() => { onPress={() => {
analytics('editattachment_confirm_press')
setIsSubmitting(true) setIsSubmitting(true)
const formData = new FormData() const formData = new FormData()
if (theAttachment.description) { if (theAttachment.description) {

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { emojis } from '@components/Emojis' import { emojis } from '@components/Emojis'
import EmojisContext from '@components/Emojis/helpers/EmojisContext' import EmojisContext from '@components/Emojis/helpers/EmojisContext'
import Icon from '@components/Icon' import Icon from '@components/Icon'
@ -36,9 +35,6 @@ const ComposeActions: React.FC = () => {
if (composeState.poll.active) return if (composeState.poll.active) return
if (composeState.attachments.uploads.length < instanceConfigurationStatusMaxAttachments) { if (composeState.attachments.uploads.length < instanceConfigurationStatusMaxAttachments) {
analytics('compose_actions_attachment_press', {
count: composeState.attachments.uploads.length
})
return chooseAndUploadAttachment({ return chooseAndUploadAttachment({
composeDispatch, composeDispatch,
showActionSheetWithOptions showActionSheetWithOptions
@ -57,9 +53,6 @@ const ComposeActions: React.FC = () => {
}, [composeState.poll.active, composeState.attachments.uploads]) }, [composeState.poll.active, composeState.attachments.uploads])
const pollOnPress = () => { const pollOnPress = () => {
if (!composeState.attachments.uploads.length) { if (!composeState.attachments.uploads.length) {
analytics('compose_actions_poll_press', {
current: composeState.poll.active
})
layoutAnimation() layoutAnimation()
composeDispatch({ composeDispatch({
type: 'poll', type: 'poll',
@ -101,31 +94,15 @@ const ComposeActions: React.FC = () => {
buttonIndex => { buttonIndex => {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
analytics('compose_actions_visibility_press', {
current: composeState.visibility,
new: 'public'
})
composeDispatch({ type: 'visibility', payload: 'public' }) composeDispatch({ type: 'visibility', payload: 'public' })
break break
case 1: case 1:
analytics('compose_actions_visibility_press', {
current: composeState.visibility,
new: 'unlisted'
})
composeDispatch({ type: 'visibility', payload: 'unlisted' }) composeDispatch({ type: 'visibility', payload: 'unlisted' })
break break
case 2: case 2:
analytics('compose_actions_visibility_press', {
current: composeState.visibility,
new: 'private'
})
composeDispatch({ type: 'visibility', payload: 'private' }) composeDispatch({ type: 'visibility', payload: 'private' })
break break
case 3: case 3:
analytics('compose_actions_visibility_press', {
current: composeState.visibility,
new: 'direct'
})
composeDispatch({ type: 'visibility', payload: 'direct' }) composeDispatch({ type: 'visibility', payload: 'direct' })
break break
} }
@ -135,9 +112,6 @@ const ComposeActions: React.FC = () => {
} }
const spoilerOnPress = () => { const spoilerOnPress = () => {
analytics('compose_actions_spoiler_press', {
current: composeState.spoiler.active
})
if (composeState.spoiler.active) { if (composeState.spoiler.active) {
composeState.textInputFocus.refs.text.current?.focus() composeState.textInputFocus.refs.text.current?.focus()
} }
@ -159,9 +133,6 @@ const ComposeActions: React.FC = () => {
} }
}, [emojis.current?.length, emojisState.targetIndex]) }, [emojis.current?.length, emojisState.targetIndex])
const emojiOnPress = () => { const emojiOnPress = () => {
analytics('compose_actions_emojis_press', {
current: emojisState.targetIndex !== -1
})
if (emojisState.targetIndex === -1) { if (emojisState.targetIndex === -1) {
Keyboard.dismiss() Keyboard.dismiss()
const focusedPropsIndex = emojisState.inputProps?.findIndex(props => props.isFocused.current) const focusedPropsIndex = emojisState.inputProps?.findIndex(props => props.isFocused.current)

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
@ -9,14 +8,7 @@ import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/inst
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import layoutAnimation from '@utils/styles/layoutAnimation' import layoutAnimation from '@utils/styles/layoutAnimation'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { import React, { RefObject, useCallback, useContext, useEffect, useMemo, useRef } from 'react'
RefObject,
useCallback,
useContext,
useEffect,
useMemo,
useRef
} from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FlatList, Pressable, StyleSheet, View } from 'react-native' import { FlatList, Pressable, StyleSheet, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit' import { Circle } from 'react-native-animated-spinkit'
@ -39,41 +31,29 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
const { colors } = useTheme() const { colors } = useTheme()
const navigation = useNavigation<any>() const navigation = useNavigation<any>()
const maxAttachments = useSelector( const maxAttachments = useSelector(getInstanceConfigurationStatusMaxAttachments, () => true)
getInstanceConfigurationStatusMaxAttachments,
() => true
)
const flatListRef = useRef<FlatList>(null) const flatListRef = useRef<FlatList>(null)
const sensitiveOnPress = useCallback(() => { const sensitiveOnPress = useCallback(
analytics('compose_attachment_sensitive_press', { () =>
current: composeState.attachments.sensitive composeDispatch({
}) type: 'attachments/sensitive',
composeDispatch({ payload: { sensitive: !composeState.attachments.sensitive }
type: 'attachments/sensitive', }),
payload: { sensitive: !composeState.attachments.sensitive } [composeState.attachments.sensitive]
}) )
}, [composeState.attachments.sensitive])
const calculateWidth = useCallback((item: ExtendedAttachment) => { const calculateWidth = useCallback((item: ExtendedAttachment) => {
if (item.local) { if (item.local) {
return ( return ((item.local.width || 100) / (item.local.height || 100)) * DEFAULT_HEIGHT
((item.local.width || 100) / (item.local.height || 100)) *
DEFAULT_HEIGHT
)
} else { } else {
if (item.remote) { if (item.remote) {
if (item.remote.meta.original.aspect) { if (item.remote.meta.original.aspect) {
return item.remote.meta.original.aspect * DEFAULT_HEIGHT return item.remote.meta.original.aspect * DEFAULT_HEIGHT
} else if ( } else if (item.remote.meta.original.width && item.remote.meta.original.height) {
item.remote.meta.original.width &&
item.remote.meta.original.height
) {
return ( return (
(item.remote.meta.original.width / (item.remote.meta.original.width / item.remote.meta.original.height) * DEFAULT_HEIGHT
item.remote.meta.original.height) *
DEFAULT_HEIGHT
) )
} else { } else {
return DEFAULT_HEIGHT return DEFAULT_HEIGHT
@ -85,19 +65,17 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
}, []) }, [])
const snapToOffsets = useMemo(() => { const snapToOffsets = useMemo(() => {
const attachmentsOffsets = composeState.attachments.uploads.map( const attachmentsOffsets = composeState.attachments.uploads.map((_, index) => {
(_, index) => { let currentOffset = 0
let currentOffset = 0 Array.from(Array(index).keys()).map(
Array.from(Array(index).keys()).map( i =>
i => (currentOffset =
(currentOffset = currentOffset +
currentOffset + calculateWidth(composeState.attachments.uploads[i]) +
calculateWidth(composeState.attachments.uploads[i]) + StyleConstants.Spacing.Global.PagePadding)
StyleConstants.Spacing.Global.PagePadding) )
) return currentOffset
return currentOffset })
}
)
return attachmentsOffsets.length < 4 return attachmentsOffsets.length < 4
? [ ? [
...attachmentsOffsets, ...attachmentsOffsets,
@ -109,14 +87,9 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
}, [composeState.attachments.uploads.length]) }, [composeState.attachments.uploads.length])
let prevOffsets = useRef<number[]>() let prevOffsets = useRef<number[]>()
useEffect(() => { useEffect(() => {
if ( if (snapToOffsets.length > (prevOffsets.current ? prevOffsets.current.length : 0)) {
snapToOffsets.length >
(prevOffsets.current ? prevOffsets.current.length : 0)
) {
flatListRef.current?.scrollToOffset({ flatListRef.current?.scrollToOffset({
offset: offset: snapToOffsets[snapToOffsets.length - 2] + snapToOffsets[snapToOffsets.length - 1]
snapToOffsets[snapToOffsets.length - 2] +
snapToOffsets[snapToOffsets.length - 1]
}) })
} }
prevOffsets.current = snapToOffsets prevOffsets.current = snapToOffsets
@ -168,10 +141,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
backgroundColor: colors.backgroundOverlayInvert backgroundColor: colors.backgroundOverlayInvert
}} }}
> >
<Circle <Circle size={StyleConstants.Font.Size.L} color={colors.primaryOverlay} />
size={StyleConstants.Font.Size.L}
color={colors.primaryOverlay}
/>
</View> </View>
) : ( ) : (
<View <View
@ -184,17 +154,15 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
}} }}
> >
<Button <Button
accessibilityLabel={t( accessibilityLabel={t('content.root.footer.attachments.remove.accessibilityLabel', {
'content.root.footer.attachments.remove.accessibilityLabel', attachment: index + 1
{ attachment: index + 1 } })}
)}
type='icon' type='icon'
content='X' content='X'
spacing='M' spacing='M'
round round
overlay overlay
onPress={() => { onPress={() => {
analytics('compose_attachment_delete')
layoutAnimation() layoutAnimation()
composeDispatch({ composeDispatch({
type: 'attachment/delete', type: 'attachment/delete',
@ -204,17 +172,15 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
}} }}
/> />
<Button <Button
accessibilityLabel={t( accessibilityLabel={t('content.root.footer.attachments.edit.accessibilityLabel', {
'content.root.footer.attachments.edit.accessibilityLabel', attachment: index + 1
{ attachment: index + 1 } })}
)}
type='icon' type='icon'
content='Edit' content='Edit'
spacing='M' spacing='M'
round round
overlay overlay
onPress={() => { onPress={() => {
analytics('compose_attachment_edit')
navigation.navigate('Screen-Compose-EditAttachment', { navigation.navigate('Screen-Compose-EditAttachment', {
index index
}) })
@ -232,9 +198,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
() => ( () => (
<Pressable <Pressable
accessible accessible
accessibilityLabel={t( accessibilityLabel={t('content.root.footer.attachments.upload.accessibilityLabel')}
'content.root.footer.attachments.upload.accessibilityLabel'
)}
style={{ style={{
height: DEFAULT_HEIGHT, height: DEFAULT_HEIGHT,
marginLeft: StyleConstants.Spacing.Global.PagePadding, marginLeft: StyleConstants.Spacing.Global.PagePadding,
@ -244,7 +208,6 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
backgroundColor: colors.backgroundOverlayInvert backgroundColor: colors.backgroundOverlayInvert
}} }}
onPress={async () => { onPress={async () => {
analytics('compose_attachment_add_container_press')
await chooseAndUploadAttachment({ await chooseAndUploadAttachment({
composeDispatch, composeDispatch,
showActionSheetWithOptions showActionSheetWithOptions
@ -258,7 +221,6 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
round round
overlay overlay
onPress={async () => { onPress={async () => {
analytics('compose_attachment_add_button_press')
await chooseAndUploadAttachment({ await chooseAndUploadAttachment({
composeDispatch, composeDispatch,
showActionSheetWithOptions showActionSheetWithOptions
@ -266,16 +228,8 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
}} }}
style={{ style={{
position: 'absolute', position: 'absolute',
top: top: (DEFAULT_HEIGHT - StyleConstants.Spacing.M * 2 - StyleConstants.Font.Size.M) / 2,
(DEFAULT_HEIGHT - left: (DEFAULT_HEIGHT - StyleConstants.Spacing.M * 2 - StyleConstants.Font.Size.M) / 2
StyleConstants.Spacing.M * 2 -
StyleConstants.Font.Size.M) /
2,
left:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.M * 2 -
StyleConstants.Font.Size.M) /
2
}} }}
/> />
</Pressable> </Pressable>
@ -327,13 +281,9 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
showsHorizontalScrollIndicator={false} showsHorizontalScrollIndicator={false}
data={composeState.attachments.uploads} data={composeState.attachments.uploads}
keyExtractor={item => keyExtractor={item => item.local?.uri || item.remote?.url || Math.random().toString()}
item.local?.uri || item.remote?.url || Math.random().toString()
}
ListFooterComponent={ ListFooterComponent={
composeState.attachments.uploads.length < maxAttachments composeState.attachments.uploads.length < maxAttachments ? listFooter : null
? listFooter
: null
} }
/> />
</View> </View>

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { MenuRow } from '@components/Menu' import { MenuRow } from '@components/Menu'
@ -134,7 +133,6 @@ const ComposePoll: React.FC = () => {
) )
})} })}
onPress={() => { onPress={() => {
analytics('compose_poll_reduce_press')
total > 2 && total > 2 &&
composeDispatch({ composeDispatch({
type: 'poll', type: 'poll',
@ -169,7 +167,6 @@ const ComposePoll: React.FC = () => {
) )
})} })}
onPress={() => { onPress={() => {
analytics('compose_poll_increase_press')
total < MAX_OPTIONS && total < MAX_OPTIONS &&
composeDispatch({ composeDispatch({
type: 'poll', type: 'poll',
@ -205,10 +202,6 @@ const ComposePoll: React.FC = () => {
}, },
index => { index => {
if (index && index < 2) { if (index && index < 2) {
analytics('compose_poll_expiration_press', {
current: multiple,
new: index === 1
})
composeDispatch({ composeDispatch({
type: 'poll', type: 'poll',
payload: { multiple: index === 1 } payload: { multiple: index === 1 }
@ -249,10 +242,6 @@ const ComposePoll: React.FC = () => {
}, },
index => { index => {
if (index !== undefined && index < expirations.length) { if (index !== undefined && index < expirations.length) {
analytics('compose_poll_expiration_press', {
current: expire,
new: expirations[index]
})
composeDispatch({ composeDispatch({
type: 'poll', type: 'poll',
// @ts-ignore // @ts-ignore

View File

@ -1,5 +1,4 @@
import ComponentAccount from '@components/Account' import ComponentAccount from '@components/Account'
import analytics from '@components/analytics'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import ComponentHashtag from '@components/Hashtag' import ComponentHashtag from '@components/Hashtag'
import React, { useContext, useEffect } from 'react' import React, { useContext, useEffect } from 'react'
@ -18,9 +17,6 @@ const ComposeRootSuggestion: React.FC<Props> = ({ item }) => {
}, [composeState.text.raw.length]) }, [composeState.text.raw.length])
const onPress = () => { const onPress = () => {
analytics('compose_suggestion_press', {
type: item.acct ? 'account' : 'hashtag'
})
const focusedInput = composeState.textInputFocus.current const focusedInput = composeState.textInputFocus.current
const updatedText = (): string => { const updatedText = (): string => {
const main = item.acct ? `@${item.acct}` : `#${item.name}` const main = item.acct ? `@${item.acct}` : `#${item.name}`
@ -48,7 +44,7 @@ const ComposeRootSuggestion: React.FC<Props> = ({ item }) => {
} }
return item.acct ? ( return item.acct ? (
<ComponentAccount account={item} onPress={onPress} origin='suggestion' /> <ComponentAccount account={item} onPress={onPress} />
) : ( ) : (
<ComponentHashtag hashtag={item} onPress={onPress} origin='suggestion' /> <ComponentHashtag hashtag={item} onPress={onPress} origin='suggestion' />
) )

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header' import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header'
import { useActionSheet } from '@expo/react-native-action-sheet' import { useActionSheet } from '@expo/react-native-action-sheet'
@ -49,7 +48,6 @@ const ScreenImagesViewer = ({
const { showActionSheetWithOptions } = useActionSheet() const { showActionSheetWithOptions } = useActionSheet()
const onPress = useCallback(() => { const onPress = useCallback(() => {
analytics('imageviewer_more_press')
showActionSheetWithOptions( showActionSheetWithOptions(
{ {
options: [ options: [
@ -63,11 +61,9 @@ const ScreenImagesViewer = ({
async buttonIndex => { async buttonIndex => {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
analytics('imageviewer_more_save_press')
saveImage({ theme, image: imageUrls[currentIndex] }) saveImage({ theme, image: imageUrls[currentIndex] })
break break
case 1: case 1:
analytics('imageviewer_more_share_press')
switch (Platform.OS) { switch (Platform.OS) {
case 'ios': case 'ios':
await Share.share({ url: imageUrls[currentIndex].url }) await Share.share({ url: imageUrls[currentIndex].url })
@ -179,7 +175,6 @@ const ScreenImagesViewer = ({
</View> </View>
<LongPressGestureHandler <LongPressGestureHandler
onEnded={() => { onEnded={() => {
analytics('imageviewer_more_press')
showActionSheetWithOptions( showActionSheetWithOptions(
{ {
options: [ options: [
@ -193,11 +188,9 @@ const ScreenImagesViewer = ({
async buttonIndex => { async buttonIndex => {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
analytics('imageviewer_more_save_press')
saveImage({ theme, image: imageUrls[currentIndex] }) saveImage({ theme, image: imageUrls[currentIndex] })
break break
case 1: case 1:
analytics('imageviewer_more_share_press')
switch (Platform.OS) { switch (Platform.OS) {
case 'ios': case 'ios':
await Share.share({ url: imageUrls[currentIndex].url }) await Share.share({ url: imageUrls[currentIndex].url })

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { HeaderCenter, HeaderRight } from '@components/Header' import { HeaderCenter, HeaderRight } from '@components/Header'
import Timeline from '@components/Timeline' import Timeline from '@components/Timeline'
import TimelineDefault from '@components/Timeline/Default' import TimelineDefault from '@components/Timeline/Default'
@ -76,13 +75,12 @@ const TabLocal = React.memo(
accessibilityLabel={t('common.search.accessibilityLabel')} accessibilityLabel={t('common.search.accessibilityLabel')}
accessibilityHint={t('common.search.accessibilityHint')} accessibilityHint={t('common.search.accessibilityHint')}
content='Search' content='Search'
onPress={() => { onPress={() =>
analytics('search_tap', { page: 'Local' })
navigation.navigate('Tab-Local', { navigation.navigate('Tab-Local', {
screen: 'Tab-Shared-Search', screen: 'Tab-Shared-Search',
params: { text: undefined } params: { text: undefined }
}) })
}} }
/> />
) )
}} }}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer, MenuRow } from '@components/Menu'
import { useActionSheet } from '@expo/react-native-action-sheet' import { useActionSheet } from '@expo/react-native-action-sheet'
import { useAppDispatch } from '@root/store' import { useAppDispatch } from '@root/store'
@ -44,18 +43,12 @@ const TabMeProfileRoot: React.FC<
case 0: case 0:
case 1: case 1:
case 2: case 2:
const indexVisibilityMapping = [ const indexVisibilityMapping = ['public', 'unlisted', 'private'] as [
'public', 'public',
'unlisted', 'unlisted',
'private' 'private'
] as ['public', 'unlisted', 'private'] ]
if (data?.source.privacy !== indexVisibilityMapping[buttonIndex]) { if (data?.source.privacy !== indexVisibilityMapping[buttonIndex]) {
analytics('me_profile_visibility', {
current: t(
`me.profile.root.visibility.options.${data?.source.privacy}`
),
new: indexVisibilityMapping[buttonIndex]
})
mutateAsync({ mutateAsync({
theme, theme,
messageRef, messageRef,
@ -75,10 +68,6 @@ const TabMeProfileRoot: React.FC<
}, [theme, data?.source?.privacy]) }, [theme, data?.source?.privacy])
const onPressSensitive = useCallback(() => { const onPressSensitive = useCallback(() => {
analytics('me_profile_sensitive', {
current: data?.source.sensitive,
new: data?.source.sensitive === undefined ? true : !data.source.sensitive
})
mutateAsync({ mutateAsync({
theme, theme,
messageRef, messageRef,
@ -93,10 +82,6 @@ const TabMeProfileRoot: React.FC<
}, [data?.source.sensitive]) }, [data?.source.sensitive])
const onPressLock = useCallback(() => { const onPressLock = useCallback(() => {
analytics('me_profile_lock', {
current: data?.locked,
new: data?.locked === undefined ? true : !data.locked
})
mutateAsync({ mutateAsync({
theme, theme,
messageRef, messageRef,
@ -111,10 +96,6 @@ const TabMeProfileRoot: React.FC<
}, [theme, data?.locked]) }, [theme, data?.locked])
const onPressBot = useCallback(() => { const onPressBot = useCallback(() => {
analytics('me_profile_bot', {
current: data?.bot,
new: data?.bot === undefined ? true : !data.bot
})
mutateAsync({ mutateAsync({
theme, theme,
messageRef, messageRef,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer, MenuRow } from '@components/Menu'
@ -28,10 +27,7 @@ import { useSelector } from 'react-redux'
const TabMePush: React.FC = () => { const TabMePush: React.FC = () => {
const { colors } = useTheme() const { colors } = useTheme()
const { t } = useTranslation('screenTabs') const { t } = useTranslation('screenTabs')
const instanceAccount = useSelector( const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev?.acct === next?.acct)
getInstanceAccount,
(prev, next) => prev?.acct === next?.acct
)
const instanceUri = useSelector(getInstanceUri) const instanceUri = useSelector(getInstanceUri)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
@ -70,15 +66,7 @@ const TabMePush: React.FC = () => {
const alerts = useMemo(() => { const alerts = useMemo(() => {
return instancePush?.alerts return instancePush?.alerts
? ( ? (
[ ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'status'] as [
'follow',
'follow_request',
'favourite',
'reblog',
'mention',
'poll',
'status'
] as [
'follow', 'follow',
'follow_request', 'follow_request',
'favourite', 'favourite',
@ -91,15 +79,9 @@ const TabMePush: React.FC = () => {
<MenuRow <MenuRow
key={alert} key={alert}
title={t(`me.push.${alert}.heading`)} title={t(`me.push.${alert}.heading`)}
switchDisabled={ switchDisabled={!pushEnabled || !instancePush.global.value || isLoading}
!pushEnabled || !instancePush.global.value || isLoading
}
switchValue={instancePush?.alerts[alert].value} switchValue={instancePush?.alerts[alert].value}
switchOnValueChange={() => { switchOnValueChange={() =>
analytics(`me_push_${alert}`, {
current: instancePush?.alerts[alert].value,
new: !instancePush?.alerts[alert].value
})
dispatch( dispatch(
updateInstancePushAlert({ updateInstancePushAlert({
changed: alert, changed: alert,
@ -112,7 +94,7 @@ const TabMePush: React.FC = () => {
} }
}) })
) )
}} }
/> />
)) ))
: null : null
@ -127,23 +109,18 @@ const TabMePush: React.FC = () => {
<Button <Button
type='text' type='text'
content={ content={
pushCanAskAgain pushCanAskAgain ? t('me.push.enable.direct') : t('me.push.enable.settings')
? t('me.push.enable.direct')
: t('me.push.enable.settings')
} }
style={{ style={{
marginTop: StyleConstants.Spacing.Global.PagePadding, marginTop: StyleConstants.Spacing.Global.PagePadding,
marginHorizontal: marginHorizontal: StyleConstants.Spacing.Global.PagePadding * 2
StyleConstants.Spacing.Global.PagePadding * 2
}} }}
onPress={async () => { onPress={async () => {
if (pushCanAskAgain) { if (pushCanAskAgain) {
analytics('me_push_enabled_dialogue')
const result = await Notifications.requestPermissionsAsync() const result = await Notifications.requestPermissionsAsync()
setPushEnabled(result.granted) setPushEnabled(result.granted)
setPushCanAskAgain(result.canAskAgain) setPushCanAskAgain(result.canAskAgain)
} else { } else {
analytics('me_push_enabled_setting')
Linking.openSettings() Linking.openSettings()
} }
}} }}
@ -158,16 +135,8 @@ const TabMePush: React.FC = () => {
description={t('me.push.global.description')} description={t('me.push.global.description')}
loading={instancePush?.global.loading} loading={instancePush?.global.loading}
switchDisabled={!pushEnabled || isLoading} switchDisabled={!pushEnabled || isLoading}
switchValue={ switchValue={pushEnabled === false ? false : instancePush?.global.value}
pushEnabled === false ? false : instancePush?.global.value switchOnValueChange={() => dispatch(updateInstancePush(!instancePush?.global.value))}
}
switchOnValueChange={() => {
analytics('me_push_global', {
current: instancePush?.global.value,
new: !instancePush?.global.value
})
dispatch(updateInstancePush(!instancePush?.global.value))
}}
/> />
</MenuContainer> </MenuContainer>
<MenuContainer> <MenuContainer>
@ -175,25 +144,16 @@ const TabMePush: React.FC = () => {
title={t('me.push.decode.heading')} title={t('me.push.decode.heading')}
description={t('me.push.decode.description')} description={t('me.push.decode.description')}
loading={instancePush?.decode.loading} loading={instancePush?.decode.loading}
switchDisabled={ switchDisabled={!pushEnabled || !instancePush?.global.value || isLoading}
!pushEnabled || !instancePush?.global.value || isLoading
}
switchValue={instancePush?.decode.value} switchValue={instancePush?.decode.value}
switchOnValueChange={() => { switchOnValueChange={() =>
analytics('me_push_decode', {
current: instancePush?.decode.value,
new: !instancePush?.decode.value
})
dispatch(updateInstancePushDecode(!instancePush?.decode.value)) dispatch(updateInstancePushDecode(!instancePush?.decode.value))
}} }
/> />
<MenuRow <MenuRow
title={t('me.push.howitworks')} title={t('me.push.howitworks')}
iconBack='ExternalLink' iconBack='ExternalLink'
onPress={() => { onPress={() => WebBrowser.openBrowserAsync('https://tooot.app/how-push-works')}
analytics('me_push_howitworks')
WebBrowser.openBrowserAsync('https://tooot.app/how-push-works')
}}
/> />
</MenuContainer> </MenuContainer>
<MenuContainer>{alerts}</MenuContainer> <MenuContainer>{alerts}</MenuContainer>
@ -207,11 +167,7 @@ const TabMePush: React.FC = () => {
alignItems: 'center' alignItems: 'center'
}} }}
> >
<Icon <Icon name='Frown' size={StyleConstants.Font.Size.L} color={colors.primaryDefault} />
name='Frown'
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}> <CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
{t('me.push.notAvailable')} {t('me.push.notAvailable')}
</CustomText> </CustomText>

View File

@ -1,11 +1,6 @@
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer } from '@components/Menu'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { getInstanceVersion } from '@utils/slices/instancesSlice' import { getInstanceVersion } from '@utils/slices/instancesSlice'
import {
changeAnalytics,
getSettingsAnalytics
} from '@utils/slices/settingsSlice'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import Constants from 'expo-constants' import Constants from 'expo-constants'
@ -14,25 +9,13 @@ import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
const SettingsAnalytics: React.FC = () => { const SettingsAnalytics: React.FC = () => {
const dispatch = useAppDispatch()
const { colors } = useTheme() const { colors } = useTheme()
const { t } = useTranslation('screenTabs') const { t } = useTranslation('screenTabs')
const settingsAnalytics = useSelector(getSettingsAnalytics)
const instanceVersion = useSelector(getInstanceVersion, () => true) const instanceVersion = useSelector(getInstanceVersion, () => true)
return ( return (
<> <>
<MenuContainer>
<MenuRow
title={t('me.settings.analytics.heading')}
description={t('me.settings.analytics.description')}
switchValue={settingsAnalytics}
switchOnValueChange={() =>
dispatch(changeAnalytics(!settingsAnalytics))
}
/>
</MenuContainer>
<MenuContainer> <MenuContainer>
<CustomText <CustomText
fontStyle='S' fontStyle='S'

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer, MenuRow } from '@components/Menu'
import { useActionSheet } from '@expo/react-native-action-sheet' import { useActionSheet } from '@expo/react-native-action-sheet'
@ -77,26 +76,14 @@ const SettingsApp: React.FC = () => {
buttonIndex => { buttonIndex => {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
analytics('settings_appearance_press', {
current: settingsTheme,
new: 'auto'
})
haptics('Success') haptics('Success')
dispatch(changeTheme('auto')) dispatch(changeTheme('auto'))
break break
case 1: case 1:
analytics('settings_appearance_press', {
current: settingsTheme,
new: 'light'
})
haptics('Success') haptics('Success')
dispatch(changeTheme('light')) dispatch(changeTheme('light'))
break break
case 2: case 2:
analytics('settings_appearance_press', {
current: settingsTheme,
new: 'dark'
})
haptics('Success') haptics('Success')
dispatch(changeTheme('dark')) dispatch(changeTheme('dark'))
break break
@ -123,18 +110,10 @@ const SettingsApp: React.FC = () => {
buttonIndex => { buttonIndex => {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
analytics('settings_darktheme_press', {
current: settingsDarkTheme,
new: 'lighter'
})
haptics('Success') haptics('Success')
dispatch(changeDarkTheme('lighter')) dispatch(changeDarkTheme('lighter'))
break break
case 1: case 1:
analytics('settings_darktheme_press', {
current: settingsDarkTheme,
new: 'darker'
})
haptics('Success') haptics('Success')
dispatch(changeDarkTheme('darker')) dispatch(changeDarkTheme('darker'))
break break
@ -161,18 +140,10 @@ const SettingsApp: React.FC = () => {
buttonIndex => { buttonIndex => {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
analytics('settings_browser_press', {
current: settingsBrowser,
new: 'internal'
})
haptics('Success') haptics('Success')
dispatch(changeBrowser('internal')) dispatch(changeBrowser('internal'))
break break
case 1: case 1:
analytics('settings_browser_press', {
current: settingsBrowser,
new: 'external'
})
haptics('Success') haptics('Success')
dispatch(changeBrowser('external')) dispatch(changeBrowser('external'))
break break
@ -185,13 +156,7 @@ const SettingsApp: React.FC = () => {
title={t('me.settings.staticEmoji.heading')} title={t('me.settings.staticEmoji.heading')}
description={t('me.settings.staticEmoji.description')} description={t('me.settings.staticEmoji.description')}
switchValue={settingsStaticEmoji} switchValue={settingsStaticEmoji}
switchOnValueChange={() => { switchOnValueChange={() => dispatch(changeStaticEmoji(!settingsStaticEmoji))}
analytics('settings_staticemoji_press', {
current: settingsStaticEmoji.toString(),
new: !settingsStaticEmoji.toString()
})
dispatch(changeStaticEmoji(!settingsStaticEmoji))
}}
/> />
</MenuContainer> </MenuContainer>
) )

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer, MenuRow } from '@components/Menu'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
@ -33,29 +32,20 @@ const SettingsTooot: React.FC = () => {
<Icon name='MessageSquare' size={StyleConstants.Font.Size.M} color={colors.secondary} /> <Icon name='MessageSquare' size={StyleConstants.Font.Size.M} color={colors.secondary} />
} }
iconBack='ChevronRight' iconBack='ChevronRight'
onPress={() => { onPress={() => Linking.openURL('https://feedback.tooot.app/feature-requests')}
analytics('settings_feedback_press')
Linking.openURL('https://feedback.tooot.app/feature-requests')
}}
/> />
<MenuRow <MenuRow
title={t('me.settings.support.heading')} title={t('me.settings.support.heading')}
content={<Icon name='Heart' size={StyleConstants.Font.Size.M} color={colors.red} />} content={<Icon name='Heart' size={StyleConstants.Font.Size.M} color={colors.red} />}
iconBack='ChevronRight' iconBack='ChevronRight'
onPress={() => { onPress={() => Linking.openURL('https://www.buymeacoffee.com/xmflsct')}
analytics('settings_support_press')
Linking.openURL('https://www.buymeacoffee.com/xmflsct')
}}
/> />
{isDevelopment || isRelease ? ( {isDevelopment || isRelease ? (
<MenuRow <MenuRow
title={t('me.settings.review.heading')} title={t('me.settings.review.heading')}
content={<Icon name='Star' size={StyleConstants.Font.Size.M} color='#FF9500' />} content={<Icon name='Star' size={StyleConstants.Font.Size.M} color='#FF9500' />}
iconBack='ChevronRight' iconBack='ChevronRight'
onPress={() => { onPress={() => StoreReview?.isAvailableAsync().then(() => StoreReview?.requestReview())}
analytics('settings_review_press')
StoreReview?.isAvailableAsync().then(() => StoreReview?.requestReview())
}}
/> />
) : null} ) : null}
<MenuRow <MenuRow

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer, MenuRow } from '@components/Menu'
import { LOCALES } from '@root/i18n/locales' import { LOCALES } from '@root/i18n/locales'
@ -21,10 +20,6 @@ const TabMeSettingsLanguage: React.FC<
const dispatch = useDispatch() const dispatch = useDispatch()
const change = (lang: string) => { const change = (lang: string) => {
analytics('settings_language_press', {
current: i18n.language,
new: lang
})
haptics('Success') haptics('Success')
dispatch(changeLanguage(lang)) dispatch(changeLanguage(lang))

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { HeaderCenter, HeaderRight } from '@components/Header' import { HeaderCenter, HeaderRight } from '@components/Header'
import Timeline from '@components/Timeline' import Timeline from '@components/Timeline'
import TimelineNotifications from '@components/Timeline/Notifications' import TimelineNotifications from '@components/Timeline/Notifications'
@ -29,12 +28,11 @@ const TabNotifications = React.memo(
accessibilityLabel={t('notifications.filter.accessibilityLabel')} accessibilityLabel={t('notifications.filter.accessibilityLabel')}
accessibilityHint={t('notifications.filter.accessibilityHint')} accessibilityHint={t('notifications.filter.accessibilityHint')}
content='Filter' content='Filter'
onPress={() => { onPress={() =>
analytics('notificationsfilter_tap')
navigationRef.navigate('Screen-Actions', { navigationRef.navigate('Screen-Actions', {
type: 'notifications_filter' type: 'notifications_filter'
}) })
}} }
/> />
) )
}), }),

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { HeaderRight } from '@components/Header' import { HeaderRight } from '@components/Header'
import Timeline from '@components/Timeline' import Timeline from '@components/Timeline'
import TimelineDefault from '@components/Timeline/Default' import TimelineDefault from '@components/Timeline/Default'
@ -51,13 +50,12 @@ const TabPublic = React.memo(
accessibilityLabel={t('common.search.accessibilityLabel')} accessibilityLabel={t('common.search.accessibilityLabel')}
accessibilityHint={t('common.search.accessibilityHint')} accessibilityHint={t('common.search.accessibilityHint')}
content='Search' content='Search'
onPress={() => { onPress={() =>
analytics('search_tap', { page: pages[segment].key })
navigation.navigate('Tab-Public', { navigation.navigate('Tab-Public', {
screen: 'Tab-Shared-Search', screen: 'Tab-Shared-Search',
params: { text: undefined } params: { text: undefined }
}) })
}} }
/> />
) )
}), }),

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
@ -8,13 +7,7 @@ import { useTimelineQuery } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect } from 'react' import React, { useCallback, useEffect } from 'react'
import { import { Dimensions, ListRenderItem, Pressable, StyleSheet, View } from 'react-native'
Dimensions,
ListRenderItem,
Pressable,
StyleSheet,
View
} from 'react-native'
import { FlatList } from 'react-native-gesture-handler' import { FlatList } from 'react-native-gesture-handler'
import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated' import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated'
@ -24,16 +17,13 @@ export interface Props {
const AccountAttachments = React.memo( const AccountAttachments = React.memo(
({ account }: Props) => { ({ account }: Props) => {
const navigation = const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const { colors } = useTheme() const { colors } = useTheme()
const DISPLAY_AMOUNT = 6 const DISPLAY_AMOUNT = 6
const width = const width =
(Dimensions.get('screen').width - (Dimensions.get('screen').width - StyleConstants.Spacing.Global.PagePadding * 2) / 4
StyleConstants.Spacing.Global.PagePadding * 2) /
4
const queryKeyParams = { const queryKeyParams = {
page: 'Account_Attachments' as 'Account_Attachments', page: 'Account_Attachments' as 'Account_Attachments',
@ -62,9 +52,7 @@ const AccountAttachments = React.memo(
return ( return (
<Pressable <Pressable
onPress={() => { onPress={() => {
analytics('account_attachment_more_press') account && navigation.push('Tab-Shared-Attachments', { account })
account &&
navigation.push('Tab-Shared-Attachments', { account })
}} }}
children={ children={
<View <View
@ -91,21 +79,15 @@ const AccountAttachments = React.memo(
return ( return (
<GracefullyImage <GracefullyImage
uri={{ uri={{
original: original: item.media_attachments[0]?.preview_url || item.media_attachments[0]?.url,
item.media_attachments[0]?.preview_url ||
item.media_attachments[0]?.url,
remote: item.media_attachments[0]?.remote_url remote: item.media_attachments[0]?.remote_url
}} }}
blurhash={ blurhash={
item.media_attachments[0] && item.media_attachments[0] && (item.media_attachments[0].blurhash || undefined)
(item.media_attachments[0].blurhash || undefined)
} }
dimension={{ width: width, height: width }} dimension={{ width: width, height: width }}
style={{ marginLeft: StyleConstants.Spacing.Global.PagePadding }} style={{ marginLeft: StyleConstants.Spacing.Global.PagePadding }}
onPress={() => { onPress={() => navigation.push('Tab-Shared-Toot', { toot: item })}
analytics('account_attachment_item_press')
navigation.push('Tab-Shared-Toot', { toot: item })
}}
/> />
) )
} }
@ -116,9 +98,7 @@ const AccountAttachments = React.memo(
const styleContainer = useAnimatedStyle(() => { const styleContainer = useAnimatedStyle(() => {
if (flattenData.length) { if (flattenData.length) {
return { return {
height: withTiming( height: withTiming(width + StyleConstants.Spacing.Global.PagePadding * 2),
width + StyleConstants.Spacing.Global.PagePadding * 2
),
paddingVertical: StyleConstants.Spacing.Global.PagePadding, paddingVertical: StyleConstants.Spacing.Global.PagePadding,
borderTopWidth: 1, borderTopWidth: 1,
borderTopColor: colors.border borderTopColor: colors.border

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import { RelationshipOutgoing } from '@components/Relationship' import { RelationshipOutgoing } from '@components/Relationship'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
@ -25,13 +24,12 @@ const Conversation = ({ account }: { account: Mastodon.Account }) => {
type='icon' type='icon'
content='Mail' content='Mail'
style={styles.actionLeft} style={styles.actionLeft}
onPress={() => { onPress={() =>
analytics('account_DM_press')
navigation.navigate('Screen-Compose', { navigation.navigate('Screen-Compose', {
type: 'conversation', type: 'conversation',
accts: [account.acct] accts: [account.acct]
}) })
}} }
/> />
) : null ) : null
} }
@ -51,10 +49,7 @@ const AccountInformationActions: React.FC<Props> = ({ account, myInfo }) => {
<Button <Button
type='text' type='text'
content={t('shared.account.moved')} content={t('shared.account.moved')}
onPress={() => { onPress={() => navigation.push('Tab-Shared-Account', { account: accountMoved })}
analytics('account_gotomoved_press')
navigation.push('Tab-Shared-Account', { account: accountMoved })
}}
/> />
</View> </View>
) )
@ -74,9 +69,7 @@ const AccountInformationActions: React.FC<Props> = ({ account, myInfo }) => {
} }
const instanceAccount = useSelector(getInstanceAccount, () => true) const instanceAccount = useSelector(getInstanceAccount, () => true)
const ownAccount = const ownAccount = account?.id === instanceAccount?.id && account?.acct === instanceAccount?.acct
account?.id === instanceAccount?.id &&
account?.acct === instanceAccount?.acct
if (!ownAccount && account) { if (!ownAccount && account) {
return ( return (

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import GracefullyImage from '@components/GracefullyImage' import GracefullyImage from '@components/GracefullyImage'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
@ -25,7 +24,6 @@ const AccountInformationAvatar: React.FC<Props> = ({
<Pressable <Pressable
disabled={!myInfo} disabled={!myInfo}
onPress={() => { onPress={() => {
analytics('account_avatar_press')
myInfo && account && navigation.push('Tab-Shared-Account', { account }) myInfo && account && navigation.push('Tab-Shared-Account', { account })
}} }}
style={styles.base} style={styles.base}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack' import { StackNavigationProp } from '@react-navigation/stack'
@ -33,7 +32,6 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
count: account.statuses_count || 0 count: account.statuses_count || 0
})} })}
onPress={() => { onPress={() => {
analytics('account_stats_toots_press')
myInfo && account && navigation.push('Tab-Shared-Account', { account }) myInfo && account && navigation.push('Tab-Shared-Account', { account })
}} }}
/> />
@ -52,17 +50,14 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
children={t('shared.account.summary.following_count', { children={t('shared.account.summary.following_count', {
count: account.following_count count: account.following_count
})} })}
onPress={() => { onPress={() =>
analytics('account_stats_following_press', {
count: account.following_count
})
navigation.push('Tab-Shared-Users', { navigation.push('Tab-Shared-Users', {
reference: 'accounts', reference: 'accounts',
id: account.id, id: account.id,
type: 'following', type: 'following',
count: account.following_count count: account.following_count
}) })
}} }
/> />
) : ( ) : (
<PlaceholderLine <PlaceholderLine
@ -79,17 +74,14 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
children={t('shared.account.summary.followers_count', { children={t('shared.account.summary.followers_count', {
count: account.followers_count count: account.followers_count
})} })}
onPress={() => { onPress={() =>
analytics('account_stats_followers_press', {
count: account.followers_count
})
navigation.push('Tab-Shared-Users', { navigation.push('Tab-Shared-Users', {
reference: 'accounts', reference: 'accounts',
id: account.id, id: account.id,
type: 'followers', type: 'followers',
count: account.followers_count count: account.followers_count
}) })
}} }
/> />
) : ( ) : (
<PlaceholderLine <PlaceholderLine

View File

@ -9,18 +9,10 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react' import React, { useCallback, useMemo } from 'react'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { import { KeyboardAvoidingView, Platform, SectionList, StyleSheet, View } from 'react-native'
KeyboardAvoidingView,
Platform,
SectionList,
StyleSheet,
View
} from 'react-native'
import { Circle } from 'react-native-animated-spinkit' import { Circle } from 'react-native-animated-spinkit'
const TabSharedSearch: React.FC< const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>> = ({
TabSharedStackScreenProps<'Tab-Shared-Search'>
> = ({
route: { route: {
params: { text } params: { text }
} }
@ -75,10 +67,7 @@ const TabSharedSearch: React.FC<
<View> <View>
{status === 'loading' ? ( {status === 'loading' ? (
<View style={{ flex: 1, alignItems: 'center' }}> <View style={{ flex: 1, alignItems: 'center' }}>
<Circle <Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
size={StyleConstants.Font.Size.M * 1.25}
color={colors.secondary}
/>
</View> </View>
) : ( ) : (
<> <>
@ -96,39 +85,25 @@ const TabSharedSearch: React.FC<
}} }}
/> />
</CustomText> </CustomText>
<CustomText <CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
{t('shared.search.empty.advanced.header')} {t('shared.search.empty.advanced.header')}
</CustomText> </CustomText>
<CustomText <CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]} <CustomText style={{ color: colors.secondary }}>@username@domain</CustomText>
>
<CustomText style={{ color: colors.secondary }}>
@username@domain
</CustomText>
{' '} {' '}
{t('shared.search.empty.advanced.example.account')} {t('shared.search.empty.advanced.example.account')}
</CustomText> </CustomText>
<CustomText <CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]} <CustomText style={{ color: colors.secondary }}>#example</CustomText>
>
<CustomText style={{ color: colors.secondary }}>
#example
</CustomText>
{' '} {' '}
{t('shared.search.empty.advanced.example.hashtag')} {t('shared.search.empty.advanced.example.hashtag')}
</CustomText> </CustomText>
<CustomText <CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<CustomText style={{ color: colors.secondary }}>URL</CustomText> <CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '} {' '}
{t('shared.search.empty.advanced.example.statusLink')} {t('shared.search.empty.advanced.example.statusLink')}
</CustomText> </CustomText>
<CustomText <CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<CustomText style={{ color: colors.secondary }}>URL</CustomText> <CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '} {' '}
{t('shared.search.empty.advanced.example.accountLink')} {t('shared.search.empty.advanced.example.accountLink')}
@ -140,21 +115,18 @@ const TabSharedSearch: React.FC<
) )
}, [status]) }, [status])
const listItem = useCallback( const listItem = useCallback(({ item, section }: { item: any; section: any }) => {
({ item, section }: { item: any; section: any }) => { switch (section.title) {
switch (section.title) { case 'accounts':
case 'accounts': return <ComponentAccount account={item} />
return <ComponentAccount account={item} origin='search' /> case 'hashtags':
case 'hashtags': return <ComponentHashtag hashtag={item} origin='search' />
return <ComponentHashtag hashtag={item} origin='search' /> case 'statuses':
case 'statuses': return <TimelineDefault item={item} disableDetails />
return <TimelineDefault item={item} disableDetails origin='search' /> default:
default: return null
return null }
} }, [])
},
[]
)
return ( return (
<KeyboardAvoidingView <KeyboardAvoidingView
@ -195,10 +167,7 @@ const TabSharedSearch: React.FC<
backgroundColor: colors.backgroundDefault backgroundColor: colors.backgroundDefault
}} }}
> >
<CustomText <CustomText fontStyle='S' style={{ textAlign: 'center', color: colors.secondary }}>
fontStyle='S'
style={{ textAlign: 'center', color: colors.secondary }}
>
<Trans <Trans
i18nKey='screenTabs:shared.search.notFound' i18nKey='screenTabs:shared.search.notFound'
values={{ searchTerm: text, type: translation }} values={{ searchTerm: text, type: translation }}

View File

@ -34,7 +34,7 @@ const TabSharedUsers = React.memo(
data={flattenData} data={flattenData}
style={styles.flatList} style={styles.flatList}
renderItem={({ item }) => ( renderItem={({ item }) => (
<ComponentAccount account={item} origin='relationship' /> <ComponentAccount account={item} />
)} )}
onEndReached={onEndReached} onEndReached={onEndReached}
onEndReachedThreshold={0.75} onEndReachedThreshold={0.75}

View File

@ -55,7 +55,7 @@ const settingsPersistConfig = {
key: 'settings', key: 'settings',
prefix, prefix,
storage: AsyncStorage, storage: AsyncStorage,
version: 1, version: 3,
// @ts-ignore // @ts-ignore
migrate: createMigrate(settingsMigration) migrate: createMigrate(settingsMigration)
} }

View File

@ -1,6 +1,7 @@
import { SettingsV0 } from './v0' import { SettingsV0 } from './v0'
import { SettingsV1 } from './v1' import { SettingsV1 } from './v1'
import { SettingsV2 } from './v2' import { SettingsV2 } from './v2'
import { SettingsV3 } from './v3'
const settingsMigration = { const settingsMigration = {
1: (state: SettingsV0): SettingsV1 => { 1: (state: SettingsV0): SettingsV1 => {
@ -15,6 +16,10 @@ const settingsMigration = {
darkTheme: 'lighter', darkTheme: 'lighter',
staticEmoji: false staticEmoji: false
} }
},
3: (state: SettingsV2): SettingsV3 => {
const { analytics, ...rest } = state
return rest
} }
} }

View File

@ -0,0 +1,8 @@
export type SettingsV3 = {
fontsize: -1 | 0 | 1 | 2 | 3
language: string
theme: 'light' | 'dark' | 'auto'
darkTheme: 'lighter' | 'darker'
browser: 'internal' | 'external'
staticEmoji: boolean
}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import features from '@helpers/features' import features from '@helpers/features'
import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { RootState } from '@root/store' import { RootState } from '@root/store'
@ -184,8 +183,6 @@ const instancesSlice = createSlice({
} }
}) })
} }
analytics('login')
}) })
.addCase(addInstance.rejected, (state, action) => { .addCase(addInstance.rejected, (state, action) => {
console.error(state.instances) console.error(state.instances)
@ -204,8 +201,6 @@ const instancesSlice = createSlice({
} }
}) })
state.instances.length && (state.instances[state.instances.length - 1].active = true) state.instances.length && (state.instances[state.instances.length - 1].active = true)
analytics('logout')
}) })
.addCase(removeInstance.rejected, (state, action) => { .addCase(removeInstance.rejected, (state, action) => {
console.error(state) console.error(state)

View File

@ -1,72 +1,43 @@
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { LOCALES } from '@root/i18n/locales' import { LOCALES } from '@root/i18n/locales'
import { RootState } from '@root/store' import { RootState } from '@root/store'
import { SettingsV2 } from '@utils/migrations/settings/v2' import { SettingsV3 } from '@utils/migrations/settings/v3'
import * as Analytics from 'expo-firebase-analytics'
import * as Localization from 'expo-localization' import * as Localization from 'expo-localization'
import { pickBy } from 'lodash' import { pickBy } from 'lodash'
export const changeAnalytics = createAsyncThunk( export type SettingsState = SettingsV3
'settings/changeAnalytics',
async (newValue: SettingsState['analytics']) => {
await Analytics.setAnalyticsCollectionEnabled(newValue)
return { newValue }
}
)
export type SettingsState = SettingsV2
export const settingsInitialState = { export const settingsInitialState = {
fontsize: 0, fontsize: 0,
notification: { notification: {
enabled: false enabled: false
}, },
language: Object.keys( language: Object.keys(pickBy(LOCALES, (_, key) => Localization.locale.startsWith(key)))
pickBy(LOCALES, (_, key) => Localization.locale.startsWith(key)) ? Object.keys(pickBy(LOCALES, (_, key) => Localization.locale.startsWith(key)))[0]
)
? Object.keys(
pickBy(LOCALES, (_, key) => Localization.locale.startsWith(key))
)[0]
: 'en', : 'en',
theme: 'auto', theme: 'auto',
darkTheme: 'lighter', darkTheme: 'lighter',
browser: 'internal', browser: 'internal',
staticEmoji: false, staticEmoji: false
analytics: true
} }
const settingsSlice = createSlice({ const settingsSlice = createSlice({
name: 'settings', name: 'settings',
initialState: settingsInitialState as SettingsState, initialState: settingsInitialState as SettingsState,
reducers: { reducers: {
changeFontsize: ( changeFontsize: (state, action: PayloadAction<SettingsState['fontsize']>) => {
state,
action: PayloadAction<SettingsState['fontsize']>
) => {
state.fontsize = action.payload state.fontsize = action.payload
}, },
changeLanguage: ( changeLanguage: (state, action: PayloadAction<NonNullable<SettingsState['language']>>) => {
state,
action: PayloadAction<NonNullable<SettingsState['language']>>
) => {
state.language = action.payload state.language = action.payload
}, },
changeTheme: ( changeTheme: (state, action: PayloadAction<NonNullable<SettingsState['theme']>>) => {
state,
action: PayloadAction<NonNullable<SettingsState['theme']>>
) => {
state.theme = action.payload state.theme = action.payload
}, },
changeDarkTheme: ( changeDarkTheme: (state, action: PayloadAction<NonNullable<SettingsState['darkTheme']>>) => {
state,
action: PayloadAction<NonNullable<SettingsState['darkTheme']>>
) => {
state.darkTheme = action.payload state.darkTheme = action.payload
}, },
changeBrowser: ( changeBrowser: (state, action: PayloadAction<NonNullable<SettingsState['browser']>>) => {
state,
action: PayloadAction<NonNullable<SettingsState['browser']>>
) => {
state.browser = action.payload state.browser = action.payload
}, },
changeStaticEmoji: ( changeStaticEmoji: (
@ -75,25 +46,15 @@ const settingsSlice = createSlice({
) => { ) => {
state.staticEmoji = action.payload state.staticEmoji = action.payload
} }
},
extraReducers: builder => {
builder.addCase(changeAnalytics.fulfilled, (state, action) => {
state.analytics = action.payload.newValue
})
} }
}) })
export const getSettingsFontsize = (state: RootState) => export const getSettingsFontsize = (state: RootState) => state.settings.fontsize || 0
state.settings.fontsize || 0
export const getSettingsLanguage = (state: RootState) => state.settings.language export const getSettingsLanguage = (state: RootState) => state.settings.language
export const getSettingsTheme = (state: RootState) => state.settings.theme export const getSettingsTheme = (state: RootState) => state.settings.theme
export const getSettingsDarkTheme = (state: RootState) => export const getSettingsDarkTheme = (state: RootState) => state.settings.darkTheme
state.settings.darkTheme
export const getSettingsBrowser = (state: RootState) => state.settings.browser export const getSettingsBrowser = (state: RootState) => state.settings.browser
export const getSettingsStaticEmoji = (state: RootState) => export const getSettingsStaticEmoji = (state: RootState) => state.settings.staticEmoji
state.settings.staticEmoji
export const getSettingsAnalytics = (state: RootState) =>
state.settings.analytics
export const { export const {
changeFontsize, changeFontsize,

View File

@ -5659,20 +5659,6 @@ expo-file-system@^15.1.1, expo-file-system@~15.1.0, expo-file-system@~15.1.1:
dependencies: dependencies:
uuid "^3.4.0" uuid "^3.4.0"
expo-firebase-analytics@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/expo-firebase-analytics/-/expo-firebase-analytics-8.0.0.tgz#69b17bf48317d95a55f28cbd485e06d4800c134b"
integrity sha512-nWYa5vm2BX+qXrB0UQPMb0vh+QSGpx9G78TetRQAa+M+96j5Y0qUEsSKWkKvkICFF8ItnhNz2vdDNWZrMLefnw==
dependencies:
expo-firebase-core "~6.0.0"
expo-firebase-core@~6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/expo-firebase-core/-/expo-firebase-core-6.0.0.tgz#854fb72b6769f3c6d3caa5797c3f8d4effe9a564"
integrity sha512-ZMcvRxKuAjZ0V4+VCuYKQ9P3Br8nGUORCbG41ewyLnLXBwov85AdBx4/5lA7T5cX1oOmv2fKMnU3gqCR+s6Veg==
dependencies:
expo-constants "~14.0.0"
expo-font@~11.0.1: expo-font@~11.0.1:
version "11.0.1" version "11.0.1"
resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-11.0.1.tgz#0758ce4e505995d0193a33e3c4325b35bf1fb7f7" resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-11.0.1.tgz#0758ce4e505995d0193a33e3c4325b35bf1fb7f7"